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-or-later
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 = -1;
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 #if G_BYTE_ORDER == G_BIG_ENDIAN
295 0x0a010101, 0x0a020202
297 0x0101010a, 0x0202020a
301 /* Fixed IP address values */
302 #if G_BYTE_ORDER == G_BIG_ENDIAN
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 /* https://tools.ietf.org/html/rfc2460#section-8.1 */
338 static struct { /* pseudo header ipv6 for checksum calculation */
339 struct e_in6_addr src_addr6;
340 struct e_in6_addr dst_addr6;
354 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
368 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
377 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
389 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
391 static char tempbuf[64];
393 /*----------------------------------------------------------------------
394 * Stuff for writing a PCap file
396 #define PCAP_SNAPLEN 0xffff
398 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
399 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
401 /*----------------------------------------------------------------------
402 * Parse a single hex number
403 * Will abort the program if it can't parse the number
404 * Pass in TRUE if this is an offset, FALSE if not
407 parse_num(const char *str, int offset, guint32* num)
412 fprintf(stderr, "FATAL ERROR: str is NULL\n");
416 *num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
418 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
424 /*----------------------------------------------------------------------
425 * Write this byte into current packet
428 write_byte(const char *str)
432 if (parse_num(str, FALSE, &num) != EXIT_SUCCESS)
435 packet_buf[curr_offset] = (guint8) num;
437 if (curr_offset - header_length >= max_offset) /* packet full */
438 if (start_new_packet(TRUE) != EXIT_SUCCESS)
444 /*----------------------------------------------------------------------
445 * Write a number of bytes into current packet
449 write_bytes (const char bytes[], guint32 nbytes)
453 if (curr_offset + nbytes < WTAP_MAX_PACKET_SIZE_STANDARD) {
454 for (i = 0; i < nbytes; i++) {
455 packet_buf[curr_offset] = bytes[i];
461 /*----------------------------------------------------------------------
462 * Remove bytes from the current packet
465 unwrite_bytes (guint32 nbytes)
467 curr_offset -= nbytes;
470 /*----------------------------------------------------------------------
471 * Compute one's complement checksum (from RFC1071)
474 in_checksum (void *buf, guint32 count)
477 guint16 *addr = (guint16 *)buf;
480 /* This is the inner loop */
481 sum += g_ntohs(* (guint16 *) addr);
486 /* Add left-over byte, if any */
488 sum += g_ntohs(* (guint8 *) addr);
490 /* Fold 32-bit sum to 16 bits */
492 sum = (sum & 0xffff) + (sum >> 16);
498 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
499 * That code is copyrighted by D. Otis and has been modified.
502 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
503 static guint32 crc_c[256] =
505 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
506 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
507 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
508 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
509 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
510 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
511 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
512 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
513 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
514 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
515 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
516 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
517 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
518 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
519 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
520 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
521 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
522 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
523 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
524 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
525 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
526 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
527 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
528 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
529 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
530 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
531 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
532 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
533 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
534 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
535 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
536 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
537 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
538 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
539 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
540 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
541 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
542 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
543 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
544 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
545 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
546 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
547 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
548 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
549 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
550 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
551 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
552 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
553 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
554 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
555 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
556 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
557 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
558 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
559 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
560 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
561 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
562 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
563 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
564 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
565 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
566 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
567 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
568 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
572 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
578 for (i = 0; i < len; i++)
585 finalize_crc32c (guint32 crc)
588 guint8 byte0,byte1,byte2,byte3;
591 byte0 = result & 0xff;
592 byte1 = (result>>8) & 0xff;
593 byte2 = (result>>16) & 0xff;
594 byte3 = (result>>24) & 0xff;
595 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
600 number_of_padding_bytes (guint32 length)
604 remainder = length % 4;
609 return 4 - remainder;
612 /*----------------------------------------------------------------------
613 * Write current packet out
616 write_current_packet (gboolean cont)
619 guint16 padding_length = 0;
623 if (curr_offset > header_length) {
624 /* Write the packet */
626 /* Is direction indication on with an inbound packet? */
627 gboolean isInbound = has_direction && (direction == 2);
629 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
631 hdr_ethernet_proto = 0x86DD;
635 /* Compute packet length */
636 length = curr_offset;
638 padding_length = number_of_padding_bytes(length - header_length );
642 /* Reset curr_offset, since we now write the headers */
645 /* Write Ethernet header */
647 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
648 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
651 /* Write IP header */
654 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
655 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
658 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
659 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
662 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
663 HDR_IP.protocol = (guint8) hdr_ip_proto;
664 HDR_IP.hdr_checksum = 0;
665 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
666 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
668 /* initialize pseudo header for checksum calculation */
669 pseudoh.src_addr = HDR_IP.src_addr;
670 pseudoh.dest_addr = HDR_IP.dest_addr;
672 pseudoh.protocol = (guint8) hdr_ip_proto;
674 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
675 } else if (hdr_udp) {
676 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
678 } else if (hdr_ipv6) {
679 if (memcmp(isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr)))
680 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(ws_in6_addr));
681 if (memcmp(isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr)))
682 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(ws_in6_addr));
684 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
685 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
686 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset - sizeof(HDR_IPv6) + padding_length);
687 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
688 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
689 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
691 /* initialize pseudo ipv6 header for checksum calculation */
692 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
693 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
694 memset(pseudoh6.zero, 0, sizeof(pseudoh6.zero));
695 pseudoh6.next_header = (guint8) hdr_ip_proto;
697 pseudoh6.length = g_htons(length - header_length + sizeof(HDR_TCP));
698 } else if (hdr_udp) {
699 pseudoh6.length = g_htons(length - header_length + sizeof(HDR_UDP));
703 /* Write UDP header */
708 /* initialize the UDP header */
709 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
710 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
711 HDR_UDP.length = hdr_ipv6 ? pseudoh6.length : pseudoh.length;
712 HDR_UDP.checksum = 0;
713 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
714 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
716 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
718 x16 = in_checksum(packet_buf + header_length, length - header_length);
720 x16 = (u & 0xffff) + (u>>16);
721 HDR_UDP.checksum = g_htons(x16);
722 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
723 HDR_UDP.checksum = g_htons(1);
724 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
727 /* Write TCP header */
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 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : 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'},
1462 /* Get the compile-time version information string */
1463 comp_info_str = get_compiled_version_info(NULL, NULL);
1465 /* get the run-time version information string */
1466 runtime_info_str = get_runtime_version_info(NULL);
1468 /* Add it to the information to be reported on a crash. */
1469 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1474 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1475 g_string_free(comp_info_str, TRUE);
1476 g_string_free(runtime_info_str, TRUE);
1478 /* Scan CLI parameters */
1479 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1482 printf("Text2pcap (Wireshark) %s\n"
1483 "Generate a capture file from an ASCII hexdump of packets.\n"
1484 "See https://www.wireshark.org for more information.\n",
1485 get_ws_vcs_version_info());
1486 print_usage(stdout);
1489 case 'd': if (!quiet) debug++; break;
1490 case 'D': has_direction = TRUE; break;
1491 case 'q': quiet = TRUE; debug = FALSE; break;
1492 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1493 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1494 case 'n': use_pcapng = TRUE; break;
1496 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1497 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1498 print_usage(stderr);
1499 return EXIT_FAILURE;
1501 switch (optarg[0]) {
1502 case 'o': offset_base = 8; break;
1503 case 'h': offset_base = 16; break;
1504 case 'd': offset_base = 10; break;
1508 hdr_ethernet = TRUE;
1509 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1510 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1511 print_usage(stderr);
1512 return EXIT_FAILURE;
1517 hdr_ip_proto = strtol(optarg, &p, 10);
1518 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1519 hdr_ip_proto > 255) {
1520 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1521 print_usage(stderr);
1522 return EXIT_FAILURE;
1524 hdr_ethernet = TRUE;
1525 hdr_ethernet_proto = 0x800;
1530 hdr_data_chunk = FALSE;
1533 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1534 if (p == optarg || (*p != ',' && *p != '\0')) {
1535 fprintf(stderr, "Bad src port for '-%c'\n", c);
1536 print_usage(stderr);
1537 return EXIT_FAILURE;
1540 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1541 print_usage(stderr);
1542 return EXIT_FAILURE;
1546 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1547 if (p == optarg || (*p != ',' && *p != '\0')) {
1548 fprintf(stderr, "Bad dest port for '-s'\n");
1549 print_usage(stderr);
1550 return EXIT_FAILURE;
1553 fprintf(stderr, "No tag specified for '-%c'\n", c);
1554 print_usage(stderr);
1555 return EXIT_FAILURE;
1559 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1560 if (p == optarg || *p != '\0') {
1561 fprintf(stderr, "Bad tag for '-%c'\n", c);
1562 print_usage(stderr);
1563 return EXIT_FAILURE;
1567 hdr_ethernet = TRUE;
1568 hdr_ethernet_proto = 0x800;
1572 hdr_data_chunk = TRUE;
1575 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1576 if (p == optarg || (*p != ',' && *p != '\0')) {
1577 fprintf(stderr, "Bad src port for '-%c'\n", c);
1578 print_usage(stderr);
1579 return EXIT_FAILURE;
1582 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1583 print_usage(stderr);
1584 return EXIT_FAILURE;
1588 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1589 if (p == optarg || (*p != ',' && *p != '\0')) {
1590 fprintf(stderr, "Bad dest port for '-s'\n");
1591 print_usage(stderr);
1592 return EXIT_FAILURE;
1595 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1596 print_usage(stderr);
1597 return EXIT_FAILURE;
1601 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1602 if (p == optarg || *p != '\0') {
1603 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1604 print_usage(stderr);
1605 return EXIT_FAILURE;
1609 hdr_ethernet = TRUE;
1610 hdr_ethernet_proto = 0x800;
1621 hdr_data_chunk = FALSE;
1622 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1623 if (p == optarg || (*p != ',' && *p != '\0')) {
1624 fprintf(stderr, "Bad src port for '-u'\n");
1625 print_usage(stderr);
1626 return EXIT_FAILURE;
1629 fprintf(stderr, "No dest port specified for '-u'\n");
1630 print_usage(stderr);
1631 return EXIT_FAILURE;
1635 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1636 if (p == optarg || *p != '\0') {
1637 fprintf(stderr, "Bad dest port for '-u'\n");
1638 print_usage(stderr);
1639 return EXIT_FAILURE;
1642 hdr_ethernet = TRUE;
1643 hdr_ethernet_proto = 0x800;
1650 hdr_data_chunk = FALSE;
1651 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1652 if (p == optarg || (*p != ',' && *p != '\0')) {
1653 fprintf(stderr, "Bad src port for '-T'\n");
1654 print_usage(stderr);
1655 return EXIT_FAILURE;
1658 fprintf(stderr, "No dest port specified for '-u'\n");
1659 print_usage(stderr);
1660 return EXIT_FAILURE;
1664 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1665 if (p == optarg || *p != '\0') {
1666 fprintf(stderr, "Bad dest port for '-T'\n");
1667 print_usage(stderr);
1668 return EXIT_FAILURE;
1671 hdr_ethernet = TRUE;
1672 hdr_ethernet_proto = 0x800;
1676 identify_ascii = TRUE;
1680 comp_info_str = get_compiled_version_info(NULL, NULL);
1681 runtime_info_str = get_runtime_version_info(NULL);
1682 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1683 g_string_free(comp_info_str, TRUE);
1684 g_string_free(runtime_info_str, TRUE);
1690 p = strchr(optarg, ',');
1693 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1694 print_usage(stderr);
1695 return EXIT_FAILURE;
1702 hdr_ethernet_proto = 0x86DD;
1707 hdr_ethernet_proto = 0x800;
1709 hdr_ethernet = TRUE;
1711 if (hdr_ipv6 == TRUE) {
1712 if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
1713 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1714 print_usage(stderr);
1715 return EXIT_FAILURE;
1718 if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
1719 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1720 print_usage(stderr);
1721 return EXIT_FAILURE;
1727 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1728 print_usage(stderr);
1729 return EXIT_FAILURE;
1732 if (hdr_ipv6 == TRUE) {
1733 if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
1734 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1735 print_usage(stderr);
1736 return EXIT_FAILURE;
1739 if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
1740 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1741 print_usage(stderr);
1742 return EXIT_FAILURE;
1750 print_usage(stderr);
1751 return EXIT_FAILURE;
1755 if (optind >= argc || argc-optind < 2) {
1756 fprintf(stderr, "Must specify input and output filename\n");
1757 print_usage(stderr);
1758 return EXIT_FAILURE;
1761 if (max_offset > WTAP_MAX_PACKET_SIZE_STANDARD) {
1762 fprintf(stderr, "Maximum packet length cannot be more than %d bytes\n",
1763 WTAP_MAX_PACKET_SIZE_STANDARD);
1764 return EXIT_FAILURE;
1767 if (strcmp(argv[optind], "-") != 0) {
1768 input_filename = argv[optind];
1769 input_file = ws_fopen(input_filename, "rb");
1771 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1772 input_filename, g_strerror(errno));
1773 return EXIT_FAILURE;
1776 input_filename = "Standard input";
1780 if (strcmp(argv[optind+1], "-") != 0) {
1781 /* Write to a file. Open the file, in binary mode. */
1782 output_filename = argv[optind+1];
1783 output_file = ws_fopen(output_filename, "wb");
1785 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1786 output_filename, g_strerror(errno));
1787 return EXIT_FAILURE;
1790 /* Write to the standard output. */
1792 /* Put the standard output in binary mode. */
1793 if (_setmode(1, O_BINARY) == -1) {
1794 /* "Should not happen" */
1795 fprintf(stderr, "Cannot put standard output in binary mode: %s\n",
1797 return EXIT_FAILURE;
1800 output_filename = "Standard output";
1801 output_file = stdout;
1804 /* Some validation */
1805 if (pcap_link_type != 1 && hdr_ethernet) {
1806 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1807 return EXIT_FAILURE;
1810 /* Set up our variables */
1813 input_filename = "Standard input";
1816 output_file = stdout;
1817 output_filename = "Standard output";
1820 ts_sec = time(0); /* initialize to current time */
1821 now_tm = localtime(&ts_sec);
1822 if (now_tm == NULL) {
1824 * This shouldn't happen - on UN*X, this should Just Work, and
1825 * on Windows, it won't work if ts_sec is before the Epoch,
1826 * but it's long after 1970, so....
1828 fprintf(stderr, "localtime(right now) failed\n");
1829 return EXIT_FAILURE;
1831 timecode_default = *now_tm;
1832 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1834 if (hdr_ip_proto != -1 && !(hdr_ip || hdr_ipv6)) {
1835 /* If -i <proto> option is specified without -4 or -6 then add the default IPv4 header */
1839 if ((hdr_tcp || hdr_udp || hdr_sctp) && !(hdr_ip || hdr_ipv6)) {
1841 * If TCP (-T), UDP (-u) or SCTP (-s/-S) header options are specified
1842 * but none of IPv4 (-4) or IPv6 (-6) options then add an IPv4 header
1847 /* Display summary of our state */
1849 fprintf(stderr, "Input from: %s\n", input_filename);
1850 fprintf(stderr, "Output to: %s\n", output_filename);
1851 fprintf(stderr, "Output format: %s\n", use_pcapng ? "pcapng" : "pcap");
1853 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1854 hdr_ethernet_proto);
1855 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1857 if (hdr_ipv6) fprintf(stderr, "Generate dummy IPv6 header: Protocol: %ld\n",
1859 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1860 hdr_src_port, hdr_dest_port);
1861 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1862 hdr_src_port, hdr_dest_port);
1863 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1864 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1865 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1866 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1869 return EXIT_SUCCESS;
1873 real_main(int argc, char *argv[])
1875 int ret = EXIT_SUCCESS;
1878 create_app_running_mutex();
1881 if (parse_options(argc, argv) != EXIT_SUCCESS) {
1886 assert(input_file != NULL);
1887 assert(output_file != NULL);
1889 if (write_file_header() != EXIT_SUCCESS) {
1896 header_length += (int)sizeof(HDR_ETHERNET);
1899 ip_offset = header_length;
1900 header_length += (int)sizeof(HDR_IP);
1901 } else if (hdr_ipv6) {
1902 ip_offset = header_length;
1903 header_length += (int)sizeof(HDR_IPv6);
1906 header_length += (int)sizeof(HDR_SCTP);
1908 if (hdr_data_chunk) {
1909 header_length += (int)sizeof(HDR_DATA_CHUNK);
1912 header_length += (int)sizeof(HDR_TCP);
1915 header_length += (int)sizeof(HDR_UDP);
1917 curr_offset = header_length;
1919 text2pcap_in = input_file;
1920 if (text2pcap_scan() == EXIT_SUCCESS) {
1921 if (write_current_packet(FALSE) != EXIT_SUCCESS)
1927 fprintf(stderr, "\n-------------------------\n");
1929 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1930 num_packets_read, (num_packets_read == 1) ? "" : "s",
1931 num_packets_written, (num_packets_written == 1) ? "" : "s",
1932 bytes_written, (bytes_written == 1) ? "" : "s");
1939 fclose(output_file);
1946 wmain(int argc, wchar_t *wc_argv[])
1950 argv = arg_list_utf_16to8(argc, wc_argv);
1951 return real_main(argc, argv);
1955 main(int argc, char *argv[])
1957 return real_main(argc, argv);
1962 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1967 * indent-tabs-mode: nil
1970 * vi: set shiftwidth=4 tabstop=8 expandtab:
1971 * :indentSize=4:tabSize=8:noTabs=true: