1 /**-*-C-*-**********************************************************************
5 * Utility to convert an ASCII hexdump into a libpcap-format capture file
7 * (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *******************************************************************************/
29 /*******************************************************************************
31 * This utility reads in an ASCII hexdump of this common format:
33 * 00000000 00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
34 * 00000010 03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3...
\7f..
35 * 00000020 03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
36 * 00000030 01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
38 * Each bytestring line consists of an offset, one or more bytes, and
39 * text at the end. An offset is defined as a hex string of more than
40 * two characters. A byte is defined as a hex string of exactly two
41 * characters. The text at the end is ignored, as is any text before
42 * the offset. Bytes read from a bytestring line are added to the
43 * current packet only if all the following conditions are satisfied:
45 * - No text appears between the offset and the bytes (any bytes appearing after
46 * such text would be ignored)
48 * - The offset must be arithmetically correct, i.e. if the offset is 00000020, then
49 * exactly 32 bytes must have been read into this packet before this. If the offset
50 * is wrong, the packet is immediately terminated
52 * A packet start is signaled by a zero offset.
54 * Lines starting with #TEXT2PCAP are directives. These allow the user
55 * to embed instructions into the capture file which allows text2pcap
56 * to take some actions (e.g. specifying the encapsulation
57 * etc.). Currently no directives are implemented.
59 * Lines beginning with # which are not directives are ignored as
60 * comments. Currently all non-hexdump text is ignored by text2pcap;
61 * in the future, text processing may be added, but lines prefixed
62 * with '#' will still be ignored.
64 * The output is a libpcap packet containing Ethernet frames by
65 * default. This program takes options which allow the user to add
66 * dummy Ethernet, IP and UDP or TCP headers to the packets in order
67 * to allow dumps of L3 or higher protocols to be decoded.
69 * Considerable flexibility is built into this code to read hexdumps
70 * of slightly different formats. For example, any text prefixing the
71 * hexdump line is dropped (including mail forwarding '>'). The offset
72 * can be any hex number of four digits or greater.
74 * This converter cannot read a single packet greater than 64KiB-1. Packet
75 * snaplength is automatically set to 64KiB-1.
81 * Just make sure we include the prototype for strptime as well
82 * (needed for glibc 2.2) but make sure we do this only if not
90 # define _XOPEN_SOURCE 600
95 * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms
96 * using glibc, to expand the set of things system header files define.
98 * Unfortunately, on other platforms, such as some versions of Solaris
99 * (including Solaris 10), it *reduces* that set as well, causing
100 * strptime() not to be declared, presumably because the version of the
101 * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and
102 * blah blah blah namespace pollution blah blah blah.
104 * So we define __EXTENSIONS__ so that "strptime()" is declared.
106 #ifndef __EXTENSIONS__
107 # define __EXTENSIONS__
113 #include <wsutil/file_util.h>
114 #include <wsutil/crash_info.h>
115 #include <ws_version_info.h>
116 #include <wsutil/inet_addr.h>
128 #ifndef HAVE_GETOPT_LONG
129 #include "wsutil/wsgetopt.h"
132 #ifndef HAVE_STRPTIME
133 # include "wsutil/strptime.h"
136 #include "writecap/pcapio.h"
137 #include "text2pcap.h"
140 #include <wsutil/unicode-utils.h>
143 /*--- Options --------------------------------------------------------------------*/
146 static gboolean use_pcapng = FALSE;
149 static int debug = 0;
151 static int quiet = FALSE;
153 /* Dummy Ethernet header */
154 static int hdr_ethernet = FALSE;
155 static guint32 hdr_ethernet_proto = 0;
157 /* Dummy IP header */
158 static int hdr_ip = FALSE;
159 static int hdr_ipv6 = FALSE;
160 static long hdr_ip_proto = 0;
162 /* Destination and source addresses for IP header */
163 static guint32 hdr_ip_dest_addr = 0;
164 static guint32 hdr_ip_src_addr = 0;
165 static struct e_in6_addr hdr_ipv6_dest_addr = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
166 static struct e_in6_addr hdr_ipv6_src_addr = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
167 static struct e_in6_addr NO_IPv6_ADDRESS = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
169 /* Dummy UDP header */
170 static int hdr_udp = FALSE;
171 static guint32 hdr_dest_port = 0;
172 static guint32 hdr_src_port = 0;
174 /* Dummy TCP header */
175 static int hdr_tcp = FALSE;
177 /* TCP sequence numbers when has_direction is true */
178 static guint32 tcp_in_seq_num = 0;
179 static guint32 tcp_out_seq_num = 0;
181 /* Dummy SCTP header */
182 static int hdr_sctp = FALSE;
183 static guint32 hdr_sctp_src = 0;
184 static guint32 hdr_sctp_dest = 0;
185 static guint32 hdr_sctp_tag = 0;
187 /* Dummy DATA chunk header */
188 static int hdr_data_chunk = FALSE;
189 static guint8 hdr_data_chunk_type = 0;
190 static guint8 hdr_data_chunk_bits = 0;
191 static guint32 hdr_data_chunk_tsn = 0;
192 static guint16 hdr_data_chunk_sid = 0;
193 static guint16 hdr_data_chunk_ssn = 0;
194 static guint32 hdr_data_chunk_ppid = 0;
196 /* ASCII text dump identification */
197 static int identify_ascii = FALSE;
199 static gboolean has_direction = FALSE;
200 static guint32 direction = 0;
202 /*--- Local date -----------------------------------------------------------------*/
204 /* This is where we store the packet currently being built */
205 #define MAX_PACKET 65535
206 static guint8 packet_buf[MAX_PACKET];
207 static guint32 header_length;
208 static guint32 ip_offset;
209 static guint32 curr_offset;
210 static guint32 max_offset = MAX_PACKET;
211 static guint32 packet_start = 0;
213 static void start_new_packet(gboolean);
215 /* This buffer contains strings present before the packet offset 0 */
216 #define PACKET_PREAMBLE_MAX_LEN 2048
217 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
218 static int packet_preamble_len = 0;
220 /* Number of packets read and written */
221 static guint32 num_packets_read = 0;
222 static guint32 num_packets_written = 0;
223 static guint64 bytes_written = 0;
225 /* Time code of packet, derived from packet_preamble */
226 static time_t ts_sec = 0;
227 static guint32 ts_nsec = 0;
228 static char *ts_fmt = NULL;
229 static struct tm timecode_default;
231 static guint8* pkt_lnstart;
234 static const char *input_filename;
235 static FILE *input_file = NULL;
237 static const char *output_filename;
238 static FILE *output_file = NULL;
240 /* Offset base to parse */
241 static guint32 offset_base = 16;
245 /* ----- State machine -----------------------------------------------------------*/
247 /* Current state of parser */
249 INIT, /* Waiting for start of new packet */
250 START_OF_LINE, /* Starting from beginning of line */
251 READ_OFFSET, /* Just read the offset */
252 READ_BYTE, /* Just read a byte */
253 READ_TEXT /* Just read text - ignore until EOL */
255 static parser_state_t state = INIT;
257 static const char *state_str[] = {"Init",
264 static const char *token_str[] = {"",
272 /* ----- Skeleton Packet Headers --------------------------------------------------*/
280 static hdr_ethernet_t HDR_ETHERNET = {
281 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
282 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
288 guint16 packet_length;
289 guint16 identification;
294 guint16 hdr_checksum;
299 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
300 #ifdef WORDS_BIGENDIAN
301 0x0a010101, 0x0a020202
303 0x0101010a, 0x0202020a
307 /* Fixed IP address values */
308 #ifdef WORDS_BIGENDIAN
309 #define IP_SRC 0x0a010101
310 #define IP_DST 0x0a020202
312 #define IP_SRC 0x0101010a
313 #define IP_DST 0x0202020a
316 static struct { /* pseudo header for checksum calculation */
325 /* headers taken from glibc */
330 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
331 guint16 ip6_un1_plen; /* payload length */
332 guint8 ip6_un1_nxt; /* next header */
333 guint8 ip6_un1_hlim; /* hop limit */
335 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
337 struct e_in6_addr ip6_src; /* source address */
338 struct e_in6_addr ip6_dst; /* destination address */
341 static hdr_ipv6_t HDR_IPv6;
343 static struct { /* pseudo header ipv6 for checksum calculation */
344 struct e_in6_addr src_addr6;
345 struct e_in6_addr dst_addr6;
358 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
372 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
381 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
393 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
395 static char tempbuf[64];
397 /*----------------------------------------------------------------------
398 * Stuff for writing a PCap file
400 #define PCAP_SNAPLEN 0xffff
402 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
403 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
405 /*----------------------------------------------------------------------
406 * Parse a single hex number
407 * Will abort the program if it can't parse the number
408 * Pass in TRUE if this is an offset, FALSE if not
411 parse_num (const char *str, int offset)
417 fprintf(stderr, "FATAL ERROR: str is NULL\n");
421 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
423 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
429 /*----------------------------------------------------------------------
430 * Write this byte into current packet
433 write_byte (const char *str)
437 num = parse_num(str, FALSE);
438 packet_buf[curr_offset] = (guint8) num;
440 if (curr_offset - header_length >= max_offset) /* packet full */
441 start_new_packet(TRUE);
444 /*----------------------------------------------------------------------
445 * Write a number of bytes into current packet
449 write_bytes (const char bytes[], guint32 nbytes)
453 if (curr_offset + nbytes < MAX_PACKET) {
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;
624 if (curr_offset > header_length) {
625 /* Write the packet */
627 /* Is direction indication on with an inbound packet? */
628 gboolean isInbound = has_direction && (direction == 2);
630 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
632 hdr_ethernet_proto = 0x86DD;
636 /* Compute packet length */
637 length = curr_offset;
639 padding_length = number_of_padding_bytes(length - header_length );
643 /* Reset curr_offset, since we now write the headers */
646 /* Write Ethernet header */
648 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
649 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
652 /* Write IP header */
655 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
656 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
659 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
660 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
663 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
664 HDR_IP.protocol = (guint8) hdr_ip_proto;
665 HDR_IP.hdr_checksum = 0;
666 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
667 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
668 } else if (hdr_ipv6) {
669 if (memcmp(isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, &NO_IPv6_ADDRESS, sizeof(struct e_in6_addr)))
670 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct e_in6_addr));
671 if (memcmp(isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, &NO_IPv6_ADDRESS, sizeof(struct e_in6_addr)))
672 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct e_in6_addr));
674 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
675 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
676 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
677 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
678 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
679 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
681 /* initialize pseudo ipv6 header for checksum calculation */
682 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
683 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
685 pseudoh6.protocol = (guint8) hdr_ip_proto;
686 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
687 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
691 /* initialize pseudo header for checksum calculation */
692 pseudoh.src_addr = HDR_IP.src_addr;
693 pseudoh.dest_addr = HDR_IP.dest_addr;
695 pseudoh.protocol = (guint8) hdr_ip_proto;
696 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
699 /* Write UDP header */
704 /* initialize the UDP header */
705 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
706 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
707 HDR_UDP.length = pseudoh.length;
708 HDR_UDP.checksum = 0;
709 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
710 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
712 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
714 x16 = in_checksum(packet_buf + header_length, length - header_length);
716 x16 = (u & 0xffff) + (u>>16);
717 HDR_UDP.checksum = g_htons(x16);
718 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
719 HDR_UDP.checksum = g_htons(1);
720 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
723 /* Write TCP header */
728 /* initialize pseudo header for checksum calculation */
729 pseudoh.src_addr = HDR_IP.src_addr;
730 pseudoh.dest_addr = HDR_IP.dest_addr;
732 pseudoh.protocol = (guint8) hdr_ip_proto;
733 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
734 /* initialize the TCP header */
735 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
736 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
737 /* set ack number if we have direction */
739 HDR_TCP.flags = 0x10;
740 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
741 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
747 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
748 HDR_TCP.window = g_htons(0x2000);
749 HDR_TCP.checksum = 0;
750 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
751 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
753 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
755 x16 = in_checksum(packet_buf + header_length, length - header_length);
757 x16 = (u & 0xffff) + (u>>16);
758 HDR_TCP.checksum = g_htons(x16);
759 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
760 HDR_TCP.checksum = g_htons(1);
761 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
763 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
764 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
767 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
768 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
772 /* Compute DATA chunk header */
773 if (hdr_data_chunk) {
774 hdr_data_chunk_bits = 0;
775 if (packet_start == 0) {
776 hdr_data_chunk_bits |= 0x02;
779 hdr_data_chunk_bits |= 0x01;
781 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
782 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
783 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
784 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
785 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
786 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
787 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
788 hdr_data_chunk_tsn++;
790 hdr_data_chunk_ssn++;
794 /* Write SCTP common header */
798 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
799 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
800 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
801 HDR_SCTP.checksum = g_htonl(0);
802 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
803 if (hdr_data_chunk) {
804 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
805 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
806 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
808 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
810 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
811 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
812 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
815 /* Write DATA chunk header */
816 if (hdr_data_chunk) {
817 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
820 /* Reset curr_offset, since we now write the trailers */
821 curr_offset = length;
823 /* Write DATA chunk padding */
824 if (hdr_data_chunk && (padding_length > 0)) {
825 memset(tempbuf, 0, padding_length);
826 write_bytes((const char *)&tempbuf, padding_length);
827 length += padding_length;
830 /* Write Ethernet trailer */
831 if (hdr_ethernet && (length < 60)) {
832 memset(tempbuf, 0, 60 - length);
833 write_bytes((const char *)&tempbuf, 60 - length);
837 success = pcapng_write_enhanced_packet_block(output_file,
843 packet_buf, direction,
844 &bytes_written, &err);
846 success = libpcap_write_packet(output_file,
847 ts_sec, ts_nsec/1000,
850 &bytes_written, &err);
853 fprintf(stderr, "File write error [%s] : %s\n",
854 output_filename, g_strerror(err));
857 if (ts_fmt == NULL) {
858 /* fake packet counter */
865 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
867 num_packets_written++;
870 packet_start += curr_offset - header_length;
871 curr_offset = header_length;
875 /*----------------------------------------------------------------------
876 * Write file header and trailer
879 write_file_header (void)
888 appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
889 comment = g_strdup_printf("Generated from input file %s.", input_filename);
890 success = pcapng_write_session_header_block(output_file,
895 -1, /* section_length */
901 success = pcapng_write_interface_description_block(output_file,
915 success = libpcap_write_file_header(output_file, pcap_link_type,
917 &bytes_written, &err);
920 fprintf(stderr, "File write error [%s] : %s\n",
921 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 write_current_packet(cont);
1105 /* Ensure we parse the packet preamble as it may contain the time */
1109 /*----------------------------------------------------------------------
1110 * Process a directive
1113 process_directive (char *str)
1115 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1118 /*----------------------------------------------------------------------
1119 * Parse a single token (called from the scanner)
1122 parse_token (token_t token, char *str)
1133 * This is implemented as a simple state machine of five states.
1134 * State transitions are caused by tokens being received from the
1135 * scanner. The code should be self-documenting.
1139 /* Sanitize - remove all '\r' */
1141 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1143 fprintf(stderr, "(%s, %s \"%s\") -> (",
1144 state_str[state], token_str[token], str ? str : "");
1149 /* ----- Waiting for new packet -------------------------------------------*/
1151 if (!str && token != T_EOL) goto fail_null_str;
1154 append_to_preamble(str);
1157 process_directive(str);
1160 num = parse_num(str, TRUE);
1162 /* New packet starts here */
1163 start_new_packet(FALSE);
1164 state = READ_OFFSET;
1165 pkt_lnstart = packet_buf + num;
1169 /* Some describing text may be parsed as offset, but the invalid
1170 offset will be checked in the state of START_OF_LINE, so
1171 we add this transition to gain flexibility */
1172 state = START_OF_LINE;
1179 /* ----- Processing packet, start of new line -----------------------------*/
1181 if (!str && token != T_EOL) goto fail_null_str;
1184 append_to_preamble(str);
1187 process_directive(str);
1190 num = parse_num(str, TRUE);
1192 /* New packet starts here */
1193 start_new_packet(FALSE);
1195 state = READ_OFFSET;
1196 } else if ((num - packet_start) != curr_offset - header_length) {
1198 * The offset we read isn't the one we expected.
1199 * This may only mean that we mistakenly interpreted
1200 * some text as byte values (e.g., if the text dump
1201 * of packet data included a number with spaces around
1202 * it). If the offset is less than what we expected,
1203 * assume that's the problem, and throw away the putative
1204 * extra byte values.
1206 if (num < curr_offset) {
1207 unwrite_bytes(curr_offset - num);
1208 state = READ_OFFSET;
1210 /* Bad offset; switch to INIT state */
1212 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1214 write_current_packet(FALSE);
1218 state = READ_OFFSET;
1220 pkt_lnstart = packet_buf + num;
1223 state = START_OF_LINE;
1230 /* ----- Processing packet, read offset -----------------------------------*/
1234 /* Record the byte */
1236 if (!str) goto fail_null_str;
1245 state = START_OF_LINE;
1252 /* ----- Processing packet, read byte -------------------------------------*/
1256 /* Record the byte */
1265 if (token == T_EOL) {
1267 state = START_OF_LINE;
1269 if (identify_ascii) {
1270 /* Here a line of pkt bytes reading is finished
1271 compare the ascii and hex to avoid such situation:
1272 "61 62 20 ab ", when ab is ascii dump then it should
1273 not be treat as byte */
1275 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1276 s2 = "ab ", s1 = "616220"
1277 we should find out the largest tail of s1 matches the head
1278 of s2, it means the matched part in tail is the ASCII dump
1279 of the head byte. These matched should be rollback */
1280 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1281 s2 = (char*)g_malloc((line_size+1)/4+1);
1282 /* gather the possible pattern */
1283 for (i = 0; i < (line_size+1)/4; i++) {
1284 tmp_str[0] = pkt_lnstart[i*3];
1285 tmp_str[1] = pkt_lnstart[i*3+1];
1287 /* it is a valid convertable string */
1288 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1291 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1293 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1294 if (!(pkt_lnstart[i*3+2] == ' ')) {
1300 /* If packet line start contains possible byte pattern, the line end
1301 should contain the matched pattern if the user open the -a flag.
1302 The packet will be possible invalid if the byte pattern cannot find
1303 a matched one in the line of packet buffer.*/
1305 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1306 unwrite_bytes(rollback);
1308 /* Not matched. This line contains invalid packet bytes, so
1309 discard the whole line */
1311 unwrite_bytes(line_size);
1322 /* ----- Processing packet, read text -------------------------------------*/
1326 state = START_OF_LINE;
1334 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1339 fprintf(stderr, ", %s)\n", state_str[state]);
1344 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1349 /*----------------------------------------------------------------------
1350 * Print usage string and exit
1353 print_usage (FILE *output)
1357 "Usage: text2pcap [options] <infile> <outfile>\n"
1359 "where <infile> specifies input filename (use - for standard input)\n"
1360 " <outfile> specifies output filename (use - for standard output)\n"
1363 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1364 " default is hex.\n"
1365 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1366 " the specified argument is a format string of the sort\n"
1367 " supported by strptime.\n"
1368 " Example: The time \"10:15:14.5476\" has the format code\n"
1369 " \"%%H:%%M:%%S.\"\n"
1370 " NOTE: The subsecond component delimiter, '.', must be\n"
1371 " given, but no pattern is required; the remaining\n"
1372 " number is assumed to be fractions of a second.\n"
1373 " NOTE: Date/time fields from the current date/time are\n"
1374 " used as the default for unspecified fields.\n"
1375 " -D the text before the packet starts with an I or an O,\n"
1376 " indicating that the packet is inbound or outbound.\n"
1377 " This is only stored if the output format is PCAP-NG.\n"
1378 " -a enable ASCII text dump identification.\n"
1379 " The start of the ASCII text dump can be identified\n"
1380 " and excluded from the packet data, even if it looks\n"
1381 " like a HEX dump.\n"
1382 " NOTE: Do not enable it if the input file does not\n"
1383 " contain the ASCII text dump.\n"
1386 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1387 " http://www.tcpdump.org/linktypes.html for a list of\n"
1388 " numbers. Use this option if your dump is a complete\n"
1389 " hex dump of an encapsulated packet and you wish to\n"
1390 " specify the exact type of encapsulation.\n"
1391 " Example: -l 7 for ARCNet packets.\n"
1392 " -m <max-packet> max packet length in output; default is %d\n"
1394 "Prepend dummy header:\n"
1395 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1397 " Example: -e 0x806 to specify an ARP packet.\n"
1398 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1400 " Automatically prepends Ethernet header as well.\n"
1402 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1403 " dest and source address.\n"
1404 " Example: -4 10.0.0.1,10.0.0.2\n"
1405 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1406 " dest and source address.\n"
1407 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1408 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1409 " source and destination ports (in DECIMAL).\n"
1410 " Automatically prepends Ethernet & IP headers as well.\n"
1411 " Example: -u 1000,69 to make the packets look like\n"
1412 " TFTP/UDP packets.\n"
1413 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1414 " source and destination ports (in DECIMAL).\n"
1415 " Automatically prepends Ethernet & IP headers as well.\n"
1416 " Example: -T 50,60\n"
1417 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1418 " source/dest ports and verification tag (in DECIMAL).\n"
1419 " Automatically prepends Ethernet & IP headers as well.\n"
1420 " Example: -s 30,40,34\n"
1421 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1422 " source/dest ports and verification tag 0.\n"
1423 " Automatically prepends a dummy SCTP DATA\n"
1424 " chunk header with payload protocol identifier ppi.\n"
1425 " Example: -S 30,40,34\n"
1428 " -h display this help and exit.\n"
1429 " -d show detailed debug of parser states.\n"
1430 " -q generate no output at all (automatically disables -d).\n"
1431 " -n use PCAP-NG instead of PCAP as output format.\n"
1436 /*----------------------------------------------------------------------
1440 parse_options (int argc, char *argv[])
1442 GString *comp_info_str;
1443 GString *runtime_info_str;
1446 static const struct option long_options[] = {
1447 {"help", no_argument, NULL, 'h'},
1448 {"version", no_argument, NULL, 'v'},
1453 arg_list_utf_16to8(argc, argv);
1454 create_app_running_mutex();
1457 /* Get the compile-time version information string */
1458 comp_info_str = get_compiled_version_info(NULL, NULL);
1460 /* get the run-time version information string */
1461 runtime_info_str = get_runtime_version_info(NULL);
1463 /* Add it to the information to be reported on a crash. */
1464 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1469 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1471 /* Scan CLI parameters */
1472 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1475 printf("Text2pcap (Wireshark) %s\n"
1476 "Generate a capture file from an ASCII hexdump of packets.\n"
1477 "See https://www.wireshark.org for more information.\n",
1478 get_ws_vcs_version_info());
1479 print_usage(stdout);
1482 case 'd': if (!quiet) debug++; break;
1483 case 'D': has_direction = TRUE; break;
1484 case 'q': quiet = TRUE; debug = FALSE; break;
1485 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1486 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1487 case 'n': use_pcapng = TRUE; break;
1489 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1490 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1491 print_usage(stderr);
1494 switch (optarg[0]) {
1495 case 'o': offset_base = 8; break;
1496 case 'h': offset_base = 16; break;
1497 case 'd': offset_base = 10; break;
1501 hdr_ethernet = TRUE;
1502 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1503 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1504 print_usage(stderr);
1511 hdr_ip_proto = strtol(optarg, &p, 10);
1512 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1513 hdr_ip_proto > 255) {
1514 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1515 print_usage(stderr);
1518 hdr_ethernet = TRUE;
1519 hdr_ethernet_proto = 0x800;
1524 hdr_data_chunk = FALSE;
1527 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1528 if (p == optarg || (*p != ',' && *p != '\0')) {
1529 fprintf(stderr, "Bad src port for '-%c'\n", c);
1530 print_usage(stderr);
1534 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1535 print_usage(stderr);
1540 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1541 if (p == optarg || (*p != ',' && *p != '\0')) {
1542 fprintf(stderr, "Bad dest port for '-s'\n");
1543 print_usage(stderr);
1547 fprintf(stderr, "No tag specified for '-%c'\n", c);
1548 print_usage(stderr);
1553 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1554 if (p == optarg || *p != '\0') {
1555 fprintf(stderr, "Bad tag for '-%c'\n", c);
1556 print_usage(stderr);
1562 hdr_ethernet = TRUE;
1563 hdr_ethernet_proto = 0x800;
1567 hdr_data_chunk = TRUE;
1570 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1571 if (p == optarg || (*p != ',' && *p != '\0')) {
1572 fprintf(stderr, "Bad src port for '-%c'\n", c);
1573 print_usage(stderr);
1577 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1578 print_usage(stderr);
1583 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1584 if (p == optarg || (*p != ',' && *p != '\0')) {
1585 fprintf(stderr, "Bad dest port for '-s'\n");
1586 print_usage(stderr);
1590 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1591 print_usage(stderr);
1596 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1597 if (p == optarg || *p != '\0') {
1598 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1599 print_usage(stderr);
1605 hdr_ethernet = TRUE;
1606 hdr_ethernet_proto = 0x800;
1617 hdr_data_chunk = FALSE;
1618 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1619 if (p == optarg || (*p != ',' && *p != '\0')) {
1620 fprintf(stderr, "Bad src port for '-u'\n");
1621 print_usage(stderr);
1625 fprintf(stderr, "No dest port specified for '-u'\n");
1626 print_usage(stderr);
1631 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1632 if (p == optarg || *p != '\0') {
1633 fprintf(stderr, "Bad dest port for '-u'\n");
1634 print_usage(stderr);
1639 hdr_ethernet = TRUE;
1640 hdr_ethernet_proto = 0x800;
1647 hdr_data_chunk = FALSE;
1648 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1649 if (p == optarg || (*p != ',' && *p != '\0')) {
1650 fprintf(stderr, "Bad src port for '-T'\n");
1651 print_usage(stderr);
1655 fprintf(stderr, "No dest port specified for '-u'\n");
1656 print_usage(stderr);
1661 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1662 if (p == optarg || *p != '\0') {
1663 fprintf(stderr, "Bad dest port for '-T'\n");
1664 print_usage(stderr);
1669 hdr_ethernet = TRUE;
1670 hdr_ethernet_proto = 0x800;
1674 identify_ascii = TRUE;
1678 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1679 g_string_free(comp_info_str, TRUE);
1680 g_string_free(runtime_info_str, TRUE);
1686 p = strchr(optarg, ',');
1689 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1690 print_usage(stderr);
1698 hdr_ethernet_proto = 0x86DD;
1703 hdr_ethernet_proto = 0x800;
1705 hdr_ethernet = TRUE;
1707 if (hdr_ipv6 == TRUE) {
1708 if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
1709 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1710 print_usage(stderr);
1714 if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
1715 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1716 print_usage(stderr);
1723 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1724 print_usage(stderr);
1728 if (hdr_ipv6 == TRUE) {
1729 if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
1730 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1731 print_usage(stderr);
1735 if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
1736 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1737 print_usage(stderr);
1746 print_usage(stderr);
1751 if (optind >= argc || argc-optind < 2) {
1752 fprintf(stderr, "Must specify input and output filename\n");
1753 print_usage(stderr);
1757 if (strcmp(argv[optind], "-")) {
1758 input_filename = g_strdup(argv[optind]);
1759 input_file = ws_fopen(input_filename, "rb");
1761 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1762 input_filename, g_strerror(errno));
1766 input_filename = "Standard input";
1770 if (strcmp(argv[optind+1], "-")) {
1771 output_filename = g_strdup(argv[optind+1]);
1772 output_file = ws_fopen(output_filename, "wb");
1774 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1775 output_filename, g_strerror(errno));
1779 output_filename = "Standard output";
1780 output_file = stdout;
1783 /* Some validation */
1784 if (pcap_link_type != 1 && hdr_ethernet) {
1785 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1789 /* Set up our variables */
1792 input_filename = "Standard input";
1795 output_file = stdout;
1796 output_filename = "Standard output";
1799 ts_sec = time(0); /* initialize to current time */
1800 timecode_default = *localtime(&ts_sec);
1801 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1803 /* Display summary of our state */
1805 fprintf(stderr, "Input from: %s\n", input_filename);
1806 fprintf(stderr, "Output to: %s\n", output_filename);
1807 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1809 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1810 hdr_ethernet_proto);
1811 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1813 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1814 hdr_src_port, hdr_dest_port);
1815 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1816 hdr_src_port, hdr_dest_port);
1817 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1818 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1819 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1820 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1825 main(int argc, char *argv[])
1827 parse_options(argc, argv);
1829 assert(input_file != NULL);
1830 assert(output_file != NULL);
1832 write_file_header();
1836 header_length += (int)sizeof(HDR_ETHERNET);
1839 ip_offset = header_length;
1840 header_length += (int)sizeof(HDR_IP);
1841 } else if (hdr_ipv6) {
1842 ip_offset = header_length;
1843 header_length += (int)sizeof(HDR_IPv6);
1846 header_length += (int)sizeof(HDR_SCTP);
1848 if (hdr_data_chunk) {
1849 header_length += (int)sizeof(HDR_DATA_CHUNK);
1852 header_length += (int)sizeof(HDR_TCP);
1855 header_length += (int)sizeof(HDR_UDP);
1857 curr_offset = header_length;
1862 write_current_packet(FALSE);
1864 fclose(output_file);
1866 fprintf(stderr, "\n-------------------------\n");
1868 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1869 num_packets_read, (num_packets_read == 1) ? "" : "s",
1870 num_packets_written, (num_packets_written == 1) ? "" : "s",
1871 bytes_written, (bytes_written == 1) ? "" : "s");
1877 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1882 * indent-tabs-mode: nil
1885 * vi: set shiftwidth=4 tabstop=8 expandtab:
1886 * :indentSize=4:tabSize=8:noTabs=true: