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>
129 #include <zlib.h> /* to get the libz version number */
132 #ifndef HAVE_GETOPT_LONG
133 #include "wsutil/wsgetopt.h"
136 #ifndef HAVE_STRPTIME
137 # include "wsutil/strptime.h"
141 #include "text2pcap.h"
144 #include <wsutil/unicode-utils.h>
147 #ifdef HAVE_ARPA_INET_H
148 #include <arpa/inet.h>
151 #ifdef HAVE_WINSOCK2_H
152 #include <winsock2.h> /* needed to define AF_ values on Windows */
155 #ifdef HAVE_SYS_SOCKET_H
156 #include <sys/socket.h>
159 #ifdef NEED_INET_V6DEFS_H
160 # include "wsutil/inet_v6defs.h"
163 /*--- Options --------------------------------------------------------------------*/
166 static gboolean use_pcapng = FALSE;
169 static int debug = 0;
171 static int quiet = FALSE;
173 /* Dummy Ethernet header */
174 static int hdr_ethernet = FALSE;
175 static guint32 hdr_ethernet_proto = 0;
177 /* Dummy IP header */
178 static int hdr_ip = FALSE;
179 static int hdr_ipv6 = FALSE;
180 static long hdr_ip_proto = 0;
182 /* Destination and source addresses for IP header */
183 static guint32 hdr_ip_dest_addr = 0;
184 static guint32 hdr_ip_src_addr = 0;
185 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
186 static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
187 static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
189 /* Dummy UDP header */
190 static int hdr_udp = FALSE;
191 static guint32 hdr_dest_port = 0;
192 static guint32 hdr_src_port = 0;
194 /* Dummy TCP header */
195 static int hdr_tcp = FALSE;
197 /* TCP sequence numbers when has_direction is true */
198 static guint32 tcp_in_seq_num = 0;
199 static guint32 tcp_out_seq_num = 0;
201 /* Dummy SCTP header */
202 static int hdr_sctp = FALSE;
203 static guint32 hdr_sctp_src = 0;
204 static guint32 hdr_sctp_dest = 0;
205 static guint32 hdr_sctp_tag = 0;
207 /* Dummy DATA chunk header */
208 static int hdr_data_chunk = FALSE;
209 static guint8 hdr_data_chunk_type = 0;
210 static guint8 hdr_data_chunk_bits = 0;
211 static guint32 hdr_data_chunk_tsn = 0;
212 static guint16 hdr_data_chunk_sid = 0;
213 static guint16 hdr_data_chunk_ssn = 0;
214 static guint32 hdr_data_chunk_ppid = 0;
216 /* ASCII text dump identification */
217 static int identify_ascii = FALSE;
219 static gboolean has_direction = FALSE;
220 static guint32 direction = 0;
222 /*--- Local date -----------------------------------------------------------------*/
224 /* This is where we store the packet currently being built */
225 #define MAX_PACKET 65535
226 static guint8 packet_buf[MAX_PACKET];
227 static guint32 header_length;
228 static guint32 ip_offset;
229 static guint32 curr_offset;
230 static guint32 max_offset = MAX_PACKET;
231 static guint32 packet_start = 0;
233 static void start_new_packet(gboolean);
235 /* This buffer contains strings present before the packet offset 0 */
236 #define PACKET_PREAMBLE_MAX_LEN 2048
237 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
238 static int packet_preamble_len = 0;
240 /* Number of packets read and written */
241 static guint32 num_packets_read = 0;
242 static guint32 num_packets_written = 0;
243 static guint64 bytes_written = 0;
245 /* Time code of packet, derived from packet_preamble */
246 static time_t ts_sec = 0;
247 static guint32 ts_nsec = 0;
248 static char *ts_fmt = NULL;
249 static struct tm timecode_default;
251 static guint8* pkt_lnstart;
254 static const char *input_filename;
255 static FILE *input_file = NULL;
257 static const char *output_filename;
258 static FILE *output_file = NULL;
260 /* Offset base to parse */
261 static guint32 offset_base = 16;
265 /* ----- State machine -----------------------------------------------------------*/
267 /* Current state of parser */
269 INIT, /* Waiting for start of new packet */
270 START_OF_LINE, /* Starting from beginning of line */
271 READ_OFFSET, /* Just read the offset */
272 READ_BYTE, /* Just read a byte */
273 READ_TEXT /* Just read text - ignore until EOL */
275 static parser_state_t state = INIT;
277 static const char *state_str[] = {"Init",
284 static const char *token_str[] = {"",
292 /* ----- Skeleton Packet Headers --------------------------------------------------*/
300 static hdr_ethernet_t HDR_ETHERNET = {
301 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
302 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
308 guint16 packet_length;
309 guint16 identification;
314 guint16 hdr_checksum;
319 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
320 #ifdef WORDS_BIGENDIAN
321 0x0a010101, 0x0a020202
323 0x0101010a, 0x0202020a
327 /* Fixed IP address values */
328 #ifdef WORDS_BIGENDIAN
329 #define IP_SRC 0x0a010101
330 #define IP_DST 0x0a020202
332 #define IP_SRC 0x0101010a
333 #define IP_DST 0x0202020a
336 static struct { /* pseudo header for checksum calculation */
345 /* headers taken from glibc */
352 guint8 __u6_addr8[16];
353 guint16 __u6_addr16[8];
354 guint32 __u6_addr32[4];
361 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
362 guint16 ip6_un1_plen; /* payload length */
363 guint8 ip6_un1_nxt; /* next header */
364 guint8 ip6_un1_hlim; /* hop limit */
366 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
368 struct hdr_in6_addr ip6_src; /* source address */
369 struct hdr_in6_addr ip6_dst; /* destination address */
372 static hdr_ipv6_t HDR_IPv6;
374 static struct { /* pseudo header ipv6 for checksum calculation */
375 struct hdr_in6_addr src_addr6;
376 struct hdr_in6_addr dst_addr6;
389 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
403 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
412 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
424 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
426 static char tempbuf[64];
428 /*----------------------------------------------------------------------
429 * Stuff for writing a PCap file
431 #define PCAP_SNAPLEN 0xffff
433 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
434 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
436 /*----------------------------------------------------------------------
437 * Parse a single hex number
438 * Will abort the program if it can't parse the number
439 * Pass in TRUE if this is an offset, FALSE if not
442 parse_num (const char *str, int offset)
448 fprintf(stderr, "FATAL ERROR: str is NULL\n");
452 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
454 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
460 /*----------------------------------------------------------------------
461 * Write this byte into current packet
464 write_byte (const char *str)
468 num = parse_num(str, FALSE);
469 packet_buf[curr_offset] = (guint8) num;
471 if (curr_offset - header_length >= max_offset) /* packet full */
472 start_new_packet(TRUE);
475 /*----------------------------------------------------------------------
476 * Write a number of bytes into current packet
480 write_bytes (const char bytes[], guint32 nbytes)
484 if (curr_offset + nbytes < MAX_PACKET) {
485 for (i = 0; i < nbytes; i++) {
486 packet_buf[curr_offset] = bytes[i];
492 /*----------------------------------------------------------------------
493 * Remove bytes from the current packet
496 unwrite_bytes (guint32 nbytes)
498 curr_offset -= nbytes;
501 /*----------------------------------------------------------------------
502 * Compute one's complement checksum (from RFC1071)
505 in_checksum (void *buf, guint32 count)
508 guint16 *addr = (guint16 *)buf;
511 /* This is the inner loop */
512 sum += g_ntohs(* (guint16 *) addr);
517 /* Add left-over byte, if any */
519 sum += g_ntohs(* (guint8 *) addr);
521 /* Fold 32-bit sum to 16 bits */
523 sum = (sum & 0xffff) + (sum >> 16);
529 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
530 * That code is copyrighted by D. Otis and has been modified.
533 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
534 static guint32 crc_c[256] =
536 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
537 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
538 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
539 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
540 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
541 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
542 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
543 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
544 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
545 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
546 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
547 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
548 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
549 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
550 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
551 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
552 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
553 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
554 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
555 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
556 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
557 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
558 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
559 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
560 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
561 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
562 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
563 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
564 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
565 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
566 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
567 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
568 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
569 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
570 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
571 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
572 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
573 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
574 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
575 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
576 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
577 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
578 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
579 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
580 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
581 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
582 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
583 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
584 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
585 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
586 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
587 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
588 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
589 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
590 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
591 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
592 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
593 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
594 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
595 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
596 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
597 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
598 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
599 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
603 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
609 for (i = 0; i < len; i++)
616 finalize_crc32c (guint32 crc)
619 guint8 byte0,byte1,byte2,byte3;
622 byte0 = result & 0xff;
623 byte1 = (result>>8) & 0xff;
624 byte2 = (result>>16) & 0xff;
625 byte3 = (result>>24) & 0xff;
626 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
631 number_of_padding_bytes (guint32 length)
635 remainder = length % 4;
640 return 4 - remainder;
643 /*----------------------------------------------------------------------
644 * Write current packet out
647 write_current_packet (gboolean cont)
650 guint16 padding_length = 0;
655 if (curr_offset > header_length) {
656 /* Write the packet */
658 /* Is direction indication on with an inbound packet? */
659 gboolean isInbound = has_direction && (direction == 2);
661 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
663 hdr_ethernet_proto = 0x86DD;
667 /* Compute packet length */
668 length = curr_offset;
670 padding_length = number_of_padding_bytes(length - header_length );
674 /* Reset curr_offset, since we now write the headers */
677 /* Write Ethernet header */
679 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
680 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
683 /* Write IP header */
686 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
687 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
690 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
691 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
694 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
695 HDR_IP.protocol = (guint8) hdr_ip_proto;
696 HDR_IP.hdr_checksum = 0;
697 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
698 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
699 } else if (hdr_ipv6) {
700 if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
701 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
702 if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
703 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
705 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
706 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
707 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
708 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
709 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
710 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
712 /* initialize pseudo ipv6 header for checksum calculation */
713 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
714 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
716 pseudoh6.protocol = (guint8) hdr_ip_proto;
717 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
718 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
722 /* initialize pseudo header for checksum calculation */
723 pseudoh.src_addr = HDR_IP.src_addr;
724 pseudoh.dest_addr = HDR_IP.dest_addr;
726 pseudoh.protocol = (guint8) hdr_ip_proto;
727 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
730 /* Write UDP header */
735 /* initialize the UDP header */
736 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
737 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
738 HDR_UDP.length = pseudoh.length;
739 HDR_UDP.checksum = 0;
740 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
741 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
743 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
745 x16 = in_checksum(packet_buf + header_length, length - header_length);
747 x16 = (u & 0xffff) + (u>>16);
748 HDR_UDP.checksum = g_htons(x16);
749 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
750 HDR_UDP.checksum = g_htons(1);
751 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
754 /* Write TCP header */
759 /* initialize pseudo header for checksum calculation */
760 pseudoh.src_addr = HDR_IP.src_addr;
761 pseudoh.dest_addr = HDR_IP.dest_addr;
763 pseudoh.protocol = (guint8) hdr_ip_proto;
764 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
765 /* initialize the TCP header */
766 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
767 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
768 /* set ack number if we have direction */
770 HDR_TCP.flags = 0x10;
771 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
772 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
778 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
779 HDR_TCP.window = g_htons(0x2000);
780 HDR_TCP.checksum = 0;
781 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
782 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
784 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
786 x16 = in_checksum(packet_buf + header_length, length - header_length);
788 x16 = (u & 0xffff) + (u>>16);
789 HDR_TCP.checksum = g_htons(x16);
790 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
791 HDR_TCP.checksum = g_htons(1);
792 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
794 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
795 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
798 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
799 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
803 /* Compute DATA chunk header */
804 if (hdr_data_chunk) {
805 hdr_data_chunk_bits = 0;
806 if (packet_start == 0) {
807 hdr_data_chunk_bits |= 0x02;
810 hdr_data_chunk_bits |= 0x01;
812 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
813 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
814 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
815 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
816 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
817 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
818 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
819 hdr_data_chunk_tsn++;
821 hdr_data_chunk_ssn++;
825 /* Write SCTP common header */
829 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
830 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
831 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
832 HDR_SCTP.checksum = g_htonl(0);
833 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
834 if (hdr_data_chunk) {
835 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
836 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
837 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
839 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
841 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
842 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
843 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
846 /* Write DATA chunk header */
847 if (hdr_data_chunk) {
848 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
851 /* Reset curr_offset, since we now write the trailers */
852 curr_offset = length;
854 /* Write DATA chunk padding */
855 if (hdr_data_chunk && (padding_length > 0)) {
856 memset(tempbuf, 0, padding_length);
857 write_bytes((const char *)&tempbuf, padding_length);
858 length += padding_length;
861 /* Write Ethernet trailer */
862 if (hdr_ethernet && (length < 60)) {
863 memset(tempbuf, 0, 60 - length);
864 write_bytes((const char *)&tempbuf, 60 - length);
868 success = pcapng_write_enhanced_packet_block(output_file,
874 packet_buf, direction,
875 &bytes_written, &err);
877 success = libpcap_write_packet(output_file,
878 ts_sec, ts_nsec/1000,
881 &bytes_written, &err);
884 fprintf(stderr, "File write error [%s] : %s\n",
885 output_filename, g_strerror(err));
888 if (ts_fmt == NULL) {
889 /* fake packet counter */
896 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
898 num_packets_written++;
901 packet_start += curr_offset - header_length;
902 curr_offset = header_length;
906 /*----------------------------------------------------------------------
907 * Write file header and trailer
910 write_file_header (void)
919 appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
920 comment = g_strdup_printf("Generated from input file %s.", input_filename);
921 success = pcapng_write_session_header_block(output_file,
926 -1, /* section_length */
932 success = pcapng_write_interface_description_block(output_file,
946 success = libpcap_write_file_header(output_file, pcap_link_type,
948 &bytes_written, &err);
951 fprintf(stderr, "File write error [%s] : %s\n",
952 output_filename, g_strerror(err));
957 /*----------------------------------------------------------------------
958 * Append a token to the packet preamble.
961 append_to_preamble (char *str)
965 if (packet_preamble_len != 0) {
966 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
967 return; /* no room to add more preamble */
968 /* Add a blank separator between the previous token and this token. */
969 packet_preamble[packet_preamble_len++] = ' ';
971 toklen = strlen(str);
973 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
974 return; /* no room to add the token to the preamble */
975 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
976 packet_preamble_len += (int) toklen;
979 char xs[PACKET_PREAMBLE_MAX_LEN];
980 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
981 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
982 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
987 /*----------------------------------------------------------------------
988 * Parse the preamble to get the timecode.
992 parse_preamble (void)
1001 * Null-terminate the preamble.
1003 packet_preamble[packet_preamble_len] = '\0';
1005 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1007 if (has_direction) {
1008 switch (packet_preamble[0]) {
1011 direction = 0x00000001;
1012 packet_preamble[0] = ' ';
1016 direction = 0x00000002;
1017 packet_preamble[0] = ' ';
1020 direction = 0x00000000;
1024 while (packet_preamble[i] == ' ' ||
1025 packet_preamble[i] == '\r' ||
1026 packet_preamble[i] == '\t') {
1029 packet_preamble_len -= i;
1030 /* Also move the trailing '\0'. */
1031 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1036 * If no "-t" flag was specified, don't attempt to parse the packet
1037 * preamble to extract a time stamp.
1039 if (ts_fmt == NULL) {
1040 /* Clear Preamble */
1041 packet_preamble_len = 0;
1046 * Initialize to today localtime, just in case not all fields
1047 * of the date and time are specified.
1050 timecode = timecode_default;
1053 /* Ensure preamble has more than two chars before attempting to parse.
1054 * This should cover line breaks etc that get counted.
1056 if (strlen(packet_preamble) > 2) {
1057 /* Get Time leaving subseconds */
1058 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1059 if (subsecs != NULL) {
1060 /* Get the long time from the tm structure */
1061 /* (will return -1 if failure) */
1062 ts_sec = mktime( &timecode );
1064 ts_sec = -1; /* we failed to parse it */
1066 /* This will ensure incorrectly parsed dates get set to zero */
1068 /* Sanitize - remove all '\r' */
1070 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1071 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1072 packet_preamble, ts_fmt);
1074 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1075 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1076 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1078 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1081 /* Parse subseconds */
1082 ts_nsec = (guint32)strtol(subsecs, &p, 10);
1088 * Convert that number to a number
1089 * of microseconds; if it's N digits
1090 * long, it's in units of 10^(-N) seconds,
1091 * so, to convert it to units of
1092 * 10^-9 seconds, we multiply by
1095 subseclen = (int) (p - subsecs);
1096 if (subseclen > 9) {
1098 * *More* than 9 digits; 9-N is
1099 * negative, so we divide by
1102 for (i = subseclen - 9; i != 0; i--)
1104 } else if (subseclen < 9) {
1105 for (i = 9 - subseclen; i != 0; i--)
1113 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1114 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1115 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1119 /* Clear Preamble */
1120 packet_preamble_len = 0;
1123 /*----------------------------------------------------------------------
1124 * Start a new packet
1127 start_new_packet (gboolean cont)
1130 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1132 /* Write out the current packet, if required */
1133 write_current_packet(cont);
1136 /* Ensure we parse the packet preamble as it may contain the time */
1140 /*----------------------------------------------------------------------
1141 * Process a directive
1144 process_directive (char *str)
1146 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1149 /*----------------------------------------------------------------------
1150 * Parse a single token (called from the scanner)
1153 parse_token (token_t token, char *str)
1164 * This is implemented as a simple state machine of five states.
1165 * State transitions are caused by tokens being received from the
1166 * scanner. The code should be self-documenting.
1170 /* Sanitize - remove all '\r' */
1172 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1174 fprintf(stderr, "(%s, %s \"%s\") -> (",
1175 state_str[state], token_str[token], str ? str : "");
1180 /* ----- Waiting for new packet -------------------------------------------*/
1182 if (!str && token != T_EOL) goto fail_null_str;
1185 append_to_preamble(str);
1188 process_directive(str);
1191 num = parse_num(str, TRUE);
1193 /* New packet starts here */
1194 start_new_packet(FALSE);
1195 state = READ_OFFSET;
1196 pkt_lnstart = packet_buf + num;
1200 /* Some describing text may be parsed as offset, but the invalid
1201 offset will be checked in the state of START_OF_LINE, so
1202 we add this transition to gain flexibility */
1203 state = START_OF_LINE;
1210 /* ----- Processing packet, start of new line -----------------------------*/
1212 if (!str && token != T_EOL) goto fail_null_str;
1215 append_to_preamble(str);
1218 process_directive(str);
1221 num = parse_num(str, TRUE);
1223 /* New packet starts here */
1224 start_new_packet(FALSE);
1226 state = READ_OFFSET;
1227 } else if ((num - packet_start) != curr_offset - header_length) {
1229 * The offset we read isn't the one we expected.
1230 * This may only mean that we mistakenly interpreted
1231 * some text as byte values (e.g., if the text dump
1232 * of packet data included a number with spaces around
1233 * it). If the offset is less than what we expected,
1234 * assume that's the problem, and throw away the putative
1235 * extra byte values.
1237 if (num < curr_offset) {
1238 unwrite_bytes(curr_offset - num);
1239 state = READ_OFFSET;
1241 /* Bad offset; switch to INIT state */
1243 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1245 write_current_packet(FALSE);
1249 state = READ_OFFSET;
1251 pkt_lnstart = packet_buf + num;
1254 state = START_OF_LINE;
1261 /* ----- Processing packet, read offset -----------------------------------*/
1265 /* Record the byte */
1267 if (!str) goto fail_null_str;
1276 state = START_OF_LINE;
1283 /* ----- Processing packet, read byte -------------------------------------*/
1287 /* Record the byte */
1296 if (token == T_EOL) {
1298 state = START_OF_LINE;
1300 if (identify_ascii) {
1301 /* Here a line of pkt bytes reading is finished
1302 compare the ascii and hex to avoid such situation:
1303 "61 62 20 ab ", when ab is ascii dump then it should
1304 not be treat as byte */
1306 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1307 s2 = "ab ", s1 = "616220"
1308 we should find out the largest tail of s1 matches the head
1309 of s2, it means the matched part in tail is the ASCII dump
1310 of the head byte. These matched should be rollback */
1311 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1312 s2 = (char*)g_malloc((line_size+1)/4+1);
1313 /* gather the possible pattern */
1314 for (i = 0; i < (line_size+1)/4; i++) {
1315 tmp_str[0] = pkt_lnstart[i*3];
1316 tmp_str[1] = pkt_lnstart[i*3+1];
1318 /* it is a valid convertable string */
1319 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1322 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1324 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1325 if (!(pkt_lnstart[i*3+2] == ' ')) {
1331 /* If packet line start contains possible byte pattern, the line end
1332 should contain the matched pattern if the user open the -a flag.
1333 The packet will be possible invalid if the byte pattern cannot find
1334 a matched one in the line of packet buffer.*/
1336 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1337 unwrite_bytes(rollback);
1339 /* Not matched. This line contains invalid packet bytes, so
1340 discard the whole line */
1342 unwrite_bytes(line_size);
1353 /* ----- Processing packet, read text -------------------------------------*/
1357 state = START_OF_LINE;
1365 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1370 fprintf(stderr, ", %s)\n", state_str[state]);
1375 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1380 /*----------------------------------------------------------------------
1381 * Print usage string and exit
1384 print_usage (FILE *output)
1388 "Usage: text2pcap [options] <infile> <outfile>\n"
1390 "where <infile> specifies input filename (use - for standard input)\n"
1391 " <outfile> specifies output filename (use - for standard output)\n"
1394 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1395 " default is hex.\n"
1396 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1397 " the specified argument is a format string of the sort\n"
1398 " supported by strptime.\n"
1399 " Example: The time \"10:15:14.5476\" has the format code\n"
1400 " \"%%H:%%M:%%S.\"\n"
1401 " NOTE: The subsecond component delimiter, '.', must be\n"
1402 " given, but no pattern is required; the remaining\n"
1403 " number is assumed to be fractions of a second.\n"
1404 " NOTE: Date/time fields from the current date/time are\n"
1405 " used as the default for unspecified fields.\n"
1406 " -D the text before the packet starts with an I or an O,\n"
1407 " indicating that the packet is inbound or outbound.\n"
1408 " This is only stored if the output format is PCAP-NG.\n"
1409 " -a enable ASCII text dump identification.\n"
1410 " The start of the ASCII text dump can be identified\n"
1411 " and excluded from the packet data, even if it looks\n"
1412 " like a HEX dump.\n"
1413 " NOTE: Do not enable it if the input file does not\n"
1414 " contain the ASCII text dump.\n"
1417 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1418 " http://www.tcpdump.org/linktypes.html for a list of\n"
1419 " numbers. Use this option if your dump is a complete\n"
1420 " hex dump of an encapsulated packet and you wish to\n"
1421 " specify the exact type of encapsulation.\n"
1422 " Example: -l 7 for ARCNet packets.\n"
1423 " -m <max-packet> max packet length in output; default is %d\n"
1425 "Prepend dummy header:\n"
1426 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1428 " Example: -e 0x806 to specify an ARP packet.\n"
1429 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1431 " Automatically prepends Ethernet header as well.\n"
1433 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1434 " dest and source address.\n"
1435 " Example: -4 10.0.0.1,10.0.0.2\n"
1436 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1437 " dest and source address.\n"
1438 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1439 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1440 " source and destination ports (in DECIMAL).\n"
1441 " Automatically prepends Ethernet & IP headers as well.\n"
1442 " Example: -u 1000,69 to make the packets look like\n"
1443 " TFTP/UDP packets.\n"
1444 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1445 " source and destination ports (in DECIMAL).\n"
1446 " Automatically prepends Ethernet & IP headers as well.\n"
1447 " Example: -T 50,60\n"
1448 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1449 " source/dest ports and verification tag (in DECIMAL).\n"
1450 " Automatically prepends Ethernet & IP headers as well.\n"
1451 " Example: -s 30,40,34\n"
1452 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1453 " source/dest ports and verification tag 0.\n"
1454 " Automatically prepends a dummy SCTP DATA\n"
1455 " chunk header with payload protocol identifier ppi.\n"
1456 " Example: -S 30,40,34\n"
1459 " -h display this help and exit.\n"
1460 " -d show detailed debug of parser states.\n"
1461 " -q generate no output at all (automatically disables -d).\n"
1462 " -n use PCAP-NG instead of PCAP as output format.\n"
1468 get_text2pcap_compiled_info(GString *str)
1471 g_string_append(str, ", ");
1473 g_string_append(str, "with libz ");
1475 g_string_append(str, ZLIB_VERSION);
1476 #else /* ZLIB_VERSION */
1477 g_string_append(str, "(version unknown)");
1478 #endif /* ZLIB_VERSION */
1479 #else /* HAVE_LIBZ */
1480 g_string_append(str, "without libz");
1481 #endif /* HAVE_LIBZ */
1485 get_text2pcap_runtime_info(GString *str)
1488 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1489 g_string_append_printf(str, ", with libz %s", zlibVersion());
1493 /*----------------------------------------------------------------------
1497 parse_options (int argc, char *argv[])
1499 GString *comp_info_str;
1500 GString *runtime_info_str;
1503 static const struct option long_options[] = {
1504 {"help", no_argument, NULL, 'h'},
1505 {"version", no_argument, NULL, 'v'},
1510 arg_list_utf_16to8(argc, argv);
1511 create_app_running_mutex();
1514 /* Get the compile-time version information string */
1515 comp_info_str = get_compiled_version_info(NULL, get_text2pcap_compiled_info);
1517 /* get the run-time version information string */
1518 runtime_info_str = get_runtime_version_info(get_text2pcap_runtime_info);
1520 /* Add it to the information to be reported on a crash. */
1521 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1526 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1528 /* Scan CLI parameters */
1529 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1532 printf("Text2pcap (Wireshark) %s\n"
1533 "Generate a capture file from an ASCII hexdump of packets.\n"
1534 "See https://www.wireshark.org for more information.\n",
1535 get_ws_vcs_version_info());
1536 print_usage(stdout);
1539 case 'd': if (!quiet) debug++; break;
1540 case 'D': has_direction = TRUE; break;
1541 case 'q': quiet = TRUE; debug = FALSE; break;
1542 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1543 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1544 case 'n': use_pcapng = TRUE; break;
1546 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1547 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1548 print_usage(stderr);
1551 switch (optarg[0]) {
1552 case 'o': offset_base = 8; break;
1553 case 'h': offset_base = 16; break;
1554 case 'd': offset_base = 10; break;
1558 hdr_ethernet = TRUE;
1559 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1560 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1561 print_usage(stderr);
1568 hdr_ip_proto = strtol(optarg, &p, 10);
1569 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1570 hdr_ip_proto > 255) {
1571 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1572 print_usage(stderr);
1575 hdr_ethernet = TRUE;
1576 hdr_ethernet_proto = 0x800;
1581 hdr_data_chunk = FALSE;
1584 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1585 if (p == optarg || (*p != ',' && *p != '\0')) {
1586 fprintf(stderr, "Bad src port for '-%c'\n", c);
1587 print_usage(stderr);
1591 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1592 print_usage(stderr);
1597 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1598 if (p == optarg || (*p != ',' && *p != '\0')) {
1599 fprintf(stderr, "Bad dest port for '-s'\n");
1600 print_usage(stderr);
1604 fprintf(stderr, "No tag specified for '-%c'\n", c);
1605 print_usage(stderr);
1610 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1611 if (p == optarg || *p != '\0') {
1612 fprintf(stderr, "Bad tag for '-%c'\n", c);
1613 print_usage(stderr);
1619 hdr_ethernet = TRUE;
1620 hdr_ethernet_proto = 0x800;
1624 hdr_data_chunk = TRUE;
1627 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1628 if (p == optarg || (*p != ',' && *p != '\0')) {
1629 fprintf(stderr, "Bad src port for '-%c'\n", c);
1630 print_usage(stderr);
1634 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1635 print_usage(stderr);
1640 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1641 if (p == optarg || (*p != ',' && *p != '\0')) {
1642 fprintf(stderr, "Bad dest port for '-s'\n");
1643 print_usage(stderr);
1647 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1648 print_usage(stderr);
1653 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1654 if (p == optarg || *p != '\0') {
1655 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1656 print_usage(stderr);
1662 hdr_ethernet = TRUE;
1663 hdr_ethernet_proto = 0x800;
1674 hdr_data_chunk = FALSE;
1675 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1676 if (p == optarg || (*p != ',' && *p != '\0')) {
1677 fprintf(stderr, "Bad src port for '-u'\n");
1678 print_usage(stderr);
1682 fprintf(stderr, "No dest port specified for '-u'\n");
1683 print_usage(stderr);
1688 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1689 if (p == optarg || *p != '\0') {
1690 fprintf(stderr, "Bad dest port for '-u'\n");
1691 print_usage(stderr);
1696 hdr_ethernet = TRUE;
1697 hdr_ethernet_proto = 0x800;
1704 hdr_data_chunk = FALSE;
1705 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1706 if (p == optarg || (*p != ',' && *p != '\0')) {
1707 fprintf(stderr, "Bad src port for '-T'\n");
1708 print_usage(stderr);
1712 fprintf(stderr, "No dest port specified for '-u'\n");
1713 print_usage(stderr);
1718 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1719 if (p == optarg || *p != '\0') {
1720 fprintf(stderr, "Bad dest port for '-T'\n");
1721 print_usage(stderr);
1726 hdr_ethernet = TRUE;
1727 hdr_ethernet_proto = 0x800;
1731 identify_ascii = TRUE;
1735 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1736 g_string_free(comp_info_str, TRUE);
1737 g_string_free(runtime_info_str, TRUE);
1743 p = strchr(optarg, ',');
1746 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1747 print_usage(stderr);
1755 hdr_ethernet_proto = 0x86DD;
1760 hdr_ethernet_proto = 0x800;
1762 hdr_ethernet = TRUE;
1764 if (hdr_ipv6 == TRUE) {
1765 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1766 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1767 print_usage(stderr);
1771 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1772 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1773 print_usage(stderr);
1780 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1781 print_usage(stderr);
1785 if (hdr_ipv6 == TRUE) {
1786 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1787 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1788 print_usage(stderr);
1792 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1793 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1794 print_usage(stderr);
1803 print_usage(stderr);
1808 if (optind >= argc || argc-optind < 2) {
1809 fprintf(stderr, "Must specify input and output filename\n");
1810 print_usage(stderr);
1814 if (strcmp(argv[optind], "-")) {
1815 input_filename = g_strdup(argv[optind]);
1816 input_file = ws_fopen(input_filename, "rb");
1818 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1819 input_filename, g_strerror(errno));
1823 input_filename = "Standard input";
1827 if (strcmp(argv[optind+1], "-")) {
1828 output_filename = g_strdup(argv[optind+1]);
1829 output_file = ws_fopen(output_filename, "wb");
1831 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1832 output_filename, g_strerror(errno));
1836 output_filename = "Standard output";
1837 output_file = stdout;
1840 /* Some validation */
1841 if (pcap_link_type != 1 && hdr_ethernet) {
1842 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1846 /* Set up our variables */
1849 input_filename = "Standard input";
1852 output_file = stdout;
1853 output_filename = "Standard output";
1856 ts_sec = time(0); /* initialize to current time */
1857 timecode_default = *localtime(&ts_sec);
1858 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1860 /* Display summary of our state */
1862 fprintf(stderr, "Input from: %s\n", input_filename);
1863 fprintf(stderr, "Output to: %s\n", output_filename);
1864 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1866 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1867 hdr_ethernet_proto);
1868 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1870 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1871 hdr_src_port, hdr_dest_port);
1872 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1873 hdr_src_port, hdr_dest_port);
1874 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1875 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1876 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1877 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1882 main(int argc, char *argv[])
1884 parse_options(argc, argv);
1886 assert(input_file != NULL);
1887 assert(output_file != NULL);
1889 write_file_header();
1893 header_length += (int)sizeof(HDR_ETHERNET);
1896 ip_offset = header_length;
1897 header_length += (int)sizeof(HDR_IP);
1898 } else if (hdr_ipv6) {
1899 ip_offset = header_length;
1900 header_length += (int)sizeof(HDR_IPv6);
1903 header_length += (int)sizeof(HDR_SCTP);
1905 if (hdr_data_chunk) {
1906 header_length += (int)sizeof(HDR_DATA_CHUNK);
1909 header_length += (int)sizeof(HDR_TCP);
1912 header_length += (int)sizeof(HDR_UDP);
1914 curr_offset = header_length;
1919 write_current_packet(FALSE);
1921 fclose(output_file);
1923 fprintf(stderr, "\n-------------------------\n");
1925 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1926 num_packets_read, (num_packets_read == 1) ? "" : "s",
1927 num_packets_written, (num_packets_written == 1) ? "" : "s",
1928 bytes_written, (bytes_written == 1) ? "" : "s");
1934 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1939 * indent-tabs-mode: nil
1942 * vi: set shiftwidth=4 tabstop=8 expandtab:
1943 * :indentSize=4:tabSize=8:noTabs=true: