1 /**-*-C-*-**********************************************************************
5 * Utility to convert an ASCII hexdump into a libpcap-format capture file
7 * (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *******************************************************************************/
29 /*******************************************************************************
31 * This utility reads in an ASCII hexdump of this common format:
33 * 00000000 00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
34 * 00000010 03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3...
\7f..
35 * 00000020 03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
36 * 00000030 01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
38 * Each bytestring line consists of an offset, one or more bytes, and
39 * text at the end. An offset is defined as a hex string of more than
40 * two characters. A byte is defined as a hex string of exactly two
41 * characters. The text at the end is ignored, as is any text before
42 * the offset. Bytes read from a bytestring line are added to the
43 * current packet only if all the following conditions are satisfied:
45 * - No text appears between the offset and the bytes (any bytes appearing after
46 * such text would be ignored)
48 * - The offset must be arithmetically correct, i.e. if the offset is 00000020, then
49 * exactly 32 bytes must have been read into this packet before this. If the offset
50 * is wrong, the packet is immediately terminated
52 * A packet start is signaled by a zero offset.
54 * Lines starting with #TEXT2PCAP are directives. These allow the user
55 * to embed instructions into the capture file which allows text2pcap
56 * to take some actions (e.g. specifying the encapsulation
57 * etc.). Currently no directives are implemented.
59 * Lines beginning with # which are not directives are ignored as
60 * comments. Currently all non-hexdump text is ignored by text2pcap;
61 * in the future, text processing may be added, but lines prefixed
62 * with '#' will still be ignored.
64 * The output is a libpcap packet containing Ethernet frames by
65 * default. This program takes options which allow the user to add
66 * dummy Ethernet, IP and UDP or TCP headers to the packets in order
67 * to allow dumps of L3 or higher protocols to be decoded.
69 * Considerable flexibility is built into this code to read hexdumps
70 * of slightly different formats. For example, any text prefixing the
71 * hexdump line is dropped (including mail forwarding '>'). The offset
72 * can be any hex number of four digits or greater.
74 * This converter cannot read a single packet greater than 64KiB-1. Packet
75 * snaplength is automatically set to 64KiB-1.
81 * Just make sure we include the prototype for strptime as well
82 * (needed for glibc 2.2) but make sure we do this only if not
90 # define _XOPEN_SOURCE 600
95 * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms
96 * using glibc, to expand the set of things system header files define.
98 * Unfortunately, on other platforms, such as some versions of Solaris
99 * (including Solaris 10), it *reduces* that set as well, causing
100 * strptime() not to be declared, presumably because the version of the
101 * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and
102 * blah blah blah namespace pollution blah blah blah.
104 * So we define __EXTENSIONS__ so that "strptime()" is declared.
106 #ifndef __EXTENSIONS__
107 # define __EXTENSIONS__
113 #include <wsutil/file_util.h>
114 #include <wsutil/crash_info.h>
115 #include <wsutil/ws_version_info.h>
132 #include <zlib.h> /* to get the libz version number */
135 #ifndef HAVE_GETOPT_LONG
136 #include "wsutil/wsgetopt.h"
139 #ifndef HAVE_STRPTIME
140 # include "wsutil/strptime.h"
144 #include "text2pcap.h"
147 #include <wsutil/unicode-utils.h>
150 #ifdef HAVE_ARPA_INET_H
151 #include <arpa/inet.h>
154 #ifdef HAVE_WINSOCK2_H
155 #include <winsock2.h> /* needed to define AF_ values on Windows */
158 #ifndef HAVE_INET_ATON
159 # include "wsutil/inet_aton.h"
162 #ifdef HAVE_SYS_SOCKET_H
163 #include <sys/socket.h>
166 #ifdef NEED_INET_V6DEFS_H
167 # include "wsutil/inet_v6defs.h"
170 /*--- Options --------------------------------------------------------------------*/
173 static gboolean use_pcapng = FALSE;
176 static int debug = 0;
178 static int quiet = FALSE;
180 /* Dummy Ethernet header */
181 static int hdr_ethernet = FALSE;
182 static guint32 hdr_ethernet_proto = 0;
184 /* Dummy IP header */
185 static int hdr_ip = FALSE;
186 static int hdr_ipv6 = FALSE;
187 static long hdr_ip_proto = 0;
189 /* Destination and source addresses for IP header */
190 static guint32 hdr_ip_dest_addr = 0;
191 static guint32 hdr_ip_src_addr = 0;
192 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
193 static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
194 static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
196 /* Dummy UDP header */
197 static int hdr_udp = FALSE;
198 static guint32 hdr_dest_port = 0;
199 static guint32 hdr_src_port = 0;
201 /* Dummy TCP header */
202 static int hdr_tcp = FALSE;
204 /* TCP sequence numbers when has_direction is true */
205 static guint32 tcp_in_seq_num = 0;
206 static guint32 tcp_out_seq_num = 0;
208 /* Dummy SCTP header */
209 static int hdr_sctp = FALSE;
210 static guint32 hdr_sctp_src = 0;
211 static guint32 hdr_sctp_dest = 0;
212 static guint32 hdr_sctp_tag = 0;
214 /* Dummy DATA chunk header */
215 static int hdr_data_chunk = FALSE;
216 static guint8 hdr_data_chunk_type = 0;
217 static guint8 hdr_data_chunk_bits = 0;
218 static guint32 hdr_data_chunk_tsn = 0;
219 static guint16 hdr_data_chunk_sid = 0;
220 static guint16 hdr_data_chunk_ssn = 0;
221 static guint32 hdr_data_chunk_ppid = 0;
223 /* ASCII text dump identification */
224 static int identify_ascii = FALSE;
226 static gboolean has_direction = FALSE;
227 static guint32 direction = 0;
229 /*--- Local date -----------------------------------------------------------------*/
231 /* This is where we store the packet currently being built */
232 #define MAX_PACKET 65535
233 static guint8 packet_buf[MAX_PACKET];
234 static guint32 header_length;
235 static guint32 ip_offset;
236 static guint32 curr_offset;
237 static guint32 max_offset = MAX_PACKET;
238 static guint32 packet_start = 0;
240 static void start_new_packet(gboolean);
242 /* This buffer contains strings present before the packet offset 0 */
243 #define PACKET_PREAMBLE_MAX_LEN 2048
244 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
245 static int packet_preamble_len = 0;
247 /* Number of packets read and written */
248 static guint32 num_packets_read = 0;
249 static guint32 num_packets_written = 0;
250 static guint64 bytes_written = 0;
252 /* Time code of packet, derived from packet_preamble */
253 static time_t ts_sec = 0;
254 static guint32 ts_nsec = 0;
255 static char *ts_fmt = NULL;
256 static struct tm timecode_default;
258 static guint8* pkt_lnstart;
261 static const char *input_filename;
262 static FILE *input_file = NULL;
264 static const char *output_filename;
265 static FILE *output_file = NULL;
267 /* Offset base to parse */
268 static guint32 offset_base = 16;
272 /* ----- State machine -----------------------------------------------------------*/
274 /* Current state of parser */
276 INIT, /* Waiting for start of new packet */
277 START_OF_LINE, /* Starting from beginning of line */
278 READ_OFFSET, /* Just read the offset */
279 READ_BYTE, /* Just read a byte */
280 READ_TEXT /* Just read text - ignore until EOL */
282 static parser_state_t state = INIT;
284 static const char *state_str[] = {"Init",
291 static const char *token_str[] = {"",
299 /* ----- Skeleton Packet Headers --------------------------------------------------*/
307 static hdr_ethernet_t HDR_ETHERNET = {
308 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
309 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
315 guint16 packet_length;
316 guint16 identification;
321 guint16 hdr_checksum;
326 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
327 #ifdef WORDS_BIGENDIAN
328 0x0a010101, 0x0a020202
330 0x0101010a, 0x0202020a
334 /* Fixed IP address values */
335 #ifdef WORDS_BIGENDIAN
336 #define IP_SRC 0x0a010101
337 #define IP_DST 0x0a020202
339 #define IP_SRC 0x0101010a
340 #define IP_DST 0x0202020a
343 static struct { /* pseudo header for checksum calculation */
352 /* headers taken from glibc */
359 guint8 __u6_addr8[16];
360 guint16 __u6_addr16[8];
361 guint32 __u6_addr32[4];
368 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
369 guint16 ip6_un1_plen; /* payload length */
370 guint8 ip6_un1_nxt; /* next header */
371 guint8 ip6_un1_hlim; /* hop limit */
373 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
375 struct hdr_in6_addr ip6_src; /* source address */
376 struct hdr_in6_addr ip6_dst; /* destination address */
379 static hdr_ipv6_t HDR_IPv6;
381 static struct { /* pseudo header ipv6 for checksum calculation */
382 struct hdr_in6_addr src_addr6;
383 struct hdr_in6_addr dst_addr6;
396 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
410 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
419 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
431 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
433 static char tempbuf[64];
435 /*----------------------------------------------------------------------
436 * Stuff for writing a PCap file
438 #define PCAP_SNAPLEN 0xffff
440 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
441 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
443 /*----------------------------------------------------------------------
444 * Parse a single hex number
445 * Will abort the program if it can't parse the number
446 * Pass in TRUE if this is an offset, FALSE if not
449 parse_num (const char *str, int offset)
455 fprintf(stderr, "FATAL ERROR: str is NULL\n");
459 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
461 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
467 /*----------------------------------------------------------------------
468 * Write this byte into current packet
471 write_byte (const char *str)
475 num = parse_num(str, FALSE);
476 packet_buf[curr_offset] = (guint8) num;
478 if (curr_offset - header_length >= max_offset) /* packet full */
479 start_new_packet(TRUE);
482 /*----------------------------------------------------------------------
483 * Write a number of bytes into current packet
487 write_bytes (const char bytes[], guint32 nbytes)
491 if (curr_offset + nbytes < MAX_PACKET) {
492 for (i = 0; i < nbytes; i++) {
493 packet_buf[curr_offset] = bytes[i];
499 /*----------------------------------------------------------------------
500 * Remove bytes from the current packet
503 unwrite_bytes (guint32 nbytes)
505 curr_offset -= nbytes;
508 /*----------------------------------------------------------------------
509 * Compute one's complement checksum (from RFC1071)
512 in_checksum (void *buf, guint32 count)
515 guint16 *addr = (guint16 *)buf;
518 /* This is the inner loop */
519 sum += g_ntohs(* (guint16 *) addr);
524 /* Add left-over byte, if any */
526 sum += g_ntohs(* (guint8 *) addr);
528 /* Fold 32-bit sum to 16 bits */
530 sum = (sum & 0xffff) + (sum >> 16);
536 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
537 * That code is copyrighted by D. Otis and has been modified.
540 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
541 static guint32 crc_c[256] =
543 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
544 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
545 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
546 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
547 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
548 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
549 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
550 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
551 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
552 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
553 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
554 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
555 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
556 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
557 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
558 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
559 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
560 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
561 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
562 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
563 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
564 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
565 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
566 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
567 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
568 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
569 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
570 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
571 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
572 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
573 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
574 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
575 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
576 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
577 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
578 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
579 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
580 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
581 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
582 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
583 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
584 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
585 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
586 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
587 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
588 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
589 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
590 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
591 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
592 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
593 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
594 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
595 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
596 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
597 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
598 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
599 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
600 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
601 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
602 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
603 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
604 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
605 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
606 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
610 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
616 for (i = 0; i < len; i++)
623 finalize_crc32c (guint32 crc)
626 guint8 byte0,byte1,byte2,byte3;
629 byte0 = result & 0xff;
630 byte1 = (result>>8) & 0xff;
631 byte2 = (result>>16) & 0xff;
632 byte3 = (result>>24) & 0xff;
633 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
638 number_of_padding_bytes (guint32 length)
642 remainder = length % 4;
647 return 4 - remainder;
650 /*----------------------------------------------------------------------
651 * Write current packet out
654 write_current_packet (gboolean cont)
657 guint16 padding_length = 0;
662 if (curr_offset > header_length) {
663 /* Write the packet */
665 /* Is direction indication on with an inbound packet? */
666 gboolean isInbound = has_direction && (direction == 2);
668 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
670 hdr_ethernet_proto = 0x86DD;
674 /* Compute packet length */
675 length = curr_offset;
677 padding_length = number_of_padding_bytes(length - header_length );
681 /* Reset curr_offset, since we now write the headers */
684 /* Write Ethernet header */
686 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
687 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
690 /* Write IP header */
693 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
694 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
697 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
698 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
701 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
702 HDR_IP.protocol = (guint8) hdr_ip_proto;
703 HDR_IP.hdr_checksum = 0;
704 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
705 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
706 } else if (hdr_ipv6) {
707 if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
708 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
709 if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
710 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
712 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
713 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
714 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
715 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
716 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
717 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
719 /* initialize pseudo ipv6 header for checksum calculation */
720 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
721 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
723 pseudoh6.protocol = (guint8) hdr_ip_proto;
724 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
725 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
729 /* initialize pseudo header for checksum calculation */
730 pseudoh.src_addr = HDR_IP.src_addr;
731 pseudoh.dest_addr = HDR_IP.dest_addr;
733 pseudoh.protocol = (guint8) hdr_ip_proto;
734 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
737 /* Write UDP header */
742 /* initialize the UDP header */
743 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
744 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
745 HDR_UDP.length = pseudoh.length;
746 HDR_UDP.checksum = 0;
747 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
748 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
750 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
752 x16 = in_checksum(packet_buf + header_length, length - header_length);
754 x16 = (u & 0xffff) + (u>>16);
755 HDR_UDP.checksum = g_htons(x16);
756 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
757 HDR_UDP.checksum = g_htons(1);
758 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
761 /* Write TCP header */
766 /* initialize pseudo header for checksum calculation */
767 pseudoh.src_addr = HDR_IP.src_addr;
768 pseudoh.dest_addr = HDR_IP.dest_addr;
770 pseudoh.protocol = (guint8) hdr_ip_proto;
771 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
772 /* initialize the TCP header */
773 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
774 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
775 /* set ack number if we have direction */
777 HDR_TCP.flags = 0x10;
778 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
779 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
785 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
786 HDR_TCP.window = g_htons(0x2000);
787 HDR_TCP.checksum = 0;
788 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
789 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
791 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
793 x16 = in_checksum(packet_buf + header_length, length - header_length);
795 x16 = (u & 0xffff) + (u>>16);
796 HDR_TCP.checksum = g_htons(x16);
797 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
798 HDR_TCP.checksum = g_htons(1);
799 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
801 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
802 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
805 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
806 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
810 /* Compute DATA chunk header */
811 if (hdr_data_chunk) {
812 hdr_data_chunk_bits = 0;
813 if (packet_start == 0) {
814 hdr_data_chunk_bits |= 0x02;
817 hdr_data_chunk_bits |= 0x01;
819 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
820 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
821 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
822 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
823 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
824 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
825 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
826 hdr_data_chunk_tsn++;
828 hdr_data_chunk_ssn++;
832 /* Write SCTP common header */
836 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
837 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
838 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
839 HDR_SCTP.checksum = g_htonl(0);
840 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
841 if (hdr_data_chunk) {
842 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
843 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
844 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
846 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
848 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
849 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
850 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
853 /* Write DATA chunk header */
854 if (hdr_data_chunk) {
855 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
858 /* Reset curr_offset, since we now write the trailers */
859 curr_offset = length;
861 /* Write DATA chunk padding */
862 if (hdr_data_chunk && (padding_length > 0)) {
863 memset(tempbuf, 0, padding_length);
864 write_bytes((const char *)&tempbuf, padding_length);
865 length += padding_length;
868 /* Write Ethernet trailer */
869 if (hdr_ethernet && (length < 60)) {
870 memset(tempbuf, 0, 60 - length);
871 write_bytes((const char *)&tempbuf, 60 - length);
875 success = pcapng_write_enhanced_packet_block(output_file,
881 packet_buf, direction,
882 &bytes_written, &err);
884 success = libpcap_write_packet(output_file,
885 ts_sec, ts_nsec/1000,
888 &bytes_written, &err);
891 fprintf(stderr, "File write error [%s] : %s\n",
892 output_filename, g_strerror(err));
895 if (ts_fmt == NULL) {
896 /* fake packet counter */
903 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
905 num_packets_written++;
908 packet_start += curr_offset - header_length;
909 curr_offset = header_length;
913 /*----------------------------------------------------------------------
914 * Write file header and trailer
917 write_file_header (void)
926 appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
927 comment = g_strdup_printf("Generated from input file %s.", input_filename);
928 success = pcapng_write_session_header_block(output_file,
933 -1, /* section_length */
939 success = pcapng_write_interface_description_block(output_file,
953 success = libpcap_write_file_header(output_file, pcap_link_type,
955 &bytes_written, &err);
958 fprintf(stderr, "File write error [%s] : %s\n",
959 output_filename, g_strerror(err));
965 write_file_trailer (void)
971 success = pcapng_write_interface_statistics_block(output_file,
974 "Counters provided by text2pcap",
978 num_packets_written - num_packets_written,
985 fprintf(stderr, "File write error [%s] : %s\n",
986 output_filename, g_strerror(err));
992 /*----------------------------------------------------------------------
993 * Append a token to the packet preamble.
996 append_to_preamble (char *str)
1000 if (packet_preamble_len != 0) {
1001 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1002 return; /* no room to add more preamble */
1003 /* Add a blank separator between the previous token and this token. */
1004 packet_preamble[packet_preamble_len++] = ' ';
1006 toklen = strlen(str);
1008 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1009 return; /* no room to add the token to the preamble */
1010 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1011 packet_preamble_len += (int) toklen;
1014 char xs[PACKET_PREAMBLE_MAX_LEN];
1015 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1016 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1017 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1022 /*----------------------------------------------------------------------
1023 * Parse the preamble to get the timecode.
1027 parse_preamble (void)
1036 * Null-terminate the preamble.
1038 packet_preamble[packet_preamble_len] = '\0';
1040 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1042 if (has_direction) {
1043 switch (packet_preamble[0]) {
1046 direction = 0x00000001;
1047 packet_preamble[0] = ' ';
1051 direction = 0x00000002;
1052 packet_preamble[0] = ' ';
1055 direction = 0x00000000;
1059 while (packet_preamble[i] == ' ' ||
1060 packet_preamble[i] == '\r' ||
1061 packet_preamble[i] == '\t') {
1064 packet_preamble_len -= i;
1065 /* Also move the trailing '\0'. */
1066 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1071 * If no "-t" flag was specified, don't attempt to parse the packet
1072 * preamble to extract a time stamp.
1074 if (ts_fmt == NULL) {
1075 /* Clear Preamble */
1076 packet_preamble_len = 0;
1081 * Initialize to today localtime, just in case not all fields
1082 * of the date and time are specified.
1085 timecode = timecode_default;
1088 /* Ensure preamble has more than two chars before attempting to parse.
1089 * This should cover line breaks etc that get counted.
1091 if (strlen(packet_preamble) > 2) {
1092 /* Get Time leaving subseconds */
1093 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1094 if (subsecs != NULL) {
1095 /* Get the long time from the tm structure */
1096 /* (will return -1 if failure) */
1097 ts_sec = mktime( &timecode );
1099 ts_sec = -1; /* we failed to parse it */
1101 /* This will ensure incorrectly parsed dates get set to zero */
1103 /* Sanitize - remove all '\r' */
1105 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1106 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1107 packet_preamble, ts_fmt);
1109 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1110 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1111 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1113 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1116 /* Parse subseconds */
1117 ts_nsec = (guint32)strtol(subsecs, &p, 10);
1123 * Convert that number to a number
1124 * of microseconds; if it's N digits
1125 * long, it's in units of 10^(-N) seconds,
1126 * so, to convert it to units of
1127 * 10^-9 seconds, we multiply by
1130 subseclen = (int) (p - subsecs);
1131 if (subseclen > 9) {
1133 * *More* than 9 digits; 9-N is
1134 * negative, so we divide by
1137 for (i = subseclen - 9; i != 0; i--)
1139 } else if (subseclen < 9) {
1140 for (i = 9 - subseclen; i != 0; i--)
1148 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1149 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1150 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1154 /* Clear Preamble */
1155 packet_preamble_len = 0;
1158 /*----------------------------------------------------------------------
1159 * Start a new packet
1162 start_new_packet (gboolean cont)
1165 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1167 /* Write out the current packet, if required */
1168 write_current_packet(cont);
1171 /* Ensure we parse the packet preamble as it may contain the time */
1175 /*----------------------------------------------------------------------
1176 * Process a directive
1179 process_directive (char *str)
1181 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1184 /*----------------------------------------------------------------------
1185 * Parse a single token (called from the scanner)
1188 parse_token (token_t token, char *str)
1199 * This is implemented as a simple state machine of five states.
1200 * State transitions are caused by tokens being received from the
1201 * scanner. The code should be self-documenting.
1205 /* Sanitize - remove all '\r' */
1207 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1209 fprintf(stderr, "(%s, %s \"%s\") -> (",
1210 state_str[state], token_str[token], str ? str : "");
1215 /* ----- Waiting for new packet -------------------------------------------*/
1217 if (!str && token != T_EOL) goto fail_null_str;
1220 append_to_preamble(str);
1223 process_directive(str);
1226 num = parse_num(str, TRUE);
1228 /* New packet starts here */
1229 start_new_packet(FALSE);
1230 state = READ_OFFSET;
1231 pkt_lnstart = packet_buf + num;
1235 /* Some describing text may be parsed as offset, but the invalid
1236 offset will be checked in the state of START_OF_LINE, so
1237 we add this transition to gain flexibility */
1238 state = START_OF_LINE;
1245 /* ----- Processing packet, start of new line -----------------------------*/
1247 if (!str && token != T_EOL) goto fail_null_str;
1250 append_to_preamble(str);
1253 process_directive(str);
1256 num = parse_num(str, TRUE);
1258 /* New packet starts here */
1259 start_new_packet(FALSE);
1261 state = READ_OFFSET;
1262 } else if ((num - packet_start) != curr_offset - header_length) {
1264 * The offset we read isn't the one we expected.
1265 * This may only mean that we mistakenly interpreted
1266 * some text as byte values (e.g., if the text dump
1267 * of packet data included a number with spaces around
1268 * it). If the offset is less than what we expected,
1269 * assume that's the problem, and throw away the putative
1270 * extra byte values.
1272 if (num < curr_offset) {
1273 unwrite_bytes(curr_offset - num);
1274 state = READ_OFFSET;
1276 /* Bad offset; switch to INIT state */
1278 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1280 write_current_packet(FALSE);
1284 state = READ_OFFSET;
1285 pkt_lnstart = packet_buf + num;
1288 state = START_OF_LINE;
1295 /* ----- Processing packet, read offset -----------------------------------*/
1299 /* Record the byte */
1301 if (!str) goto fail_null_str;
1310 state = START_OF_LINE;
1317 /* ----- Processing packet, read byte -------------------------------------*/
1321 /* Record the byte */
1330 if (token == T_EOL) {
1332 state = START_OF_LINE;
1334 if (identify_ascii) {
1335 /* Here a line of pkt bytes reading is finished
1336 compare the ascii and hex to avoid such situation:
1337 "61 62 20 ab ", when ab is ascii dump then it should
1338 not be treat as byte */
1340 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1341 s2 = "ab ", s1 = "616220"
1342 we should find out the largest tail of s1 matches the head
1343 of s2, it means the matched part in tail is the ASCII dump
1344 of the head byte. These matched should be rollback */
1345 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1346 s2 = (char*)g_malloc((line_size+1)/4+1);
1347 /* gather the possible pattern */
1348 for (i = 0; i < (line_size+1)/4; i++) {
1349 tmp_str[0] = pkt_lnstart[i*3];
1350 tmp_str[1] = pkt_lnstart[i*3+1];
1352 /* it is a valid convertable string */
1353 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1356 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1358 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1359 if (!(pkt_lnstart[i*3+2] == ' ')) {
1365 /* If packet line start contains possible byte pattern, the line end
1366 should contain the matched pattern if the user open the -a flag.
1367 The packet will be possible invalid if the byte pattern cannot find
1368 a matched one in the line of packet buffer.*/
1370 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1371 unwrite_bytes(rollback);
1373 /* Not matched. This line contains invalid packet bytes, so
1374 discard the whole line */
1376 unwrite_bytes(line_size);
1387 /* ----- Processing packet, read text -------------------------------------*/
1391 state = START_OF_LINE;
1399 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1404 fprintf(stderr, ", %s)\n", state_str[state]);
1409 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1414 /*----------------------------------------------------------------------
1415 * Print usage string and exit
1418 print_usage (FILE *output)
1422 "Usage: text2pcap [options] <infile> <outfile>\n"
1424 "where <infile> specifies input filename (use - for standard input)\n"
1425 " <outfile> specifies output filename (use - for standard output)\n"
1428 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1429 " default is hex.\n"
1430 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1431 " the specified argument is a format string of the sort\n"
1432 " supported by strptime.\n"
1433 " Example: The time \"10:15:14.5476\" has the format code\n"
1434 " \"%%H:%%M:%%S.\"\n"
1435 " NOTE: The subsecond component delimiter, '.', must be\n"
1436 " given, but no pattern is required; the remaining\n"
1437 " number is assumed to be fractions of a second.\n"
1438 " NOTE: Date/time fields from the current date/time are\n"
1439 " used as the default for unspecified fields.\n"
1440 " -D the text before the packet starts with an I or an O,\n"
1441 " indicating that the packet is inbound or outbound.\n"
1442 " This is only stored if the output format is PCAP-NG.\n"
1443 " -a enable ASCII text dump identification.\n"
1444 " The start of the ASCII text dump can be identified\n"
1445 " and excluded from the packet data, even if it looks\n"
1446 " like a HEX dump.\n"
1447 " NOTE: Do not enable it if the input file does not\n"
1448 " contain the ASCII text dump.\n"
1451 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1452 " http://www.tcpdump.org/linktypes.html for a list of\n"
1453 " numbers. Use this option if your dump is a complete\n"
1454 " hex dump of an encapsulated packet and you wish to\n"
1455 " specify the exact type of encapsulation.\n"
1456 " Example: -l 7 for ARCNet packets.\n"
1457 " -m <max-packet> max packet length in output; default is %d\n"
1459 "Prepend dummy header:\n"
1460 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1462 " Example: -e 0x806 to specify an ARP packet.\n"
1463 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1465 " Automatically prepends Ethernet header as well.\n"
1467 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1468 " dest and source address.\n"
1469 " Example: -4 10.0.0.1,10.0.0.2\n"
1470 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1471 " dest and source address.\n"
1472 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1473 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1474 " source and destination ports (in DECIMAL).\n"
1475 " Automatically prepends Ethernet & IP headers as well.\n"
1476 " Example: -u 1000,69 to make the packets look like\n"
1477 " TFTP/UDP packets.\n"
1478 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1479 " source and destination ports (in DECIMAL).\n"
1480 " Automatically prepends Ethernet & IP headers as well.\n"
1481 " Example: -T 50,60\n"
1482 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1483 " source/dest ports and verification tag (in DECIMAL).\n"
1484 " Automatically prepends Ethernet & IP headers as well.\n"
1485 " Example: -s 30,40,34\n"
1486 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1487 " source/dest ports and verification tag 0.\n"
1488 " Automatically prepends a dummy SCTP DATA\n"
1489 " chunk header with payload protocol identifier ppi.\n"
1490 " Example: -S 30,40,34\n"
1493 " -h display this help and exit.\n"
1494 " -d show detailed debug of parser states.\n"
1495 " -q generate no output at all (automatically disables -d).\n"
1496 " -n use PCAP-NG instead of PCAP as output format.\n"
1502 get_text2pcap_compiled_info(GString *str)
1505 g_string_append(str, ", ");
1507 g_string_append(str, "with libz ");
1509 g_string_append(str, ZLIB_VERSION);
1510 #else /* ZLIB_VERSION */
1511 g_string_append(str, "(version unknown)");
1512 #endif /* ZLIB_VERSION */
1513 #else /* HAVE_LIBZ */
1514 g_string_append(str, "without libz");
1515 #endif /* HAVE_LIBZ */
1519 get_text2pcap_runtime_info(GString *str)
1522 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1523 g_string_append_printf(str, ", with libz %s", zlibVersion());
1527 /*----------------------------------------------------------------------
1531 parse_options (int argc, char *argv[])
1533 GString *comp_info_str;
1534 GString *runtime_info_str;
1537 static const struct option long_options[] = {
1538 {(char *)"help", no_argument, NULL, 'h'},
1539 {(char *)"version", no_argument, NULL, 'v'},
1544 arg_list_utf_16to8(argc, argv);
1545 create_app_running_mutex();
1548 /* Get the compile-time version information string */
1549 comp_info_str = get_compiled_version_info(NULL, get_text2pcap_compiled_info);
1551 /* get the run-time version information string */
1552 runtime_info_str = get_runtime_version_info(get_text2pcap_runtime_info);
1554 /* Add it to the information to be reported on a crash. */
1555 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1560 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1562 /* Scan CLI parameters */
1563 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1566 printf("Text2pcap (Wireshark) %s\n"
1567 "Generate a capture file from an ASCII hexdump of packets.\n"
1568 "See http://www.wireshark.org for more information.\n",
1569 get_ws_vcs_version_info());
1570 print_usage(stdout);
1573 case 'd': if (!quiet) debug++; break;
1574 case 'D': has_direction = TRUE; break;
1575 case 'q': quiet = TRUE; debug = FALSE; break;
1576 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1577 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1578 case 'n': use_pcapng = TRUE; break;
1580 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1581 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1582 print_usage(stderr);
1585 switch (optarg[0]) {
1586 case 'o': offset_base = 8; break;
1587 case 'h': offset_base = 16; break;
1588 case 'd': offset_base = 10; break;
1592 hdr_ethernet = TRUE;
1593 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1594 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1595 print_usage(stderr);
1602 hdr_ip_proto = strtol(optarg, &p, 10);
1603 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1604 hdr_ip_proto > 255) {
1605 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1606 print_usage(stderr);
1609 hdr_ethernet = TRUE;
1610 hdr_ethernet_proto = 0x800;
1615 hdr_data_chunk = FALSE;
1618 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1619 if (p == optarg || (*p != ',' && *p != '\0')) {
1620 fprintf(stderr, "Bad src port for '-%c'\n", c);
1621 print_usage(stderr);
1625 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1626 print_usage(stderr);
1631 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1632 if (p == optarg || (*p != ',' && *p != '\0')) {
1633 fprintf(stderr, "Bad dest port for '-s'\n");
1634 print_usage(stderr);
1638 fprintf(stderr, "No tag specified for '-%c'\n", c);
1639 print_usage(stderr);
1644 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1645 if (p == optarg || *p != '\0') {
1646 fprintf(stderr, "Bad tag for '-%c'\n", c);
1647 print_usage(stderr);
1653 hdr_ethernet = TRUE;
1654 hdr_ethernet_proto = 0x800;
1658 hdr_data_chunk = TRUE;
1661 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1662 if (p == optarg || (*p != ',' && *p != '\0')) {
1663 fprintf(stderr, "Bad src port for '-%c'\n", c);
1664 print_usage(stderr);
1668 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1669 print_usage(stderr);
1674 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1675 if (p == optarg || (*p != ',' && *p != '\0')) {
1676 fprintf(stderr, "Bad dest port for '-s'\n");
1677 print_usage(stderr);
1681 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1682 print_usage(stderr);
1687 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1688 if (p == optarg || *p != '\0') {
1689 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1690 print_usage(stderr);
1696 hdr_ethernet = TRUE;
1697 hdr_ethernet_proto = 0x800;
1708 hdr_data_chunk = FALSE;
1709 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1710 if (p == optarg || (*p != ',' && *p != '\0')) {
1711 fprintf(stderr, "Bad src port for '-u'\n");
1712 print_usage(stderr);
1716 fprintf(stderr, "No dest port specified for '-u'\n");
1717 print_usage(stderr);
1722 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1723 if (p == optarg || *p != '\0') {
1724 fprintf(stderr, "Bad dest port for '-u'\n");
1725 print_usage(stderr);
1730 hdr_ethernet = TRUE;
1731 hdr_ethernet_proto = 0x800;
1738 hdr_data_chunk = FALSE;
1739 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1740 if (p == optarg || (*p != ',' && *p != '\0')) {
1741 fprintf(stderr, "Bad src port for '-T'\n");
1742 print_usage(stderr);
1746 fprintf(stderr, "No dest port specified for '-u'\n");
1747 print_usage(stderr);
1752 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1753 if (p == optarg || *p != '\0') {
1754 fprintf(stderr, "Bad dest port for '-T'\n");
1755 print_usage(stderr);
1760 hdr_ethernet = TRUE;
1761 hdr_ethernet_proto = 0x800;
1765 identify_ascii = TRUE;
1769 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1770 g_string_free(comp_info_str, TRUE);
1771 g_string_free(runtime_info_str, TRUE);
1777 p = strchr(optarg, ',');
1780 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1781 print_usage(stderr);
1789 hdr_ethernet_proto = 0x86DD;
1794 hdr_ethernet_proto = 0x800;
1796 hdr_ethernet = TRUE;
1798 if (hdr_ipv6 == TRUE) {
1799 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1800 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1801 print_usage(stderr);
1805 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1806 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1807 print_usage(stderr);
1814 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1815 print_usage(stderr);
1819 if (hdr_ipv6 == TRUE) {
1820 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1821 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1822 print_usage(stderr);
1826 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1827 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1828 print_usage(stderr);
1837 print_usage(stderr);
1842 if (optind >= argc || argc-optind < 2) {
1843 fprintf(stderr, "Must specify input and output filename\n");
1844 print_usage(stderr);
1848 if (strcmp(argv[optind], "-")) {
1849 input_filename = g_strdup(argv[optind]);
1850 input_file = ws_fopen(input_filename, "rb");
1852 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1853 input_filename, g_strerror(errno));
1857 input_filename = "Standard input";
1861 if (strcmp(argv[optind+1], "-")) {
1862 output_filename = g_strdup(argv[optind+1]);
1863 output_file = ws_fopen(output_filename, "wb");
1865 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1866 output_filename, g_strerror(errno));
1870 output_filename = "Standard output";
1871 output_file = stdout;
1874 /* Some validation */
1875 if (pcap_link_type != 1 && hdr_ethernet) {
1876 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1880 /* Set up our variables */
1883 input_filename = "Standard input";
1886 output_file = stdout;
1887 output_filename = "Standard output";
1890 ts_sec = time(0); /* initialize to current time */
1891 timecode_default = *localtime(&ts_sec);
1892 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1894 /* Display summary of our state */
1896 fprintf(stderr, "Input from: %s\n", input_filename);
1897 fprintf(stderr, "Output to: %s\n", output_filename);
1898 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1900 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1901 hdr_ethernet_proto);
1902 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1904 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1905 hdr_src_port, hdr_dest_port);
1906 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1907 hdr_src_port, hdr_dest_port);
1908 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1909 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1910 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1911 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1916 main(int argc, char *argv[])
1918 parse_options(argc, argv);
1920 assert(input_file != NULL);
1921 assert(output_file != NULL);
1923 write_file_header();
1927 header_length += (int)sizeof(HDR_ETHERNET);
1930 ip_offset = header_length;
1931 header_length += (int)sizeof(HDR_IP);
1932 } else if (hdr_ipv6) {
1933 ip_offset = header_length;
1934 header_length += (int)sizeof(HDR_IPv6);
1937 header_length += (int)sizeof(HDR_SCTP);
1939 if (hdr_data_chunk) {
1940 header_length += (int)sizeof(HDR_DATA_CHUNK);
1943 header_length += (int)sizeof(HDR_TCP);
1946 header_length += (int)sizeof(HDR_UDP);
1948 curr_offset = header_length;
1953 write_current_packet(FALSE);
1954 write_file_trailer();
1956 fclose(output_file);
1958 fprintf(stderr, "\n-------------------------\n");
1960 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1961 num_packets_read, (num_packets_read == 1) ? "" : "s",
1962 num_packets_written, (num_packets_written == 1) ? "" : "s",
1963 bytes_written, (bytes_written == 1) ? "" : "s");
1969 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1974 * indent-tabs-mode: nil
1977 * vi: set shiftwidth=4 tabstop=8 expandtab:
1978 * :indentSize=4:tabSize=8:noTabs=true: