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 * SPDX-License-Identifier: GPL-2.0+
15 *******************************************************************************/
17 /*******************************************************************************
19 * This utility reads in an ASCII hexdump of this common format:
21 * 00000000 00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
22 * 00000010 03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3...
\7f..
23 * 00000020 03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
24 * 00000030 01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
26 * Each bytestring line consists of an offset, one or more bytes, and
27 * text at the end. An offset is defined as a hex string of more than
28 * two characters. A byte is defined as a hex string of exactly two
29 * characters. The text at the end is ignored, as is any text before
30 * the offset. Bytes read from a bytestring line are added to the
31 * current packet only if all the following conditions are satisfied:
33 * - No text appears between the offset and the bytes (any bytes appearing after
34 * such text would be ignored)
36 * - The offset must be arithmetically correct, i.e. if the offset is 00000020, then
37 * exactly 32 bytes must have been read into this packet before this. If the offset
38 * is wrong, the packet is immediately terminated
40 * A packet start is signaled by a zero offset.
42 * Lines starting with #TEXT2PCAP are directives. These allow the user
43 * to embed instructions into the capture file which allows text2pcap
44 * to take some actions (e.g. specifying the encapsulation
45 * etc.). Currently no directives are implemented.
47 * Lines beginning with # which are not directives are ignored as
48 * comments. Currently all non-hexdump text is ignored by text2pcap;
49 * in the future, text processing may be added, but lines prefixed
50 * with '#' will still be ignored.
52 * The output is a libpcap packet containing Ethernet frames by
53 * default. This program takes options which allow the user to add
54 * dummy Ethernet, IP and UDP or TCP headers to the packets in order
55 * to allow dumps of L3 or higher protocols to be decoded.
57 * Considerable flexibility is built into this code to read hexdumps
58 * of slightly different formats. For example, any text prefixing the
59 * hexdump line is dropped (including mail forwarding '>'). The offset
60 * can be any hex number of four digits or greater.
62 * This converter cannot read a single packet greater than 64KiB-1. Packet
63 * snaplength is automatically set to 64KiB-1.
69 * Just make sure we include the prototype for strptime as well
70 * (needed for glibc 2.2) but make sure we do this only if not
78 # define _XOPEN_SOURCE 600
83 * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms
84 * using glibc, to expand the set of things system header files define.
86 * Unfortunately, on other platforms, such as some versions of Solaris
87 * (including Solaris 10), it *reduces* that set as well, causing
88 * strptime() not to be declared, presumably because the version of the
89 * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and
90 * blah blah blah namespace pollution blah blah blah.
92 * So we define __EXTENSIONS__ so that "strptime()" is declared.
94 #ifndef __EXTENSIONS__
95 # define __EXTENSIONS__
101 #include <wsutil/file_util.h>
102 #include <wsutil/crash_info.h>
103 #include <version_info.h>
104 #include <wsutil/inet_addr.h>
107 #include <io.h> /* for _setmode */
108 #include <fcntl.h> /* for O_BINARY */
121 #ifndef HAVE_GETOPT_LONG
122 #include "wsutil/wsgetopt.h"
125 #ifndef HAVE_STRPTIME
126 # include "wsutil/strptime.h"
129 #include "writecap/pcapio.h"
130 #include "text2pcap.h"
132 #include "wiretap/wtap.h"
135 #include <wsutil/unicode-utils.h>
138 /*--- Options --------------------------------------------------------------------*/
141 static gboolean use_pcapng = FALSE;
144 static int debug = 0;
146 static int quiet = FALSE;
148 /* Dummy Ethernet header */
149 static int hdr_ethernet = FALSE;
150 static guint32 hdr_ethernet_proto = 0;
152 /* Dummy IP header */
153 static int hdr_ip = FALSE;
154 static int hdr_ipv6 = FALSE;
155 static long hdr_ip_proto = 0;
157 /* Destination and source addresses for IP header */
158 static guint32 hdr_ip_dest_addr = 0;
159 static guint32 hdr_ip_src_addr = 0;
160 static ws_in6_addr hdr_ipv6_dest_addr = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
161 static ws_in6_addr hdr_ipv6_src_addr = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
162 static ws_in6_addr NO_IPv6_ADDRESS = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
164 /* Dummy UDP header */
165 static int hdr_udp = FALSE;
166 static guint32 hdr_dest_port = 0;
167 static guint32 hdr_src_port = 0;
169 /* Dummy TCP header */
170 static int hdr_tcp = FALSE;
172 /* TCP sequence numbers when has_direction is true */
173 static guint32 tcp_in_seq_num = 0;
174 static guint32 tcp_out_seq_num = 0;
176 /* Dummy SCTP header */
177 static int hdr_sctp = FALSE;
178 static guint32 hdr_sctp_src = 0;
179 static guint32 hdr_sctp_dest = 0;
180 static guint32 hdr_sctp_tag = 0;
182 /* Dummy DATA chunk header */
183 static int hdr_data_chunk = FALSE;
184 static guint8 hdr_data_chunk_type = 0;
185 static guint8 hdr_data_chunk_bits = 0;
186 static guint32 hdr_data_chunk_tsn = 0;
187 static guint16 hdr_data_chunk_sid = 0;
188 static guint16 hdr_data_chunk_ssn = 0;
189 static guint32 hdr_data_chunk_ppid = 0;
191 /* ASCII text dump identification */
192 static int identify_ascii = FALSE;
194 static gboolean has_direction = FALSE;
195 static guint32 direction = 0;
197 /*--- Local date -----------------------------------------------------------------*/
199 /* This is where we store the packet currently being built */
200 static guint8 packet_buf[WTAP_MAX_PACKET_SIZE_STANDARD];
201 static guint32 header_length;
202 static guint32 ip_offset;
203 static guint32 curr_offset;
204 static guint32 max_offset = WTAP_MAX_PACKET_SIZE_STANDARD;
205 static guint32 packet_start = 0;
207 static int start_new_packet(gboolean);
209 /* This buffer contains strings present before the packet offset 0 */
210 #define PACKET_PREAMBLE_MAX_LEN 2048
211 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
212 static int packet_preamble_len = 0;
214 /* Number of packets read and written */
215 static guint32 num_packets_read = 0;
216 static guint32 num_packets_written = 0;
217 static guint64 bytes_written = 0;
219 /* Time code of packet, derived from packet_preamble */
220 static time_t ts_sec = 0;
221 static guint32 ts_nsec = 0;
222 static char *ts_fmt = NULL;
223 static struct tm timecode_default;
225 static guint8* pkt_lnstart;
228 static char *input_filename;
229 static FILE *input_file = NULL;
231 static char *output_filename;
232 static FILE *output_file = NULL;
234 /* Offset base to parse */
235 static guint32 offset_base = 16;
237 extern FILE *text2pcap_in;
239 /* ----- State machine -----------------------------------------------------------*/
241 /* Current state of parser */
243 INIT, /* Waiting for start of new packet */
244 START_OF_LINE, /* Starting from beginning of line */
245 READ_OFFSET, /* Just read the offset */
246 READ_BYTE, /* Just read a byte */
247 READ_TEXT /* Just read text - ignore until EOL */
249 static parser_state_t state = INIT;
251 static const char *state_str[] = {"Init",
258 static const char *token_str[] = {"",
266 /* ----- Skeleton Packet Headers --------------------------------------------------*/
274 static hdr_ethernet_t HDR_ETHERNET = {
275 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
276 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
282 guint16 packet_length;
283 guint16 identification;
288 guint16 hdr_checksum;
293 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
294 #ifdef WORDS_BIGENDIAN
295 0x0a010101, 0x0a020202
297 0x0101010a, 0x0202020a
301 /* Fixed IP address values */
302 #ifdef WORDS_BIGENDIAN
303 #define IP_SRC 0x0a010101
304 #define IP_DST 0x0a020202
306 #define IP_SRC 0x0101010a
307 #define IP_DST 0x0202020a
310 static struct { /* pseudo header for checksum calculation */
319 /* headers taken from glibc */
324 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
325 guint16 ip6_un1_plen; /* payload length */
326 guint8 ip6_un1_nxt; /* next header */
327 guint8 ip6_un1_hlim; /* hop limit */
329 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
331 ws_in6_addr ip6_src; /* source address */
332 ws_in6_addr ip6_dst; /* destination address */
335 static hdr_ipv6_t HDR_IPv6;
337 static struct { /* pseudo header ipv6 for checksum calculation */
338 struct e_in6_addr src_addr6;
339 struct e_in6_addr dst_addr6;
352 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
366 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
375 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
387 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
389 static char tempbuf[64];
391 /*----------------------------------------------------------------------
392 * Stuff for writing a PCap file
394 #define PCAP_SNAPLEN 0xffff
396 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
397 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
399 /*----------------------------------------------------------------------
400 * Parse a single hex number
401 * Will abort the program if it can't parse the number
402 * Pass in TRUE if this is an offset, FALSE if not
405 parse_num(const char *str, int offset, guint32* num)
410 fprintf(stderr, "FATAL ERROR: str is NULL\n");
414 *num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
416 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
422 /*----------------------------------------------------------------------
423 * Write this byte into current packet
426 write_byte(const char *str)
430 if (parse_num(str, FALSE, &num) != EXIT_SUCCESS)
433 packet_buf[curr_offset] = (guint8) num;
435 if (curr_offset - header_length >= max_offset) /* packet full */
436 if (start_new_packet(TRUE) != EXIT_SUCCESS)
442 /*----------------------------------------------------------------------
443 * Write a number of bytes into current packet
447 write_bytes (const char bytes[], guint32 nbytes)
451 if (curr_offset + nbytes < WTAP_MAX_PACKET_SIZE_STANDARD) {
452 for (i = 0; i < nbytes; i++) {
453 packet_buf[curr_offset] = bytes[i];
459 /*----------------------------------------------------------------------
460 * Remove bytes from the current packet
463 unwrite_bytes (guint32 nbytes)
465 curr_offset -= nbytes;
468 /*----------------------------------------------------------------------
469 * Compute one's complement checksum (from RFC1071)
472 in_checksum (void *buf, guint32 count)
475 guint16 *addr = (guint16 *)buf;
478 /* This is the inner loop */
479 sum += g_ntohs(* (guint16 *) addr);
484 /* Add left-over byte, if any */
486 sum += g_ntohs(* (guint8 *) addr);
488 /* Fold 32-bit sum to 16 bits */
490 sum = (sum & 0xffff) + (sum >> 16);
496 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
497 * That code is copyrighted by D. Otis and has been modified.
500 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
501 static guint32 crc_c[256] =
503 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
504 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
505 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
506 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
507 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
508 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
509 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
510 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
511 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
512 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
513 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
514 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
515 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
516 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
517 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
518 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
519 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
520 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
521 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
522 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
523 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
524 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
525 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
526 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
527 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
528 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
529 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
530 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
531 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
532 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
533 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
534 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
535 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
536 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
537 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
538 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
539 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
540 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
541 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
542 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
543 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
544 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
545 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
546 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
547 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
548 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
549 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
550 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
551 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
552 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
553 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
554 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
555 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
556 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
557 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
558 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
559 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
560 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
561 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
562 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
563 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
564 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
565 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
566 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
570 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
576 for (i = 0; i < len; i++)
583 finalize_crc32c (guint32 crc)
586 guint8 byte0,byte1,byte2,byte3;
589 byte0 = result & 0xff;
590 byte1 = (result>>8) & 0xff;
591 byte2 = (result>>16) & 0xff;
592 byte3 = (result>>24) & 0xff;
593 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
598 number_of_padding_bytes (guint32 length)
602 remainder = length % 4;
607 return 4 - remainder;
610 /*----------------------------------------------------------------------
611 * Write current packet out
614 write_current_packet (gboolean cont)
617 guint16 padding_length = 0;
622 if (curr_offset > header_length) {
623 /* Write the packet */
625 /* Is direction indication on with an inbound packet? */
626 gboolean isInbound = has_direction && (direction == 2);
628 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
630 hdr_ethernet_proto = 0x86DD;
634 /* Compute packet length */
635 length = curr_offset;
637 padding_length = number_of_padding_bytes(length - header_length );
641 /* Reset curr_offset, since we now write the headers */
644 /* Write Ethernet header */
646 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
647 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
650 /* Write IP header */
653 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
654 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
657 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
658 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
661 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
662 HDR_IP.protocol = (guint8) hdr_ip_proto;
663 HDR_IP.hdr_checksum = 0;
664 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
665 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
666 } else if (hdr_ipv6) {
667 if (memcmp(isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr)))
668 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(ws_in6_addr));
669 if (memcmp(isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr)))
670 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(ws_in6_addr));
672 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
673 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
674 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
675 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
676 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
677 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
679 /* initialize pseudo ipv6 header for checksum calculation */
680 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
681 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
683 pseudoh6.protocol = (guint8) hdr_ip_proto;
684 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
685 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
689 /* initialize pseudo header for checksum calculation */
690 pseudoh.src_addr = HDR_IP.src_addr;
691 pseudoh.dest_addr = HDR_IP.dest_addr;
693 pseudoh.protocol = (guint8) hdr_ip_proto;
694 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
697 /* Write UDP header */
702 /* initialize the UDP header */
703 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
704 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
705 HDR_UDP.length = pseudoh.length;
706 HDR_UDP.checksum = 0;
707 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
708 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
710 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
712 x16 = in_checksum(packet_buf + header_length, length - header_length);
714 x16 = (u & 0xffff) + (u>>16);
715 HDR_UDP.checksum = g_htons(x16);
716 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
717 HDR_UDP.checksum = g_htons(1);
718 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
721 /* Write TCP header */
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_TCP));
732 /* initialize the TCP header */
733 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
734 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
735 /* set ack number if we have direction */
737 HDR_TCP.flags = 0x10;
738 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
739 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
745 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
746 HDR_TCP.window = g_htons(0x2000);
747 HDR_TCP.checksum = 0;
748 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
749 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
751 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
753 x16 = in_checksum(packet_buf + header_length, length - header_length);
755 x16 = (u & 0xffff) + (u>>16);
756 HDR_TCP.checksum = g_htons(x16);
757 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
758 HDR_TCP.checksum = g_htons(1);
759 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
761 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
762 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
765 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
766 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
770 /* Compute DATA chunk header */
771 if (hdr_data_chunk) {
772 hdr_data_chunk_bits = 0;
773 if (packet_start == 0) {
774 hdr_data_chunk_bits |= 0x02;
777 hdr_data_chunk_bits |= 0x01;
779 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
780 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
781 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
782 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
783 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
784 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
785 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
786 hdr_data_chunk_tsn++;
788 hdr_data_chunk_ssn++;
792 /* Write SCTP common header */
796 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
797 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
798 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
799 HDR_SCTP.checksum = g_htonl(0);
800 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
801 if (hdr_data_chunk) {
802 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
803 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
804 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
806 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
808 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
809 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
810 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
813 /* Write DATA chunk header */
814 if (hdr_data_chunk) {
815 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
818 /* Reset curr_offset, since we now write the trailers */
819 curr_offset = length;
821 /* Write DATA chunk padding */
822 if (hdr_data_chunk && (padding_length > 0)) {
823 memset(tempbuf, 0, padding_length);
824 write_bytes((const char *)&tempbuf, padding_length);
825 length += padding_length;
828 /* Write Ethernet trailer */
829 if (hdr_ethernet && (length < 60)) {
830 memset(tempbuf, 0, 60 - length);
831 write_bytes((const char *)&tempbuf, 60 - length);
835 success = pcapng_write_enhanced_packet_block(output_file,
841 packet_buf, direction,
842 &bytes_written, &err);
844 success = libpcap_write_packet(output_file,
845 ts_sec, ts_nsec/1000,
848 &bytes_written, &err);
851 fprintf(stderr, "File write error [%s] : %s\n",
852 output_filename, g_strerror(err));
855 if (ts_fmt == NULL) {
856 /* fake packet counter */
863 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
865 num_packets_written++;
868 packet_start += curr_offset - header_length;
869 curr_offset = header_length;
873 /*----------------------------------------------------------------------
874 * Write file header and trailer
877 write_file_header (void)
886 appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
887 comment = g_strdup_printf("Generated from input file %s.", input_filename);
888 success = pcapng_write_session_header_block(output_file,
893 -1, /* section_length */
899 success = pcapng_write_interface_description_block(output_file,
913 success = libpcap_write_file_header(output_file, pcap_link_type,
915 &bytes_written, &err);
918 fprintf(stderr, "File write error [%s] : %s\n",
919 output_filename, g_strerror(err));
926 /*----------------------------------------------------------------------
927 * Append a token to the packet preamble.
930 append_to_preamble (char *str)
934 if (packet_preamble_len != 0) {
935 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
936 return; /* no room to add more preamble */
937 /* Add a blank separator between the previous token and this token. */
938 packet_preamble[packet_preamble_len++] = ' ';
940 toklen = strlen(str);
942 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
943 return; /* no room to add the token to the preamble */
944 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
945 packet_preamble_len += (int) toklen;
948 char xs[PACKET_PREAMBLE_MAX_LEN];
949 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
950 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
951 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
956 /*----------------------------------------------------------------------
957 * Parse the preamble to get the timecode.
961 parse_preamble (void)
970 * Null-terminate the preamble.
972 packet_preamble[packet_preamble_len] = '\0';
974 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
977 switch (packet_preamble[0]) {
980 direction = 0x00000001;
981 packet_preamble[0] = ' ';
985 direction = 0x00000002;
986 packet_preamble[0] = ' ';
989 direction = 0x00000000;
993 while (packet_preamble[i] == ' ' ||
994 packet_preamble[i] == '\r' ||
995 packet_preamble[i] == '\t') {
998 packet_preamble_len -= i;
999 /* Also move the trailing '\0'. */
1000 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1005 * If no "-t" flag was specified, don't attempt to parse the packet
1006 * preamble to extract a time stamp.
1008 if (ts_fmt == NULL) {
1009 /* Clear Preamble */
1010 packet_preamble_len = 0;
1015 * Initialize to today localtime, just in case not all fields
1016 * of the date and time are specified.
1019 timecode = timecode_default;
1022 /* Ensure preamble has more than two chars before attempting to parse.
1023 * This should cover line breaks etc that get counted.
1025 if (strlen(packet_preamble) > 2) {
1026 /* Get Time leaving subseconds */
1027 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1028 if (subsecs != NULL) {
1029 /* Get the long time from the tm structure */
1030 /* (will return -1 if failure) */
1031 ts_sec = mktime( &timecode );
1033 ts_sec = -1; /* we failed to parse it */
1035 /* This will ensure incorrectly parsed dates get set to zero */
1037 /* Sanitize - remove all '\r' */
1039 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1040 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1041 packet_preamble, ts_fmt);
1043 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1044 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1045 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1047 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1050 /* Parse subseconds */
1051 ts_nsec = (guint32)strtol(subsecs, &p, 10);
1057 * Convert that number to a number
1058 * of microseconds; if it's N digits
1059 * long, it's in units of 10^(-N) seconds,
1060 * so, to convert it to units of
1061 * 10^-9 seconds, we multiply by
1064 subseclen = (int) (p - subsecs);
1065 if (subseclen > 9) {
1067 * *More* than 9 digits; 9-N is
1068 * negative, so we divide by
1071 for (i = subseclen - 9; i != 0; i--)
1073 } else if (subseclen < 9) {
1074 for (i = 9 - subseclen; i != 0; i--)
1082 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1083 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1084 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1088 /* Clear Preamble */
1089 packet_preamble_len = 0;
1092 /*----------------------------------------------------------------------
1093 * Start a new packet
1096 start_new_packet (gboolean cont)
1099 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1101 /* Write out the current packet, if required */
1102 if (write_current_packet(cont) != EXIT_SUCCESS)
1103 return EXIT_FAILURE;
1106 /* Ensure we parse the packet preamble as it may contain the time */
1109 return EXIT_SUCCESS;
1112 /*----------------------------------------------------------------------
1113 * Process a directive
1116 process_directive (char *str)
1118 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1121 /*----------------------------------------------------------------------
1122 * Parse a single token (called from the scanner)
1125 parse_token (token_t token, char *str)
1136 * This is implemented as a simple state machine of five states.
1137 * State transitions are caused by tokens being received from the
1138 * scanner. The code should be self-documenting.
1142 /* Sanitize - remove all '\r' */
1144 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1146 fprintf(stderr, "(%s, %s \"%s\") -> (",
1147 state_str[state], token_str[token], str ? str : "");
1152 /* ----- Waiting for new packet -------------------------------------------*/
1154 if (!str && token != T_EOL) goto fail_null_str;
1157 append_to_preamble(str);
1160 process_directive(str);
1163 if (parse_num(str, TRUE, &num) != EXIT_SUCCESS)
1164 return EXIT_FAILURE;
1166 /* New packet starts here */
1167 if (start_new_packet(FALSE) != EXIT_SUCCESS)
1168 return EXIT_FAILURE;
1169 state = READ_OFFSET;
1170 pkt_lnstart = packet_buf + num;
1174 /* Some describing text may be parsed as offset, but the invalid
1175 offset will be checked in the state of START_OF_LINE, so
1176 we add this transition to gain flexibility */
1177 state = START_OF_LINE;
1184 /* ----- Processing packet, start of new line -----------------------------*/
1186 if (!str && token != T_EOL) goto fail_null_str;
1189 append_to_preamble(str);
1192 process_directive(str);
1195 if (parse_num(str, TRUE, &num) != EXIT_SUCCESS)
1196 return EXIT_FAILURE;
1198 /* New packet starts here */
1199 if (start_new_packet(FALSE) != EXIT_SUCCESS)
1200 return EXIT_FAILURE;
1202 state = READ_OFFSET;
1203 } else if ((num - packet_start) != curr_offset - header_length) {
1205 * The offset we read isn't the one we expected.
1206 * This may only mean that we mistakenly interpreted
1207 * some text as byte values (e.g., if the text dump
1208 * of packet data included a number with spaces around
1209 * it). If the offset is less than what we expected,
1210 * assume that's the problem, and throw away the putative
1211 * extra byte values.
1213 if (num < curr_offset) {
1214 unwrite_bytes(curr_offset - num);
1215 state = READ_OFFSET;
1217 /* Bad offset; switch to INIT state */
1219 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1221 if (write_current_packet(FALSE) != EXIT_SUCCESS)
1222 return EXIT_FAILURE;
1226 state = READ_OFFSET;
1228 pkt_lnstart = packet_buf + num;
1231 state = START_OF_LINE;
1238 /* ----- Processing packet, read offset -----------------------------------*/
1242 /* Record the byte */
1244 if (!str) goto fail_null_str;
1245 if (write_byte(str) != EXIT_SUCCESS)
1246 return EXIT_FAILURE;
1254 state = START_OF_LINE;
1261 /* ----- Processing packet, read byte -------------------------------------*/
1265 /* Record the byte */
1266 if (write_byte(str) != EXIT_SUCCESS)
1267 return EXIT_FAILURE;
1275 if (token == T_EOL) {
1277 state = START_OF_LINE;
1279 if (identify_ascii) {
1280 /* Here a line of pkt bytes reading is finished
1281 compare the ascii and hex to avoid such situation:
1282 "61 62 20 ab ", when ab is ascii dump then it should
1283 not be treat as byte */
1285 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1286 s2 = "ab ", s1 = "616220"
1287 we should find out the largest tail of s1 matches the head
1288 of s2, it means the matched part in tail is the ASCII dump
1289 of the head byte. These matched should be rollback */
1290 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1291 s2 = (char*)g_malloc((line_size+1)/4+1);
1292 /* gather the possible pattern */
1293 for (i = 0; i < (line_size+1)/4; i++) {
1294 tmp_str[0] = pkt_lnstart[i*3];
1295 tmp_str[1] = pkt_lnstart[i*3+1];
1297 /* it is a valid convertable string */
1298 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1301 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1303 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1304 if (!(pkt_lnstart[i*3+2] == ' ')) {
1310 /* If packet line start contains possible byte pattern, the line end
1311 should contain the matched pattern if the user open the -a flag.
1312 The packet will be possible invalid if the byte pattern cannot find
1313 a matched one in the line of packet buffer.*/
1315 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1316 unwrite_bytes(rollback);
1318 /* Not matched. This line contains invalid packet bytes, so
1319 discard the whole line */
1321 unwrite_bytes(line_size);
1332 /* ----- Processing packet, read text -------------------------------------*/
1336 state = START_OF_LINE;
1344 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1345 return EXIT_FAILURE;
1349 fprintf(stderr, ", %s)\n", state_str[state]);
1351 return EXIT_SUCCESS;
1354 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1355 return EXIT_FAILURE;
1358 /*----------------------------------------------------------------------
1359 * Print usage string and exit
1362 print_usage (FILE *output)
1366 "Usage: text2pcap [options] <infile> <outfile>\n"
1368 "where <infile> specifies input filename (use - for standard input)\n"
1369 " <outfile> specifies output filename (use - for standard output)\n"
1372 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1373 " default is hex.\n"
1374 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1375 " the specified argument is a format string of the sort\n"
1376 " supported by strptime.\n"
1377 " Example: The time \"10:15:14.5476\" has the format code\n"
1378 " \"%%H:%%M:%%S.\"\n"
1379 " NOTE: The subsecond component delimiter, '.', must be\n"
1380 " given, but no pattern is required; the remaining\n"
1381 " number is assumed to be fractions of a second.\n"
1382 " NOTE: Date/time fields from the current date/time are\n"
1383 " used as the default for unspecified fields.\n"
1384 " -D the text before the packet starts with an I or an O,\n"
1385 " indicating that the packet is inbound or outbound.\n"
1386 " This is only stored if the output format is pcapng.\n"
1387 " -a enable ASCII text dump identification.\n"
1388 " The start of the ASCII text dump can be identified\n"
1389 " and excluded from the packet data, even if it looks\n"
1390 " like a HEX dump.\n"
1391 " NOTE: Do not enable it if the input file does not\n"
1392 " contain the ASCII text dump.\n"
1395 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1396 " http://www.tcpdump.org/linktypes.html for a list of\n"
1397 " numbers. Use this option if your dump is a complete\n"
1398 " hex dump of an encapsulated packet and you wish to\n"
1399 " specify the exact type of encapsulation.\n"
1400 " Example: -l 7 for ARCNet packets.\n"
1401 " -m <max-packet> max packet length in output; default is %d\n"
1403 "Prepend dummy header:\n"
1404 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1406 " Example: -e 0x806 to specify an ARP packet.\n"
1407 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1409 " Automatically prepends Ethernet header as well.\n"
1411 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1412 " dest and source address.\n"
1413 " Example: -4 10.0.0.1,10.0.0.2\n"
1414 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1415 " dest and source address.\n"
1416 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1417 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1418 " source and destination ports (in DECIMAL).\n"
1419 " Automatically prepends Ethernet & IP headers as well.\n"
1420 " Example: -u 1000,69 to make the packets look like\n"
1421 " TFTP/UDP packets.\n"
1422 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1423 " source and destination ports (in DECIMAL).\n"
1424 " Automatically prepends Ethernet & IP headers as well.\n"
1425 " Example: -T 50,60\n"
1426 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1427 " source/dest ports and verification tag (in DECIMAL).\n"
1428 " Automatically prepends Ethernet & IP headers as well.\n"
1429 " Example: -s 30,40,34\n"
1430 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1431 " source/dest ports and verification tag 0.\n"
1432 " Automatically prepends a dummy SCTP DATA\n"
1433 " chunk header with payload protocol identifier ppi.\n"
1434 " Example: -S 30,40,34\n"
1437 " -h display this help and exit.\n"
1438 " -d show detailed debug of parser states.\n"
1439 " -q generate no output at all (automatically disables -d).\n"
1440 " -n use pcapng instead of pcap as output format.\n"
1442 WTAP_MAX_PACKET_SIZE_STANDARD);
1445 /*----------------------------------------------------------------------
1449 parse_options (int argc, char *argv[])
1451 GString *comp_info_str;
1452 GString *runtime_info_str;
1455 static const struct option long_options[] = {
1456 {"help", no_argument, NULL, 'h'},
1457 {"version", no_argument, NULL, 'v'},
1463 arg_list_utf_16to8(argc, argv);
1464 create_app_running_mutex();
1467 /* Get the compile-time version information string */
1468 comp_info_str = get_compiled_version_info(NULL, NULL);
1470 /* get the run-time version information string */
1471 runtime_info_str = get_runtime_version_info(NULL);
1473 /* Add it to the information to be reported on a crash. */
1474 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1479 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1480 g_string_free(comp_info_str, TRUE);
1481 g_string_free(runtime_info_str, TRUE);
1483 /* Scan CLI parameters */
1484 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1487 printf("Text2pcap (Wireshark) %s\n"
1488 "Generate a capture file from an ASCII hexdump of packets.\n"
1489 "See https://www.wireshark.org for more information.\n",
1490 get_ws_vcs_version_info());
1491 print_usage(stdout);
1494 case 'd': if (!quiet) debug++; break;
1495 case 'D': has_direction = TRUE; break;
1496 case 'q': quiet = TRUE; debug = FALSE; break;
1497 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1498 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1499 case 'n': use_pcapng = TRUE; break;
1501 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1502 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1503 print_usage(stderr);
1504 return EXIT_FAILURE;
1506 switch (optarg[0]) {
1507 case 'o': offset_base = 8; break;
1508 case 'h': offset_base = 16; break;
1509 case 'd': offset_base = 10; break;
1513 hdr_ethernet = TRUE;
1514 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1515 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1516 print_usage(stderr);
1517 return EXIT_FAILURE;
1523 hdr_ip_proto = strtol(optarg, &p, 10);
1524 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1525 hdr_ip_proto > 255) {
1526 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1527 print_usage(stderr);
1528 return EXIT_FAILURE;
1530 hdr_ethernet = TRUE;
1531 hdr_ethernet_proto = 0x800;
1536 hdr_data_chunk = FALSE;
1539 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1540 if (p == optarg || (*p != ',' && *p != '\0')) {
1541 fprintf(stderr, "Bad src port for '-%c'\n", c);
1542 print_usage(stderr);
1543 return EXIT_FAILURE;
1546 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1547 print_usage(stderr);
1548 return EXIT_FAILURE;
1552 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1553 if (p == optarg || (*p != ',' && *p != '\0')) {
1554 fprintf(stderr, "Bad dest port for '-s'\n");
1555 print_usage(stderr);
1556 return EXIT_FAILURE;
1559 fprintf(stderr, "No tag specified for '-%c'\n", c);
1560 print_usage(stderr);
1561 return EXIT_FAILURE;
1565 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1566 if (p == optarg || *p != '\0') {
1567 fprintf(stderr, "Bad tag for '-%c'\n", c);
1568 print_usage(stderr);
1569 return EXIT_FAILURE;
1574 hdr_ethernet = TRUE;
1575 hdr_ethernet_proto = 0x800;
1579 hdr_data_chunk = TRUE;
1582 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1583 if (p == optarg || (*p != ',' && *p != '\0')) {
1584 fprintf(stderr, "Bad src port for '-%c'\n", c);
1585 print_usage(stderr);
1586 return EXIT_FAILURE;
1589 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1590 print_usage(stderr);
1591 return EXIT_FAILURE;
1595 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1596 if (p == optarg || (*p != ',' && *p != '\0')) {
1597 fprintf(stderr, "Bad dest port for '-s'\n");
1598 print_usage(stderr);
1599 return EXIT_FAILURE;
1602 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1603 print_usage(stderr);
1604 return EXIT_FAILURE;
1608 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1609 if (p == optarg || *p != '\0') {
1610 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1611 print_usage(stderr);
1612 return EXIT_FAILURE;
1617 hdr_ethernet = TRUE;
1618 hdr_ethernet_proto = 0x800;
1629 hdr_data_chunk = FALSE;
1630 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1631 if (p == optarg || (*p != ',' && *p != '\0')) {
1632 fprintf(stderr, "Bad src port for '-u'\n");
1633 print_usage(stderr);
1634 return EXIT_FAILURE;
1637 fprintf(stderr, "No dest port specified for '-u'\n");
1638 print_usage(stderr);
1639 return EXIT_FAILURE;
1643 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1644 if (p == optarg || *p != '\0') {
1645 fprintf(stderr, "Bad dest port for '-u'\n");
1646 print_usage(stderr);
1647 return EXIT_FAILURE;
1651 hdr_ethernet = TRUE;
1652 hdr_ethernet_proto = 0x800;
1659 hdr_data_chunk = FALSE;
1660 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1661 if (p == optarg || (*p != ',' && *p != '\0')) {
1662 fprintf(stderr, "Bad src port for '-T'\n");
1663 print_usage(stderr);
1664 return EXIT_FAILURE;
1667 fprintf(stderr, "No dest port specified for '-u'\n");
1668 print_usage(stderr);
1669 return EXIT_FAILURE;
1673 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1674 if (p == optarg || *p != '\0') {
1675 fprintf(stderr, "Bad dest port for '-T'\n");
1676 print_usage(stderr);
1677 return EXIT_FAILURE;
1681 hdr_ethernet = TRUE;
1682 hdr_ethernet_proto = 0x800;
1686 identify_ascii = TRUE;
1690 comp_info_str = get_compiled_version_info(NULL, NULL);
1691 runtime_info_str = get_runtime_version_info(NULL);
1692 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1693 g_string_free(comp_info_str, TRUE);
1694 g_string_free(runtime_info_str, TRUE);
1700 p = strchr(optarg, ',');
1703 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1704 print_usage(stderr);
1705 return EXIT_FAILURE;
1712 hdr_ethernet_proto = 0x86DD;
1717 hdr_ethernet_proto = 0x800;
1719 hdr_ethernet = TRUE;
1721 if (hdr_ipv6 == TRUE) {
1722 if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
1723 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1724 print_usage(stderr);
1725 return EXIT_FAILURE;
1728 if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
1729 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1730 print_usage(stderr);
1731 return EXIT_FAILURE;
1737 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1738 print_usage(stderr);
1739 return EXIT_FAILURE;
1742 if (hdr_ipv6 == TRUE) {
1743 if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
1744 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1745 print_usage(stderr);
1746 return EXIT_FAILURE;
1749 if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
1750 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1751 print_usage(stderr);
1752 return EXIT_FAILURE;
1760 print_usage(stderr);
1761 return EXIT_FAILURE;
1765 if (optind >= argc || argc-optind < 2) {
1766 fprintf(stderr, "Must specify input and output filename\n");
1767 print_usage(stderr);
1768 return EXIT_FAILURE;
1771 if (max_offset > WTAP_MAX_PACKET_SIZE_STANDARD) {
1772 fprintf(stderr, "Maximum packet length cannot be more than %d bytes\n",
1773 WTAP_MAX_PACKET_SIZE_STANDARD);
1774 return EXIT_FAILURE;
1777 if (strcmp(argv[optind], "-") != 0) {
1778 input_filename = argv[optind];
1779 input_file = ws_fopen(input_filename, "rb");
1781 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1782 input_filename, g_strerror(errno));
1783 return EXIT_FAILURE;
1786 input_filename = "Standard input";
1790 if (strcmp(argv[optind+1], "-") != 0) {
1791 /* Write to a file. Open the file, in binary mode. */
1792 output_filename = argv[optind+1];
1793 output_file = ws_fopen(output_filename, "wb");
1795 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1796 output_filename, g_strerror(errno));
1797 return EXIT_FAILURE;
1800 /* Write to the standard output. */
1802 /* Put the standard output in binary mode. */
1803 if (_setmode(1, O_BINARY) == -1) {
1804 /* "Should not happen" */
1805 fprintf(stderr, "Cannot put standard output in binary mode: %s\n",
1807 return EXIT_FAILURE;
1810 output_filename = "Standard output";
1811 output_file = stdout;
1814 /* Some validation */
1815 if (pcap_link_type != 1 && hdr_ethernet) {
1816 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1817 return EXIT_FAILURE;
1820 /* Set up our variables */
1823 input_filename = "Standard input";
1826 output_file = stdout;
1827 output_filename = "Standard output";
1830 ts_sec = time(0); /* initialize to current time */
1831 now_tm = localtime(&ts_sec);
1832 if (now_tm == NULL) {
1834 * This shouldn't happen - on UN*X, this should Just Work, and
1835 * on Windows, it won't work if ts_sec is before the Epoch,
1836 * but it's long after 1970, so....
1838 fprintf(stderr, "localtime(right now) failed\n");
1839 return EXIT_FAILURE;
1841 timecode_default = *now_tm;
1842 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1844 /* Display summary of our state */
1846 fprintf(stderr, "Input from: %s\n", input_filename);
1847 fprintf(stderr, "Output to: %s\n", output_filename);
1848 fprintf(stderr, "Output format: %s\n", use_pcapng ? "pcapng" : "pcap");
1850 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1851 hdr_ethernet_proto);
1852 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1854 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1855 hdr_src_port, hdr_dest_port);
1856 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1857 hdr_src_port, hdr_dest_port);
1858 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1859 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1860 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1861 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1864 return EXIT_SUCCESS;
1868 main(int argc, char *argv[])
1870 int ret = EXIT_SUCCESS;
1872 if (parse_options(argc, argv) != EXIT_SUCCESS) {
1877 assert(input_file != NULL);
1878 assert(output_file != NULL);
1880 if (write_file_header() != EXIT_SUCCESS) {
1887 header_length += (int)sizeof(HDR_ETHERNET);
1890 ip_offset = header_length;
1891 header_length += (int)sizeof(HDR_IP);
1892 } else if (hdr_ipv6) {
1893 ip_offset = header_length;
1894 header_length += (int)sizeof(HDR_IPv6);
1897 header_length += (int)sizeof(HDR_SCTP);
1899 if (hdr_data_chunk) {
1900 header_length += (int)sizeof(HDR_DATA_CHUNK);
1903 header_length += (int)sizeof(HDR_TCP);
1906 header_length += (int)sizeof(HDR_UDP);
1908 curr_offset = header_length;
1910 text2pcap_in = input_file;
1911 if (text2pcap_lex() == EXIT_SUCCESS) {
1912 if (write_current_packet(FALSE) != EXIT_SUCCESS)
1918 fprintf(stderr, "\n-------------------------\n");
1920 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1921 num_packets_read, (num_packets_read == 1) ? "" : "s",
1922 num_packets_written, (num_packets_written == 1) ? "" : "s",
1923 bytes_written, (bytes_written == 1) ? "" : "s");
1926 text2pcap_lex_destroy();
1931 fclose(output_file);
1937 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1942 * indent-tabs-mode: nil
1945 * vi: set shiftwidth=4 tabstop=8 expandtab:
1946 * :indentSize=4:tabSize=8:noTabs=true: