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/os_version_info.h>
116 #include <wsutil/ws_version_info.h>
133 #include <zlib.h> /* to get the libz version number */
136 #ifndef HAVE_GETOPT_LONG
137 #include "wsutil/wsgetopt.h"
140 #ifndef HAVE_STRPTIME
141 # include "wsutil/strptime.h"
145 #include "text2pcap.h"
146 #include "version_info.h"
149 #include <wsutil/unicode-utils.h>
152 #ifdef HAVE_ARPA_INET_H
153 #include <arpa/inet.h>
156 #ifdef HAVE_WINSOCK2_H
157 #include <winsock2.h> /* needed to define AF_ values on Windows */
160 #ifndef HAVE_INET_ATON
161 # include "wsutil/inet_aton.h"
164 #ifdef HAVE_SYS_SOCKET_H
165 #include <sys/socket.h>
168 #ifdef NEED_INET_V6DEFS_H
169 # include "wsutil/inet_v6defs.h"
172 /*--- Options --------------------------------------------------------------------*/
175 static gboolean use_pcapng = FALSE;
178 static int debug = 0;
180 static int quiet = FALSE;
182 /* Dummy Ethernet header */
183 static int hdr_ethernet = FALSE;
184 static guint32 hdr_ethernet_proto = 0;
186 /* Dummy IP header */
187 static int hdr_ip = FALSE;
188 static int hdr_ipv6 = FALSE;
189 static long hdr_ip_proto = 0;
191 /* Destination and source addresses for IP header */
192 static guint32 hdr_ip_dest_addr = 0;
193 static guint32 hdr_ip_src_addr = 0;
194 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
195 static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
196 static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
198 /* Dummy UDP header */
199 static int hdr_udp = FALSE;
200 static guint32 hdr_dest_port = 0;
201 static guint32 hdr_src_port = 0;
203 /* Dummy TCP header */
204 static int hdr_tcp = FALSE;
206 /* TCP sequence numbers when has_direction is true */
207 static guint32 tcp_in_seq_num = 0;
208 static guint32 tcp_out_seq_num = 0;
210 /* Dummy SCTP header */
211 static int hdr_sctp = FALSE;
212 static guint32 hdr_sctp_src = 0;
213 static guint32 hdr_sctp_dest = 0;
214 static guint32 hdr_sctp_tag = 0;
216 /* Dummy DATA chunk header */
217 static int hdr_data_chunk = FALSE;
218 static guint8 hdr_data_chunk_type = 0;
219 static guint8 hdr_data_chunk_bits = 0;
220 static guint32 hdr_data_chunk_tsn = 0;
221 static guint16 hdr_data_chunk_sid = 0;
222 static guint16 hdr_data_chunk_ssn = 0;
223 static guint32 hdr_data_chunk_ppid = 0;
225 /* ASCII text dump identification */
226 static int identify_ascii = FALSE;
228 static gboolean has_direction = FALSE;
229 static guint32 direction = 0;
231 /*--- Local date -----------------------------------------------------------------*/
233 /* This is where we store the packet currently being built */
234 #define MAX_PACKET 65535
235 static guint8 packet_buf[MAX_PACKET];
236 static guint32 header_length;
237 static guint32 ip_offset;
238 static guint32 curr_offset;
239 static guint32 max_offset = MAX_PACKET;
240 static guint32 packet_start = 0;
242 static void start_new_packet(gboolean);
244 /* This buffer contains strings present before the packet offset 0 */
245 #define PACKET_PREAMBLE_MAX_LEN 2048
246 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
247 static int packet_preamble_len = 0;
249 /* Number of packets read and written */
250 static guint32 num_packets_read = 0;
251 static guint32 num_packets_written = 0;
252 static guint64 bytes_written = 0;
254 /* Time code of packet, derived from packet_preamble */
255 static time_t ts_sec = 0;
256 static guint32 ts_nsec = 0;
257 static char *ts_fmt = NULL;
258 static struct tm timecode_default;
260 static guint8* pkt_lnstart;
263 static const char *input_filename;
264 static FILE *input_file = NULL;
266 static const char *output_filename;
267 static FILE *output_file = NULL;
269 /* Offset base to parse */
270 static guint32 offset_base = 16;
274 /* ----- State machine -----------------------------------------------------------*/
276 /* Current state of parser */
278 INIT, /* Waiting for start of new packet */
279 START_OF_LINE, /* Starting from beginning of line */
280 READ_OFFSET, /* Just read the offset */
281 READ_BYTE, /* Just read a byte */
282 READ_TEXT /* Just read text - ignore until EOL */
284 static parser_state_t state = INIT;
286 static const char *state_str[] = {"Init",
293 static const char *token_str[] = {"",
301 /* ----- Skeleton Packet Headers --------------------------------------------------*/
309 static hdr_ethernet_t HDR_ETHERNET = {
310 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
311 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
317 guint16 packet_length;
318 guint16 identification;
323 guint16 hdr_checksum;
328 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
329 #ifdef WORDS_BIGENDIAN
330 0x0a010101, 0x0a020202
332 0x0101010a, 0x0202020a
336 /* Fixed IP address values */
337 #ifdef WORDS_BIGENDIAN
338 #define IP_SRC 0x0a010101
339 #define IP_DST 0x0a020202
341 #define IP_SRC 0x0101010a
342 #define IP_DST 0x0202020a
345 static struct { /* pseudo header for checksum calculation */
354 /* headers taken from glibc */
361 guint8 __u6_addr8[16];
362 guint16 __u6_addr16[8];
363 guint32 __u6_addr32[4];
370 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
371 guint16 ip6_un1_plen; /* payload length */
372 guint8 ip6_un1_nxt; /* next header */
373 guint8 ip6_un1_hlim; /* hop limit */
375 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
377 struct hdr_in6_addr ip6_src; /* source address */
378 struct hdr_in6_addr ip6_dst; /* destination address */
381 static hdr_ipv6_t HDR_IPv6;
383 static struct { /* pseudo header ipv6 for checksum calculation */
384 struct hdr_in6_addr src_addr6;
385 struct hdr_in6_addr dst_addr6;
398 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
412 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
421 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
433 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
435 static char tempbuf[64];
437 /*----------------------------------------------------------------------
438 * Stuff for writing a PCap file
440 #define PCAP_SNAPLEN 0xffff
442 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
443 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
445 /*----------------------------------------------------------------------
446 * Parse a single hex number
447 * Will abort the program if it can't parse the number
448 * Pass in TRUE if this is an offset, FALSE if not
451 parse_num (const char *str, int offset)
457 fprintf(stderr, "FATAL ERROR: str is NULL\n");
461 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
463 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
469 /*----------------------------------------------------------------------
470 * Write this byte into current packet
473 write_byte (const char *str)
477 num = parse_num(str, FALSE);
478 packet_buf[curr_offset] = (guint8) num;
480 if (curr_offset - header_length >= max_offset) /* packet full */
481 start_new_packet(TRUE);
484 /*----------------------------------------------------------------------
485 * Write a number of bytes into current packet
489 write_bytes (const char bytes[], guint32 nbytes)
493 if (curr_offset + nbytes < MAX_PACKET) {
494 for (i = 0; i < nbytes; i++) {
495 packet_buf[curr_offset] = bytes[i];
501 /*----------------------------------------------------------------------
502 * Remove bytes from the current packet
505 unwrite_bytes (guint32 nbytes)
507 curr_offset -= nbytes;
510 /*----------------------------------------------------------------------
511 * Compute one's complement checksum (from RFC1071)
514 in_checksum (void *buf, guint32 count)
517 guint16 *addr = (guint16 *)buf;
520 /* This is the inner loop */
521 sum += g_ntohs(* (guint16 *) addr);
526 /* Add left-over byte, if any */
528 sum += g_ntohs(* (guint8 *) addr);
530 /* Fold 32-bit sum to 16 bits */
532 sum = (sum & 0xffff) + (sum >> 16);
538 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
539 * That code is copyrighted by D. Otis and has been modified.
542 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
543 static guint32 crc_c[256] =
545 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
546 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
547 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
548 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
549 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
550 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
551 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
552 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
553 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
554 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
555 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
556 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
557 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
558 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
559 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
560 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
561 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
562 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
563 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
564 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
565 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
566 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
567 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
568 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
569 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
570 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
571 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
572 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
573 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
574 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
575 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
576 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
577 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
578 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
579 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
580 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
581 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
582 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
583 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
584 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
585 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
586 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
587 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
588 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
589 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
590 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
591 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
592 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
593 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
594 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
595 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
596 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
597 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
598 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
599 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
600 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
601 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
602 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
603 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
604 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
605 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
606 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
607 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
608 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
612 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
618 for (i = 0; i < len; i++)
625 finalize_crc32c (guint32 crc)
628 guint8 byte0,byte1,byte2,byte3;
631 byte0 = result & 0xff;
632 byte1 = (result>>8) & 0xff;
633 byte2 = (result>>16) & 0xff;
634 byte3 = (result>>24) & 0xff;
635 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
640 number_of_padding_bytes (guint32 length)
644 remainder = length % 4;
649 return 4 - remainder;
652 /*----------------------------------------------------------------------
653 * Write current packet out
656 write_current_packet (gboolean cont)
659 guint16 padding_length = 0;
664 if (curr_offset > header_length) {
665 /* Write the packet */
667 /* Is direction indication on with an inbound packet? */
668 gboolean isInbound = has_direction && (direction == 2);
670 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
672 hdr_ethernet_proto = 0x86DD;
676 /* Compute packet length */
677 length = curr_offset;
679 padding_length = number_of_padding_bytes(length - header_length );
683 /* Reset curr_offset, since we now write the headers */
686 /* Write Ethernet header */
688 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
689 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
692 /* Write IP header */
695 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
696 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
699 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
700 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
703 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
704 HDR_IP.protocol = (guint8) hdr_ip_proto;
705 HDR_IP.hdr_checksum = 0;
706 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
707 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
708 } else if (hdr_ipv6) {
709 if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
710 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
711 if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
712 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
714 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
715 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
716 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
717 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
718 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
719 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
721 /* initialize pseudo ipv6 header for checksum calculation */
722 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
723 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
725 pseudoh6.protocol = (guint8) hdr_ip_proto;
726 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
727 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
731 /* initialize pseudo header for checksum calculation */
732 pseudoh.src_addr = HDR_IP.src_addr;
733 pseudoh.dest_addr = HDR_IP.dest_addr;
735 pseudoh.protocol = (guint8) hdr_ip_proto;
736 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
739 /* Write UDP header */
744 /* initialize the UDP header */
745 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
746 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
747 HDR_UDP.length = pseudoh.length;
748 HDR_UDP.checksum = 0;
749 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
750 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
752 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
754 x16 = in_checksum(packet_buf + header_length, length - header_length);
756 x16 = (u & 0xffff) + (u>>16);
757 HDR_UDP.checksum = g_htons(x16);
758 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
759 HDR_UDP.checksum = g_htons(1);
760 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
763 /* Write TCP header */
768 /* initialize pseudo header for checksum calculation */
769 pseudoh.src_addr = HDR_IP.src_addr;
770 pseudoh.dest_addr = HDR_IP.dest_addr;
772 pseudoh.protocol = (guint8) hdr_ip_proto;
773 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
774 /* initialize the TCP header */
775 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
776 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
777 /* set ack number if we have direction */
779 HDR_TCP.flags = 0x10;
780 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
781 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
787 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
788 HDR_TCP.window = g_htons(0x2000);
789 HDR_TCP.checksum = 0;
790 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
791 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
793 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
795 x16 = in_checksum(packet_buf + header_length, length - header_length);
797 x16 = (u & 0xffff) + (u>>16);
798 HDR_TCP.checksum = g_htons(x16);
799 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
800 HDR_TCP.checksum = g_htons(1);
801 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
803 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
804 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
807 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
808 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
812 /* Compute DATA chunk header */
813 if (hdr_data_chunk) {
814 hdr_data_chunk_bits = 0;
815 if (packet_start == 0) {
816 hdr_data_chunk_bits |= 0x02;
819 hdr_data_chunk_bits |= 0x01;
821 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
822 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
823 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
824 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
825 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
826 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
827 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
828 hdr_data_chunk_tsn++;
830 hdr_data_chunk_ssn++;
834 /* Write SCTP common header */
838 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
839 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
840 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
841 HDR_SCTP.checksum = g_htonl(0);
842 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
843 if (hdr_data_chunk) {
844 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
845 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
846 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
848 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
850 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
851 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
852 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
855 /* Write DATA chunk header */
856 if (hdr_data_chunk) {
857 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
860 /* Reset curr_offset, since we now write the trailers */
861 curr_offset = length;
863 /* Write DATA chunk padding */
864 if (hdr_data_chunk && (padding_length > 0)) {
865 memset(tempbuf, 0, padding_length);
866 write_bytes((const char *)&tempbuf, padding_length);
867 length += padding_length;
870 /* Write Ethernet trailer */
871 if (hdr_ethernet && (length < 60)) {
872 memset(tempbuf, 0, 60 - length);
873 write_bytes((const char *)&tempbuf, 60 - length);
877 success = pcapng_write_enhanced_packet_block(output_file,
883 packet_buf, direction,
884 &bytes_written, &err);
886 success = libpcap_write_packet(output_file,
887 ts_sec, ts_nsec/1000,
890 &bytes_written, &err);
893 fprintf(stderr, "File write error [%s] : %s\n",
894 output_filename, g_strerror(err));
897 if (ts_fmt == NULL) {
898 /* fake packet counter */
905 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
907 num_packets_written++;
910 packet_start += curr_offset - header_length;
911 curr_offset = header_length;
915 /*----------------------------------------------------------------------
916 * Write file header and trailer
919 write_file_header (void)
926 const char *appname = "text2pcap (" GITVERSION " from " GITBRANCH ")";
928 const char *appname = "text2pcap";
932 g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
933 success = pcapng_write_session_header_block(output_file,
942 success = pcapng_write_interface_description_block(output_file,
956 success = libpcap_write_file_header(output_file, pcap_link_type,
958 &bytes_written, &err);
961 fprintf(stderr, "File write error [%s] : %s\n",
962 output_filename, g_strerror(err));
968 write_file_trailer (void)
974 success = pcapng_write_interface_statistics_block(output_file,
977 "Counters provided by text2pcap",
981 num_packets_written - num_packets_written,
988 fprintf(stderr, "File write error [%s] : %s\n",
989 output_filename, g_strerror(err));
995 /*----------------------------------------------------------------------
996 * Append a token to the packet preamble.
999 append_to_preamble (char *str)
1003 if (packet_preamble_len != 0) {
1004 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1005 return; /* no room to add more preamble */
1006 /* Add a blank separator between the previous token and this token. */
1007 packet_preamble[packet_preamble_len++] = ' ';
1009 toklen = strlen(str);
1011 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1012 return; /* no room to add the token to the preamble */
1013 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1014 packet_preamble_len += (int) toklen;
1017 char xs[PACKET_PREAMBLE_MAX_LEN];
1018 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1019 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1020 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1025 /*----------------------------------------------------------------------
1026 * Parse the preamble to get the timecode.
1030 parse_preamble (void)
1039 * Null-terminate the preamble.
1041 packet_preamble[packet_preamble_len] = '\0';
1043 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1045 if (has_direction) {
1046 switch (packet_preamble[0]) {
1049 direction = 0x00000001;
1050 packet_preamble[0] = ' ';
1054 direction = 0x00000002;
1055 packet_preamble[0] = ' ';
1058 direction = 0x00000000;
1062 while (packet_preamble[i] == ' ' ||
1063 packet_preamble[i] == '\r' ||
1064 packet_preamble[i] == '\t') {
1067 packet_preamble_len -= i;
1068 /* Also move the trailing '\0'. */
1069 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1074 * If no "-t" flag was specified, don't attempt to parse the packet
1075 * preamble to extract a time stamp.
1077 if (ts_fmt == NULL) {
1078 /* Clear Preamble */
1079 packet_preamble_len = 0;
1084 * Initialize to today localtime, just in case not all fields
1085 * of the date and time are specified.
1088 timecode = timecode_default;
1091 /* Ensure preamble has more than two chars before attempting to parse.
1092 * This should cover line breaks etc that get counted.
1094 if (strlen(packet_preamble) > 2) {
1095 /* Get Time leaving subseconds */
1096 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1097 if (subsecs != NULL) {
1098 /* Get the long time from the tm structure */
1099 /* (will return -1 if failure) */
1100 ts_sec = mktime( &timecode );
1102 ts_sec = -1; /* we failed to parse it */
1104 /* This will ensure incorrectly parsed dates get set to zero */
1106 /* Sanitize - remove all '\r' */
1108 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1109 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1110 packet_preamble, ts_fmt);
1112 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1113 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1114 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1116 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1119 /* Parse subseconds */
1120 ts_nsec = (guint32)strtol(subsecs, &p, 10);
1126 * Convert that number to a number
1127 * of microseconds; if it's N digits
1128 * long, it's in units of 10^(-N) seconds,
1129 * so, to convert it to units of
1130 * 10^-9 seconds, we multiply by
1133 subseclen = (int) (p - subsecs);
1134 if (subseclen > 9) {
1136 * *More* than 9 digits; 9-N is
1137 * negative, so we divide by
1140 for (i = subseclen - 9; i != 0; i--)
1142 } else if (subseclen < 9) {
1143 for (i = 9 - subseclen; i != 0; i--)
1151 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1152 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1153 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1157 /* Clear Preamble */
1158 packet_preamble_len = 0;
1161 /*----------------------------------------------------------------------
1162 * Start a new packet
1165 start_new_packet (gboolean cont)
1168 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1170 /* Write out the current packet, if required */
1171 write_current_packet(cont);
1174 /* Ensure we parse the packet preamble as it may contain the time */
1178 /*----------------------------------------------------------------------
1179 * Process a directive
1182 process_directive (char *str)
1184 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1187 /*----------------------------------------------------------------------
1188 * Parse a single token (called from the scanner)
1191 parse_token (token_t token, char *str)
1202 * This is implemented as a simple state machine of five states.
1203 * State transitions are caused by tokens being received from the
1204 * scanner. The code should be self-documenting.
1208 /* Sanitize - remove all '\r' */
1210 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1212 fprintf(stderr, "(%s, %s \"%s\") -> (",
1213 state_str[state], token_str[token], str ? str : "");
1218 /* ----- Waiting for new packet -------------------------------------------*/
1220 if (!str && token != T_EOL) goto fail_null_str;
1223 append_to_preamble(str);
1226 process_directive(str);
1229 num = parse_num(str, TRUE);
1231 /* New packet starts here */
1232 start_new_packet(FALSE);
1233 state = READ_OFFSET;
1234 pkt_lnstart = packet_buf + num;
1238 /* Some describing text may be parsed as offset, but the invalid
1239 offset will be checked in the state of START_OF_LINE, so
1240 we add this transition to gain flexibility */
1241 state = START_OF_LINE;
1248 /* ----- Processing packet, start of new line -----------------------------*/
1250 if (!str && token != T_EOL) goto fail_null_str;
1253 append_to_preamble(str);
1256 process_directive(str);
1259 num = parse_num(str, TRUE);
1261 /* New packet starts here */
1262 start_new_packet(FALSE);
1264 state = READ_OFFSET;
1265 } else if ((num - packet_start) != curr_offset - header_length) {
1267 * The offset we read isn't the one we expected.
1268 * This may only mean that we mistakenly interpreted
1269 * some text as byte values (e.g., if the text dump
1270 * of packet data included a number with spaces around
1271 * it). If the offset is less than what we expected,
1272 * assume that's the problem, and throw away the putative
1273 * extra byte values.
1275 if (num < curr_offset) {
1276 unwrite_bytes(curr_offset - num);
1277 state = READ_OFFSET;
1279 /* Bad offset; switch to INIT state */
1281 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1283 write_current_packet(FALSE);
1287 state = READ_OFFSET;
1288 pkt_lnstart = packet_buf + num;
1291 state = START_OF_LINE;
1298 /* ----- Processing packet, read offset -----------------------------------*/
1302 /* Record the byte */
1304 if (!str) goto fail_null_str;
1313 state = START_OF_LINE;
1320 /* ----- Processing packet, read byte -------------------------------------*/
1324 /* Record the byte */
1333 if (token == T_EOL) {
1335 state = START_OF_LINE;
1337 if (identify_ascii) {
1338 /* Here a line of pkt bytes reading is finished
1339 compare the ascii and hex to avoid such situation:
1340 "61 62 20 ab ", when ab is ascii dump then it should
1341 not be treat as byte */
1343 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1344 s2 = "ab ", s1 = "616220"
1345 we should find out the largest tail of s1 matches the head
1346 of s2, it means the matched part in tail is the ASCII dump
1347 of the head byte. These matched should be rollback */
1348 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1349 s2 = (char*)g_malloc((line_size+1)/4+1);
1350 /* gather the possible pattern */
1351 for (i = 0; i < (line_size+1)/4; i++) {
1352 tmp_str[0] = pkt_lnstart[i*3];
1353 tmp_str[1] = pkt_lnstart[i*3+1];
1355 /* it is a valid convertable string */
1356 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[0])) {
1359 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1361 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1362 if (!(pkt_lnstart[i*3+2] == ' ')) {
1368 /* If packet line start contains possible byte pattern, the line end
1369 should contain the matched pattern if the user open the -a flag.
1370 The packet will be possible invalid if the byte pattern cannot find
1371 a matched one in the line of packet buffer.*/
1373 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1374 unwrite_bytes(rollback);
1376 /* Not matched. This line contains invalid packet bytes, so
1377 discard the whole line */
1379 unwrite_bytes(line_size);
1390 /* ----- Processing packet, read text -------------------------------------*/
1394 state = START_OF_LINE;
1402 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1407 fprintf(stderr, ", %s)\n", state_str[state]);
1412 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1417 /*----------------------------------------------------------------------
1418 * Print usage string and exit
1421 print_usage (FILE *output)
1425 "Usage: text2pcap [options] <infile> <outfile>\n"
1427 "where <infile> specifies input filename (use - for standard input)\n"
1428 " <outfile> specifies output filename (use - for standard output)\n"
1431 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1432 " default is hex.\n"
1433 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1434 " the specified argument is a format string of the sort\n"
1435 " supported by strptime.\n"
1436 " Example: The time \"10:15:14.5476\" has the format code\n"
1437 " \"%%H:%%M:%%S.\"\n"
1438 " NOTE: The subsecond component delimiter, '.', must be\n"
1439 " given, but no pattern is required; the remaining\n"
1440 " number is assumed to be fractions of a second.\n"
1441 " NOTE: Date/time fields from the current date/time are\n"
1442 " used as the default for unspecified fields.\n"
1443 " -D the text before the packet starts with an I or an O,\n"
1444 " indicating that the packet is inbound or outbound.\n"
1445 " This is only stored if the output format is PCAP-NG.\n"
1446 " -a enable ASCII text dump identification.\n"
1447 " The start of the ASCII text dump can be identified\n"
1448 " and excluded from the packet data, even if it looks\n"
1449 " like a HEX dump.\n"
1450 " NOTE: Do not enable it if the input file does not\n"
1451 " contain the ASCII text dump.\n"
1454 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1455 " http://www.tcpdump.org/linktypes.html for a list of\n"
1456 " numbers. Use this option if your dump is a complete\n"
1457 " hex dump of an encapsulated packet and you wish to\n"
1458 " specify the exact type of encapsulation.\n"
1459 " Example: -l 7 for ARCNet packets.\n"
1460 " -m <max-packet> max packet length in output; default is %d\n"
1462 "Prepend dummy header:\n"
1463 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1465 " Example: -e 0x806 to specify an ARP packet.\n"
1466 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1468 " Automatically prepends Ethernet header as well.\n"
1470 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1471 " dest and source address.\n"
1472 " Example: -4 10.0.0.1,10.0.0.2\n"
1473 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1474 " dest and source address.\n"
1475 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1476 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1477 " source and destination ports (in DECIMAL).\n"
1478 " Automatically prepends Ethernet & IP headers as well.\n"
1479 " Example: -u 1000,69 to make the packets look like\n"
1480 " TFTP/UDP packets.\n"
1481 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1482 " source and destination ports (in DECIMAL).\n"
1483 " Automatically prepends Ethernet & IP headers as well.\n"
1484 " Example: -T 50,60\n"
1485 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1486 " source/dest ports and verification tag (in DECIMAL).\n"
1487 " Automatically prepends Ethernet & IP headers as well.\n"
1488 " Example: -s 30,40,34\n"
1489 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1490 " source/dest ports and verification tag 0.\n"
1491 " Automatically prepends a dummy SCTP DATA\n"
1492 " chunk header with payload protocol identifier ppi.\n"
1493 " Example: -S 30,40,34\n"
1496 " -h display this help and exit.\n"
1497 " -d show detailed debug of parser states.\n"
1498 " -q generate no output at all (automatically disables -d).\n"
1499 " -n use PCAP-NG instead of PCAP as output format.\n"
1505 get_text2pcap_compiled_info(GString *str)
1508 g_string_append(str, ", ");
1510 g_string_append(str, "with libz ");
1512 g_string_append(str, ZLIB_VERSION);
1513 #else /* ZLIB_VERSION */
1514 g_string_append(str, "(version unknown)");
1515 #endif /* ZLIB_VERSION */
1516 #else /* HAVE_LIBZ */
1517 g_string_append(str, "without libz");
1518 #endif /* HAVE_LIBZ */
1522 get_text2pcap_runtime_info(GString *str)
1525 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1526 g_string_append_printf(str, ", with libz %s", zlibVersion());
1530 /*----------------------------------------------------------------------
1534 parse_options (int argc, char *argv[])
1536 GString *comp_info_str;
1537 GString *runtime_info_str;
1540 static const struct option long_options[] = {
1541 {(char *)"help", no_argument, NULL, 'h'},
1542 {(char *)"version", no_argument, NULL, 'v'},
1547 arg_list_utf_16to8(argc, argv);
1548 create_app_running_mutex();
1551 /* Assemble the compile-time version information string */
1552 comp_info_str = g_string_new("Compiled ");
1553 get_compiled_version_info(comp_info_str, NULL, get_text2pcap_compiled_info);
1555 /* Assemble the run-time version information string */
1556 runtime_info_str = g_string_new("Running ");
1557 get_runtime_version_info(runtime_info_str, get_text2pcap_runtime_info);
1559 /* Add it to the information to be reported on a crash. */
1560 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1565 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1567 /* Scan CLI parameters */
1568 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1571 printf("Text2pcap (Wireshark) %s\n"
1572 "Generate a capture file from an ASCII hexdump of packets.\n"
1573 "See http://www.wireshark.org for more information.\n",
1574 get_ws_vcs_version_info());
1575 print_usage(stdout);
1578 case 'd': if (!quiet) debug++; break;
1579 case 'D': has_direction = TRUE; break;
1580 case 'q': quiet = TRUE; debug = FALSE; break;
1581 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1582 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1583 case 'n': use_pcapng = TRUE; break;
1585 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1586 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1587 print_usage(stderr);
1590 switch (optarg[0]) {
1591 case 'o': offset_base = 8; break;
1592 case 'h': offset_base = 16; break;
1593 case 'd': offset_base = 10; break;
1597 hdr_ethernet = TRUE;
1598 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1599 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1600 print_usage(stderr);
1607 hdr_ip_proto = strtol(optarg, &p, 10);
1608 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1609 hdr_ip_proto > 255) {
1610 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1611 print_usage(stderr);
1614 hdr_ethernet = TRUE;
1615 hdr_ethernet_proto = 0x800;
1620 hdr_data_chunk = FALSE;
1623 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1624 if (p == optarg || (*p != ',' && *p != '\0')) {
1625 fprintf(stderr, "Bad src port for '-%c'\n", c);
1626 print_usage(stderr);
1630 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1631 print_usage(stderr);
1636 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1637 if (p == optarg || (*p != ',' && *p != '\0')) {
1638 fprintf(stderr, "Bad dest port for '-s'\n");
1639 print_usage(stderr);
1643 fprintf(stderr, "No tag specified for '-%c'\n", c);
1644 print_usage(stderr);
1649 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1650 if (p == optarg || *p != '\0') {
1651 fprintf(stderr, "Bad tag for '-%c'\n", c);
1652 print_usage(stderr);
1658 hdr_ethernet = TRUE;
1659 hdr_ethernet_proto = 0x800;
1663 hdr_data_chunk = TRUE;
1666 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1667 if (p == optarg || (*p != ',' && *p != '\0')) {
1668 fprintf(stderr, "Bad src port for '-%c'\n", c);
1669 print_usage(stderr);
1673 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1674 print_usage(stderr);
1679 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1680 if (p == optarg || (*p != ',' && *p != '\0')) {
1681 fprintf(stderr, "Bad dest port for '-s'\n");
1682 print_usage(stderr);
1686 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1687 print_usage(stderr);
1692 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1693 if (p == optarg || *p != '\0') {
1694 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1695 print_usage(stderr);
1701 hdr_ethernet = TRUE;
1702 hdr_ethernet_proto = 0x800;
1713 hdr_data_chunk = FALSE;
1714 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1715 if (p == optarg || (*p != ',' && *p != '\0')) {
1716 fprintf(stderr, "Bad src port for '-u'\n");
1717 print_usage(stderr);
1721 fprintf(stderr, "No dest port specified for '-u'\n");
1722 print_usage(stderr);
1727 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1728 if (p == optarg || *p != '\0') {
1729 fprintf(stderr, "Bad dest port for '-u'\n");
1730 print_usage(stderr);
1735 hdr_ethernet = TRUE;
1736 hdr_ethernet_proto = 0x800;
1743 hdr_data_chunk = FALSE;
1744 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1745 if (p == optarg || (*p != ',' && *p != '\0')) {
1746 fprintf(stderr, "Bad src port for '-T'\n");
1747 print_usage(stderr);
1751 fprintf(stderr, "No dest port specified for '-u'\n");
1752 print_usage(stderr);
1757 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1758 if (p == optarg || *p != '\0') {
1759 fprintf(stderr, "Bad dest port for '-T'\n");
1760 print_usage(stderr);
1765 hdr_ethernet = TRUE;
1766 hdr_ethernet_proto = 0x800;
1770 identify_ascii = TRUE;
1774 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1775 g_string_free(comp_info_str, TRUE);
1776 g_string_free(runtime_info_str, TRUE);
1782 p = strchr(optarg, ',');
1785 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1786 print_usage(stderr);
1794 hdr_ethernet_proto = 0x86DD;
1799 hdr_ethernet_proto = 0x800;
1801 hdr_ethernet = TRUE;
1803 if (hdr_ipv6 == TRUE) {
1804 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1805 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1806 print_usage(stderr);
1810 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1811 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1812 print_usage(stderr);
1819 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1820 print_usage(stderr);
1824 if (hdr_ipv6 == TRUE) {
1825 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1826 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1827 print_usage(stderr);
1831 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1832 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1833 print_usage(stderr);
1842 print_usage(stderr);
1847 if (optind >= argc || argc-optind < 2) {
1848 fprintf(stderr, "Must specify input and output filename\n");
1849 print_usage(stderr);
1853 if (strcmp(argv[optind], "-")) {
1854 input_filename = g_strdup(argv[optind]);
1855 input_file = ws_fopen(input_filename, "rb");
1857 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1858 input_filename, g_strerror(errno));
1862 input_filename = "Standard input";
1866 if (strcmp(argv[optind+1], "-")) {
1867 output_filename = g_strdup(argv[optind+1]);
1868 output_file = ws_fopen(output_filename, "wb");
1870 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1871 output_filename, g_strerror(errno));
1875 output_filename = "Standard output";
1876 output_file = stdout;
1879 /* Some validation */
1880 if (pcap_link_type != 1 && hdr_ethernet) {
1881 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1885 /* Set up our variables */
1888 input_filename = "Standard input";
1891 output_file = stdout;
1892 output_filename = "Standard output";
1895 ts_sec = time(0); /* initialize to current time */
1896 timecode_default = *localtime(&ts_sec);
1897 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1899 /* Display summary of our state */
1901 fprintf(stderr, "Input from: %s\n", input_filename);
1902 fprintf(stderr, "Output to: %s\n", output_filename);
1903 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1905 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1906 hdr_ethernet_proto);
1907 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1909 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1910 hdr_src_port, hdr_dest_port);
1911 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1912 hdr_src_port, hdr_dest_port);
1913 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1914 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1915 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
1916 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1921 main(int argc, char *argv[])
1923 parse_options(argc, argv);
1925 assert(input_file != NULL);
1926 assert(output_file != NULL);
1928 write_file_header();
1932 header_length += (int)sizeof(HDR_ETHERNET);
1935 ip_offset = header_length;
1936 header_length += (int)sizeof(HDR_IP);
1937 } else if (hdr_ipv6) {
1938 ip_offset = header_length;
1939 header_length += (int)sizeof(HDR_IPv6);
1942 header_length += (int)sizeof(HDR_SCTP);
1944 if (hdr_data_chunk) {
1945 header_length += (int)sizeof(HDR_DATA_CHUNK);
1948 header_length += (int)sizeof(HDR_TCP);
1951 header_length += (int)sizeof(HDR_UDP);
1953 curr_offset = header_length;
1958 write_current_packet(FALSE);
1959 write_file_trailer();
1961 fclose(output_file);
1963 fprintf(stderr, "\n-------------------------\n");
1965 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1966 num_packets_read, (num_packets_read == 1) ? "" : "s",
1967 num_packets_written, (num_packets_written == 1) ? "" : "s",
1968 bytes_written, (bytes_written == 1) ? "" : "s");
1974 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1979 * indent-tabs-mode: nil
1982 * vi: set shiftwidth=4 tabstop=8 expandtab:
1983 * :indentSize=4:tabSize=8:noTabs=true: