1 /**-*-C-*-**********************************************************************
5 * Utility to convert an ASCII hexdump into a libpcap-format capture file
7 * (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *******************************************************************************/
29 /*******************************************************************************
31 * This utility reads in an ASCII hexdump of this common format:
33 * 00000000 00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
34 * 00000010 03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3...
\7f..
35 * 00000020 03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
36 * 00000030 01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
38 * Each bytestring line consists of an offset, one or more bytes, and
39 * text at the end. An offset is defined as a hex string of more than
40 * two characters. A byte is defined as a hex string of exactly two
41 * characters. The text at the end is ignored, as is any text before
42 * the offset. Bytes read from a bytestring line are added to the
43 * current packet only if all the following conditions are satisfied:
45 * - No text appears between the offset and the bytes (any bytes appearing after
46 * such text would be ignored)
48 * - The offset must be arithmetically correct, i.e. if the offset is 00000020, then
49 * exactly 32 bytes must have been read into this packet before this. If the offset
50 * is wrong, the packet is immediately terminated
52 * A packet start is signaled by a zero offset.
54 * Lines starting with #TEXT2PCAP are directives. These allow the user
55 * to embed instructions into the capture file which allows text2pcap
56 * to take some actions (e.g. specifying the encapsulation
57 * etc.). Currently no directives are implemented.
59 * Lines beginning with # which are not directives are ignored as
60 * comments. Currently all non-hexdump text is ignored by text2pcap;
61 * in the future, text processing may be added, but lines prefixed
62 * with '#' will still be ignored.
64 * The output is a libpcap packet containing Ethernet frames by
65 * default. This program takes options which allow the user to add
66 * dummy Ethernet, IP and UDP or TCP headers to the packets in order
67 * to allow dumps of L3 or higher protocols to be decoded.
69 * Considerable flexibility is built into this code to read hexdumps
70 * of slightly different formats. For example, any text prefixing the
71 * hexdump line is dropped (including mail forwarding '>'). The offset
72 * can be any hex number of four digits or greater.
74 * This converter cannot read a single packet greater than 64KiB-1. Packet
75 * snaplength is automatically set to 64KiB-1.
81 * Just make sure we include the prototype for strptime as well
82 * (needed for glibc 2.2) but make sure we do this only if not
90 # define _XOPEN_SOURCE 600
95 * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms
96 * using glibc, to expand the set of things system header files define.
98 * Unfortunately, on other platforms, such as some versions of Solaris
99 * (including Solaris 10), it *reduces* that set as well, causing
100 * strptime() not to be declared, presumably because the version of the
101 * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and
102 * blah blah blah namespace pollution blah blah blah.
104 * So we define __EXTENSIONS__ so that "strptime()" is declared.
106 #ifndef __EXTENSIONS__
107 # define __EXTENSIONS__
113 #include <wsutil/file_util.h>
114 #include <wsutil/crash_info.h>
115 #include <wsutil/ws_diag_control.h>
116 #include <wsutil/ws_version_info.h>
117 #include <wsutil/inet_addr.h>
130 #include <zlib.h> /* to get the libz version number */
133 #ifndef HAVE_GETOPT_LONG
134 #include "wsutil/wsgetopt.h"
137 #ifndef HAVE_STRPTIME
138 # include "wsutil/strptime.h"
142 #include "text2pcap.h"
145 #include <wsutil/unicode-utils.h>
148 /*--- Options --------------------------------------------------------------------*/
151 static gboolean use_pcapng = FALSE;
154 static int debug = 0;
156 static int quiet = FALSE;
158 /* Dummy Ethernet header */
159 static int hdr_ethernet = FALSE;
160 static guint32 hdr_ethernet_proto = 0;
162 /* Dummy IP header */
163 static int hdr_ip = FALSE;
164 static int hdr_ipv6 = FALSE;
165 static long hdr_ip_proto = 0;
167 /* Destination and source addresses for IP header */
168 static guint32 hdr_ip_dest_addr = 0;
169 static guint32 hdr_ip_src_addr = 0;
170 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}};
171 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}};
172 static struct e_in6_addr NO_IPv6_ADDRESS = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
174 /* Dummy UDP header */
175 static int hdr_udp = FALSE;
176 static guint32 hdr_dest_port = 0;
177 static guint32 hdr_src_port = 0;
179 /* Dummy TCP header */
180 static int hdr_tcp = FALSE;
182 /* TCP sequence numbers when has_direction is true */
183 static guint32 tcp_in_seq_num = 0;
184 static guint32 tcp_out_seq_num = 0;
186 /* Dummy SCTP header */
187 static int hdr_sctp = FALSE;
188 static guint32 hdr_sctp_src = 0;
189 static guint32 hdr_sctp_dest = 0;
190 static guint32 hdr_sctp_tag = 0;
192 /* Dummy DATA chunk header */
193 static int hdr_data_chunk = FALSE;
194 static guint8 hdr_data_chunk_type = 0;
195 static guint8 hdr_data_chunk_bits = 0;
196 static guint32 hdr_data_chunk_tsn = 0;
197 static guint16 hdr_data_chunk_sid = 0;
198 static guint16 hdr_data_chunk_ssn = 0;
199 static guint32 hdr_data_chunk_ppid = 0;
201 /* ASCII text dump identification */
202 static int identify_ascii = FALSE;
204 static gboolean has_direction = FALSE;
205 static guint32 direction = 0;
207 /*--- Local date -----------------------------------------------------------------*/
209 /* This is where we store the packet currently being built */
210 #define MAX_PACKET 65535
211 static guint8 packet_buf[MAX_PACKET];
212 static guint32 header_length;
213 static guint32 ip_offset;
214 static guint32 curr_offset;
215 static guint32 max_offset = MAX_PACKET;
216 static guint32 packet_start = 0;
218 static void start_new_packet(gboolean);
220 /* This buffer contains strings present before the packet offset 0 */
221 #define PACKET_PREAMBLE_MAX_LEN 2048
222 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
223 static int packet_preamble_len = 0;
225 /* Number of packets read and written */
226 static guint32 num_packets_read = 0;
227 static guint32 num_packets_written = 0;
228 static guint64 bytes_written = 0;
230 /* Time code of packet, derived from packet_preamble */
231 static time_t ts_sec = 0;
232 static guint32 ts_nsec = 0;
233 static char *ts_fmt = NULL;
234 static struct tm timecode_default;
236 static guint8* pkt_lnstart;
239 static const char *input_filename;
240 static FILE *input_file = NULL;
242 static const char *output_filename;
243 static FILE *output_file = NULL;
245 /* Offset base to parse */
246 static guint32 offset_base = 16;
250 /* ----- State machine -----------------------------------------------------------*/
252 /* Current state of parser */
254 INIT, /* Waiting for start of new packet */
255 START_OF_LINE, /* Starting from beginning of line */
256 READ_OFFSET, /* Just read the offset */
257 READ_BYTE, /* Just read a byte */
258 READ_TEXT /* Just read text - ignore until EOL */
260 static parser_state_t state = INIT;
262 static const char *state_str[] = {"Init",
269 static const char *token_str[] = {"",
277 /* ----- Skeleton Packet Headers --------------------------------------------------*/
285 static hdr_ethernet_t HDR_ETHERNET = {
286 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
287 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
293 guint16 packet_length;
294 guint16 identification;
299 guint16 hdr_checksum;
304 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
305 #ifdef WORDS_BIGENDIAN
306 0x0a010101, 0x0a020202
308 0x0101010a, 0x0202020a
312 /* Fixed IP address values */
313 #ifdef WORDS_BIGENDIAN
314 #define IP_SRC 0x0a010101
315 #define IP_DST 0x0a020202
317 #define IP_SRC 0x0101010a
318 #define IP_DST 0x0202020a
321 static struct { /* pseudo header for checksum calculation */
330 /* headers taken from glibc */
335 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
336 guint16 ip6_un1_plen; /* payload length */
337 guint8 ip6_un1_nxt; /* next header */
338 guint8 ip6_un1_hlim; /* hop limit */
340 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
342 struct e_in6_addr ip6_src; /* source address */
343 struct e_in6_addr ip6_dst; /* destination address */
346 static hdr_ipv6_t HDR_IPv6;
348 static struct { /* pseudo header ipv6 for checksum calculation */
349 struct e_in6_addr src_addr6;
350 struct e_in6_addr dst_addr6;
363 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
377 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
386 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
398 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
400 static char tempbuf[64];
402 /*----------------------------------------------------------------------
403 * Stuff for writing a PCap file
405 #define PCAP_SNAPLEN 0xffff
407 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
408 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
410 /*----------------------------------------------------------------------
411 * Parse a single hex number
412 * Will abort the program if it can't parse the number
413 * Pass in TRUE if this is an offset, FALSE if not
416 parse_num (const char *str, int offset)
422 fprintf(stderr, "FATAL ERROR: str is NULL\n");
426 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
428 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
434 /*----------------------------------------------------------------------
435 * Write this byte into current packet
438 write_byte (const char *str)
442 num = parse_num(str, FALSE);
443 packet_buf[curr_offset] = (guint8) num;
445 if (curr_offset - header_length >= max_offset) /* packet full */
446 start_new_packet(TRUE);
449 /*----------------------------------------------------------------------
450 * Write a number of bytes into current packet
454 write_bytes (const char bytes[], guint32 nbytes)
458 if (curr_offset + nbytes < MAX_PACKET) {
459 for (i = 0; i < nbytes; i++) {
460 packet_buf[curr_offset] = bytes[i];
466 /*----------------------------------------------------------------------
467 * Remove bytes from the current packet
470 unwrite_bytes (guint32 nbytes)
472 curr_offset -= nbytes;
475 /*----------------------------------------------------------------------
476 * Compute one's complement checksum (from RFC1071)
479 in_checksum (void *buf, guint32 count)
482 guint16 *addr = (guint16 *)buf;
485 /* This is the inner loop */
486 sum += g_ntohs(* (guint16 *) addr);
491 /* Add left-over byte, if any */
493 sum += g_ntohs(* (guint8 *) addr);
495 /* Fold 32-bit sum to 16 bits */
497 sum = (sum & 0xffff) + (sum >> 16);
503 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
504 * That code is copyrighted by D. Otis and has been modified.
507 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
508 static guint32 crc_c[256] =
510 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
511 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
512 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
513 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
514 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
515 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
516 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
517 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
518 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
519 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
520 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
521 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
522 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
523 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
524 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
525 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
526 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
527 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
528 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
529 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
530 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
531 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
532 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
533 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
534 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
535 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
536 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
537 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
538 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
539 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
540 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
541 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
542 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
543 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
544 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
545 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
546 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
547 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
548 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
549 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
550 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
551 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
552 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
553 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
554 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
555 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
556 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
557 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
558 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
559 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
560 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
561 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
562 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
563 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
564 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
565 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
566 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
567 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
568 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
569 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
570 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
571 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
572 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
573 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
577 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
583 for (i = 0; i < len; i++)
590 finalize_crc32c (guint32 crc)
593 guint8 byte0,byte1,byte2,byte3;
596 byte0 = result & 0xff;
597 byte1 = (result>>8) & 0xff;
598 byte2 = (result>>16) & 0xff;
599 byte3 = (result>>24) & 0xff;
600 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
605 number_of_padding_bytes (guint32 length)
609 remainder = length % 4;
614 return 4 - remainder;
617 /*----------------------------------------------------------------------
618 * Write current packet out
621 write_current_packet (gboolean cont)
624 guint16 padding_length = 0;
629 if (curr_offset > header_length) {
630 /* Write the packet */
632 /* Is direction indication on with an inbound packet? */
633 gboolean isInbound = has_direction && (direction == 2);
635 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
637 hdr_ethernet_proto = 0x86DD;
641 /* Compute packet length */
642 length = curr_offset;
644 padding_length = number_of_padding_bytes(length - header_length );
648 /* Reset curr_offset, since we now write the headers */
651 /* Write Ethernet header */
653 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
654 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
657 /* Write IP header */
660 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
661 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
664 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
665 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
668 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
669 HDR_IP.protocol = (guint8) hdr_ip_proto;
670 HDR_IP.hdr_checksum = 0;
671 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
672 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
673 } else if (hdr_ipv6) {
674 if (memcmp(isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, &NO_IPv6_ADDRESS, sizeof(struct e_in6_addr)))
675 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct e_in6_addr));
676 if (memcmp(isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, &NO_IPv6_ADDRESS, sizeof(struct e_in6_addr)))
677 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct e_in6_addr));
679 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
680 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
681 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
682 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
683 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
684 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
686 /* initialize pseudo ipv6 header for checksum calculation */
687 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
688 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
690 pseudoh6.protocol = (guint8) hdr_ip_proto;
691 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
692 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
696 /* initialize pseudo header for checksum calculation */
697 pseudoh.src_addr = HDR_IP.src_addr;
698 pseudoh.dest_addr = HDR_IP.dest_addr;
700 pseudoh.protocol = (guint8) hdr_ip_proto;
701 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
704 /* Write UDP header */
709 /* initialize the UDP header */
710 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
711 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
712 HDR_UDP.length = pseudoh.length;
713 HDR_UDP.checksum = 0;
714 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
715 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
717 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
719 x16 = in_checksum(packet_buf + header_length, length - header_length);
721 x16 = (u & 0xffff) + (u>>16);
722 HDR_UDP.checksum = g_htons(x16);
723 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
724 HDR_UDP.checksum = g_htons(1);
725 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
728 /* Write TCP header */
733 /* initialize pseudo header for checksum calculation */
734 pseudoh.src_addr = HDR_IP.src_addr;
735 pseudoh.dest_addr = HDR_IP.dest_addr;
737 pseudoh.protocol = (guint8) hdr_ip_proto;
738 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
739 /* initialize the TCP header */
740 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
741 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
742 /* set ack number if we have direction */
744 HDR_TCP.flags = 0x10;
745 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
746 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
752 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
753 HDR_TCP.window = g_htons(0x2000);
754 HDR_TCP.checksum = 0;
755 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
756 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
758 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
760 x16 = in_checksum(packet_buf + header_length, length - header_length);
762 x16 = (u & 0xffff) + (u>>16);
763 HDR_TCP.checksum = g_htons(x16);
764 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
765 HDR_TCP.checksum = g_htons(1);
766 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
768 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
769 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
772 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
773 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
777 /* Compute DATA chunk header */
778 if (hdr_data_chunk) {
779 hdr_data_chunk_bits = 0;
780 if (packet_start == 0) {
781 hdr_data_chunk_bits |= 0x02;
784 hdr_data_chunk_bits |= 0x01;
786 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
787 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
788 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
789 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
790 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
791 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
792 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
793 hdr_data_chunk_tsn++;
795 hdr_data_chunk_ssn++;
799 /* Write SCTP common header */
803 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
804 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
805 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
806 HDR_SCTP.checksum = g_htonl(0);
807 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
808 if (hdr_data_chunk) {
809 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
810 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
811 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
813 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
815 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
816 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
817 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
820 /* Write DATA chunk header */
821 if (hdr_data_chunk) {
822 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
825 /* Reset curr_offset, since we now write the trailers */
826 curr_offset = length;
828 /* Write DATA chunk padding */
829 if (hdr_data_chunk && (padding_length > 0)) {
830 memset(tempbuf, 0, padding_length);
831 write_bytes((const char *)&tempbuf, padding_length);
832 length += padding_length;
835 /* Write Ethernet trailer */
836 if (hdr_ethernet && (length < 60)) {
837 memset(tempbuf, 0, 60 - length);
838 write_bytes((const char *)&tempbuf, 60 - length);
842 success = pcapng_write_enhanced_packet_block(output_file,
848 packet_buf, direction,
849 &bytes_written, &err);
851 success = libpcap_write_packet(output_file,
852 ts_sec, ts_nsec/1000,
855 &bytes_written, &err);
858 fprintf(stderr, "File write error [%s] : %s\n",
859 output_filename, g_strerror(err));
862 if (ts_fmt == NULL) {
863 /* fake packet counter */
870 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
872 num_packets_written++;
875 packet_start += curr_offset - header_length;
876 curr_offset = header_length;
880 /*----------------------------------------------------------------------
881 * Write file header and trailer
884 write_file_header (void)
893 appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
894 comment = g_strdup_printf("Generated from input file %s.", input_filename);
895 success = pcapng_write_session_header_block(output_file,
900 -1, /* section_length */
906 success = pcapng_write_interface_description_block(output_file,
920 success = libpcap_write_file_header(output_file, pcap_link_type,
922 &bytes_written, &err);
925 fprintf(stderr, "File write error [%s] : %s\n",
926 output_filename, g_strerror(err));
931 /*----------------------------------------------------------------------
932 * Append a token to the packet preamble.
935 append_to_preamble (char *str)
939 if (packet_preamble_len != 0) {
940 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
941 return; /* no room to add more preamble */
942 /* Add a blank separator between the previous token and this token. */
943 packet_preamble[packet_preamble_len++] = ' ';
945 toklen = strlen(str);
947 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
948 return; /* no room to add the token to the preamble */
949 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
950 packet_preamble_len += (int) toklen;
953 char xs[PACKET_PREAMBLE_MAX_LEN];
954 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
955 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
956 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
961 /*----------------------------------------------------------------------
962 * Parse the preamble to get the timecode.
966 parse_preamble (void)
975 * Null-terminate the preamble.
977 packet_preamble[packet_preamble_len] = '\0';
979 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
982 switch (packet_preamble[0]) {
985 direction = 0x00000001;
986 packet_preamble[0] = ' ';
990 direction = 0x00000002;
991 packet_preamble[0] = ' ';
994 direction = 0x00000000;
998 while (packet_preamble[i] == ' ' ||
999 packet_preamble[i] == '\r' ||
1000 packet_preamble[i] == '\t') {
1003 packet_preamble_len -= i;
1004 /* Also move the trailing '\0'. */
1005 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1010 * If no "-t" flag was specified, don't attempt to parse the packet
1011 * preamble to extract a time stamp.
1013 if (ts_fmt == NULL) {
1014 /* Clear Preamble */
1015 packet_preamble_len = 0;
1020 * Initialize to today localtime, just in case not all fields
1021 * of the date and time are specified.
1024 timecode = timecode_default;
1027 /* Ensure preamble has more than two chars before attempting to parse.
1028 * This should cover line breaks etc that get counted.
1030 if (strlen(packet_preamble) > 2) {
1031 /* Get Time leaving subseconds */
1032 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1033 if (subsecs != NULL) {
1034 /* Get the long time from the tm structure */
1035 /* (will return -1 if failure) */
1036 ts_sec = mktime( &timecode );
1038 ts_sec = -1; /* we failed to parse it */
1040 /* This will ensure incorrectly parsed dates get set to zero */
1042 /* Sanitize - remove all '\r' */
1044 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1045 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1046 packet_preamble, ts_fmt);
1048 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1049 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1050 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1052 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1055 /* Parse subseconds */
1056 ts_nsec = (guint32)strtol(subsecs, &p, 10);
1062 * Convert that number to a number
1063 * of microseconds; if it's N digits
1064 * long, it's in units of 10^(-N) seconds,
1065 * so, to convert it to units of
1066 * 10^-9 seconds, we multiply by
1069 subseclen = (int) (p - subsecs);
1070 if (subseclen > 9) {
1072 * *More* than 9 digits; 9-N is
1073 * negative, so we divide by
1076 for (i = subseclen - 9; i != 0; i--)
1078 } else if (subseclen < 9) {
1079 for (i = 9 - subseclen; i != 0; i--)
1087 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1088 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1089 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1093 /* Clear Preamble */
1094 packet_preamble_len = 0;
1097 /*----------------------------------------------------------------------
1098 * Start a new packet
1101 start_new_packet (gboolean cont)
1104 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1106 /* Write out the current packet, if required */
1107 write_current_packet(cont);
1110 /* Ensure we parse the packet preamble as it may contain the time */
1114 /*----------------------------------------------------------------------
1115 * Process a directive
1118 process_directive (char *str)
1120 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1123 /*----------------------------------------------------------------------
1124 * Parse a single token (called from the scanner)
1127 parse_token (token_t token, char *str)
1138 * This is implemented as a simple state machine of five states.
1139 * State transitions are caused by tokens being received from the
1140 * scanner. The code should be self-documenting.
1144 /* Sanitize - remove all '\r' */
1146 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1148 fprintf(stderr, "(%s, %s \"%s\") -> (",
1149 state_str[state], token_str[token], str ? str : "");
1154 /* ----- Waiting for new packet -------------------------------------------*/
1156 if (!str && token != T_EOL) goto fail_null_str;
1159 append_to_preamble(str);
1162 process_directive(str);
1165 num = parse_num(str, TRUE);
1167 /* New packet starts here */
1168 start_new_packet(FALSE);
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 num = parse_num(str, TRUE);
1197 /* New packet starts here */
1198 start_new_packet(FALSE);
1200 state = READ_OFFSET;
1201 } else if ((num - packet_start) != curr_offset - header_length) {
1203 * The offset we read isn't the one we expected.
1204 * This may only mean that we mistakenly interpreted
1205 * some text as byte values (e.g., if the text dump
1206 * of packet data included a number with spaces around
1207 * it). If the offset is less than what we expected,
1208 * assume that's the problem, and throw away the putative
1209 * extra byte values.
1211 if (num < curr_offset) {
1212 unwrite_bytes(curr_offset - num);
1213 state = READ_OFFSET;
1215 /* Bad offset; switch to INIT state */
1217 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1219 write_current_packet(FALSE);
1223 state = READ_OFFSET;
1225 pkt_lnstart = packet_buf + num;
1228 state = START_OF_LINE;
1235 /* ----- Processing packet, read offset -----------------------------------*/
1239 /* Record the byte */
1241 if (!str) goto fail_null_str;
1250 state = START_OF_LINE;
1257 /* ----- Processing packet, read byte -------------------------------------*/
1261 /* Record the byte */
1270 if (token == T_EOL) {
1272 state = START_OF_LINE;
1274 if (identify_ascii) {
1275 /* Here a line of pkt bytes reading is finished
1276 compare the ascii and hex to avoid such situation:
1277 "61 62 20 ab ", when ab is ascii dump then it should
1278 not be treat as byte */
1280 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1281 s2 = "ab ", s1 = "616220"
1282 we should find out the largest tail of s1 matches the head
1283 of s2, it means the matched part in tail is the ASCII dump
1284 of the head byte. These matched should be rollback */
1285 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1286 s2 = (char*)g_malloc((line_size+1)/4+1);
1287 /* gather the possible pattern */
1288 for (i = 0; i < (line_size+1)/4; i++) {
1289 tmp_str[0] = pkt_lnstart[i*3];
1290 tmp_str[1] = pkt_lnstart[i*3+1];
1292 /* it is a valid convertable string */
1293 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1296 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1298 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1299 if (!(pkt_lnstart[i*3+2] == ' ')) {
1305 /* If packet line start contains possible byte pattern, the line end
1306 should contain the matched pattern if the user open the -a flag.
1307 The packet will be possible invalid if the byte pattern cannot find
1308 a matched one in the line of packet buffer.*/
1310 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1311 unwrite_bytes(rollback);
1313 /* Not matched. This line contains invalid packet bytes, so
1314 discard the whole line */
1316 unwrite_bytes(line_size);
1327 /* ----- Processing packet, read text -------------------------------------*/
1331 state = START_OF_LINE;
1339 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1344 fprintf(stderr, ", %s)\n", state_str[state]);
1349 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1354 /*----------------------------------------------------------------------
1355 * Print usage string and exit
1358 print_usage (FILE *output)
1362 "Usage: text2pcap [options] <infile> <outfile>\n"
1364 "where <infile> specifies input filename (use - for standard input)\n"
1365 " <outfile> specifies output filename (use - for standard output)\n"
1368 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1369 " default is hex.\n"
1370 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1371 " the specified argument is a format string of the sort\n"
1372 " supported by strptime.\n"
1373 " Example: The time \"10:15:14.5476\" has the format code\n"
1374 " \"%%H:%%M:%%S.\"\n"
1375 " NOTE: The subsecond component delimiter, '.', must be\n"
1376 " given, but no pattern is required; the remaining\n"
1377 " number is assumed to be fractions of a second.\n"
1378 " NOTE: Date/time fields from the current date/time are\n"
1379 " used as the default for unspecified fields.\n"
1380 " -D the text before the packet starts with an I or an O,\n"
1381 " indicating that the packet is inbound or outbound.\n"
1382 " This is only stored if the output format is PCAP-NG.\n"
1383 " -a enable ASCII text dump identification.\n"
1384 " The start of the ASCII text dump can be identified\n"
1385 " and excluded from the packet data, even if it looks\n"
1386 " like a HEX dump.\n"
1387 " NOTE: Do not enable it if the input file does not\n"
1388 " contain the ASCII text dump.\n"
1391 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1392 " http://www.tcpdump.org/linktypes.html for a list of\n"
1393 " numbers. Use this option if your dump is a complete\n"
1394 " hex dump of an encapsulated packet and you wish to\n"
1395 " specify the exact type of encapsulation.\n"
1396 " Example: -l 7 for ARCNet packets.\n"
1397 " -m <max-packet> max packet length in output; default is %d\n"
1399 "Prepend dummy header:\n"
1400 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1402 " Example: -e 0x806 to specify an ARP packet.\n"
1403 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1405 " Automatically prepends Ethernet header as well.\n"
1407 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1408 " dest and source address.\n"
1409 " Example: -4 10.0.0.1,10.0.0.2\n"
1410 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1411 " dest and source address.\n"
1412 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1413 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1414 " source and destination ports (in DECIMAL).\n"
1415 " Automatically prepends Ethernet & IP headers as well.\n"
1416 " Example: -u 1000,69 to make the packets look like\n"
1417 " TFTP/UDP packets.\n"
1418 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1419 " source and destination ports (in DECIMAL).\n"
1420 " Automatically prepends Ethernet & IP headers as well.\n"
1421 " Example: -T 50,60\n"
1422 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1423 " source/dest ports and verification tag (in DECIMAL).\n"
1424 " Automatically prepends Ethernet & IP headers as well.\n"
1425 " Example: -s 30,40,34\n"
1426 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1427 " source/dest ports and verification tag 0.\n"
1428 " Automatically prepends a dummy SCTP DATA\n"
1429 " chunk header with payload protocol identifier ppi.\n"
1430 " Example: -S 30,40,34\n"
1433 " -h display this help and exit.\n"
1434 " -d show detailed debug of parser states.\n"
1435 " -q generate no output at all (automatically disables -d).\n"
1436 " -n use PCAP-NG instead of PCAP as output format.\n"
1442 get_text2pcap_compiled_info(GString *str)
1445 g_string_append(str, ", ");
1447 g_string_append(str, "with libz ");
1449 g_string_append(str, ZLIB_VERSION);
1450 #else /* ZLIB_VERSION */
1451 g_string_append(str, "(version unknown)");
1452 #endif /* ZLIB_VERSION */
1453 #else /* HAVE_LIBZ */
1454 g_string_append(str, "without libz");
1455 #endif /* HAVE_LIBZ */
1459 get_text2pcap_runtime_info(GString *str)
1462 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1463 g_string_append_printf(str, ", with libz %s", zlibVersion());
1467 /*----------------------------------------------------------------------
1471 parse_options (int argc, char *argv[])
1473 GString *comp_info_str;
1474 GString *runtime_info_str;
1477 static const struct option long_options[] = {
1478 {"help", no_argument, NULL, 'h'},
1479 {"version", no_argument, NULL, 'v'},
1484 arg_list_utf_16to8(argc, argv);
1485 create_app_running_mutex();
1488 /* Get the compile-time version information string */
1489 comp_info_str = get_compiled_version_info(NULL, get_text2pcap_compiled_info);
1491 /* get the run-time version information string */
1492 runtime_info_str = get_runtime_version_info(get_text2pcap_runtime_info);
1494 /* Add it to the information to be reported on a crash. */
1495 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1500 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1502 /* Scan CLI parameters */
1503 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1506 printf("Text2pcap (Wireshark) %s\n"
1507 "Generate a capture file from an ASCII hexdump of packets.\n"
1508 "See https://www.wireshark.org for more information.\n",
1509 get_ws_vcs_version_info());
1510 print_usage(stdout);
1513 case 'd': if (!quiet) debug++; break;
1514 case 'D': has_direction = TRUE; break;
1515 case 'q': quiet = TRUE; debug = FALSE; break;
1516 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1517 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1518 case 'n': use_pcapng = TRUE; break;
1520 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1521 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1522 print_usage(stderr);
1525 switch (optarg[0]) {
1526 case 'o': offset_base = 8; break;
1527 case 'h': offset_base = 16; break;
1528 case 'd': offset_base = 10; break;
1532 hdr_ethernet = TRUE;
1533 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1534 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1535 print_usage(stderr);
1542 hdr_ip_proto = strtol(optarg, &p, 10);
1543 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1544 hdr_ip_proto > 255) {
1545 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1546 print_usage(stderr);
1549 hdr_ethernet = TRUE;
1550 hdr_ethernet_proto = 0x800;
1555 hdr_data_chunk = FALSE;
1558 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1559 if (p == optarg || (*p != ',' && *p != '\0')) {
1560 fprintf(stderr, "Bad src port for '-%c'\n", c);
1561 print_usage(stderr);
1565 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1566 print_usage(stderr);
1571 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1572 if (p == optarg || (*p != ',' && *p != '\0')) {
1573 fprintf(stderr, "Bad dest port for '-s'\n");
1574 print_usage(stderr);
1578 fprintf(stderr, "No tag specified for '-%c'\n", c);
1579 print_usage(stderr);
1584 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1585 if (p == optarg || *p != '\0') {
1586 fprintf(stderr, "Bad tag for '-%c'\n", c);
1587 print_usage(stderr);
1593 hdr_ethernet = TRUE;
1594 hdr_ethernet_proto = 0x800;
1598 hdr_data_chunk = TRUE;
1601 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1602 if (p == optarg || (*p != ',' && *p != '\0')) {
1603 fprintf(stderr, "Bad src port for '-%c'\n", c);
1604 print_usage(stderr);
1608 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1609 print_usage(stderr);
1614 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1615 if (p == optarg || (*p != ',' && *p != '\0')) {
1616 fprintf(stderr, "Bad dest port for '-s'\n");
1617 print_usage(stderr);
1621 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1622 print_usage(stderr);
1627 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1628 if (p == optarg || *p != '\0') {
1629 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1630 print_usage(stderr);
1636 hdr_ethernet = TRUE;
1637 hdr_ethernet_proto = 0x800;
1648 hdr_data_chunk = FALSE;
1649 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1650 if (p == optarg || (*p != ',' && *p != '\0')) {
1651 fprintf(stderr, "Bad src port for '-u'\n");
1652 print_usage(stderr);
1656 fprintf(stderr, "No dest port specified for '-u'\n");
1657 print_usage(stderr);
1662 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1663 if (p == optarg || *p != '\0') {
1664 fprintf(stderr, "Bad dest port for '-u'\n");
1665 print_usage(stderr);
1670 hdr_ethernet = TRUE;
1671 hdr_ethernet_proto = 0x800;
1678 hdr_data_chunk = FALSE;
1679 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1680 if (p == optarg || (*p != ',' && *p != '\0')) {
1681 fprintf(stderr, "Bad src port for '-T'\n");
1682 print_usage(stderr);
1686 fprintf(stderr, "No dest port specified for '-u'\n");
1687 print_usage(stderr);
1692 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1693 if (p == optarg || *p != '\0') {
1694 fprintf(stderr, "Bad dest port for '-T'\n");
1695 print_usage(stderr);
1700 hdr_ethernet = TRUE;
1701 hdr_ethernet_proto = 0x800;
1705 identify_ascii = TRUE;
1709 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1710 g_string_free(comp_info_str, TRUE);
1711 g_string_free(runtime_info_str, TRUE);
1717 p = strchr(optarg, ',');
1720 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1721 print_usage(stderr);
1729 hdr_ethernet_proto = 0x86DD;
1734 hdr_ethernet_proto = 0x800;
1736 hdr_ethernet = TRUE;
1738 if (hdr_ipv6 == TRUE) {
1739 if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
1740 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1741 print_usage(stderr);
1745 if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
1746 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1747 print_usage(stderr);
1754 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1755 print_usage(stderr);
1759 if (hdr_ipv6 == TRUE) {
1760 if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
1761 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1762 print_usage(stderr);
1766 if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
1767 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1768 print_usage(stderr);
1777 print_usage(stderr);
1782 if (optind >= argc || argc-optind < 2) {
1783 fprintf(stderr, "Must specify input and output filename\n");
1784 print_usage(stderr);
1788 if (strcmp(argv[optind], "-")) {
1789 input_filename = g_strdup(argv[optind]);
1790 input_file = ws_fopen(input_filename, "rb");
1792 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1793 input_filename, g_strerror(errno));
1797 input_filename = "Standard input";
1801 if (strcmp(argv[optind+1], "-")) {
1802 output_filename = g_strdup(argv[optind+1]);
1803 output_file = ws_fopen(output_filename, "wb");
1805 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1806 output_filename, g_strerror(errno));
1810 output_filename = "Standard output";
1811 output_file = stdout;
1814 /* Some validation */
1815 if (pcap_link_type != 1 && hdr_ethernet) {
1816 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1820 /* Set up our variables */
1823 input_filename = "Standard input";
1826 output_file = stdout;
1827 output_filename = "Standard output";
1830 ts_sec = time(0); /* initialize to current time */
1831 timecode_default = *localtime(&ts_sec);
1832 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1834 /* Display summary of our state */
1836 fprintf(stderr, "Input from: %s\n", input_filename);
1837 fprintf(stderr, "Output to: %s\n", output_filename);
1838 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1840 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1841 hdr_ethernet_proto);
1842 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1844 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1845 hdr_src_port, hdr_dest_port);
1846 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1847 hdr_src_port, hdr_dest_port);
1848 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1849 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1850 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1851 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1856 main(int argc, char *argv[])
1858 parse_options(argc, argv);
1860 assert(input_file != NULL);
1861 assert(output_file != NULL);
1863 write_file_header();
1867 header_length += (int)sizeof(HDR_ETHERNET);
1870 ip_offset = header_length;
1871 header_length += (int)sizeof(HDR_IP);
1872 } else if (hdr_ipv6) {
1873 ip_offset = header_length;
1874 header_length += (int)sizeof(HDR_IPv6);
1877 header_length += (int)sizeof(HDR_SCTP);
1879 if (hdr_data_chunk) {
1880 header_length += (int)sizeof(HDR_DATA_CHUNK);
1883 header_length += (int)sizeof(HDR_TCP);
1886 header_length += (int)sizeof(HDR_UDP);
1888 curr_offset = header_length;
1893 write_current_packet(FALSE);
1895 fclose(output_file);
1897 fprintf(stderr, "\n-------------------------\n");
1899 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1900 num_packets_read, (num_packets_read == 1) ? "" : "s",
1901 num_packets_written, (num_packets_written == 1) ? "" : "s",
1902 bytes_written, (bytes_written == 1) ? "" : "s");
1908 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1913 * indent-tabs-mode: nil
1916 * vi: set shiftwidth=4 tabstop=8 expandtab:
1917 * :indentSize=4:tabSize=8:noTabs=true: