1 /**-*-C-*-**********************************************************************
5 * Utility to convert an ASCII hexdump into a libpcap-format capture file
7 * (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *******************************************************************************/
29 /*******************************************************************************
31 * This utility reads in an ASCII hexdump of this common format:
33 * 00000000 00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
34 * 00000010 03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3...
\7f..
35 * 00000020 03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
36 * 00000030 01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
38 * Each bytestring line consists of an offset, one or more bytes, and
39 * text at the end. An offset is defined as a hex string of more than
40 * two characters. A byte is defined as a hex string of exactly two
41 * characters. The text at the end is ignored, as is any text before
42 * the offset. Bytes read from a bytestring line are added to the
43 * current packet only if all the following conditions are satisfied:
45 * - No text appears between the offset and the bytes (any bytes appearing after
46 * such text would be ignored)
48 * - The offset must be arithmetically correct, i.e. if the offset is 00000020, then
49 * exactly 32 bytes must have been read into this packet before this. If the offset
50 * is wrong, the packet is immediately terminated
52 * A packet start is signaled by a zero offset.
54 * Lines starting with #TEXT2PCAP are directives. These allow the user
55 * to embed instructions into the capture file which allows text2pcap
56 * to take some actions (e.g. specifying the encapsulation
57 * etc.). Currently no directives are implemented.
59 * Lines beginning with # which are not directives are ignored as
60 * comments. Currently all non-hexdump text is ignored by text2pcap;
61 * in the future, text processing may be added, but lines prefixed
62 * with '#' will still be ignored.
64 * The output is a libpcap packet containing Ethernet frames by
65 * default. This program takes options which allow the user to add
66 * dummy Ethernet, IP and UDP or TCP headers to the packets in order
67 * to allow dumps of L3 or higher protocols to be decoded.
69 * Considerable flexibility is built into this code to read hexdumps
70 * of slightly different formats. For example, any text prefixing the
71 * hexdump line is dropped (including mail forwarding '>'). The offset
72 * can be any hex number of four digits or greater.
74 * This converter cannot read a single packet greater than 64KiB-1. Packet
75 * snaplength is automatically set to 64KiB-1.
81 * Just make sure we include the prototype for strptime as well
82 * (needed for glibc 2.2) but make sure we do this only if not
90 # define _XOPEN_SOURCE 600
95 * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms
96 * using glibc, to expand the set of things system header files define.
98 * Unfortunately, on other platforms, such as some versions of Solaris
99 * (including Solaris 10), it *reduces* that set as well, causing
100 * strptime() not to be declared, presumably because the version of the
101 * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and
102 * blah blah blah namespace pollution blah blah blah.
104 * So we define __EXTENSIONS__ so that "strptime()" is declared.
106 #ifndef __EXTENSIONS__
107 # define __EXTENSIONS__
113 #include <wsutil/file_util.h>
114 #include <wsutil/crash_info.h>
115 #include <wsutil/ws_diag_control.h>
116 #include <wsutil/ws_version_info.h>
129 #include <zlib.h> /* to get the libz version number */
132 #ifndef HAVE_GETOPT_LONG
133 #include "wsutil/wsgetopt.h"
136 #ifndef HAVE_STRPTIME
137 # include "wsutil/strptime.h"
141 #include "text2pcap.h"
144 #include <wsutil/unicode-utils.h>
147 #ifdef HAVE_ARPA_INET_H
148 #include <arpa/inet.h>
151 #ifdef HAVE_WINSOCK2_H
152 #include <winsock2.h> /* needed to define AF_ values on Windows */
155 #ifndef HAVE_INET_ATON
156 # include "wsutil/inet_aton.h"
159 #ifdef HAVE_SYS_SOCKET_H
160 #include <sys/socket.h>
163 #ifdef NEED_INET_V6DEFS_H
164 # include "wsutil/inet_v6defs.h"
167 /*--- Options --------------------------------------------------------------------*/
170 static gboolean use_pcapng = FALSE;
173 static int debug = 0;
175 static int quiet = FALSE;
177 /* Dummy Ethernet header */
178 static int hdr_ethernet = FALSE;
179 static guint32 hdr_ethernet_proto = 0;
181 /* Dummy IP header */
182 static int hdr_ip = FALSE;
183 static int hdr_ipv6 = FALSE;
184 static long hdr_ip_proto = 0;
186 /* Destination and source addresses for IP header */
187 static guint32 hdr_ip_dest_addr = 0;
188 static guint32 hdr_ip_src_addr = 0;
189 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
190 static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
191 static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
193 /* Dummy UDP header */
194 static int hdr_udp = FALSE;
195 static guint32 hdr_dest_port = 0;
196 static guint32 hdr_src_port = 0;
198 /* Dummy TCP header */
199 static int hdr_tcp = FALSE;
201 /* TCP sequence numbers when has_direction is true */
202 static guint32 tcp_in_seq_num = 0;
203 static guint32 tcp_out_seq_num = 0;
205 /* Dummy SCTP header */
206 static int hdr_sctp = FALSE;
207 static guint32 hdr_sctp_src = 0;
208 static guint32 hdr_sctp_dest = 0;
209 static guint32 hdr_sctp_tag = 0;
211 /* Dummy DATA chunk header */
212 static int hdr_data_chunk = FALSE;
213 static guint8 hdr_data_chunk_type = 0;
214 static guint8 hdr_data_chunk_bits = 0;
215 static guint32 hdr_data_chunk_tsn = 0;
216 static guint16 hdr_data_chunk_sid = 0;
217 static guint16 hdr_data_chunk_ssn = 0;
218 static guint32 hdr_data_chunk_ppid = 0;
220 /* ASCII text dump identification */
221 static int identify_ascii = FALSE;
223 static gboolean has_direction = FALSE;
224 static guint32 direction = 0;
226 /*--- Local date -----------------------------------------------------------------*/
228 /* This is where we store the packet currently being built */
229 #define MAX_PACKET 65535
230 static guint8 packet_buf[MAX_PACKET];
231 static guint32 header_length;
232 static guint32 ip_offset;
233 static guint32 curr_offset;
234 static guint32 max_offset = MAX_PACKET;
235 static guint32 packet_start = 0;
237 static void start_new_packet(gboolean);
239 /* This buffer contains strings present before the packet offset 0 */
240 #define PACKET_PREAMBLE_MAX_LEN 2048
241 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
242 static int packet_preamble_len = 0;
244 /* Number of packets read and written */
245 static guint32 num_packets_read = 0;
246 static guint32 num_packets_written = 0;
247 static guint64 bytes_written = 0;
249 /* Time code of packet, derived from packet_preamble */
250 static time_t ts_sec = 0;
251 static guint32 ts_nsec = 0;
252 static char *ts_fmt = NULL;
253 static struct tm timecode_default;
255 static guint8* pkt_lnstart;
258 static const char *input_filename;
259 static FILE *input_file = NULL;
261 static const char *output_filename;
262 static FILE *output_file = NULL;
264 /* Offset base to parse */
265 static guint32 offset_base = 16;
269 /* ----- State machine -----------------------------------------------------------*/
271 /* Current state of parser */
273 INIT, /* Waiting for start of new packet */
274 START_OF_LINE, /* Starting from beginning of line */
275 READ_OFFSET, /* Just read the offset */
276 READ_BYTE, /* Just read a byte */
277 READ_TEXT /* Just read text - ignore until EOL */
279 static parser_state_t state = INIT;
281 static const char *state_str[] = {"Init",
288 static const char *token_str[] = {"",
296 /* ----- Skeleton Packet Headers --------------------------------------------------*/
304 static hdr_ethernet_t HDR_ETHERNET = {
305 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
306 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
312 guint16 packet_length;
313 guint16 identification;
318 guint16 hdr_checksum;
323 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
324 #ifdef WORDS_BIGENDIAN
325 0x0a010101, 0x0a020202
327 0x0101010a, 0x0202020a
331 /* Fixed IP address values */
332 #ifdef WORDS_BIGENDIAN
333 #define IP_SRC 0x0a010101
334 #define IP_DST 0x0a020202
336 #define IP_SRC 0x0101010a
337 #define IP_DST 0x0202020a
340 static struct { /* pseudo header for checksum calculation */
349 /* headers taken from glibc */
356 guint8 __u6_addr8[16];
357 guint16 __u6_addr16[8];
358 guint32 __u6_addr32[4];
365 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
366 guint16 ip6_un1_plen; /* payload length */
367 guint8 ip6_un1_nxt; /* next header */
368 guint8 ip6_un1_hlim; /* hop limit */
370 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
372 struct hdr_in6_addr ip6_src; /* source address */
373 struct hdr_in6_addr ip6_dst; /* destination address */
376 static hdr_ipv6_t HDR_IPv6;
378 static struct { /* pseudo header ipv6 for checksum calculation */
379 struct hdr_in6_addr src_addr6;
380 struct hdr_in6_addr dst_addr6;
393 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
407 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
416 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
428 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
430 static char tempbuf[64];
432 /*----------------------------------------------------------------------
433 * Stuff for writing a PCap file
435 #define PCAP_SNAPLEN 0xffff
437 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
438 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
440 /*----------------------------------------------------------------------
441 * Parse a single hex number
442 * Will abort the program if it can't parse the number
443 * Pass in TRUE if this is an offset, FALSE if not
446 parse_num (const char *str, int offset)
452 fprintf(stderr, "FATAL ERROR: str is NULL\n");
456 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
458 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
464 /*----------------------------------------------------------------------
465 * Write this byte into current packet
468 write_byte (const char *str)
472 num = parse_num(str, FALSE);
473 packet_buf[curr_offset] = (guint8) num;
475 if (curr_offset - header_length >= max_offset) /* packet full */
476 start_new_packet(TRUE);
479 /*----------------------------------------------------------------------
480 * Write a number of bytes into current packet
484 write_bytes (const char bytes[], guint32 nbytes)
488 if (curr_offset + nbytes < MAX_PACKET) {
489 for (i = 0; i < nbytes; i++) {
490 packet_buf[curr_offset] = bytes[i];
496 /*----------------------------------------------------------------------
497 * Remove bytes from the current packet
500 unwrite_bytes (guint32 nbytes)
502 curr_offset -= nbytes;
505 /*----------------------------------------------------------------------
506 * Compute one's complement checksum (from RFC1071)
509 in_checksum (void *buf, guint32 count)
512 guint16 *addr = (guint16 *)buf;
515 /* This is the inner loop */
516 sum += g_ntohs(* (guint16 *) addr);
521 /* Add left-over byte, if any */
523 sum += g_ntohs(* (guint8 *) addr);
525 /* Fold 32-bit sum to 16 bits */
527 sum = (sum & 0xffff) + (sum >> 16);
533 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
534 * That code is copyrighted by D. Otis and has been modified.
537 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
538 static guint32 crc_c[256] =
540 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
541 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
542 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
543 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
544 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
545 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
546 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
547 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
548 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
549 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
550 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
551 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
552 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
553 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
554 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
555 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
556 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
557 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
558 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
559 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
560 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
561 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
562 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
563 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
564 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
565 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
566 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
567 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
568 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
569 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
570 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
571 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
572 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
573 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
574 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
575 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
576 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
577 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
578 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
579 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
580 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
581 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
582 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
583 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
584 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
585 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
586 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
587 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
588 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
589 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
590 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
591 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
592 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
593 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
594 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
595 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
596 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
597 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
598 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
599 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
600 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
601 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
602 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
603 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
607 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
613 for (i = 0; i < len; i++)
620 finalize_crc32c (guint32 crc)
623 guint8 byte0,byte1,byte2,byte3;
626 byte0 = result & 0xff;
627 byte1 = (result>>8) & 0xff;
628 byte2 = (result>>16) & 0xff;
629 byte3 = (result>>24) & 0xff;
630 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
635 number_of_padding_bytes (guint32 length)
639 remainder = length % 4;
644 return 4 - remainder;
647 /*----------------------------------------------------------------------
648 * Write current packet out
651 write_current_packet (gboolean cont)
654 guint16 padding_length = 0;
659 if (curr_offset > header_length) {
660 /* Write the packet */
662 /* Is direction indication on with an inbound packet? */
663 gboolean isInbound = has_direction && (direction == 2);
665 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
667 hdr_ethernet_proto = 0x86DD;
671 /* Compute packet length */
672 length = curr_offset;
674 padding_length = number_of_padding_bytes(length - header_length );
678 /* Reset curr_offset, since we now write the headers */
681 /* Write Ethernet header */
683 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
684 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
687 /* Write IP header */
690 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
691 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
694 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
695 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
698 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
699 HDR_IP.protocol = (guint8) hdr_ip_proto;
700 HDR_IP.hdr_checksum = 0;
701 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
702 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
703 } else if (hdr_ipv6) {
704 if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
705 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
706 if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
707 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
709 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
710 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
711 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
712 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
713 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
714 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
716 /* initialize pseudo ipv6 header for checksum calculation */
717 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
718 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
720 pseudoh6.protocol = (guint8) hdr_ip_proto;
721 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
722 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
726 /* initialize pseudo header for checksum calculation */
727 pseudoh.src_addr = HDR_IP.src_addr;
728 pseudoh.dest_addr = HDR_IP.dest_addr;
730 pseudoh.protocol = (guint8) hdr_ip_proto;
731 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
734 /* Write UDP header */
739 /* initialize the UDP header */
740 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
741 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
742 HDR_UDP.length = pseudoh.length;
743 HDR_UDP.checksum = 0;
744 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
745 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
747 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
749 x16 = in_checksum(packet_buf + header_length, length - header_length);
751 x16 = (u & 0xffff) + (u>>16);
752 HDR_UDP.checksum = g_htons(x16);
753 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
754 HDR_UDP.checksum = g_htons(1);
755 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
758 /* Write TCP header */
763 /* initialize pseudo header for checksum calculation */
764 pseudoh.src_addr = HDR_IP.src_addr;
765 pseudoh.dest_addr = HDR_IP.dest_addr;
767 pseudoh.protocol = (guint8) hdr_ip_proto;
768 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
769 /* initialize the TCP header */
770 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
771 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
772 /* set ack number if we have direction */
774 HDR_TCP.flags = 0x10;
775 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
776 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
782 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
783 HDR_TCP.window = g_htons(0x2000);
784 HDR_TCP.checksum = 0;
785 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
786 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
788 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
790 x16 = in_checksum(packet_buf + header_length, length - header_length);
792 x16 = (u & 0xffff) + (u>>16);
793 HDR_TCP.checksum = g_htons(x16);
794 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
795 HDR_TCP.checksum = g_htons(1);
796 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
798 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
799 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
802 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
803 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
807 /* Compute DATA chunk header */
808 if (hdr_data_chunk) {
809 hdr_data_chunk_bits = 0;
810 if (packet_start == 0) {
811 hdr_data_chunk_bits |= 0x02;
814 hdr_data_chunk_bits |= 0x01;
816 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
817 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
818 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
819 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
820 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
821 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
822 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
823 hdr_data_chunk_tsn++;
825 hdr_data_chunk_ssn++;
829 /* Write SCTP common header */
833 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
834 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
835 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
836 HDR_SCTP.checksum = g_htonl(0);
837 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
838 if (hdr_data_chunk) {
839 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
840 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
841 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
843 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
845 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
846 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
847 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
850 /* Write DATA chunk header */
851 if (hdr_data_chunk) {
852 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
855 /* Reset curr_offset, since we now write the trailers */
856 curr_offset = length;
858 /* Write DATA chunk padding */
859 if (hdr_data_chunk && (padding_length > 0)) {
860 memset(tempbuf, 0, padding_length);
861 write_bytes((const char *)&tempbuf, padding_length);
862 length += padding_length;
865 /* Write Ethernet trailer */
866 if (hdr_ethernet && (length < 60)) {
867 memset(tempbuf, 0, 60 - length);
868 write_bytes((const char *)&tempbuf, 60 - length);
872 success = pcapng_write_enhanced_packet_block(output_file,
878 packet_buf, direction,
879 &bytes_written, &err);
881 success = libpcap_write_packet(output_file,
882 ts_sec, ts_nsec/1000,
885 &bytes_written, &err);
888 fprintf(stderr, "File write error [%s] : %s\n",
889 output_filename, g_strerror(err));
892 if (ts_fmt == NULL) {
893 /* fake packet counter */
900 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
902 num_packets_written++;
905 packet_start += curr_offset - header_length;
906 curr_offset = header_length;
910 /*----------------------------------------------------------------------
911 * Write file header and trailer
914 write_file_header (void)
923 appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
924 comment = g_strdup_printf("Generated from input file %s.", input_filename);
925 success = pcapng_write_session_header_block(output_file,
930 -1, /* section_length */
936 success = pcapng_write_interface_description_block(output_file,
950 success = libpcap_write_file_header(output_file, pcap_link_type,
952 &bytes_written, &err);
955 fprintf(stderr, "File write error [%s] : %s\n",
956 output_filename, g_strerror(err));
962 write_file_trailer (void)
968 success = pcapng_write_interface_statistics_block(output_file,
971 "Counters provided by text2pcap",
975 num_packets_written - num_packets_written,
982 fprintf(stderr, "File write error [%s] : %s\n",
983 output_filename, g_strerror(err));
989 /*----------------------------------------------------------------------
990 * Append a token to the packet preamble.
993 append_to_preamble (char *str)
997 if (packet_preamble_len != 0) {
998 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
999 return; /* no room to add more preamble */
1000 /* Add a blank separator between the previous token and this token. */
1001 packet_preamble[packet_preamble_len++] = ' ';
1003 toklen = strlen(str);
1005 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1006 return; /* no room to add the token to the preamble */
1007 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1008 packet_preamble_len += (int) toklen;
1011 char xs[PACKET_PREAMBLE_MAX_LEN];
1012 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1013 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1014 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1019 /*----------------------------------------------------------------------
1020 * Parse the preamble to get the timecode.
1024 parse_preamble (void)
1033 * Null-terminate the preamble.
1035 packet_preamble[packet_preamble_len] = '\0';
1037 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1039 if (has_direction) {
1040 switch (packet_preamble[0]) {
1043 direction = 0x00000001;
1044 packet_preamble[0] = ' ';
1048 direction = 0x00000002;
1049 packet_preamble[0] = ' ';
1052 direction = 0x00000000;
1056 while (packet_preamble[i] == ' ' ||
1057 packet_preamble[i] == '\r' ||
1058 packet_preamble[i] == '\t') {
1061 packet_preamble_len -= i;
1062 /* Also move the trailing '\0'. */
1063 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1068 * If no "-t" flag was specified, don't attempt to parse the packet
1069 * preamble to extract a time stamp.
1071 if (ts_fmt == NULL) {
1072 /* Clear Preamble */
1073 packet_preamble_len = 0;
1078 * Initialize to today localtime, just in case not all fields
1079 * of the date and time are specified.
1082 timecode = timecode_default;
1085 /* Ensure preamble has more than two chars before attempting to parse.
1086 * This should cover line breaks etc that get counted.
1088 if (strlen(packet_preamble) > 2) {
1089 /* Get Time leaving subseconds */
1090 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1091 if (subsecs != NULL) {
1092 /* Get the long time from the tm structure */
1093 /* (will return -1 if failure) */
1094 ts_sec = mktime( &timecode );
1096 ts_sec = -1; /* we failed to parse it */
1098 /* This will ensure incorrectly parsed dates get set to zero */
1100 /* Sanitize - remove all '\r' */
1102 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1103 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1104 packet_preamble, ts_fmt);
1106 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1107 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1108 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1110 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1113 /* Parse subseconds */
1114 ts_nsec = (guint32)strtol(subsecs, &p, 10);
1120 * Convert that number to a number
1121 * of microseconds; if it's N digits
1122 * long, it's in units of 10^(-N) seconds,
1123 * so, to convert it to units of
1124 * 10^-9 seconds, we multiply by
1127 subseclen = (int) (p - subsecs);
1128 if (subseclen > 9) {
1130 * *More* than 9 digits; 9-N is
1131 * negative, so we divide by
1134 for (i = subseclen - 9; i != 0; i--)
1136 } else if (subseclen < 9) {
1137 for (i = 9 - subseclen; i != 0; i--)
1145 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1146 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1147 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1151 /* Clear Preamble */
1152 packet_preamble_len = 0;
1155 /*----------------------------------------------------------------------
1156 * Start a new packet
1159 start_new_packet (gboolean cont)
1162 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1164 /* Write out the current packet, if required */
1165 write_current_packet(cont);
1168 /* Ensure we parse the packet preamble as it may contain the time */
1172 /*----------------------------------------------------------------------
1173 * Process a directive
1176 process_directive (char *str)
1178 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1181 /*----------------------------------------------------------------------
1182 * Parse a single token (called from the scanner)
1185 parse_token (token_t token, char *str)
1196 * This is implemented as a simple state machine of five states.
1197 * State transitions are caused by tokens being received from the
1198 * scanner. The code should be self-documenting.
1202 /* Sanitize - remove all '\r' */
1204 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1206 fprintf(stderr, "(%s, %s \"%s\") -> (",
1207 state_str[state], token_str[token], str ? str : "");
1212 /* ----- Waiting for new packet -------------------------------------------*/
1214 if (!str && token != T_EOL) goto fail_null_str;
1217 append_to_preamble(str);
1220 process_directive(str);
1223 num = parse_num(str, TRUE);
1225 /* New packet starts here */
1226 start_new_packet(FALSE);
1227 state = READ_OFFSET;
1228 pkt_lnstart = packet_buf + num;
1232 /* Some describing text may be parsed as offset, but the invalid
1233 offset will be checked in the state of START_OF_LINE, so
1234 we add this transition to gain flexibility */
1235 state = START_OF_LINE;
1242 /* ----- Processing packet, start of new line -----------------------------*/
1244 if (!str && token != T_EOL) goto fail_null_str;
1247 append_to_preamble(str);
1250 process_directive(str);
1253 num = parse_num(str, TRUE);
1255 /* New packet starts here */
1256 start_new_packet(FALSE);
1258 state = READ_OFFSET;
1259 } else if ((num - packet_start) != curr_offset - header_length) {
1261 * The offset we read isn't the one we expected.
1262 * This may only mean that we mistakenly interpreted
1263 * some text as byte values (e.g., if the text dump
1264 * of packet data included a number with spaces around
1265 * it). If the offset is less than what we expected,
1266 * assume that's the problem, and throw away the putative
1267 * extra byte values.
1269 if (num < curr_offset) {
1270 unwrite_bytes(curr_offset - num);
1271 state = READ_OFFSET;
1273 /* Bad offset; switch to INIT state */
1275 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1277 write_current_packet(FALSE);
1281 state = READ_OFFSET;
1282 pkt_lnstart = packet_buf + num;
1285 state = START_OF_LINE;
1292 /* ----- Processing packet, read offset -----------------------------------*/
1296 /* Record the byte */
1298 if (!str) goto fail_null_str;
1307 state = START_OF_LINE;
1314 /* ----- Processing packet, read byte -------------------------------------*/
1318 /* Record the byte */
1327 if (token == T_EOL) {
1329 state = START_OF_LINE;
1331 if (identify_ascii) {
1332 /* Here a line of pkt bytes reading is finished
1333 compare the ascii and hex to avoid such situation:
1334 "61 62 20 ab ", when ab is ascii dump then it should
1335 not be treat as byte */
1337 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1338 s2 = "ab ", s1 = "616220"
1339 we should find out the largest tail of s1 matches the head
1340 of s2, it means the matched part in tail is the ASCII dump
1341 of the head byte. These matched should be rollback */
1342 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1343 s2 = (char*)g_malloc((line_size+1)/4+1);
1344 /* gather the possible pattern */
1345 for (i = 0; i < (line_size+1)/4; i++) {
1346 tmp_str[0] = pkt_lnstart[i*3];
1347 tmp_str[1] = pkt_lnstart[i*3+1];
1349 /* it is a valid convertable string */
1350 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1353 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1355 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1356 if (!(pkt_lnstart[i*3+2] == ' ')) {
1362 /* If packet line start contains possible byte pattern, the line end
1363 should contain the matched pattern if the user open the -a flag.
1364 The packet will be possible invalid if the byte pattern cannot find
1365 a matched one in the line of packet buffer.*/
1367 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1368 unwrite_bytes(rollback);
1370 /* Not matched. This line contains invalid packet bytes, so
1371 discard the whole line */
1373 unwrite_bytes(line_size);
1384 /* ----- Processing packet, read text -------------------------------------*/
1388 state = START_OF_LINE;
1396 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1401 fprintf(stderr, ", %s)\n", state_str[state]);
1406 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1411 /*----------------------------------------------------------------------
1412 * Print usage string and exit
1415 print_usage (FILE *output)
1419 "Usage: text2pcap [options] <infile> <outfile>\n"
1421 "where <infile> specifies input filename (use - for standard input)\n"
1422 " <outfile> specifies output filename (use - for standard output)\n"
1425 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1426 " default is hex.\n"
1427 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1428 " the specified argument is a format string of the sort\n"
1429 " supported by strptime.\n"
1430 " Example: The time \"10:15:14.5476\" has the format code\n"
1431 " \"%%H:%%M:%%S.\"\n"
1432 " NOTE: The subsecond component delimiter, '.', must be\n"
1433 " given, but no pattern is required; the remaining\n"
1434 " number is assumed to be fractions of a second.\n"
1435 " NOTE: Date/time fields from the current date/time are\n"
1436 " used as the default for unspecified fields.\n"
1437 " -D the text before the packet starts with an I or an O,\n"
1438 " indicating that the packet is inbound or outbound.\n"
1439 " This is only stored if the output format is PCAP-NG.\n"
1440 " -a enable ASCII text dump identification.\n"
1441 " The start of the ASCII text dump can be identified\n"
1442 " and excluded from the packet data, even if it looks\n"
1443 " like a HEX dump.\n"
1444 " NOTE: Do not enable it if the input file does not\n"
1445 " contain the ASCII text dump.\n"
1448 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1449 " http://www.tcpdump.org/linktypes.html for a list of\n"
1450 " numbers. Use this option if your dump is a complete\n"
1451 " hex dump of an encapsulated packet and you wish to\n"
1452 " specify the exact type of encapsulation.\n"
1453 " Example: -l 7 for ARCNet packets.\n"
1454 " -m <max-packet> max packet length in output; default is %d\n"
1456 "Prepend dummy header:\n"
1457 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1459 " Example: -e 0x806 to specify an ARP packet.\n"
1460 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1462 " Automatically prepends Ethernet header as well.\n"
1464 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1465 " dest and source address.\n"
1466 " Example: -4 10.0.0.1,10.0.0.2\n"
1467 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1468 " dest and source address.\n"
1469 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1470 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1471 " source and destination ports (in DECIMAL).\n"
1472 " Automatically prepends Ethernet & IP headers as well.\n"
1473 " Example: -u 1000,69 to make the packets look like\n"
1474 " TFTP/UDP packets.\n"
1475 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1476 " source and destination ports (in DECIMAL).\n"
1477 " Automatically prepends Ethernet & IP headers as well.\n"
1478 " Example: -T 50,60\n"
1479 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1480 " source/dest ports and verification tag (in DECIMAL).\n"
1481 " Automatically prepends Ethernet & IP headers as well.\n"
1482 " Example: -s 30,40,34\n"
1483 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1484 " source/dest ports and verification tag 0.\n"
1485 " Automatically prepends a dummy SCTP DATA\n"
1486 " chunk header with payload protocol identifier ppi.\n"
1487 " Example: -S 30,40,34\n"
1490 " -h display this help and exit.\n"
1491 " -d show detailed debug of parser states.\n"
1492 " -q generate no output at all (automatically disables -d).\n"
1493 " -n use PCAP-NG instead of PCAP as output format.\n"
1499 get_text2pcap_compiled_info(GString *str)
1502 g_string_append(str, ", ");
1504 g_string_append(str, "with libz ");
1506 g_string_append(str, ZLIB_VERSION);
1507 #else /* ZLIB_VERSION */
1508 g_string_append(str, "(version unknown)");
1509 #endif /* ZLIB_VERSION */
1510 #else /* HAVE_LIBZ */
1511 g_string_append(str, "without libz");
1512 #endif /* HAVE_LIBZ */
1516 get_text2pcap_runtime_info(GString *str)
1519 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1520 g_string_append_printf(str, ", with libz %s", zlibVersion());
1524 /*----------------------------------------------------------------------
1528 parse_options (int argc, char *argv[])
1530 GString *comp_info_str;
1531 GString *runtime_info_str;
1535 static const struct option long_options[] = {
1536 {(char *)"help", no_argument, NULL, 'h'},
1537 {(char *)"version", no_argument, NULL, 'v'},
1543 arg_list_utf_16to8(argc, argv);
1544 create_app_running_mutex();
1547 /* Get the compile-time version information string */
1548 comp_info_str = get_compiled_version_info(NULL, get_text2pcap_compiled_info);
1550 /* get the run-time version information string */
1551 runtime_info_str = get_runtime_version_info(get_text2pcap_runtime_info);
1553 /* Add it to the information to be reported on a crash. */
1554 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1559 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1561 /* Scan CLI parameters */
1562 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1565 printf("Text2pcap (Wireshark) %s\n"
1566 "Generate a capture file from an ASCII hexdump of packets.\n"
1567 "See http://www.wireshark.org for more information.\n",
1568 get_ws_vcs_version_info());
1569 print_usage(stdout);
1572 case 'd': if (!quiet) debug++; break;
1573 case 'D': has_direction = TRUE; break;
1574 case 'q': quiet = TRUE; debug = FALSE; break;
1575 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1576 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1577 case 'n': use_pcapng = TRUE; break;
1579 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1580 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1581 print_usage(stderr);
1584 switch (optarg[0]) {
1585 case 'o': offset_base = 8; break;
1586 case 'h': offset_base = 16; break;
1587 case 'd': offset_base = 10; break;
1591 hdr_ethernet = TRUE;
1592 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1593 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1594 print_usage(stderr);
1601 hdr_ip_proto = strtol(optarg, &p, 10);
1602 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1603 hdr_ip_proto > 255) {
1604 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1605 print_usage(stderr);
1608 hdr_ethernet = TRUE;
1609 hdr_ethernet_proto = 0x800;
1614 hdr_data_chunk = FALSE;
1617 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1618 if (p == optarg || (*p != ',' && *p != '\0')) {
1619 fprintf(stderr, "Bad src port for '-%c'\n", c);
1620 print_usage(stderr);
1624 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1625 print_usage(stderr);
1630 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1631 if (p == optarg || (*p != ',' && *p != '\0')) {
1632 fprintf(stderr, "Bad dest port for '-s'\n");
1633 print_usage(stderr);
1637 fprintf(stderr, "No tag specified for '-%c'\n", c);
1638 print_usage(stderr);
1643 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1644 if (p == optarg || *p != '\0') {
1645 fprintf(stderr, "Bad tag for '-%c'\n", c);
1646 print_usage(stderr);
1652 hdr_ethernet = TRUE;
1653 hdr_ethernet_proto = 0x800;
1657 hdr_data_chunk = TRUE;
1660 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1661 if (p == optarg || (*p != ',' && *p != '\0')) {
1662 fprintf(stderr, "Bad src port for '-%c'\n", c);
1663 print_usage(stderr);
1667 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1668 print_usage(stderr);
1673 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1674 if (p == optarg || (*p != ',' && *p != '\0')) {
1675 fprintf(stderr, "Bad dest port for '-s'\n");
1676 print_usage(stderr);
1680 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1681 print_usage(stderr);
1686 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1687 if (p == optarg || *p != '\0') {
1688 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1689 print_usage(stderr);
1695 hdr_ethernet = TRUE;
1696 hdr_ethernet_proto = 0x800;
1707 hdr_data_chunk = FALSE;
1708 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1709 if (p == optarg || (*p != ',' && *p != '\0')) {
1710 fprintf(stderr, "Bad src port for '-u'\n");
1711 print_usage(stderr);
1715 fprintf(stderr, "No dest port specified for '-u'\n");
1716 print_usage(stderr);
1721 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1722 if (p == optarg || *p != '\0') {
1723 fprintf(stderr, "Bad dest port for '-u'\n");
1724 print_usage(stderr);
1729 hdr_ethernet = TRUE;
1730 hdr_ethernet_proto = 0x800;
1737 hdr_data_chunk = FALSE;
1738 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1739 if (p == optarg || (*p != ',' && *p != '\0')) {
1740 fprintf(stderr, "Bad src port for '-T'\n");
1741 print_usage(stderr);
1745 fprintf(stderr, "No dest port specified for '-u'\n");
1746 print_usage(stderr);
1751 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1752 if (p == optarg || *p != '\0') {
1753 fprintf(stderr, "Bad dest port for '-T'\n");
1754 print_usage(stderr);
1759 hdr_ethernet = TRUE;
1760 hdr_ethernet_proto = 0x800;
1764 identify_ascii = TRUE;
1768 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1769 g_string_free(comp_info_str, TRUE);
1770 g_string_free(runtime_info_str, TRUE);
1776 p = strchr(optarg, ',');
1779 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1780 print_usage(stderr);
1788 hdr_ethernet_proto = 0x86DD;
1793 hdr_ethernet_proto = 0x800;
1795 hdr_ethernet = TRUE;
1797 if (hdr_ipv6 == TRUE) {
1798 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1799 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1800 print_usage(stderr);
1804 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1805 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1806 print_usage(stderr);
1813 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1814 print_usage(stderr);
1818 if (hdr_ipv6 == TRUE) {
1819 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1820 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1821 print_usage(stderr);
1825 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1826 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1827 print_usage(stderr);
1836 print_usage(stderr);
1841 if (optind >= argc || argc-optind < 2) {
1842 fprintf(stderr, "Must specify input and output filename\n");
1843 print_usage(stderr);
1847 if (strcmp(argv[optind], "-")) {
1848 input_filename = g_strdup(argv[optind]);
1849 input_file = ws_fopen(input_filename, "rb");
1851 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1852 input_filename, g_strerror(errno));
1856 input_filename = "Standard input";
1860 if (strcmp(argv[optind+1], "-")) {
1861 output_filename = g_strdup(argv[optind+1]);
1862 output_file = ws_fopen(output_filename, "wb");
1864 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1865 output_filename, g_strerror(errno));
1869 output_filename = "Standard output";
1870 output_file = stdout;
1873 /* Some validation */
1874 if (pcap_link_type != 1 && hdr_ethernet) {
1875 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1879 /* Set up our variables */
1882 input_filename = "Standard input";
1885 output_file = stdout;
1886 output_filename = "Standard output";
1889 ts_sec = time(0); /* initialize to current time */
1890 timecode_default = *localtime(&ts_sec);
1891 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1893 /* Display summary of our state */
1895 fprintf(stderr, "Input from: %s\n", input_filename);
1896 fprintf(stderr, "Output to: %s\n", output_filename);
1897 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1899 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1900 hdr_ethernet_proto);
1901 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1903 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1904 hdr_src_port, hdr_dest_port);
1905 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1906 hdr_src_port, hdr_dest_port);
1907 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1908 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1909 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1910 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1915 main(int argc, char *argv[])
1917 parse_options(argc, argv);
1919 assert(input_file != NULL);
1920 assert(output_file != NULL);
1922 write_file_header();
1926 header_length += (int)sizeof(HDR_ETHERNET);
1929 ip_offset = header_length;
1930 header_length += (int)sizeof(HDR_IP);
1931 } else if (hdr_ipv6) {
1932 ip_offset = header_length;
1933 header_length += (int)sizeof(HDR_IPv6);
1936 header_length += (int)sizeof(HDR_SCTP);
1938 if (hdr_data_chunk) {
1939 header_length += (int)sizeof(HDR_DATA_CHUNK);
1942 header_length += (int)sizeof(HDR_TCP);
1945 header_length += (int)sizeof(HDR_UDP);
1947 curr_offset = header_length;
1952 write_current_packet(FALSE);
1953 write_file_trailer();
1955 fclose(output_file);
1957 fprintf(stderr, "\n-------------------------\n");
1959 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1960 num_packets_read, (num_packets_read == 1) ? "" : "s",
1961 num_packets_written, (num_packets_written == 1) ? "" : "s",
1962 bytes_written, (bytes_written == 1) ? "" : "s");
1968 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1973 * indent-tabs-mode: nil
1976 * vi: set shiftwidth=4 tabstop=8 expandtab:
1977 * :indentSize=4:tabSize=8:noTabs=true: