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>
131 #include "wsutil/wsgetopt.h"
134 #ifdef NEED_STRPTIME_H
135 # include "wsutil/strptime.h"
139 #include "text2pcap.h"
143 #include <wsutil/unicode-utils.h>
146 #ifdef HAVE_ARPA_INET_H
147 #include <arpa/inet.h>
150 #ifdef HAVE_WINSOCK2_H
151 #include <winsock2.h> /* needed to define AF_ values on Windows */
154 #ifndef HAVE_INET_ATON_H
155 # include "wsutil/inet_aton.h"
158 #ifdef HAVE_SYS_SOCKET_H
159 #include <sys/socket.h>
162 #ifdef NEED_INET_V6DEFS_H
163 # include "wsutil/inet_v6defs.h"
166 /*--- Options --------------------------------------------------------------------*/
169 static gboolean use_pcapng = FALSE;
172 static int debug = 0;
174 static int quiet = FALSE;
176 /* Dummy Ethernet header */
177 static int hdr_ethernet = FALSE;
178 static guint32 hdr_ethernet_proto = 0;
180 /* Dummy IP header */
181 static int hdr_ip = FALSE;
182 static int hdr_ipv6 = FALSE;
183 static long hdr_ip_proto = 0;
185 /* Destination and source addresses for IP header */
186 static guint32 hdr_ip_dest_addr = 0;
187 static guint32 hdr_ip_src_addr = 0;
188 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
189 static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
190 static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
192 /* Dummy UDP header */
193 static int hdr_udp = FALSE;
194 static guint32 hdr_dest_port = 0;
195 static guint32 hdr_src_port = 0;
197 /* Dummy TCP header */
198 static int hdr_tcp = FALSE;
200 /* TCP sequence numbers when has_direction is true */
201 static guint32 tcp_in_seq_num = 0;
202 static guint32 tcp_out_seq_num = 0;
204 /* Dummy SCTP header */
205 static int hdr_sctp = FALSE;
206 static guint32 hdr_sctp_src = 0;
207 static guint32 hdr_sctp_dest = 0;
208 static guint32 hdr_sctp_tag = 0;
210 /* Dummy DATA chunk header */
211 static int hdr_data_chunk = FALSE;
212 static guint8 hdr_data_chunk_type = 0;
213 static guint8 hdr_data_chunk_bits = 0;
214 static guint32 hdr_data_chunk_tsn = 0;
215 static guint16 hdr_data_chunk_sid = 0;
216 static guint16 hdr_data_chunk_ssn = 0;
217 static guint32 hdr_data_chunk_ppid = 0;
219 /* ASCII text dump identification */
220 static int identify_ascii = FALSE;
222 static gboolean has_direction = FALSE;
223 static guint32 direction = 0;
225 /*--- Local date -----------------------------------------------------------------*/
227 /* This is where we store the packet currently being built */
228 #define MAX_PACKET 65535
229 static guint8 packet_buf[MAX_PACKET];
230 static guint32 header_length;
231 static guint32 ip_offset;
232 static guint32 curr_offset;
233 static guint32 max_offset = MAX_PACKET;
234 static guint32 packet_start = 0;
236 static void start_new_packet(gboolean);
238 /* This buffer contains strings present before the packet offset 0 */
239 #define PACKET_PREAMBLE_MAX_LEN 2048
240 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
241 static int packet_preamble_len = 0;
243 /* Number of packets read and written */
244 static guint32 num_packets_read = 0;
245 static guint32 num_packets_written = 0;
246 static guint64 bytes_written = 0;
248 /* Time code of packet, derived from packet_preamble */
249 static time_t ts_sec = 0;
250 static guint32 ts_usec = 0;
251 static char *ts_fmt = NULL;
252 static struct tm timecode_default;
254 static guint8* pkt_lnstart;
257 static const char *input_filename;
258 static FILE *input_file = NULL;
260 static const char *output_filename;
261 static FILE *output_file = NULL;
263 /* Offset base to parse */
264 static guint32 offset_base = 16;
268 /* ----- State machine -----------------------------------------------------------*/
270 /* Current state of parser */
272 INIT, /* Waiting for start of new packet */
273 START_OF_LINE, /* Starting from beginning of line */
274 READ_OFFSET, /* Just read the offset */
275 READ_BYTE, /* Just read a byte */
276 READ_TEXT /* Just read text - ignore until EOL */
278 static parser_state_t state = INIT;
280 static const char *state_str[] = {"Init",
287 static const char *token_str[] = {"",
295 /* ----- Skeleton Packet Headers --------------------------------------------------*/
303 static hdr_ethernet_t HDR_ETHERNET = {
304 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
305 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
311 guint16 packet_length;
312 guint16 identification;
317 guint16 hdr_checksum;
322 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
323 #ifdef WORDS_BIGENDIAN
324 0x0a010101, 0x0a020202
326 0x0101010a, 0x0202020a
330 /* Fixed IP address values */
331 #ifdef WORDS_BIGENDIAN
332 #define IP_SRC 0x0a010101
333 #define IP_DST 0x0a020202
335 #define IP_SRC 0x0101010a
336 #define IP_DST 0x0202020a
339 static struct { /* pseudo header for checksum calculation */
348 /* headers taken from glibc */
355 guint8 __u6_addr8[16];
356 guint16 __u6_addr16[8];
357 guint32 __u6_addr32[4];
364 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
365 guint16 ip6_un1_plen; /* payload length */
366 guint8 ip6_un1_nxt; /* next header */
367 guint8 ip6_un1_hlim; /* hop limit */
369 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
371 struct hdr_in6_addr ip6_src; /* source address */
372 struct hdr_in6_addr ip6_dst; /* destination address */
375 static hdr_ipv6_t HDR_IPv6;
377 static struct { /* pseudo header ipv6 for checksum calculation */
378 struct hdr_in6_addr src_addr6;
379 struct hdr_in6_addr dst_addr6;
392 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
406 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
415 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
427 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
429 static char tempbuf[64];
431 /*----------------------------------------------------------------------
432 * Stuff for writing a PCap file
434 #define PCAP_MAGIC 0xa1b2c3d4
435 #define PCAP_SNAPLEN 0xffff
437 /* "libpcap" file header (minus magic number). */
439 guint32 magic; /* magic */
440 guint16 version_major; /* major version number */
441 guint16 version_minor; /* minor version number */
442 guint32 thiszone; /* GMT to local correction */
443 guint32 sigfigs; /* accuracy of timestamps */
444 guint32 snaplen; /* max length of captured packets, in octets */
445 guint32 network; /* data link type */
448 /* "libpcap" record header. */
450 guint32 ts_sec; /* timestamp seconds */
451 guint32 ts_usec; /* timestamp microseconds */
452 guint32 incl_len; /* number of octets of packet saved in file */
453 guint32 orig_len; /* actual length of packet */
456 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
457 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
459 /*----------------------------------------------------------------------
460 * Parse a single hex number
461 * Will abort the program if it can't parse the number
462 * Pass in TRUE if this is an offset, FALSE if not
465 parse_num (const char *str, int offset)
471 fprintf(stderr, "FATAL ERROR: str is NULL\n");
475 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
477 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
483 /*----------------------------------------------------------------------
484 * Write this byte into current packet
487 write_byte (const char *str)
491 num = parse_num(str, FALSE);
492 packet_buf[curr_offset] = (guint8) num;
494 if (curr_offset - header_length >= max_offset) /* packet full */
495 start_new_packet(TRUE);
498 /*----------------------------------------------------------------------
499 * Write a number of bytes into current packet
503 write_bytes (const char bytes[], guint32 nbytes)
507 if (curr_offset + nbytes < MAX_PACKET) {
508 for (i = 0; i < nbytes; i++) {
509 packet_buf[curr_offset] = bytes[i];
515 /*----------------------------------------------------------------------
516 * Remove bytes from the current packet
519 unwrite_bytes (guint32 nbytes)
521 curr_offset -= nbytes;
524 /*----------------------------------------------------------------------
525 * Compute one's complement checksum (from RFC1071)
528 in_checksum (void *buf, guint32 count)
531 guint16 *addr = (guint16 *)buf;
534 /* This is the inner loop */
535 sum += g_ntohs(* (guint16 *) addr);
540 /* Add left-over byte, if any */
542 sum += g_ntohs(* (guint8 *) addr);
544 /* Fold 32-bit sum to 16 bits */
546 sum = (sum & 0xffff) + (sum >> 16);
552 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
553 * That code is copyrighted by D. Otis and has been modified.
556 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
557 static guint32 crc_c[256] =
559 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
560 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
561 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
562 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
563 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
564 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
565 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
566 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
567 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
568 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
569 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
570 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
571 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
572 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
573 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
574 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
575 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
576 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
577 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
578 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
579 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
580 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
581 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
582 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
583 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
584 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
585 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
586 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
587 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
588 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
589 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
590 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
591 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
592 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
593 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
594 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
595 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
596 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
597 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
598 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
599 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
600 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
601 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
602 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
603 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
604 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
605 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
606 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
607 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
608 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
609 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
610 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
611 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
612 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
613 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
614 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
615 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
616 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
617 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
618 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
619 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
620 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
621 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
622 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
626 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
632 for (i = 0; i < len; i++)
633 CRC32C(crc32, buf[i]);
639 finalize_crc32c (guint32 crc32)
642 guint8 byte0,byte1,byte2,byte3;
645 byte0 = result & 0xff;
646 byte1 = (result>>8) & 0xff;
647 byte2 = (result>>16) & 0xff;
648 byte3 = (result>>24) & 0xff;
649 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
654 number_of_padding_bytes (guint32 length)
658 remainder = length % 4;
663 return 4 - remainder;
666 /*----------------------------------------------------------------------
667 * Write current packet out
670 write_current_packet (gboolean cont)
673 guint16 padding_length = 0;
678 if (curr_offset > header_length) {
679 /* Write the packet */
681 /* Is direction indication on with an inbound packet? */
682 gboolean isInbound = has_direction && (direction == 2);
684 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
686 hdr_ethernet_proto = 0x86DD;
690 /* Compute packet length */
691 length = curr_offset;
693 padding_length = number_of_padding_bytes(length - header_length );
697 /* Reset curr_offset, since we now write the headers */
700 /* Write Ethernet header */
702 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
703 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
706 /* Write IP header */
709 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
710 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
713 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
714 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
717 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
718 HDR_IP.protocol = (guint8) hdr_ip_proto;
719 HDR_IP.hdr_checksum = 0;
720 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
721 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
722 } else if (hdr_ipv6) {
723 if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
724 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
725 if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
726 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
728 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
729 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
730 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
731 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
732 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
733 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
735 /* initialize pseudo ipv6 header for checksum calculation */
736 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
737 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
739 pseudoh6.protocol = (guint8) hdr_ip_proto;
740 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
741 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
745 /* initialize pseudo header for checksum calculation */
746 pseudoh.src_addr = HDR_IP.src_addr;
747 pseudoh.dest_addr = HDR_IP.dest_addr;
749 pseudoh.protocol = (guint8) hdr_ip_proto;
750 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
753 /* Write UDP header */
758 /* initialize the UDP header */
759 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
760 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
761 HDR_UDP.length = pseudoh.length;
762 HDR_UDP.checksum = 0;
763 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
764 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
766 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
768 x16 = in_checksum(packet_buf + header_length, length - header_length);
770 x16 = (u & 0xffff) + (u>>16);
771 HDR_UDP.checksum = g_htons(x16);
772 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
773 HDR_UDP.checksum = g_htons(1);
774 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
777 /* Write TCP header */
782 /* initialize pseudo header for checksum calculation */
783 pseudoh.src_addr = HDR_IP.src_addr;
784 pseudoh.dest_addr = HDR_IP.dest_addr;
786 pseudoh.protocol = (guint8) hdr_ip_proto;
787 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
788 /* initialize the TCP header */
789 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
790 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
791 /* set ack number if we have direction */
793 HDR_TCP.flags = 0x10;
794 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
795 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
801 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
802 HDR_TCP.window = g_htons(0x2000);
803 HDR_TCP.checksum = 0;
804 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
805 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
807 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
809 x16 = in_checksum(packet_buf + header_length, length - header_length);
811 x16 = (u & 0xffff) + (u>>16);
812 HDR_TCP.checksum = g_htons(x16);
813 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
814 HDR_TCP.checksum = g_htons(1);
815 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
817 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
818 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
821 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
822 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
826 /* Compute DATA chunk header */
827 if (hdr_data_chunk) {
828 hdr_data_chunk_bits = 0;
829 if (packet_start == 0) {
830 hdr_data_chunk_bits |= 0x02;
833 hdr_data_chunk_bits |= 0x01;
835 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
836 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
837 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
838 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
839 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
840 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
841 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
842 hdr_data_chunk_tsn++;
844 hdr_data_chunk_ssn++;
848 /* Write SCTP common header */
852 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
853 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
854 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
855 HDR_SCTP.checksum = g_htonl(0);
856 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
857 if (hdr_data_chunk) {
858 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
859 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
860 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
862 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
864 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
865 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
866 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
869 /* Write DATA chunk header */
870 if (hdr_data_chunk) {
871 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
874 /* Reset curr_offset, since we now write the trailers */
875 curr_offset = length;
877 /* Write DATA chunk padding */
878 if (hdr_data_chunk && (padding_length > 0)) {
879 memset(tempbuf, 0, padding_length);
880 write_bytes((const char *)&tempbuf, padding_length);
881 length += padding_length;
884 /* Write Ethernet trailer */
885 if (hdr_ethernet && (length < 60)) {
886 memset(tempbuf, 0, 60 - length);
887 write_bytes((const char *)&tempbuf, 60 - length);
891 success = pcapng_write_enhanced_packet_block(output_file,
897 packet_buf, direction,
898 &bytes_written, &err);
900 success = libpcap_write_packet(output_file,
904 &bytes_written, &err);
907 fprintf(stderr, "File write error [%s] : %s\n",
908 output_filename, g_strerror(err));
911 if (ts_fmt == NULL) {
912 /* fake packet counter */
916 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
918 num_packets_written++;
921 packet_start += curr_offset - header_length;
922 curr_offset = header_length;
926 /*----------------------------------------------------------------------
927 * Write file header and trailer
930 write_file_header (void)
937 const char *appname = "text2pcap (" GITVERSION " from " GITBRANCH ")";
939 const char *appname = "text2pcap";
943 g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
944 success = pcapng_write_session_header_block(output_file,
953 success = pcapng_write_interface_description_block(output_file,
967 success = libpcap_write_file_header(output_file, pcap_link_type, PCAP_SNAPLEN,
968 FALSE, &bytes_written, &err);
971 fprintf(stderr, "File write error [%s] : %s\n",
972 output_filename, g_strerror(err));
978 write_file_trailer (void)
984 success = pcapng_write_interface_statistics_block(output_file,
987 "Counters provided by text2pcap",
991 num_packets_written - num_packets_written,
998 fprintf(stderr, "File write error [%s] : %s\n",
999 output_filename, g_strerror(err));
1005 /*----------------------------------------------------------------------
1006 * Append a token to the packet preamble.
1009 append_to_preamble (char *str)
1013 if (packet_preamble_len != 0) {
1014 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1015 return; /* no room to add more preamble */
1016 /* Add a blank separator between the previous token and this token. */
1017 packet_preamble[packet_preamble_len++] = ' ';
1019 toklen = strlen(str);
1021 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1022 return; /* no room to add the token to the preamble */
1023 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1024 packet_preamble_len += (int) toklen;
1027 char xs[PACKET_PREAMBLE_MAX_LEN];
1028 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1029 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1030 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1035 /*----------------------------------------------------------------------
1036 * Parse the preamble to get the timecode.
1040 parse_preamble (void)
1049 * Null-terminate the preamble.
1051 packet_preamble[packet_preamble_len] = '\0';
1053 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1055 if (has_direction) {
1056 switch (packet_preamble[0]) {
1059 direction = 0x00000001;
1060 packet_preamble[0] = ' ';
1064 direction = 0x00000002;
1065 packet_preamble[0] = ' ';
1068 direction = 0x00000000;
1072 while (packet_preamble[i] == ' ' ||
1073 packet_preamble[i] == '\r' ||
1074 packet_preamble[i] == '\t') {
1077 packet_preamble_len -= i;
1078 /* Also move the trailing '\0'. */
1079 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1084 * If no "-t" flag was specified, don't attempt to parse the packet
1085 * preamble to extract a time stamp.
1087 if (ts_fmt == NULL) {
1088 /* Clear Preamble */
1089 packet_preamble_len = 0;
1094 * Initialize to today localtime, just in case not all fields
1095 * of the date and time are specified.
1098 timecode = timecode_default;
1101 /* Ensure preamble has more than two chars before attempting to parse.
1102 * This should cover line breaks etc that get counted.
1104 if (strlen(packet_preamble) > 2) {
1105 /* Get Time leaving subseconds */
1106 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1107 if (subsecs != NULL) {
1108 /* Get the long time from the tm structure */
1109 /* (will return -1 if failure) */
1110 ts_sec = mktime( &timecode );
1112 ts_sec = -1; /* we failed to parse it */
1114 /* This will ensure incorrectly parsed dates get set to zero */
1116 /* Sanitize - remove all '\r' */
1118 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1119 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1120 packet_preamble, ts_fmt);
1122 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1123 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1124 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1126 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1129 /* Parse subseconds */
1130 ts_usec = (guint32)strtol(subsecs, &p, 10);
1136 * Convert that number to a number
1137 * of microseconds; if it's N digits
1138 * long, it's in units of 10^(-N) seconds,
1139 * so, to convert it to units of
1140 * 10^-6 seconds, we multiply by
1143 subseclen = (int) (p - subsecs);
1144 if (subseclen > 6) {
1146 * *More* than 6 digits; 6-N is
1147 * negative, so we divide by
1150 for (i = subseclen - 6; i != 0; i--)
1152 } else if (subseclen < 6) {
1153 for (i = 6 - subseclen; i != 0; i--)
1161 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1162 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1163 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_usec);
1167 /* Clear Preamble */
1168 packet_preamble_len = 0;
1171 /*----------------------------------------------------------------------
1172 * Start a new packet
1175 start_new_packet (gboolean cont)
1178 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1180 /* Write out the current packet, if required */
1181 write_current_packet(cont);
1184 /* Ensure we parse the packet preamble as it may contain the time */
1188 /*----------------------------------------------------------------------
1189 * Process a directive
1192 process_directive (char *str)
1194 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1197 /*----------------------------------------------------------------------
1198 * Parse a single token (called from the scanner)
1201 parse_token (token_t token, char *str)
1212 * This is implemented as a simple state machine of five states.
1213 * State transitions are caused by tokens being received from the
1214 * scanner. The code should be self-documenting.
1218 /* Sanitize - remove all '\r' */
1220 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1222 fprintf(stderr, "(%s, %s \"%s\") -> (",
1223 state_str[state], token_str[token], str ? str : "");
1228 /* ----- Waiting for new packet -------------------------------------------*/
1230 if (!str && token != T_EOL) goto fail_null_str;
1233 append_to_preamble(str);
1236 process_directive(str);
1239 num = parse_num(str, TRUE);
1241 /* New packet starts here */
1242 start_new_packet(FALSE);
1243 state = READ_OFFSET;
1244 pkt_lnstart = packet_buf + num;
1248 /* Some describing text may be parsed as offset, but the invalid
1249 offset will be checked in the state of START_OF_LINE, so
1250 we add this transition to gain flexibility */
1251 state = START_OF_LINE;
1258 /* ----- Processing packet, start of new line -----------------------------*/
1260 if (!str && token != T_EOL) goto fail_null_str;
1263 append_to_preamble(str);
1266 process_directive(str);
1269 num = parse_num(str, TRUE);
1271 /* New packet starts here */
1272 start_new_packet(FALSE);
1274 state = READ_OFFSET;
1275 } else if ((num - packet_start) != curr_offset - header_length) {
1277 * The offset we read isn't the one we expected.
1278 * This may only mean that we mistakenly interpreted
1279 * some text as byte values (e.g., if the text dump
1280 * of packet data included a number with spaces around
1281 * it). If the offset is less than what we expected,
1282 * assume that's the problem, and throw away the putative
1283 * extra byte values.
1285 if (num < curr_offset) {
1286 unwrite_bytes(curr_offset - num);
1287 state = READ_OFFSET;
1289 /* Bad offset; switch to INIT state */
1291 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1293 write_current_packet(FALSE);
1297 state = READ_OFFSET;
1298 pkt_lnstart = packet_buf + num;
1301 state = START_OF_LINE;
1308 /* ----- Processing packet, read offset -----------------------------------*/
1312 /* Record the byte */
1314 if (!str) goto fail_null_str;
1323 state = START_OF_LINE;
1330 /* ----- Processing packet, read byte -------------------------------------*/
1334 /* Record the byte */
1343 if (token == T_EOL) {
1345 state = START_OF_LINE;
1347 if (identify_ascii) {
1348 /* Here a line of pkt bytes reading is finished
1349 compare the ascii and hex to avoid such situation:
1350 "61 62 20 ab ", when ab is ascii dump then it should
1351 not be treat as byte */
1353 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1354 s2 = "ab ", s1 = "616220"
1355 we should find out the largest tail of s1 matches the head
1356 of s2, it means the matched part in tail is the ASCII dump
1357 of the head byte. These matched should be rollback */
1358 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1359 s2 = (char*)g_malloc((line_size+1)/4+1);
1360 /* gather the possible pattern */
1361 for (i = 0; i < (line_size+1)/4; i++) {
1362 tmp_str[0] = pkt_lnstart[i*3];
1363 tmp_str[1] = pkt_lnstart[i*3+1];
1365 /* it is a valid convertable string */
1366 if (!isxdigit(tmp_str[0]) || !isxdigit(tmp_str[0])) {
1369 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1371 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1372 if (!(pkt_lnstart[i*3+2] == ' ')) {
1378 /* If packet line start contains possible byte pattern, the line end
1379 should contain the matched pattern if the user open the -a flag.
1380 The packet will be possible invalid if the byte pattern cannot find
1381 a matched one in the line of packet buffer.*/
1383 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1384 unwrite_bytes(rollback);
1386 /* Not matched. This line contains invalid packet bytes, so
1387 discard the whole line */
1389 unwrite_bytes(line_size);
1400 /* ----- Processing packet, read text -------------------------------------*/
1404 state = START_OF_LINE;
1412 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1417 fprintf(stderr, ", %s)\n", state_str[state]);
1422 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1428 print_version(FILE *output)
1430 fprintf(output, "Text2pcap %s"
1432 " (" GITVERSION " from " GITBRANCH ")"
1437 /*----------------------------------------------------------------------
1438 * Print usage string and exit
1441 usage (gboolean is_error)
1452 print_version(output);
1454 "Generate a capture file from an ASCII hexdump of packets.\n"
1455 "See http://www.wireshark.org for more information.\n"
1457 "Usage: text2pcap [options] <infile> <outfile>\n"
1459 "where <infile> specifies input filename (use - for standard input)\n"
1460 " <outfile> specifies output filename (use - for standard output)\n"
1463 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1464 " default is hex.\n"
1465 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1466 " the specified argument is a format string of the sort\n"
1467 " supported by strptime.\n"
1468 " Example: The time \"10:15:14.5476\" has the format code\n"
1469 " \"%%H:%%M:%%S.\"\n"
1470 " NOTE: The subsecond component delimiter, '.', must be\n"
1471 " given, but no pattern is required; the remaining\n"
1472 " number is assumed to be fractions of a second.\n"
1473 " NOTE: Date/time fields from the current date/time are\n"
1474 " used as the default for unspecified fields.\n"
1475 " -D the text before the packet starts with an I or an O,\n"
1476 " indicating that the packet is inbound or outbound.\n"
1477 " This is only stored if the output format is PCAP-NG.\n"
1478 " -a enable ASCII text dump identification.\n"
1479 " The start of the ASCII text dump can be identified\n"
1480 " and excluded from the packet data, even if it looks\n"
1481 " like a HEX dump.\n"
1482 " NOTE: Do not enable it if the input file does not\n"
1483 " contain the ASCII text dump.\n"
1486 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1487 " http://www.tcpdump.org/linktypes.html for a list of\n"
1488 " numbers. Use this option if your dump is a complete\n"
1489 " hex dump of an encapsulated packet and you wish to\n"
1490 " specify the exact type of encapsulation.\n"
1491 " Example: -l 7 for ARCNet packets.\n"
1492 " -m <max-packet> max packet length in output; default is %d\n"
1494 "Prepend dummy header:\n"
1495 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1497 " Example: -e 0x806 to specify an ARP packet.\n"
1498 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1500 " Automatically prepends Ethernet header as well.\n"
1502 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1503 " dest and source address.\n"
1504 " Example: -4 10.0.0.1,10.0.0.2\n"
1505 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1506 " dest and source address.\n"
1507 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1508 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1509 " source and destination ports (in DECIMAL).\n"
1510 " Automatically prepends Ethernet & IP headers as well.\n"
1511 " Example: -u 1000,69 to make the packets look like\n"
1512 " TFTP/UDP packets.\n"
1513 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1514 " source and destination ports (in DECIMAL).\n"
1515 " Automatically prepends Ethernet & IP headers as well.\n"
1516 " Example: -T 50,60\n"
1517 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1518 " source/dest ports and verification tag (in DECIMAL).\n"
1519 " Automatically prepends Ethernet & IP headers as well.\n"
1520 " Example: -s 30,40,34\n"
1521 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1522 " source/dest ports and verification tag 0.\n"
1523 " Automatically prepends a dummy SCTP DATA\n"
1524 " chunk header with payload protocol identifier ppi.\n"
1525 " Example: -S 30,40,34\n"
1528 " -h display this help and exit.\n"
1529 " -d show detailed debug of parser states.\n"
1530 " -q generate no output at all (automatically disables -d).\n"
1531 " -n use PCAP-NG instead of PCAP as output format.\n"
1535 exit(is_error ? 1 : 0);
1538 /*----------------------------------------------------------------------
1542 parse_options (int argc, char *argv[])
1546 static const struct option long_options[] = {
1547 {(char *)"help", no_argument, NULL, 'h'},
1548 {(char *)"version", no_argument, NULL, 'v'},
1553 arg_list_utf_16to8(argc, argv);
1554 create_app_running_mutex();
1557 /* Scan CLI parameters */
1558 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1560 case '?': usage(TRUE); break;
1561 case 'h': usage(FALSE); break;
1562 case 'd': if (!quiet) debug++; break;
1563 case 'D': has_direction = TRUE; break;
1564 case 'q': quiet = TRUE; debug = FALSE; break;
1565 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1566 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1567 case 'n': use_pcapng = TRUE; break;
1569 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1570 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1573 switch (optarg[0]) {
1574 case 'o': offset_base = 8; break;
1575 case 'h': offset_base = 16; break;
1576 case 'd': offset_base = 10; break;
1580 hdr_ethernet = TRUE;
1581 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1582 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1589 hdr_ip_proto = strtol(optarg, &p, 10);
1590 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1591 hdr_ip_proto > 255) {
1592 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1595 hdr_ethernet = TRUE;
1596 hdr_ethernet_proto = 0x800;
1601 hdr_data_chunk = FALSE;
1604 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1605 if (p == optarg || (*p != ',' && *p != '\0')) {
1606 fprintf(stderr, "Bad src port for '-%c'\n", c);
1610 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1615 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1616 if (p == optarg || (*p != ',' && *p != '\0')) {
1617 fprintf(stderr, "Bad dest port for '-s'\n");
1621 fprintf(stderr, "No tag specified for '-%c'\n", c);
1626 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1627 if (p == optarg || *p != '\0') {
1628 fprintf(stderr, "Bad tag for '-%c'\n", c);
1634 hdr_ethernet = TRUE;
1635 hdr_ethernet_proto = 0x800;
1639 hdr_data_chunk = TRUE;
1642 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1643 if (p == optarg || (*p != ',' && *p != '\0')) {
1644 fprintf(stderr, "Bad src port for '-%c'\n", c);
1648 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1653 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1654 if (p == optarg || (*p != ',' && *p != '\0')) {
1655 fprintf(stderr, "Bad dest port for '-s'\n");
1659 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1664 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1665 if (p == optarg || *p != '\0') {
1666 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1672 hdr_ethernet = TRUE;
1673 hdr_ethernet_proto = 0x800;
1684 hdr_data_chunk = FALSE;
1685 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1686 if (p == optarg || (*p != ',' && *p != '\0')) {
1687 fprintf(stderr, "Bad src port for '-u'\n");
1691 fprintf(stderr, "No dest port specified for '-u'\n");
1696 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1697 if (p == optarg || *p != '\0') {
1698 fprintf(stderr, "Bad dest port for '-u'\n");
1703 hdr_ethernet = TRUE;
1704 hdr_ethernet_proto = 0x800;
1711 hdr_data_chunk = FALSE;
1712 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1713 if (p == optarg || (*p != ',' && *p != '\0')) {
1714 fprintf(stderr, "Bad src port for '-T'\n");
1718 fprintf(stderr, "No dest port specified for '-u'\n");
1723 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1724 if (p == optarg || *p != '\0') {
1725 fprintf(stderr, "Bad dest port for '-T'\n");
1730 hdr_ethernet = TRUE;
1731 hdr_ethernet_proto = 0x800;
1735 identify_ascii = TRUE;
1739 print_version(stdout);
1745 p = strchr(optarg, ',');
1748 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1756 hdr_ethernet_proto = 0x86DD;
1761 hdr_ethernet_proto = 0x800;
1763 hdr_ethernet = TRUE;
1765 if (hdr_ipv6 == TRUE) {
1766 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1767 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1771 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1772 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1779 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1783 if (hdr_ipv6 == TRUE) {
1784 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1785 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1789 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1790 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1802 if (optind >= argc || argc-optind < 2) {
1803 fprintf(stderr, "Must specify input and output filename\n");
1807 if (strcmp(argv[optind], "-")) {
1808 input_filename = g_strdup(argv[optind]);
1809 input_file = ws_fopen(input_filename, "rb");
1811 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1812 input_filename, g_strerror(errno));
1816 input_filename = "Standard input";
1820 if (strcmp(argv[optind+1], "-")) {
1821 output_filename = g_strdup(argv[optind+1]);
1822 output_file = ws_fopen(output_filename, "wb");
1824 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1825 output_filename, g_strerror(errno));
1829 output_filename = "Standard output";
1830 output_file = stdout;
1833 /* Some validation */
1834 if (pcap_link_type != 1 && hdr_ethernet) {
1835 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1839 /* Set up our variables */
1842 input_filename = "Standard input";
1845 output_file = stdout;
1846 output_filename = "Standard output";
1849 ts_sec = time(0); /* initialize to current time */
1850 timecode_default = *localtime(&ts_sec);
1851 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1853 /* Display summary of our state */
1855 fprintf(stderr, "Input from: %s\n", input_filename);
1856 fprintf(stderr, "Output to: %s\n", output_filename);
1857 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1859 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1860 hdr_ethernet_proto);
1861 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1863 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1864 hdr_src_port, hdr_dest_port);
1865 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1866 hdr_src_port, hdr_dest_port);
1867 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1868 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1869 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
1870 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1875 main(int argc, char *argv[])
1877 parse_options(argc, argv);
1879 assert(input_file != NULL);
1880 assert(output_file != NULL);
1882 write_file_header();
1886 header_length += (int)sizeof(HDR_ETHERNET);
1889 ip_offset = header_length;
1890 header_length += (int)sizeof(HDR_IP);
1891 } else if (hdr_ipv6) {
1892 ip_offset = header_length;
1893 header_length += (int)sizeof(HDR_IPv6);
1896 header_length += (int)sizeof(HDR_SCTP);
1898 if (hdr_data_chunk) {
1899 header_length += (int)sizeof(HDR_DATA_CHUNK);
1902 header_length += (int)sizeof(HDR_TCP);
1905 header_length += (int)sizeof(HDR_UDP);
1907 curr_offset = header_length;
1912 write_current_packet(FALSE);
1913 write_file_trailer();
1915 fclose(output_file);
1917 fprintf(stderr, "\n-------------------------\n");
1919 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1920 num_packets_read, (num_packets_read == 1) ? "" : "s",
1921 num_packets_written, (num_packets_written == 1) ? "" : "s",
1922 bytes_written, (bytes_written == 1) ? "" : "s");
1928 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1933 * indent-tabs-mode: nil
1936 * vi: set shiftwidth=4 tabstop=8 expandtab:
1937 * :indentSize=4:tabSize=8:noTabs=true: