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 /* TCP sequence numbers when has_direction is true */
197 static guint32 tcp_in_seq_num = 0;
198 static guint32 tcp_out_seq_num = 0;
200 /* Dummy SCTP header */
201 static int hdr_sctp = FALSE;
202 static guint32 hdr_sctp_src = 0;
203 static guint32 hdr_sctp_dest = 0;
204 static guint32 hdr_sctp_tag = 0;
206 /* Dummy DATA chunk header */
207 static int hdr_data_chunk = FALSE;
208 static guint8 hdr_data_chunk_type = 0;
209 static guint8 hdr_data_chunk_bits = 0;
210 static guint32 hdr_data_chunk_tsn = 0;
211 static guint16 hdr_data_chunk_sid = 0;
212 static guint16 hdr_data_chunk_ssn = 0;
213 static guint32 hdr_data_chunk_ppid = 0;
215 /* ASCII text dump identification */
216 static int identify_ascii = FALSE;
218 static gboolean has_direction = FALSE;
219 static guint32 direction = 0;
221 /*--- Local date -----------------------------------------------------------------*/
223 /* This is where we store the packet currently being built */
224 #define MAX_PACKET 65535
225 static guint8 packet_buf[MAX_PACKET];
226 static guint32 header_length;
227 static guint32 ip_offset;
228 static guint32 curr_offset;
229 static guint32 max_offset = MAX_PACKET;
230 static guint32 packet_start = 0;
232 static void start_new_packet(gboolean);
234 /* This buffer contains strings present before the packet offset 0 */
235 #define PACKET_PREAMBLE_MAX_LEN 2048
236 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
237 static int packet_preamble_len = 0;
239 /* Number of packets read and written */
240 static guint32 num_packets_read = 0;
241 static guint32 num_packets_written = 0;
242 static guint64 bytes_written = 0;
244 /* Time code of packet, derived from packet_preamble */
245 static time_t ts_sec = 0;
246 static guint32 ts_usec = 0;
247 static char *ts_fmt = NULL;
248 static struct tm timecode_default;
250 static guint8* pkt_lnstart;
253 static const char *input_filename;
254 static FILE *input_file = NULL;
256 static const char *output_filename;
257 static FILE *output_file = NULL;
259 /* Offset base to parse */
260 static guint32 offset_base = 16;
264 /* ----- State machine -----------------------------------------------------------*/
266 /* Current state of parser */
268 INIT, /* Waiting for start of new packet */
269 START_OF_LINE, /* Starting from beginning of line */
270 READ_OFFSET, /* Just read the offset */
271 READ_BYTE, /* Just read a byte */
272 READ_TEXT /* Just read text - ignore until EOL */
274 static parser_state_t state = INIT;
276 static const char *state_str[] = {"Init",
283 static const char *token_str[] = {"",
291 /* ----- Skeleton Packet Headers --------------------------------------------------*/
299 static hdr_ethernet_t HDR_ETHERNET = {
300 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
301 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
307 guint16 packet_length;
308 guint16 identification;
313 guint16 hdr_checksum;
318 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
319 #ifdef WORDS_BIGENDIAN
320 0x0a010101, 0x0a020202
322 0x0101010a, 0x0202020a
326 /* Fixed IP address values */
327 #ifdef WORDS_BIGENDIAN
328 #define IP_SRC 0x0a010101
329 #define IP_DST 0x0a020202
331 #define IP_SRC 0x0101010a
332 #define IP_DST 0x0202020a
335 static struct { /* pseudo header for checksum calculation */
344 /* headers taken from glibc */
351 guint8 __u6_addr8[16];
352 guint16 __u6_addr16[8];
353 guint32 __u6_addr32[4];
360 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
361 guint16 ip6_un1_plen; /* payload length */
362 guint8 ip6_un1_nxt; /* next header */
363 guint8 ip6_un1_hlim; /* hop limit */
365 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
367 struct hdr_in6_addr ip6_src; /* source address */
368 struct hdr_in6_addr ip6_dst; /* destination address */
371 static hdr_ipv6_t HDR_IPv6;
373 static struct { /* pseudo header ipv6 for checksum calculation */
374 struct hdr_in6_addr src_addr6;
375 struct hdr_in6_addr dst_addr6;
388 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
402 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
411 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
423 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
425 static char tempbuf[64];
427 /*----------------------------------------------------------------------
428 * Stuff for writing a PCap file
430 #define PCAP_MAGIC 0xa1b2c3d4
431 #define PCAP_SNAPLEN 0xffff
433 /* "libpcap" file header (minus magic number). */
435 guint32 magic; /* magic */
436 guint16 version_major; /* major version number */
437 guint16 version_minor; /* minor version number */
438 guint32 thiszone; /* GMT to local correction */
439 guint32 sigfigs; /* accuracy of timestamps */
440 guint32 snaplen; /* max length of captured packets, in octets */
441 guint32 network; /* data link type */
444 /* "libpcap" record header. */
446 guint32 ts_sec; /* timestamp seconds */
447 guint32 ts_usec; /* timestamp microseconds */
448 guint32 incl_len; /* number of octets of packet saved in file */
449 guint32 orig_len; /* actual length of packet */
452 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
453 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
455 /*----------------------------------------------------------------------
456 * Parse a single hex number
457 * Will abort the program if it can't parse the number
458 * Pass in TRUE if this is an offset, FALSE if not
461 parse_num (const char *str, int offset)
466 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
468 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
474 /*----------------------------------------------------------------------
475 * Write this byte into current packet
478 write_byte (const char *str)
482 num = parse_num(str, FALSE);
483 packet_buf[curr_offset] = (guint8) num;
485 if (curr_offset - header_length >= max_offset) /* packet full */
486 start_new_packet(TRUE);
489 /*----------------------------------------------------------------------
490 * Write a number of bytes into current packet
494 write_bytes (const char bytes[], guint32 nbytes)
498 if (curr_offset + nbytes < MAX_PACKET) {
499 for (i = 0; i < nbytes; i++) {
500 packet_buf[curr_offset] = bytes[i];
506 /*----------------------------------------------------------------------
507 * Remove bytes from the current packet
510 unwrite_bytes (guint32 nbytes)
512 curr_offset -= nbytes;
515 /*----------------------------------------------------------------------
516 * Compute one's complement checksum (from RFC1071)
519 in_checksum (void *buf, guint32 count)
522 guint16 *addr = (guint16 *)buf;
525 /* This is the inner loop */
526 sum += g_ntohs(* (guint16 *) addr);
531 /* Add left-over byte, if any */
533 sum += g_ntohs(* (guint8 *) addr);
535 /* Fold 32-bit sum to 16 bits */
537 sum = (sum & 0xffff) + (sum >> 16);
543 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
544 * That code is copyrighted by D. Otis and has been modified.
547 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
548 static guint32 crc_c[256] =
550 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
551 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
552 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
553 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
554 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
555 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
556 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
557 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
558 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
559 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
560 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
561 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
562 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
563 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
564 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
565 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
566 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
567 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
568 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
569 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
570 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
571 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
572 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
573 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
574 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
575 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
576 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
577 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
578 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
579 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
580 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
581 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
582 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
583 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
584 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
585 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
586 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
587 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
588 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
589 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
590 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
591 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
592 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
593 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
594 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
595 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
596 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
597 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
598 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
599 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
600 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
601 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
602 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
603 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
604 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
605 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
606 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
607 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
608 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
609 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
610 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
611 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
612 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
613 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
617 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
623 for (i = 0; i < len; i++)
624 CRC32C(crc32, buf[i]);
630 finalize_crc32c (guint32 crc32)
633 guint8 byte0,byte1,byte2,byte3;
636 byte0 = result & 0xff;
637 byte1 = (result>>8) & 0xff;
638 byte2 = (result>>16) & 0xff;
639 byte3 = (result>>24) & 0xff;
640 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
645 number_of_padding_bytes (guint32 length)
649 remainder = length % 4;
654 return 4 - remainder;
657 /*----------------------------------------------------------------------
658 * Write current packet out
661 write_current_packet (gboolean cont)
664 guint16 padding_length = 0;
669 if (curr_offset > header_length) {
670 /* Write the packet */
672 /* Is direction indication on with an inbound packet? */
673 gboolean isInbound = has_direction && (direction == 2);
675 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
677 hdr_ethernet_proto = 0x86DD;
681 /* Compute packet length */
682 length = curr_offset;
684 padding_length = number_of_padding_bytes(length - header_length );
688 /* Reset curr_offset, since we now write the headers */
691 /* Write Ethernet header */
693 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
694 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
697 /* Write IP header */
700 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
701 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
704 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
705 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
708 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
709 HDR_IP.protocol = (guint8) hdr_ip_proto;
710 HDR_IP.hdr_checksum = 0;
711 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
712 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
713 } else if (hdr_ipv6) {
714 if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
715 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
716 if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
717 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
719 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
720 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
721 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
722 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
723 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
724 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
726 /* initialize pseudo ipv6 header for checksum calculation */
727 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
728 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
730 pseudoh6.protocol = (guint8) hdr_ip_proto;
731 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
732 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
736 /* initialize pseudo header for checksum calculation */
737 pseudoh.src_addr = HDR_IP.src_addr;
738 pseudoh.dest_addr = HDR_IP.dest_addr;
740 pseudoh.protocol = (guint8) hdr_ip_proto;
741 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
744 /* Write UDP header */
749 /* initialize the UDP header */
750 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
751 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
752 HDR_UDP.length = pseudoh.length;
753 HDR_UDP.checksum = 0;
754 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
755 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
757 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
759 x16 = in_checksum(packet_buf + header_length, length - header_length);
761 x16 = (u & 0xffff) + (u>>16);
762 HDR_UDP.checksum = g_htons(x16);
763 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
764 HDR_UDP.checksum = g_htons(1);
765 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
768 /* Write TCP header */
773 /* initialize pseudo header for checksum calculation */
774 pseudoh.src_addr = HDR_IP.src_addr;
775 pseudoh.dest_addr = HDR_IP.dest_addr;
777 pseudoh.protocol = (guint8) hdr_ip_proto;
778 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
779 /* initialize the TCP header */
780 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
781 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
782 /* set ack number if we have direction */
784 HDR_TCP.flags = 0x10;
785 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
786 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
792 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
793 HDR_TCP.window = g_htons(0x2000);
794 HDR_TCP.checksum = 0;
795 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
796 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
798 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
800 x16 = in_checksum(packet_buf + header_length, length - header_length);
802 x16 = (u & 0xffff) + (u>>16);
803 HDR_TCP.checksum = g_htons(x16);
804 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
805 HDR_TCP.checksum = g_htons(1);
806 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
808 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
809 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
812 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
813 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
817 /* Compute DATA chunk header */
818 if (hdr_data_chunk) {
819 hdr_data_chunk_bits = 0;
820 if (packet_start == 0) {
821 hdr_data_chunk_bits |= 0x02;
824 hdr_data_chunk_bits |= 0x01;
826 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
827 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
828 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
829 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
830 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
831 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
832 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
833 hdr_data_chunk_tsn++;
835 hdr_data_chunk_ssn++;
839 /* Write SCTP common header */
843 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
844 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
845 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
846 HDR_SCTP.checksum = g_htonl(0);
847 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
848 if (hdr_data_chunk) {
849 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
850 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
851 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
853 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
855 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
856 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
857 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
860 /* Write DATA chunk header */
861 if (hdr_data_chunk) {
862 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
865 /* Reset curr_offset, since we now write the trailers */
866 curr_offset = length;
868 /* Write DATA chunk padding */
869 if (hdr_data_chunk && (padding_length > 0)) {
870 memset(tempbuf, 0, padding_length);
871 write_bytes((const char *)&tempbuf, padding_length);
872 length += padding_length;
875 /* Write Ethernet trailer */
876 if (hdr_ethernet && (length < 60)) {
877 memset(tempbuf, 0, 60 - length);
878 write_bytes((const char *)&tempbuf, 60 - length);
882 success = pcapng_write_enhanced_packet_block(output_file,
888 packet_buf, direction,
889 &bytes_written, &err);
891 success = libpcap_write_packet(output_file,
895 &bytes_written, &err);
898 fprintf(stderr, "File write error [%s] : %s\n",
899 output_filename, g_strerror(err));
902 if (ts_fmt == NULL) {
903 /* fake packet counter */
907 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
909 num_packets_written++;
912 packet_start += curr_offset - header_length;
913 curr_offset = header_length;
917 /*----------------------------------------------------------------------
918 * Write file header and trailer
921 write_file_header (void)
928 const char *appname = "text2pcap (" GITVERSION " from " GITBRANCH ")";
930 const char *appname = "text2pcap";
934 g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
935 success = pcapng_write_session_header_block(output_file,
944 success = pcapng_write_interface_description_block(output_file,
958 success = libpcap_write_file_header(output_file, pcap_link_type, PCAP_SNAPLEN,
959 FALSE, &bytes_written, &err);
962 fprintf(stderr, "File write error [%s] : %s\n",
963 output_filename, g_strerror(err));
969 write_file_trailer (void)
975 success = pcapng_write_interface_statistics_block(output_file,
978 "Counters provided by text2pcap",
982 num_packets_written - num_packets_written,
989 fprintf(stderr, "File write error [%s] : %s\n",
990 output_filename, g_strerror(err));
996 /*----------------------------------------------------------------------
997 * Append a token to the packet preamble.
1000 append_to_preamble (char *str)
1004 if (packet_preamble_len != 0) {
1005 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1006 return; /* no room to add more preamble */
1007 /* Add a blank separator between the previous token and this token. */
1008 packet_preamble[packet_preamble_len++] = ' ';
1010 toklen = strlen(str);
1012 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1013 return; /* no room to add the token to the preamble */
1014 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1015 packet_preamble_len += (int) toklen;
1018 char xs[PACKET_PREAMBLE_MAX_LEN];
1019 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1020 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1021 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1026 /*----------------------------------------------------------------------
1027 * Parse the preamble to get the timecode.
1031 parse_preamble (void)
1040 * Null-terminate the preamble.
1042 packet_preamble[packet_preamble_len] = '\0';
1044 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1046 if (has_direction) {
1047 switch (packet_preamble[0]) {
1050 direction = 0x00000001;
1051 packet_preamble[0] = ' ';
1055 direction = 0x00000002;
1056 packet_preamble[0] = ' ';
1059 direction = 0x00000000;
1063 while (packet_preamble[i] == ' ' ||
1064 packet_preamble[i] == '\r' ||
1065 packet_preamble[i] == '\t') {
1068 packet_preamble_len -= i;
1069 /* Also move the trailing '\0'. */
1070 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1075 * If no "-t" flag was specified, don't attempt to parse the packet
1076 * preamble to extract a time stamp.
1078 if (ts_fmt == NULL) {
1079 /* Clear Preamble */
1080 packet_preamble_len = 0;
1085 * Initialize to today localtime, just in case not all fields
1086 * of the date and time are specified.
1089 timecode = timecode_default;
1092 /* Ensure preamble has more than two chars before attempting to parse.
1093 * This should cover line breaks etc that get counted.
1095 if (strlen(packet_preamble) > 2) {
1096 /* Get Time leaving subseconds */
1097 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1098 if (subsecs != NULL) {
1099 /* Get the long time from the tm structure */
1100 /* (will return -1 if failure) */
1101 ts_sec = mktime( &timecode );
1103 ts_sec = -1; /* we failed to parse it */
1105 /* This will ensure incorrectly parsed dates get set to zero */
1107 /* Sanitize - remove all '\r' */
1109 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1110 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1111 packet_preamble, ts_fmt);
1113 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1114 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1115 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1117 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1120 /* Parse subseconds */
1121 ts_usec = (guint32)strtol(subsecs, &p, 10);
1127 * Convert that number to a number
1128 * of microseconds; if it's N digits
1129 * long, it's in units of 10^(-N) seconds,
1130 * so, to convert it to units of
1131 * 10^-6 seconds, we multiply by
1134 subseclen = (int) (p - subsecs);
1135 if (subseclen > 6) {
1137 * *More* than 6 digits; 6-N is
1138 * negative, so we divide by
1141 for (i = subseclen - 6; i != 0; i--)
1143 } else if (subseclen < 6) {
1144 for (i = 6 - subseclen; i != 0; i--)
1152 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1153 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1154 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_usec);
1158 /* Clear Preamble */
1159 packet_preamble_len = 0;
1162 /*----------------------------------------------------------------------
1163 * Start a new packet
1166 start_new_packet (gboolean cont)
1169 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1171 /* Write out the current packet, if required */
1172 write_current_packet(cont);
1175 /* Ensure we parse the packet preamble as it may contain the time */
1179 /*----------------------------------------------------------------------
1180 * Process a directive
1183 process_directive (char *str)
1185 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1188 /*----------------------------------------------------------------------
1189 * Parse a single token (called from the scanner)
1192 parse_token (token_t token, char *str)
1203 * This is implemented as a simple state machine of five states.
1204 * State transitions are caused by tokens being received from the
1205 * scanner. The code should be self-documenting.
1209 /* Sanitize - remove all '\r' */
1211 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1213 fprintf(stderr, "(%s, %s \"%s\") -> (",
1214 state_str[state], token_str[token], str ? str : "");
1219 /* ----- Waiting for new packet -------------------------------------------*/
1221 if (!str && token != T_EOL) goto fail_null_str;
1224 append_to_preamble(str);
1227 process_directive(str);
1230 num = parse_num(str, TRUE);
1232 /* New packet starts here */
1233 start_new_packet(FALSE);
1234 state = READ_OFFSET;
1235 pkt_lnstart = packet_buf + num;
1239 /* Some describing text may be parsed as offset, but the invalid
1240 offset will be checked in the state of START_OF_LINE, so
1241 we add this transition to gain flexibility */
1242 state = START_OF_LINE;
1249 /* ----- Processing packet, start of new line -----------------------------*/
1251 if (!str && token != T_EOL) goto fail_null_str;
1254 append_to_preamble(str);
1257 process_directive(str);
1260 num = parse_num(str, TRUE);
1262 /* New packet starts here */
1263 start_new_packet(FALSE);
1265 state = READ_OFFSET;
1266 } else if ((num - packet_start) != curr_offset - header_length) {
1268 * The offset we read isn't the one we expected.
1269 * This may only mean that we mistakenly interpreted
1270 * some text as byte values (e.g., if the text dump
1271 * of packet data included a number with spaces around
1272 * it). If the offset is less than what we expected,
1273 * assume that's the problem, and throw away the putative
1274 * extra byte values.
1276 if (num < curr_offset) {
1277 unwrite_bytes(curr_offset - num);
1278 state = READ_OFFSET;
1280 /* Bad offset; switch to INIT state */
1282 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1284 write_current_packet(FALSE);
1288 state = READ_OFFSET;
1289 pkt_lnstart = packet_buf + num;
1292 state = START_OF_LINE;
1299 /* ----- Processing packet, read offset -----------------------------------*/
1303 /* Record the byte */
1305 if (!str) goto fail_null_str;
1314 state = START_OF_LINE;
1321 /* ----- Processing packet, read byte -------------------------------------*/
1325 /* Record the byte */
1334 if (token == T_EOL) {
1336 state = START_OF_LINE;
1338 if (identify_ascii) {
1339 /* Here a line of pkt bytes reading is finished
1340 compare the ascii and hex to avoid such situation:
1341 "61 62 20 ab ", when ab is ascii dump then it should
1342 not be treat as byte */
1344 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1345 s2 = "ab ", s1 = "616220"
1346 we should find out the largest tail of s1 matches the head
1347 of s2, it means the matched part in tail is the ASCII dump
1348 of the head byte. These matched should be rollback */
1349 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1350 s2 = (char*)g_malloc((line_size+1)/4+1);
1351 /* gather the possible pattern */
1352 for (i = 0; i < (line_size+1)/4; i++) {
1353 tmp_str[0] = pkt_lnstart[i*3];
1354 tmp_str[1] = pkt_lnstart[i*3+1];
1356 /* it is a valid convertable string */
1357 if (!isxdigit(tmp_str[0]) || !isxdigit(tmp_str[0])) {
1360 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1362 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1363 if (!(pkt_lnstart[i*3+2] == ' ')) {
1369 /* If packet line start contains possible byte pattern, the line end
1370 should contain the matched pattern if the user open the -a flag.
1371 The packet will be possible invalid if the byte pattern cannot find
1372 a matched one in the line of packet buffer.*/
1374 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1375 unwrite_bytes(rollback);
1377 /* Not matched. This line contains invalid packet bytes, so
1378 discard the whole line */
1380 unwrite_bytes(line_size);
1391 /* ----- Processing packet, read text -------------------------------------*/
1395 state = START_OF_LINE;
1403 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1408 fprintf(stderr, ", %s)\n", state_str[state]);
1413 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1418 /*----------------------------------------------------------------------
1419 * Print usage string and exit
1422 usage (gboolean is_error)
1436 " (" GITVERSION " from " GITBRANCH ")"
1439 "Generate a capture file from an ASCII hexdump of packets.\n"
1440 "See http://www.wireshark.org for more information.\n"
1442 "Usage: text2pcap [options] <infile> <outfile>\n"
1444 "where <infile> specifies input filename (use - for standard input)\n"
1445 " <outfile> specifies output filename (use - for standard output)\n"
1448 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1449 " default is hex.\n"
1450 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1451 " the specified argument is a format string of the sort\n"
1452 " supported by strptime.\n"
1453 " Example: The time \"10:15:14.5476\" has the format code\n"
1454 " \"%%H:%%M:%%S.\"\n"
1455 " NOTE: The subsecond component delimiter, '.', must be\n"
1456 " given, but no pattern is required; the remaining\n"
1457 " number is assumed to be fractions of a second.\n"
1458 " NOTE: Date/time fields from the current date/time are\n"
1459 " used as the default for unspecified fields.\n"
1460 " -D the text before the packet starts with an I or an O,\n"
1461 " indicating that the packet is inbound or outbound.\n"
1462 " This is only stored if the output format is PCAP-NG.\n"
1463 " -a enable ASCII text dump identification.\n"
1464 " The start of the ASCII text dump can be identified\n"
1465 " and excluded from the packet data, even if it looks\n"
1466 " like a HEX dump.\n"
1467 " NOTE: Do not enable it if the input file does not\n"
1468 " contain the ASCII text dump.\n"
1471 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1472 " http://www.tcpdump.org/linktypes.html for a list of\n"
1473 " numbers. Use this option if your dump is a complete\n"
1474 " hex dump of an encapsulated packet and you wish to\n"
1475 " specify the exact type of encapsulation.\n"
1476 " Example: -l 7 for ARCNet packets.\n"
1477 " -m <max-packet> max packet length in output; default is %d\n"
1479 "Prepend dummy header:\n"
1480 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1482 " Example: -e 0x806 to specify an ARP packet.\n"
1483 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1485 " Automatically prepends Ethernet header as well.\n"
1487 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1488 " dest and source address.\n"
1489 " Example: -4 10.0.0.1,10.0.0.2\n"
1490 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1491 " dest and source address.\n"
1492 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1493 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1494 " source and destination ports (in DECIMAL).\n"
1495 " Automatically prepends Ethernet & IP headers as well.\n"
1496 " Example: -u 1000,69 to make the packets look like\n"
1497 " TFTP/UDP packets.\n"
1498 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1499 " source and destination ports (in DECIMAL).\n"
1500 " Automatically prepends Ethernet & IP headers as well.\n"
1501 " Example: -T 50,60\n"
1502 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1503 " source/dest ports and verification tag (in DECIMAL).\n"
1504 " Automatically prepends Ethernet & IP headers as well.\n"
1505 " Example: -s 30,40,34\n"
1506 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1507 " source/dest ports and verification tag 0.\n"
1508 " Automatically prepends a dummy SCTP DATA\n"
1509 " chunk header with payload protocol identifier ppi.\n"
1510 " Example: -S 30,40,34\n"
1513 " -h display this help and exit.\n"
1514 " -d show detailed debug of parser states.\n"
1515 " -q generate no output at all (automatically disables -d).\n"
1516 " -n use PCAP-NG instead of PCAP as output format.\n"
1518 VERSION, MAX_PACKET);
1520 exit(is_error ? 1 : 0);
1523 /*----------------------------------------------------------------------
1527 parse_options (int argc, char *argv[])
1533 arg_list_utf_16to8(argc, argv);
1534 create_app_running_mutex();
1537 /* Scan CLI parameters */
1538 while ((c = getopt(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:4:6:")) != -1) {
1540 case '?': usage(TRUE); break;
1541 case 'h': usage(FALSE); break;
1542 case 'd': if (!quiet) debug++; break;
1543 case 'D': has_direction = TRUE; break;
1544 case 'q': quiet = TRUE; debug = FALSE; break;
1545 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1546 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1547 case 'n': use_pcapng = TRUE; break;
1549 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1550 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1553 switch (optarg[0]) {
1554 case 'o': offset_base = 8; break;
1555 case 'h': offset_base = 16; break;
1556 case 'd': offset_base = 10; break;
1560 hdr_ethernet = TRUE;
1561 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1562 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1569 hdr_ip_proto = strtol(optarg, &p, 10);
1570 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1571 hdr_ip_proto > 255) {
1572 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
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);
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 tag specified for '-%c'\n", c);
1606 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1607 if (p == optarg || *p != '\0') {
1608 fprintf(stderr, "Bad tag for '-%c'\n", c);
1614 hdr_ethernet = TRUE;
1615 hdr_ethernet_proto = 0x800;
1619 hdr_data_chunk = TRUE;
1622 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1623 if (p == optarg || (*p != ',' && *p != '\0')) {
1624 fprintf(stderr, "Bad src port for '-%c'\n", c);
1628 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1633 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1634 if (p == optarg || (*p != ',' && *p != '\0')) {
1635 fprintf(stderr, "Bad dest port for '-s'\n");
1639 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1644 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1645 if (p == optarg || *p != '\0') {
1646 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1652 hdr_ethernet = TRUE;
1653 hdr_ethernet_proto = 0x800;
1664 hdr_data_chunk = FALSE;
1665 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1666 if (p == optarg || (*p != ',' && *p != '\0')) {
1667 fprintf(stderr, "Bad src port for '-u'\n");
1671 fprintf(stderr, "No dest port specified for '-u'\n");
1676 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1677 if (p == optarg || *p != '\0') {
1678 fprintf(stderr, "Bad dest port for '-u'\n");
1683 hdr_ethernet = TRUE;
1684 hdr_ethernet_proto = 0x800;
1691 hdr_data_chunk = FALSE;
1692 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1693 if (p == optarg || (*p != ',' && *p != '\0')) {
1694 fprintf(stderr, "Bad src port for '-T'\n");
1698 fprintf(stderr, "No dest port specified for '-u'\n");
1703 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1704 if (p == optarg || *p != '\0') {
1705 fprintf(stderr, "Bad dest port for '-T'\n");
1710 hdr_ethernet = TRUE;
1711 hdr_ethernet_proto = 0x800;
1715 identify_ascii = TRUE;
1720 p = strchr(optarg, ',');
1723 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1731 hdr_ethernet_proto = 0x86DD;
1736 hdr_ethernet_proto = 0x800;
1738 hdr_ethernet = TRUE;
1740 if (hdr_ipv6 == TRUE) {
1741 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1742 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1746 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1747 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1754 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1758 if (hdr_ipv6 == TRUE) {
1759 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1760 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1764 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1765 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1777 if (optind >= argc || argc-optind < 2) {
1778 fprintf(stderr, "Must specify input and output filename\n");
1782 if (strcmp(argv[optind], "-")) {
1783 input_filename = g_strdup(argv[optind]);
1784 input_file = ws_fopen(input_filename, "rb");
1786 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1787 input_filename, g_strerror(errno));
1791 input_filename = "Standard input";
1795 if (strcmp(argv[optind+1], "-")) {
1796 output_filename = g_strdup(argv[optind+1]);
1797 output_file = ws_fopen(output_filename, "wb");
1799 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1800 output_filename, g_strerror(errno));
1804 output_filename = "Standard output";
1805 output_file = stdout;
1808 /* Some validation */
1809 if (pcap_link_type != 1 && hdr_ethernet) {
1810 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1814 /* Set up our variables */
1817 input_filename = "Standard input";
1820 output_file = stdout;
1821 output_filename = "Standard output";
1824 ts_sec = time(0); /* initialize to current time */
1825 timecode_default = *localtime(&ts_sec);
1826 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1828 /* Display summary of our state */
1830 fprintf(stderr, "Input from: %s\n", input_filename);
1831 fprintf(stderr, "Output to: %s\n", output_filename);
1832 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1834 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1835 hdr_ethernet_proto);
1836 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1838 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1839 hdr_src_port, hdr_dest_port);
1840 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1841 hdr_src_port, hdr_dest_port);
1842 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1843 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1844 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
1845 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1850 main(int argc, char *argv[])
1852 parse_options(argc, argv);
1854 assert(input_file != NULL);
1855 assert(output_file != NULL);
1857 write_file_header();
1861 header_length += (int)sizeof(HDR_ETHERNET);
1864 ip_offset = header_length;
1865 header_length += (int)sizeof(HDR_IP);
1866 } else if (hdr_ipv6) {
1867 ip_offset = header_length;
1868 header_length += (int)sizeof(HDR_IPv6);
1871 header_length += (int)sizeof(HDR_SCTP);
1873 if (hdr_data_chunk) {
1874 header_length += (int)sizeof(HDR_DATA_CHUNK);
1877 header_length += (int)sizeof(HDR_TCP);
1880 header_length += (int)sizeof(HDR_UDP);
1882 curr_offset = header_length;
1887 write_current_packet(FALSE);
1888 write_file_trailer();
1890 fclose(output_file);
1892 fprintf(stderr, "\n-------------------------\n");
1894 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1895 num_packets_read, (num_packets_read == 1) ? "" : "s",
1896 num_packets_written, (num_packets_written == 1) ? "" : "s",
1897 bytes_written, (bytes_written == 1) ? "" : "s");
1903 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1908 * indent-tabs-mode: nil
1911 * vi: set shiftwidth=4 tabstop=8 expandtab:
1912 * :indentSize=4:tabSize=8:noTabs=true: