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__
114 #include <wsutil/file_util.h>
127 #include "wsutil/wsgetopt.h"
130 #ifdef NEED_STRPTIME_H
131 # include "wsutil/strptime.h"
135 #include "text2pcap.h"
139 #include <wsutil/unicode-utils.h>
142 #ifdef HAVE_ARPA_INET_H
143 #include <arpa/inet.h>
146 #ifdef HAVE_WINSOCK2_H
147 #include <winsock2.h> /* needed to define AF_ values on Windows */
150 #ifndef HAVE_INET_ATON_H
151 # include "wsutil/inet_aton.h"
154 #ifdef HAVE_SYS_SOCKET_H
155 #include <sys/socket.h>
158 #ifdef NEED_INET_V6DEFS_H
159 # include "wsutil/inet_v6defs.h"
162 /*--- Options --------------------------------------------------------------------*/
165 static gboolean use_pcapng = FALSE;
168 static int debug = 0;
170 static int quiet = FALSE;
172 /* Dummy Ethernet header */
173 static int hdr_ethernet = FALSE;
174 static guint32 hdr_ethernet_proto = 0;
176 /* Dummy IP header */
177 static int hdr_ip = FALSE;
178 static int hdr_ipv6 = FALSE;
179 static long hdr_ip_proto = 0;
181 /* Destination and source addresses for IP header */
182 static guint32 hdr_ip_dest_addr = 0;
183 static guint32 hdr_ip_src_addr = 0;
184 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
185 static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
186 static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
188 /* Dummy UDP header */
189 static int hdr_udp = FALSE;
190 static guint32 hdr_dest_port = 0;
191 static guint32 hdr_src_port = 0;
193 /* Dummy TCP header */
194 static int hdr_tcp = FALSE;
196 /* Dummy SCTP header */
197 static int hdr_sctp = FALSE;
198 static guint32 hdr_sctp_src = 0;
199 static guint32 hdr_sctp_dest = 0;
200 static guint32 hdr_sctp_tag = 0;
202 /* Dummy DATA chunk header */
203 static int hdr_data_chunk = FALSE;
204 static guint8 hdr_data_chunk_type = 0;
205 static guint8 hdr_data_chunk_bits = 0;
206 static guint32 hdr_data_chunk_tsn = 0;
207 static guint16 hdr_data_chunk_sid = 0;
208 static guint16 hdr_data_chunk_ssn = 0;
209 static guint32 hdr_data_chunk_ppid = 0;
211 /* ASCII text dump identification */
212 static int identify_ascii = FALSE;
214 static gboolean has_direction = FALSE;
215 static guint32 direction = 0;
217 /*--- Local date -----------------------------------------------------------------*/
219 /* This is where we store the packet currently being built */
220 #define MAX_PACKET 65535
221 static guint8 packet_buf[MAX_PACKET];
222 static guint32 header_length;
223 static guint32 ip_offset;
224 static guint32 curr_offset;
225 static guint32 max_offset = MAX_PACKET;
226 static guint32 packet_start = 0;
228 static void start_new_packet(gboolean);
230 /* This buffer contains strings present before the packet offset 0 */
231 #define PACKET_PREAMBLE_MAX_LEN 2048
232 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
233 static int packet_preamble_len = 0;
235 /* Number of packets read and written */
236 static guint32 num_packets_read = 0;
237 static guint32 num_packets_written = 0;
238 static guint64 bytes_written = 0;
240 /* Time code of packet, derived from packet_preamble */
241 static time_t ts_sec = 0;
242 static guint32 ts_usec = 0;
243 static char *ts_fmt = NULL;
244 static struct tm timecode_default;
246 static guint8* pkt_lnstart;
249 static const char *input_filename;
250 static FILE *input_file = NULL;
252 static const char *output_filename;
253 static FILE *output_file = NULL;
255 /* Offset base to parse */
256 static guint32 offset_base = 16;
260 /* ----- State machine -----------------------------------------------------------*/
262 /* Current state of parser */
264 INIT, /* Waiting for start of new packet */
265 START_OF_LINE, /* Starting from beginning of line */
266 READ_OFFSET, /* Just read the offset */
267 READ_BYTE, /* Just read a byte */
268 READ_TEXT /* Just read text - ignore until EOL */
270 static parser_state_t state = INIT;
272 static const char *state_str[] = {"Init",
279 static const char *token_str[] = {"",
287 /* ----- Skeleton Packet Headers --------------------------------------------------*/
295 static hdr_ethernet_t HDR_ETHERNET = {
296 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
297 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
303 guint16 packet_length;
304 guint16 identification;
309 guint16 hdr_checksum;
314 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
315 #ifdef WORDS_BIGENDIAN
316 0x0a010101, 0x0a020202
318 0x0101010a, 0x0202020a
322 static struct { /* pseudo header for checksum calculation */
331 /* headers taken from glibc */
338 guint8 __u6_addr8[16];
339 guint16 __u6_addr16[8];
340 guint32 __u6_addr32[4];
347 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
348 guint16 ip6_un1_plen; /* payload length */
349 guint8 ip6_un1_nxt; /* next header */
350 guint8 ip6_un1_hlim; /* hop limit */
352 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
354 struct hdr_in6_addr ip6_src; /* source address */
355 struct hdr_in6_addr ip6_dst; /* destination address */
358 static hdr_ipv6_t HDR_IPv6;
360 static struct { /* pseudo header ipv6 for checksum calculation */
361 struct hdr_in6_addr src_addr6;
362 struct hdr_in6_addr dst_addr6;
375 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
389 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
398 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
410 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
412 static char tempbuf[64];
414 /*----------------------------------------------------------------------
415 * Stuff for writing a PCap file
417 #define PCAP_MAGIC 0xa1b2c3d4
418 #define PCAP_SNAPLEN 0xffff
420 /* "libpcap" file header (minus magic number). */
422 guint32 magic; /* magic */
423 guint16 version_major; /* major version number */
424 guint16 version_minor; /* minor version number */
425 guint32 thiszone; /* GMT to local correction */
426 guint32 sigfigs; /* accuracy of timestamps */
427 guint32 snaplen; /* max length of captured packets, in octets */
428 guint32 network; /* data link type */
431 /* "libpcap" record header. */
433 guint32 ts_sec; /* timestamp seconds */
434 guint32 ts_usec; /* timestamp microseconds */
435 guint32 incl_len; /* number of octets of packet saved in file */
436 guint32 orig_len; /* actual length of packet */
439 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
440 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
442 /*----------------------------------------------------------------------
443 * Parse a single hex number
444 * Will abort the program if it can't parse the number
445 * Pass in TRUE if this is an offset, FALSE if not
448 parse_num (const char *str, int offset)
453 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
455 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
461 /*----------------------------------------------------------------------
462 * Write this byte into current packet
465 write_byte (const char *str)
469 num = parse_num(str, FALSE);
470 packet_buf[curr_offset] = (guint8) num;
472 if (curr_offset - header_length >= max_offset) /* packet full */
473 start_new_packet(TRUE);
476 /*----------------------------------------------------------------------
477 * Write a number of bytes into current packet
481 write_bytes (const char bytes[], guint32 nbytes)
485 if (curr_offset + nbytes < MAX_PACKET) {
486 for (i = 0; i < nbytes; i++) {
487 packet_buf[curr_offset] = bytes[i];
493 /*----------------------------------------------------------------------
494 * Remove bytes from the current packet
497 unwrite_bytes (guint32 nbytes)
499 curr_offset -= nbytes;
502 /*----------------------------------------------------------------------
503 * Compute one's complement checksum (from RFC1071)
506 in_checksum (void *buf, guint32 count)
509 guint16 *addr = (guint16 *)buf;
512 /* This is the inner loop */
513 sum += g_ntohs(* (guint16 *) addr);
518 /* Add left-over byte, if any */
520 sum += g_ntohs(* (guint8 *) addr);
522 /* Fold 32-bit sum to 16 bits */
524 sum = (sum & 0xffff) + (sum >> 16);
530 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
531 * That code is copyrighted by D. Otis and has been modified.
534 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
535 static guint32 crc_c[256] =
537 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
538 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
539 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
540 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
541 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
542 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
543 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
544 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
545 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
546 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
547 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
548 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
549 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
550 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
551 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
552 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
553 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
554 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
555 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
556 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
557 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
558 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
559 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
560 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
561 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
562 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
563 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
564 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
565 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
566 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
567 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
568 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
569 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
570 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
571 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
572 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
573 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
574 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
575 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
576 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
577 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
578 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
579 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
580 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
581 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
582 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
583 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
584 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
585 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
586 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
587 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
588 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
589 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
590 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
591 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
592 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
593 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
594 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
595 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
596 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
597 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
598 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
599 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
600 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
604 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
610 for (i = 0; i < len; i++)
611 CRC32C(crc32, buf[i]);
617 finalize_crc32c (guint32 crc32)
620 guint8 byte0,byte1,byte2,byte3;
623 byte0 = result & 0xff;
624 byte1 = (result>>8) & 0xff;
625 byte2 = (result>>16) & 0xff;
626 byte3 = (result>>24) & 0xff;
627 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
632 number_of_padding_bytes (guint32 length)
636 remainder = length % 4;
641 return 4 - remainder;
644 /*----------------------------------------------------------------------
645 * Write current packet out
648 write_current_packet (gboolean cont)
651 guint16 padding_length = 0;
656 if (curr_offset > header_length) {
657 /* Write the packet */
659 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
661 hdr_ethernet_proto = 0x86DD;
665 /* Compute packet length */
666 length = curr_offset;
668 padding_length = number_of_padding_bytes(length - header_length );
672 /* Reset curr_offset, since we now write the headers */
675 /* Write Ethernet header */
677 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
678 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
681 /* Write IP header */
683 if (hdr_ip_src_addr) HDR_IP.src_addr = hdr_ip_src_addr;
684 if (hdr_ip_dest_addr) HDR_IP.dest_addr = hdr_ip_dest_addr;
686 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
687 HDR_IP.protocol = (guint8) hdr_ip_proto;
688 HDR_IP.hdr_checksum = 0;
689 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
690 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
691 } else if (hdr_ipv6) {
692 if (memcmp(hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
693 memcpy(&HDR_IPv6.ip6_src, &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
694 if (memcmp(hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
695 memcpy(&HDR_IPv6.ip6_dst, &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
697 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
698 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
699 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
700 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
701 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
702 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
704 /* initialize pseudo ipv6 header for checksum calculation */
705 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
706 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
708 pseudoh6.protocol = (guint8) hdr_ip_proto;
709 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
710 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
714 /* initialize pseudo header for checksum calculation */
715 pseudoh.src_addr = HDR_IP.src_addr;
716 pseudoh.dest_addr = HDR_IP.dest_addr;
718 pseudoh.protocol = (guint8) hdr_ip_proto;
719 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
722 /* Write UDP header */
727 /* initialize the UDP header */
728 HDR_UDP.source_port = g_htons(hdr_src_port);
729 HDR_UDP.dest_port = g_htons(hdr_dest_port);
730 HDR_UDP.length = pseudoh.length;
731 HDR_UDP.checksum = 0;
732 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
733 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
735 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
737 x16 = in_checksum(packet_buf + header_length, length - header_length);
739 x16 = (u & 0xffff) + (u>>16);
740 HDR_UDP.checksum = g_htons(x16);
741 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
742 HDR_UDP.checksum = g_htons(1);
743 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
746 /* Write TCP header */
751 /* initialize pseudo header for checksum calculation */
752 pseudoh.src_addr = HDR_IP.src_addr;
753 pseudoh.dest_addr = HDR_IP.dest_addr;
755 pseudoh.protocol = (guint8) hdr_ip_proto;
756 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
757 /* initialize the TCP header */
758 HDR_TCP.source_port = g_htons(hdr_src_port);
759 HDR_TCP.dest_port = g_htons(hdr_dest_port);
760 /* HDR_TCP.seq_num already correct */
761 HDR_TCP.window = g_htons(0x2000);
762 HDR_TCP.checksum = 0;
763 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
764 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
766 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
768 x16 = in_checksum(packet_buf + header_length, length - header_length);
770 x16 = (u & 0xffff) + (u>>16);
771 HDR_TCP.checksum = g_htons(x16);
772 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
773 HDR_TCP.checksum = g_htons(1);
774 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
775 HDR_TCP.seq_num = g_ntohl(HDR_TCP.seq_num) + length - header_length;
776 HDR_TCP.seq_num = g_htonl(HDR_TCP.seq_num);
779 /* Compute DATA chunk header */
780 if (hdr_data_chunk) {
781 hdr_data_chunk_bits = 0;
782 if (packet_start == 0) {
783 hdr_data_chunk_bits |= 0x02;
786 hdr_data_chunk_bits |= 0x01;
788 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
789 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
790 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
791 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
792 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
793 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
794 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
795 hdr_data_chunk_tsn++;
797 hdr_data_chunk_ssn++;
801 /* Write SCTP common header */
805 HDR_SCTP.src_port = g_htons(hdr_sctp_src);
806 HDR_SCTP.dest_port = g_htons(hdr_sctp_dest);
807 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
808 HDR_SCTP.checksum = g_htonl(0);
809 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
810 if (hdr_data_chunk) {
811 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
812 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
813 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
815 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
817 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
818 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
819 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
822 /* Write DATA chunk header */
823 if (hdr_data_chunk) {
824 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
827 /* Reset curr_offset, since we now write the trailers */
828 curr_offset = length;
830 /* Write DATA chunk padding */
831 if (hdr_data_chunk && (padding_length > 0)) {
832 memset(tempbuf, 0, padding_length);
833 write_bytes((const char *)&tempbuf, padding_length);
834 length += padding_length;
837 /* Write Ethernet trailer */
838 if (hdr_ethernet && (length < 60)) {
839 memset(tempbuf, 0, 60 - length);
840 write_bytes((const char *)&tempbuf, 60 - length);
844 success = pcapng_write_enhanced_packet_block(output_file,
850 packet_buf, direction,
851 &bytes_written, &err);
853 success = libpcap_write_packet(output_file,
857 &bytes_written, &err);
860 fprintf(stderr, "File write error [%s] : %s\n",
861 output_filename, g_strerror(err));
864 if (ts_fmt == NULL) {
865 /* fake packet counter */
869 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
871 num_packets_written++;
874 packet_start += curr_offset - header_length;
875 curr_offset = header_length;
879 /*----------------------------------------------------------------------
880 * Write file header and trailer
883 write_file_header (void)
890 const char *appname = "text2pcap (" GITVERSION " from " GITBRANCH ")";
892 const char *appname = "text2pcap";
896 g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
897 success = pcapng_write_session_header_block(output_file,
906 success = pcapng_write_interface_description_block(output_file,
920 success = libpcap_write_file_header(output_file, pcap_link_type, PCAP_SNAPLEN,
921 FALSE, &bytes_written, &err);
924 fprintf(stderr, "File write error [%s] : %s\n",
925 output_filename, g_strerror(err));
931 write_file_trailer (void)
937 success = pcapng_write_interface_statistics_block(output_file,
940 "Counters provided by text2pcap",
944 num_packets_written - num_packets_written,
951 fprintf(stderr, "File write error [%s] : %s\n",
952 output_filename, g_strerror(err));
958 /*----------------------------------------------------------------------
959 * Append a token to the packet preamble.
962 append_to_preamble (char *str)
966 if (packet_preamble_len != 0) {
967 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
968 return; /* no room to add more preamble */
969 /* Add a blank separator between the previous token and this token. */
970 packet_preamble[packet_preamble_len++] = ' ';
972 toklen = strlen(str);
974 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
975 return; /* no room to add the token to the preamble */
976 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
977 packet_preamble_len += (int) toklen;
980 char xs[PACKET_PREAMBLE_MAX_LEN];
981 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
982 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
983 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
988 /*----------------------------------------------------------------------
989 * Parse the preamble to get the timecode.
993 parse_preamble (void)
1002 * Null-terminate the preamble.
1004 packet_preamble[packet_preamble_len] = '\0';
1006 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1008 if (has_direction) {
1009 switch (packet_preamble[0]) {
1012 direction = 0x00000001;
1013 packet_preamble[0] = ' ';
1017 direction = 0x00000002;
1018 packet_preamble[0] = ' ';
1021 direction = 0x00000000;
1025 while (packet_preamble[i] == ' ' ||
1026 packet_preamble[i] == '\r' ||
1027 packet_preamble[i] == '\t') {
1030 packet_preamble_len -= i;
1031 /* Also move the trailing '\0'. */
1032 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1037 * If no "-t" flag was specified, don't attempt to parse the packet
1038 * preamble to extract a time stamp.
1040 if (ts_fmt == NULL) {
1041 /* Clear Preamble */
1042 packet_preamble_len = 0;
1047 * Initialize to today localtime, just in case not all fields
1048 * of the date and time are specified.
1051 timecode = timecode_default;
1054 /* Ensure preamble has more than two chars before attempting to parse.
1055 * This should cover line breaks etc that get counted.
1057 if (strlen(packet_preamble) > 2) {
1058 /* Get Time leaving subseconds */
1059 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1060 if (subsecs != NULL) {
1061 /* Get the long time from the tm structure */
1062 /* (will return -1 if failure) */
1063 ts_sec = mktime( &timecode );
1065 ts_sec = -1; /* we failed to parse it */
1067 /* This will ensure incorrectly parsed dates get set to zero */
1069 /* Sanitize - remove all '\r' */
1071 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1072 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1073 packet_preamble, ts_fmt);
1075 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1076 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1077 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1079 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1082 /* Parse subseconds */
1083 ts_usec = (guint32)strtol(subsecs, &p, 10);
1089 * Convert that number to a number
1090 * of microseconds; if it's N digits
1091 * long, it's in units of 10^(-N) seconds,
1092 * so, to convert it to units of
1093 * 10^-6 seconds, we multiply by
1096 subseclen = (int) (p - subsecs);
1097 if (subseclen > 6) {
1099 * *More* than 6 digits; 6-N is
1100 * negative, so we divide by
1103 for (i = subseclen - 6; i != 0; i--)
1105 } else if (subseclen < 6) {
1106 for (i = 6 - subseclen; i != 0; i--)
1114 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1115 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1116 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_usec);
1120 /* Clear Preamble */
1121 packet_preamble_len = 0;
1124 /*----------------------------------------------------------------------
1125 * Start a new packet
1128 start_new_packet (gboolean cont)
1131 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1133 /* Write out the current packet, if required */
1134 write_current_packet(cont);
1137 /* Ensure we parse the packet preamble as it may contain the time */
1141 /*----------------------------------------------------------------------
1142 * Process a directive
1145 process_directive (char *str)
1147 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1150 /*----------------------------------------------------------------------
1151 * Parse a single token (called from the scanner)
1154 parse_token (token_t token, char *str)
1165 * This is implemented as a simple state machine of five states.
1166 * State transitions are caused by tokens being received from the
1167 * scanner. The code should be self-documenting.
1171 /* Sanitize - remove all '\r' */
1173 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1175 fprintf(stderr, "(%s, %s \"%s\") -> (",
1176 state_str[state], token_str[token], str ? str : "");
1181 /* ----- Waiting for new packet -------------------------------------------*/
1183 if (!str && token != T_EOL) goto fail_null_str;
1186 append_to_preamble(str);
1189 process_directive(str);
1192 num = parse_num(str, TRUE);
1194 /* New packet starts here */
1195 start_new_packet(FALSE);
1196 state = READ_OFFSET;
1197 pkt_lnstart = packet_buf + num;
1201 /* Some describing text may be parsed as offset, but the invalid
1202 offset will be checked in the state of START_OF_LINE, so
1203 we add this transition to gain flexibility */
1204 state = START_OF_LINE;
1211 /* ----- Processing packet, start of new line -----------------------------*/
1213 if (!str && token != T_EOL) goto fail_null_str;
1216 append_to_preamble(str);
1219 process_directive(str);
1222 num = parse_num(str, TRUE);
1224 /* New packet starts here */
1225 start_new_packet(FALSE);
1227 state = READ_OFFSET;
1228 } else if ((num - packet_start) != curr_offset - header_length) {
1230 * The offset we read isn't the one we expected.
1231 * This may only mean that we mistakenly interpreted
1232 * some text as byte values (e.g., if the text dump
1233 * of packet data included a number with spaces around
1234 * it). If the offset is less than what we expected,
1235 * assume that's the problem, and throw away the putative
1236 * extra byte values.
1238 if (num < curr_offset) {
1239 unwrite_bytes(curr_offset - num);
1240 state = READ_OFFSET;
1242 /* Bad offset; switch to INIT state */
1244 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1246 write_current_packet(FALSE);
1250 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 (!isxdigit(tmp_str[0]) || !isxdigit(tmp_str[0])) {
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 usage (gboolean is_error)
1398 " (" GITVERSION " from " GITBRANCH ")"
1401 "Generate a capture file from an ASCII hexdump of packets.\n"
1402 "See http://www.wireshark.org for more information.\n"
1404 "Usage: text2pcap [options] <infile> <outfile>\n"
1406 "where <infile> specifies input filename (use - for standard input)\n"
1407 " <outfile> specifies output filename (use - for standard output)\n"
1410 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1411 " default is hex.\n"
1412 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1413 " the specified argument is a format string of the sort\n"
1414 " supported by strptime.\n"
1415 " Example: The time \"10:15:14.5476\" has the format code\n"
1416 " \"%%H:%%M:%%S.\"\n"
1417 " NOTE: The subsecond component delimiter, '.', must be\n"
1418 " given, but no pattern is required; the remaining\n"
1419 " number is assumed to be fractions of a second.\n"
1420 " NOTE: Date/time fields from the current date/time are\n"
1421 " used as the default for unspecified fields.\n"
1422 " -D the text before the packet starts with an I or an O,\n"
1423 " indicating that the packet is inbound or outbound.\n"
1424 " This is only stored if the output format is PCAP-NG.\n"
1425 " -a enable ASCII text dump identification.\n"
1426 " The start of the ASCII text dump can be identified\n"
1427 " and excluded from the packet data, even if it looks\n"
1428 " like a HEX dump.\n"
1429 " NOTE: Do not enable it if the input file does not\n"
1430 " contain the ASCII text dump.\n"
1433 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1434 " http://www.tcpdump.org/linktypes.html for a list of\n"
1435 " numbers. Use this option if your dump is a complete\n"
1436 " hex dump of an encapsulated packet and you wish to\n"
1437 " specify the exact type of encapsulation.\n"
1438 " Example: -l 7 for ARCNet packets.\n"
1439 " -m <max-packet> max packet length in output; default is %d\n"
1441 "Prepend dummy header:\n"
1442 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1444 " Example: -e 0x806 to specify an ARP packet.\n"
1445 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1447 " Automatically prepends Ethernet header as well.\n"
1449 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1450 " dest and source address.\n"
1451 " Example: -4 10.0.0.1,10.0.0.2\n"
1452 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1453 " dest and source address.\n"
1454 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1455 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1456 " source and destination ports (in DECIMAL).\n"
1457 " Automatically prepends Ethernet & IP headers as well.\n"
1458 " Example: -u 1000,69 to make the packets look like\n"
1459 " TFTP/UDP packets.\n"
1460 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1461 " source and destination ports (in DECIMAL).\n"
1462 " Automatically prepends Ethernet & IP headers as well.\n"
1463 " Example: -T 50,60\n"
1464 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1465 " source/dest ports and verification tag (in DECIMAL).\n"
1466 " Automatically prepends Ethernet & IP headers as well.\n"
1467 " Example: -s 30,40,34\n"
1468 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1469 " source/dest ports and verification tag 0.\n"
1470 " Automatically prepends a dummy SCTP DATA\n"
1471 " chunk header with payload protocol identifier ppi.\n"
1472 " Example: -S 30,40,34\n"
1475 " -h display this help and exit.\n"
1476 " -d show detailed debug of parser states.\n"
1477 " -q generate no output at all (automatically disables -d).\n"
1478 " -n use PCAP-NG instead of PCAP as output format.\n"
1480 VERSION, MAX_PACKET);
1482 exit(is_error ? 1 : 0);
1485 /*----------------------------------------------------------------------
1489 parse_options (int argc, char *argv[])
1495 arg_list_utf_16to8(argc, argv);
1496 create_app_running_mutex();
1499 /* Scan CLI parameters */
1500 while ((c = getopt(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:4:6:")) != -1) {
1502 case '?': usage(TRUE); break;
1503 case 'h': usage(FALSE); break;
1504 case 'd': if (!quiet) debug++; break;
1505 case 'D': has_direction = TRUE; break;
1506 case 'q': quiet = TRUE; debug = FALSE; break;
1507 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1508 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1509 case 'n': use_pcapng = TRUE; break;
1511 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1512 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1515 switch (optarg[0]) {
1516 case 'o': offset_base = 8; break;
1517 case 'h': offset_base = 16; break;
1518 case 'd': offset_base = 10; break;
1522 hdr_ethernet = TRUE;
1523 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1524 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1531 hdr_ip_proto = strtol(optarg, &p, 10);
1532 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1533 hdr_ip_proto > 255) {
1534 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1537 hdr_ethernet = TRUE;
1538 hdr_ethernet_proto = 0x800;
1543 hdr_data_chunk = FALSE;
1546 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1547 if (p == optarg || (*p != ',' && *p != '\0')) {
1548 fprintf(stderr, "Bad src port for '-%c'\n", c);
1552 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1557 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1558 if (p == optarg || (*p != ',' && *p != '\0')) {
1559 fprintf(stderr, "Bad dest port for '-s'\n");
1563 fprintf(stderr, "No tag specified for '-%c'\n", c);
1568 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1569 if (p == optarg || *p != '\0') {
1570 fprintf(stderr, "Bad tag for '-%c'\n", c);
1576 hdr_ethernet = TRUE;
1577 hdr_ethernet_proto = 0x800;
1581 hdr_data_chunk = TRUE;
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);
1590 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1595 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1596 if (p == optarg || (*p != ',' && *p != '\0')) {
1597 fprintf(stderr, "Bad dest port for '-s'\n");
1601 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1606 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1607 if (p == optarg || *p != '\0') {
1608 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1614 hdr_ethernet = TRUE;
1615 hdr_ethernet_proto = 0x800;
1626 hdr_data_chunk = FALSE;
1627 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1628 if (p == optarg || (*p != ',' && *p != '\0')) {
1629 fprintf(stderr, "Bad src port for '-u'\n");
1633 fprintf(stderr, "No dest port specified for '-u'\n");
1638 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1639 if (p == optarg || *p != '\0') {
1640 fprintf(stderr, "Bad dest port for '-u'\n");
1645 hdr_ethernet = TRUE;
1646 hdr_ethernet_proto = 0x800;
1653 hdr_data_chunk = FALSE;
1654 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1655 if (p == optarg || (*p != ',' && *p != '\0')) {
1656 fprintf(stderr, "Bad src port for '-T'\n");
1660 fprintf(stderr, "No dest port specified for '-u'\n");
1665 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1666 if (p == optarg || *p != '\0') {
1667 fprintf(stderr, "Bad dest port for '-T'\n");
1672 hdr_ethernet = TRUE;
1673 hdr_ethernet_proto = 0x800;
1677 identify_ascii = TRUE;
1682 p = strchr(optarg, ',');
1685 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1693 hdr_ethernet_proto = 0x86DD;
1698 hdr_ethernet_proto = 0x800;
1700 hdr_ethernet = TRUE;
1702 if (hdr_ipv6 == TRUE) {
1703 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1704 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1708 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1709 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1716 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1720 if (hdr_ipv6 == TRUE) {
1721 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1722 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1726 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1727 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1739 if (optind >= argc || argc-optind < 2) {
1740 fprintf(stderr, "Must specify input and output filename\n");
1744 if (strcmp(argv[optind], "-")) {
1745 input_filename = g_strdup(argv[optind]);
1746 input_file = ws_fopen(input_filename, "rb");
1748 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1749 input_filename, g_strerror(errno));
1753 input_filename = "Standard input";
1757 if (strcmp(argv[optind+1], "-")) {
1758 output_filename = g_strdup(argv[optind+1]);
1759 output_file = ws_fopen(output_filename, "wb");
1761 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1762 output_filename, g_strerror(errno));
1766 output_filename = "Standard output";
1767 output_file = stdout;
1770 /* Some validation */
1771 if (pcap_link_type != 1 && hdr_ethernet) {
1772 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1776 /* Set up our variables */
1779 input_filename = "Standard input";
1782 output_file = stdout;
1783 output_filename = "Standard output";
1786 ts_sec = time(0); /* initialize to current time */
1787 timecode_default = *localtime(&ts_sec);
1788 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1790 /* Display summary of our state */
1792 fprintf(stderr, "Input from: %s\n", input_filename);
1793 fprintf(stderr, "Output to: %s\n", output_filename);
1794 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1796 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1797 hdr_ethernet_proto);
1798 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1800 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1801 hdr_src_port, hdr_dest_port);
1802 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1803 hdr_src_port, hdr_dest_port);
1804 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1805 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1806 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
1807 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1812 main(int argc, char *argv[])
1814 parse_options(argc, argv);
1816 assert(input_file != NULL);
1817 assert(output_file != NULL);
1819 write_file_header();
1823 header_length += (int)sizeof(HDR_ETHERNET);
1826 ip_offset = header_length;
1827 header_length += (int)sizeof(HDR_IP);
1828 } else if (hdr_ipv6) {
1829 ip_offset = header_length;
1830 header_length += (int)sizeof(HDR_IPv6);
1833 header_length += (int)sizeof(HDR_SCTP);
1835 if (hdr_data_chunk) {
1836 header_length += (int)sizeof(HDR_DATA_CHUNK);
1839 header_length += (int)sizeof(HDR_TCP);
1842 header_length += (int)sizeof(HDR_UDP);
1844 curr_offset = header_length;
1849 write_current_packet(FALSE);
1850 write_file_trailer();
1852 fclose(output_file);
1854 fprintf(stderr, "\n-------------------------\n");
1856 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1857 num_packets_read, (num_packets_read == 1) ? "" : "s",
1858 num_packets_written, (num_packets_written == 1) ? "" : "s",
1859 bytes_written, (bytes_written == 1) ? "" : "s");
1865 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1870 * indent-tabs-mode: nil
1873 * vi: set shiftwidth=4 tabstop=8 expandtab:
1874 * :indentSize=4:tabSize=8:noTabs=true: