1 /**-*-C-*-**********************************************************************
5 * Utility to convert an ASCII hexdump into a libpcap-format capture file
7 * (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *******************************************************************************/
29 /*******************************************************************************
31 * This utility reads in an ASCII hexdump of this common format:
33 * 00000000 00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
34 * 00000010 03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3...
\7f..
35 * 00000020 03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
36 * 00000030 01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
38 * Each bytestring line consists of an offset, one or more bytes, and
39 * text at the end. An offset is defined as a hex string of more than
40 * two characters. A byte is defined as a hex string of exactly two
41 * characters. The text at the end is ignored, as is any text before
42 * the offset. Bytes read from a bytestring line are added to the
43 * current packet only if all the following conditions are satisfied:
45 * - No text appears between the offset and the bytes (any bytes appearing after
46 * such text would be ignored)
48 * - The offset must be arithmetically correct, i.e. if the offset is 00000020, then
49 * exactly 32 bytes must have been read into this packet before this. If the offset
50 * is wrong, the packet is immediately terminated
52 * A packet start is signaled by a zero offset.
54 * Lines starting with #TEXT2PCAP are directives. These allow the user
55 * to embed instructions into the capture file which allows text2pcap
56 * to take some actions (e.g. specifying the encapsulation
57 * etc.). Currently no directives are implemented.
59 * Lines beginning with # which are not directives are ignored as
60 * comments. Currently all non-hexdump text is ignored by text2pcap;
61 * in the future, text processing may be added, but lines prefixed
62 * with '#' will still be ignored.
64 * The output is a libpcap packet containing Ethernet frames by
65 * default. This program takes options which allow the user to add
66 * dummy Ethernet, IP and UDP or TCP headers to the packets in order
67 * to allow dumps of L3 or higher protocols to be decoded.
69 * Considerable flexibility is built into this code to read hexdumps
70 * of slightly different formats. For example, any text prefixing the
71 * hexdump line is dropped (including mail forwarding '>'). The offset
72 * can be any hex number of four digits or greater.
74 * This converter cannot read a single packet greater than 64KiB-1. Packet
75 * snaplength is automatically set to 64KiB-1.
81 * Just make sure we include the prototype for strptime as well
82 * (needed for glibc 2.2) but make sure we do this only if not
90 # define _XOPEN_SOURCE 600
95 * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms
96 * using glibc, to expand the set of things system header files define.
98 * Unfortunately, on other platforms, such as some versions of Solaris
99 * (including Solaris 10), it *reduces* that set as well, causing
100 * strptime() not to be declared, presumably because the version of the
101 * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and
102 * blah blah blah namespace pollution blah blah blah.
104 * So we define __EXTENSIONS__ so that "strptime()" is declared.
106 #ifndef __EXTENSIONS__
107 # define __EXTENSIONS__
113 #include <wsutil/file_util.h>
114 #include <wsutil/crash_info.h>
115 #include <wsutil/ws_diag_control.h>
116 #include <wsutil/ws_version_info.h>
133 #include <zlib.h> /* to get the libz version number */
136 #ifndef HAVE_GETOPT_LONG
137 #include "wsutil/wsgetopt.h"
140 #ifndef HAVE_STRPTIME
141 # include "wsutil/strptime.h"
145 #include "text2pcap.h"
148 #include <wsutil/unicode-utils.h>
151 #ifdef HAVE_ARPA_INET_H
152 #include <arpa/inet.h>
155 #ifdef HAVE_WINSOCK2_H
156 #include <winsock2.h> /* needed to define AF_ values on Windows */
159 #ifndef HAVE_INET_ATON
160 # include "wsutil/inet_aton.h"
163 #ifdef HAVE_SYS_SOCKET_H
164 #include <sys/socket.h>
167 #ifdef NEED_INET_V6DEFS_H
168 # include "wsutil/inet_v6defs.h"
171 /*--- Options --------------------------------------------------------------------*/
174 static gboolean use_pcapng = FALSE;
177 static int debug = 0;
179 static int quiet = FALSE;
181 /* Dummy Ethernet header */
182 static int hdr_ethernet = FALSE;
183 static guint32 hdr_ethernet_proto = 0;
185 /* Dummy IP header */
186 static int hdr_ip = FALSE;
187 static int hdr_ipv6 = FALSE;
188 static long hdr_ip_proto = 0;
190 /* Destination and source addresses for IP header */
191 static guint32 hdr_ip_dest_addr = 0;
192 static guint32 hdr_ip_src_addr = 0;
193 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
194 static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
195 static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
197 /* Dummy UDP header */
198 static int hdr_udp = FALSE;
199 static guint32 hdr_dest_port = 0;
200 static guint32 hdr_src_port = 0;
202 /* Dummy TCP header */
203 static int hdr_tcp = FALSE;
205 /* TCP sequence numbers when has_direction is true */
206 static guint32 tcp_in_seq_num = 0;
207 static guint32 tcp_out_seq_num = 0;
209 /* Dummy SCTP header */
210 static int hdr_sctp = FALSE;
211 static guint32 hdr_sctp_src = 0;
212 static guint32 hdr_sctp_dest = 0;
213 static guint32 hdr_sctp_tag = 0;
215 /* Dummy DATA chunk header */
216 static int hdr_data_chunk = FALSE;
217 static guint8 hdr_data_chunk_type = 0;
218 static guint8 hdr_data_chunk_bits = 0;
219 static guint32 hdr_data_chunk_tsn = 0;
220 static guint16 hdr_data_chunk_sid = 0;
221 static guint16 hdr_data_chunk_ssn = 0;
222 static guint32 hdr_data_chunk_ppid = 0;
224 /* ASCII text dump identification */
225 static int identify_ascii = FALSE;
227 static gboolean has_direction = FALSE;
228 static guint32 direction = 0;
230 /*--- Local date -----------------------------------------------------------------*/
232 /* This is where we store the packet currently being built */
233 #define MAX_PACKET 65535
234 static guint8 packet_buf[MAX_PACKET];
235 static guint32 header_length;
236 static guint32 ip_offset;
237 static guint32 curr_offset;
238 static guint32 max_offset = MAX_PACKET;
239 static guint32 packet_start = 0;
241 static void start_new_packet(gboolean);
243 /* This buffer contains strings present before the packet offset 0 */
244 #define PACKET_PREAMBLE_MAX_LEN 2048
245 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
246 static int packet_preamble_len = 0;
248 /* Number of packets read and written */
249 static guint32 num_packets_read = 0;
250 static guint32 num_packets_written = 0;
251 static guint64 bytes_written = 0;
253 /* Time code of packet, derived from packet_preamble */
254 static time_t ts_sec = 0;
255 static guint32 ts_nsec = 0;
256 static char *ts_fmt = NULL;
257 static struct tm timecode_default;
259 static guint8* pkt_lnstart;
262 static const char *input_filename;
263 static FILE *input_file = NULL;
265 static const char *output_filename;
266 static FILE *output_file = NULL;
268 /* Offset base to parse */
269 static guint32 offset_base = 16;
273 /* ----- State machine -----------------------------------------------------------*/
275 /* Current state of parser */
277 INIT, /* Waiting for start of new packet */
278 START_OF_LINE, /* Starting from beginning of line */
279 READ_OFFSET, /* Just read the offset */
280 READ_BYTE, /* Just read a byte */
281 READ_TEXT /* Just read text - ignore until EOL */
283 static parser_state_t state = INIT;
285 static const char *state_str[] = {"Init",
292 static const char *token_str[] = {"",
300 /* ----- Skeleton Packet Headers --------------------------------------------------*/
308 static hdr_ethernet_t HDR_ETHERNET = {
309 {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
310 {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
316 guint16 packet_length;
317 guint16 identification;
322 guint16 hdr_checksum;
327 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
328 #ifdef WORDS_BIGENDIAN
329 0x0a010101, 0x0a020202
331 0x0101010a, 0x0202020a
335 /* Fixed IP address values */
336 #ifdef WORDS_BIGENDIAN
337 #define IP_SRC 0x0a010101
338 #define IP_DST 0x0a020202
340 #define IP_SRC 0x0101010a
341 #define IP_DST 0x0202020a
344 static struct { /* pseudo header for checksum calculation */
353 /* headers taken from glibc */
360 guint8 __u6_addr8[16];
361 guint16 __u6_addr16[8];
362 guint32 __u6_addr32[4];
369 guint32 ip6_un1_flow; /* 24 bits of flow-ID */
370 guint16 ip6_un1_plen; /* payload length */
371 guint8 ip6_un1_nxt; /* next header */
372 guint8 ip6_un1_hlim; /* hop limit */
374 guint8 ip6_un2_vfc; /* 4 bits version, 4 bits priority */
376 struct hdr_in6_addr ip6_src; /* source address */
377 struct hdr_in6_addr ip6_dst; /* destination address */
380 static hdr_ipv6_t HDR_IPv6;
382 static struct { /* pseudo header ipv6 for checksum calculation */
383 struct hdr_in6_addr src_addr6;
384 struct hdr_in6_addr dst_addr6;
397 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
411 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
420 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
432 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
434 static char tempbuf[64];
436 /*----------------------------------------------------------------------
437 * Stuff for writing a PCap file
439 #define PCAP_SNAPLEN 0xffff
441 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
442 static guint32 pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
444 /*----------------------------------------------------------------------
445 * Parse a single hex number
446 * Will abort the program if it can't parse the number
447 * Pass in TRUE if this is an offset, FALSE if not
450 parse_num (const char *str, int offset)
456 fprintf(stderr, "FATAL ERROR: str is NULL\n");
460 num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
462 fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
468 /*----------------------------------------------------------------------
469 * Write this byte into current packet
472 write_byte (const char *str)
476 num = parse_num(str, FALSE);
477 packet_buf[curr_offset] = (guint8) num;
479 if (curr_offset - header_length >= max_offset) /* packet full */
480 start_new_packet(TRUE);
483 /*----------------------------------------------------------------------
484 * Write a number of bytes into current packet
488 write_bytes (const char bytes[], guint32 nbytes)
492 if (curr_offset + nbytes < MAX_PACKET) {
493 for (i = 0; i < nbytes; i++) {
494 packet_buf[curr_offset] = bytes[i];
500 /*----------------------------------------------------------------------
501 * Remove bytes from the current packet
504 unwrite_bytes (guint32 nbytes)
506 curr_offset -= nbytes;
509 /*----------------------------------------------------------------------
510 * Compute one's complement checksum (from RFC1071)
513 in_checksum (void *buf, guint32 count)
516 guint16 *addr = (guint16 *)buf;
519 /* This is the inner loop */
520 sum += g_ntohs(* (guint16 *) addr);
525 /* Add left-over byte, if any */
527 sum += g_ntohs(* (guint8 *) addr);
529 /* Fold 32-bit sum to 16 bits */
531 sum = (sum & 0xffff) + (sum >> 16);
537 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
538 * That code is copyrighted by D. Otis and has been modified.
541 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
542 static guint32 crc_c[256] =
544 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
545 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
546 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
547 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
548 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
549 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
550 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
551 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
552 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
553 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
554 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
555 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
556 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
557 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
558 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
559 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
560 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
561 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
562 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
563 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
564 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
565 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
566 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
567 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
568 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
569 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
570 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
571 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
572 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
573 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
574 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
575 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
576 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
577 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
578 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
579 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
580 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
581 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
582 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
583 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
584 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
585 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
586 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
587 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
588 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
589 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
590 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
591 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
592 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
593 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
594 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
595 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
596 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
597 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
598 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
599 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
600 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
601 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
602 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
603 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
604 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
605 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
606 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
607 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
611 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
617 for (i = 0; i < len; i++)
624 finalize_crc32c (guint32 crc)
627 guint8 byte0,byte1,byte2,byte3;
630 byte0 = result & 0xff;
631 byte1 = (result>>8) & 0xff;
632 byte2 = (result>>16) & 0xff;
633 byte3 = (result>>24) & 0xff;
634 result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
639 number_of_padding_bytes (guint32 length)
643 remainder = length % 4;
648 return 4 - remainder;
651 /*----------------------------------------------------------------------
652 * Write current packet out
655 write_current_packet (gboolean cont)
658 guint16 padding_length = 0;
663 if (curr_offset > header_length) {
664 /* Write the packet */
666 /* Is direction indication on with an inbound packet? */
667 gboolean isInbound = has_direction && (direction == 2);
669 /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
671 hdr_ethernet_proto = 0x86DD;
675 /* Compute packet length */
676 length = curr_offset;
678 padding_length = number_of_padding_bytes(length - header_length );
682 /* Reset curr_offset, since we now write the headers */
685 /* Write Ethernet header */
687 HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
688 write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
691 /* Write IP header */
694 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
695 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
698 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
699 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
702 HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
703 HDR_IP.protocol = (guint8) hdr_ip_proto;
704 HDR_IP.hdr_checksum = 0;
705 HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
706 write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
707 } else if (hdr_ipv6) {
708 if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
709 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
710 if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
711 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
713 HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
714 HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
715 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
716 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (guint8) hdr_ip_proto;
717 HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
718 write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
720 /* initialize pseudo ipv6 header for checksum calculation */
721 pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
722 pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
724 pseudoh6.protocol = (guint8) hdr_ip_proto;
725 ihatemacros = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
726 pseudoh.length = g_htons(length - ihatemacros + sizeof(HDR_UDP));
730 /* initialize pseudo header for checksum calculation */
731 pseudoh.src_addr = HDR_IP.src_addr;
732 pseudoh.dest_addr = HDR_IP.dest_addr;
734 pseudoh.protocol = (guint8) hdr_ip_proto;
735 pseudoh.length = g_htons(length - header_length + sizeof(HDR_UDP));
738 /* Write UDP header */
743 /* initialize the UDP header */
744 HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
745 HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
746 HDR_UDP.length = pseudoh.length;
747 HDR_UDP.checksum = 0;
748 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
749 x16 = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
751 x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
753 x16 = in_checksum(packet_buf + header_length, length - header_length);
755 x16 = (u & 0xffff) + (u>>16);
756 HDR_UDP.checksum = g_htons(x16);
757 if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
758 HDR_UDP.checksum = g_htons(1);
759 write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
762 /* Write TCP header */
767 /* initialize pseudo header for checksum calculation */
768 pseudoh.src_addr = HDR_IP.src_addr;
769 pseudoh.dest_addr = HDR_IP.dest_addr;
771 pseudoh.protocol = (guint8) hdr_ip_proto;
772 pseudoh.length = g_htons(length - header_length + sizeof(HDR_TCP));
773 /* initialize the TCP header */
774 HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
775 HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
776 /* set ack number if we have direction */
778 HDR_TCP.flags = 0x10;
779 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
780 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
786 HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
787 HDR_TCP.window = g_htons(0x2000);
788 HDR_TCP.checksum = 0;
789 /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
790 x16 = in_checksum(&pseudoh, sizeof(pseudoh));
792 x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
794 x16 = in_checksum(packet_buf + header_length, length - header_length);
796 x16 = (u & 0xffff) + (u>>16);
797 HDR_TCP.checksum = g_htons(x16);
798 if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
799 HDR_TCP.checksum = g_htons(1);
800 write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
802 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
803 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
806 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
807 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
811 /* Compute DATA chunk header */
812 if (hdr_data_chunk) {
813 hdr_data_chunk_bits = 0;
814 if (packet_start == 0) {
815 hdr_data_chunk_bits |= 0x02;
818 hdr_data_chunk_bits |= 0x01;
820 HDR_DATA_CHUNK.type = hdr_data_chunk_type;
821 HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
822 HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
823 HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn);
824 HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid);
825 HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn);
826 HDR_DATA_CHUNK.ppid = g_htonl(hdr_data_chunk_ppid);
827 hdr_data_chunk_tsn++;
829 hdr_data_chunk_ssn++;
833 /* Write SCTP common header */
837 HDR_SCTP.src_port = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
838 HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
839 HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
840 HDR_SCTP.checksum = g_htonl(0);
841 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
842 if (hdr_data_chunk) {
843 HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
844 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
845 HDR_SCTP.checksum = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
847 HDR_SCTP.checksum = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
849 HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
850 HDR_SCTP.checksum = g_htonl(HDR_SCTP.checksum);
851 write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
854 /* Write DATA chunk header */
855 if (hdr_data_chunk) {
856 write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
859 /* Reset curr_offset, since we now write the trailers */
860 curr_offset = length;
862 /* Write DATA chunk padding */
863 if (hdr_data_chunk && (padding_length > 0)) {
864 memset(tempbuf, 0, padding_length);
865 write_bytes((const char *)&tempbuf, padding_length);
866 length += padding_length;
869 /* Write Ethernet trailer */
870 if (hdr_ethernet && (length < 60)) {
871 memset(tempbuf, 0, 60 - length);
872 write_bytes((const char *)&tempbuf, 60 - length);
876 success = pcapng_write_enhanced_packet_block(output_file,
882 packet_buf, direction,
883 &bytes_written, &err);
885 success = libpcap_write_packet(output_file,
886 ts_sec, ts_nsec/1000,
889 &bytes_written, &err);
892 fprintf(stderr, "File write error [%s] : %s\n",
893 output_filename, g_strerror(err));
896 if (ts_fmt == NULL) {
897 /* fake packet counter */
904 fprintf(stderr, "Wrote packet of %u bytes.\n", length);
906 num_packets_written++;
909 packet_start += curr_offset - header_length;
910 curr_offset = header_length;
914 /*----------------------------------------------------------------------
915 * Write file header and trailer
918 write_file_header (void)
927 appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
928 comment = g_strdup_printf("Generated from input file %s.", input_filename);
929 success = pcapng_write_session_header_block(output_file,
934 -1, /* section_length */
940 success = pcapng_write_interface_description_block(output_file,
954 success = libpcap_write_file_header(output_file, pcap_link_type,
956 &bytes_written, &err);
959 fprintf(stderr, "File write error [%s] : %s\n",
960 output_filename, g_strerror(err));
966 write_file_trailer (void)
972 success = pcapng_write_interface_statistics_block(output_file,
975 "Counters provided by text2pcap",
979 num_packets_written - num_packets_written,
986 fprintf(stderr, "File write error [%s] : %s\n",
987 output_filename, g_strerror(err));
993 /*----------------------------------------------------------------------
994 * Append a token to the packet preamble.
997 append_to_preamble (char *str)
1001 if (packet_preamble_len != 0) {
1002 if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1003 return; /* no room to add more preamble */
1004 /* Add a blank separator between the previous token and this token. */
1005 packet_preamble[packet_preamble_len++] = ' ';
1007 toklen = strlen(str);
1009 if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1010 return; /* no room to add the token to the preamble */
1011 g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1012 packet_preamble_len += (int) toklen;
1015 char xs[PACKET_PREAMBLE_MAX_LEN];
1016 g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1017 while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1018 fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1023 /*----------------------------------------------------------------------
1024 * Parse the preamble to get the timecode.
1028 parse_preamble (void)
1037 * Null-terminate the preamble.
1039 packet_preamble[packet_preamble_len] = '\0';
1041 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1043 if (has_direction) {
1044 switch (packet_preamble[0]) {
1047 direction = 0x00000001;
1048 packet_preamble[0] = ' ';
1052 direction = 0x00000002;
1053 packet_preamble[0] = ' ';
1056 direction = 0x00000000;
1060 while (packet_preamble[i] == ' ' ||
1061 packet_preamble[i] == '\r' ||
1062 packet_preamble[i] == '\t') {
1065 packet_preamble_len -= i;
1066 /* Also move the trailing '\0'. */
1067 memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1072 * If no "-t" flag was specified, don't attempt to parse the packet
1073 * preamble to extract a time stamp.
1075 if (ts_fmt == NULL) {
1076 /* Clear Preamble */
1077 packet_preamble_len = 0;
1082 * Initialize to today localtime, just in case not all fields
1083 * of the date and time are specified.
1086 timecode = timecode_default;
1089 /* Ensure preamble has more than two chars before attempting to parse.
1090 * This should cover line breaks etc that get counted.
1092 if (strlen(packet_preamble) > 2) {
1093 /* Get Time leaving subseconds */
1094 subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1095 if (subsecs != NULL) {
1096 /* Get the long time from the tm structure */
1097 /* (will return -1 if failure) */
1098 ts_sec = mktime( &timecode );
1100 ts_sec = -1; /* we failed to parse it */
1102 /* This will ensure incorrectly parsed dates get set to zero */
1104 /* Sanitize - remove all '\r' */
1106 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1107 fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1108 packet_preamble, ts_fmt);
1110 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1111 timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1112 timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1114 ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1117 /* Parse subseconds */
1118 ts_nsec = (guint32)strtol(subsecs, &p, 10);
1124 * Convert that number to a number
1125 * of microseconds; if it's N digits
1126 * long, it's in units of 10^(-N) seconds,
1127 * so, to convert it to units of
1128 * 10^-9 seconds, we multiply by
1131 subseclen = (int) (p - subsecs);
1132 if (subseclen > 9) {
1134 * *More* than 9 digits; 9-N is
1135 * negative, so we divide by
1138 for (i = subseclen - 9; i != 0; i--)
1140 } else if (subseclen < 9) {
1141 for (i = 9 - subseclen; i != 0; i--)
1149 while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1150 fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1151 fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1155 /* Clear Preamble */
1156 packet_preamble_len = 0;
1159 /*----------------------------------------------------------------------
1160 * Start a new packet
1163 start_new_packet (gboolean cont)
1166 fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1168 /* Write out the current packet, if required */
1169 write_current_packet(cont);
1172 /* Ensure we parse the packet preamble as it may contain the time */
1176 /*----------------------------------------------------------------------
1177 * Process a directive
1180 process_directive (char *str)
1182 fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1185 /*----------------------------------------------------------------------
1186 * Parse a single token (called from the scanner)
1189 parse_token (token_t token, char *str)
1200 * This is implemented as a simple state machine of five states.
1201 * State transitions are caused by tokens being received from the
1202 * scanner. The code should be self-documenting.
1206 /* Sanitize - remove all '\r' */
1208 if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1210 fprintf(stderr, "(%s, %s \"%s\") -> (",
1211 state_str[state], token_str[token], str ? str : "");
1216 /* ----- Waiting for new packet -------------------------------------------*/
1218 if (!str && token != T_EOL) goto fail_null_str;
1221 append_to_preamble(str);
1224 process_directive(str);
1227 num = parse_num(str, TRUE);
1229 /* New packet starts here */
1230 start_new_packet(FALSE);
1231 state = READ_OFFSET;
1232 pkt_lnstart = packet_buf + num;
1236 /* Some describing text may be parsed as offset, but the invalid
1237 offset will be checked in the state of START_OF_LINE, so
1238 we add this transition to gain flexibility */
1239 state = START_OF_LINE;
1246 /* ----- Processing packet, start of new line -----------------------------*/
1248 if (!str && token != T_EOL) goto fail_null_str;
1251 append_to_preamble(str);
1254 process_directive(str);
1257 num = parse_num(str, TRUE);
1259 /* New packet starts here */
1260 start_new_packet(FALSE);
1262 state = READ_OFFSET;
1263 } else if ((num - packet_start) != curr_offset - header_length) {
1265 * The offset we read isn't the one we expected.
1266 * This may only mean that we mistakenly interpreted
1267 * some text as byte values (e.g., if the text dump
1268 * of packet data included a number with spaces around
1269 * it). If the offset is less than what we expected,
1270 * assume that's the problem, and throw away the putative
1271 * extra byte values.
1273 if (num < curr_offset) {
1274 unwrite_bytes(curr_offset - num);
1275 state = READ_OFFSET;
1277 /* Bad offset; switch to INIT state */
1279 fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1281 write_current_packet(FALSE);
1285 state = READ_OFFSET;
1286 pkt_lnstart = packet_buf + num;
1289 state = START_OF_LINE;
1296 /* ----- Processing packet, read offset -----------------------------------*/
1300 /* Record the byte */
1302 if (!str) goto fail_null_str;
1311 state = START_OF_LINE;
1318 /* ----- Processing packet, read byte -------------------------------------*/
1322 /* Record the byte */
1331 if (token == T_EOL) {
1333 state = START_OF_LINE;
1335 if (identify_ascii) {
1336 /* Here a line of pkt bytes reading is finished
1337 compare the ascii and hex to avoid such situation:
1338 "61 62 20 ab ", when ab is ascii dump then it should
1339 not be treat as byte */
1341 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1342 s2 = "ab ", s1 = "616220"
1343 we should find out the largest tail of s1 matches the head
1344 of s2, it means the matched part in tail is the ASCII dump
1345 of the head byte. These matched should be rollback */
1346 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1347 s2 = (char*)g_malloc((line_size+1)/4+1);
1348 /* gather the possible pattern */
1349 for (i = 0; i < (line_size+1)/4; i++) {
1350 tmp_str[0] = pkt_lnstart[i*3];
1351 tmp_str[1] = pkt_lnstart[i*3+1];
1353 /* it is a valid convertable string */
1354 if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1357 s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1359 /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1360 if (!(pkt_lnstart[i*3+2] == ' ')) {
1366 /* If packet line start contains possible byte pattern, the line end
1367 should contain the matched pattern if the user open the -a flag.
1368 The packet will be possible invalid if the byte pattern cannot find
1369 a matched one in the line of packet buffer.*/
1371 if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1372 unwrite_bytes(rollback);
1374 /* Not matched. This line contains invalid packet bytes, so
1375 discard the whole line */
1377 unwrite_bytes(line_size);
1388 /* ----- Processing packet, read text -------------------------------------*/
1392 state = START_OF_LINE;
1400 fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1405 fprintf(stderr, ", %s)\n", state_str[state]);
1410 fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1415 /*----------------------------------------------------------------------
1416 * Print usage string and exit
1419 print_usage (FILE *output)
1423 "Usage: text2pcap [options] <infile> <outfile>\n"
1425 "where <infile> specifies input filename (use - for standard input)\n"
1426 " <outfile> specifies output filename (use - for standard output)\n"
1429 " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1430 " default is hex.\n"
1431 " -t <timefmt> treat the text before the packet as a date/time code;\n"
1432 " the specified argument is a format string of the sort\n"
1433 " supported by strptime.\n"
1434 " Example: The time \"10:15:14.5476\" has the format code\n"
1435 " \"%%H:%%M:%%S.\"\n"
1436 " NOTE: The subsecond component delimiter, '.', must be\n"
1437 " given, but no pattern is required; the remaining\n"
1438 " number is assumed to be fractions of a second.\n"
1439 " NOTE: Date/time fields from the current date/time are\n"
1440 " used as the default for unspecified fields.\n"
1441 " -D the text before the packet starts with an I or an O,\n"
1442 " indicating that the packet is inbound or outbound.\n"
1443 " This is only stored if the output format is PCAP-NG.\n"
1444 " -a enable ASCII text dump identification.\n"
1445 " The start of the ASCII text dump can be identified\n"
1446 " and excluded from the packet data, even if it looks\n"
1447 " like a HEX dump.\n"
1448 " NOTE: Do not enable it if the input file does not\n"
1449 " contain the ASCII text dump.\n"
1452 " -l <typenum> link-layer type number; default is 1 (Ethernet). See\n"
1453 " http://www.tcpdump.org/linktypes.html for a list of\n"
1454 " numbers. Use this option if your dump is a complete\n"
1455 " hex dump of an encapsulated packet and you wish to\n"
1456 " specify the exact type of encapsulation.\n"
1457 " Example: -l 7 for ARCNet packets.\n"
1458 " -m <max-packet> max packet length in output; default is %d\n"
1460 "Prepend dummy header:\n"
1461 " -e <l3pid> prepend dummy Ethernet II header with specified L3PID\n"
1463 " Example: -e 0x806 to specify an ARP packet.\n"
1464 " -i <proto> prepend dummy IP header with specified IP protocol\n"
1466 " Automatically prepends Ethernet header as well.\n"
1468 " -4 <srcip>,<destip> prepend dummy IPv4 header with specified\n"
1469 " dest and source address.\n"
1470 " Example: -4 10.0.0.1,10.0.0.2\n"
1471 " -6 <srcip>,<destip> replace IPv6 header with specified\n"
1472 " dest and source address.\n"
1473 " Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1474 " -u <srcp>,<destp> prepend dummy UDP header with specified\n"
1475 " source and destination ports (in DECIMAL).\n"
1476 " Automatically prepends Ethernet & IP headers as well.\n"
1477 " Example: -u 1000,69 to make the packets look like\n"
1478 " TFTP/UDP packets.\n"
1479 " -T <srcp>,<destp> prepend dummy TCP header with specified\n"
1480 " source and destination ports (in DECIMAL).\n"
1481 " Automatically prepends Ethernet & IP headers as well.\n"
1482 " Example: -T 50,60\n"
1483 " -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1484 " source/dest ports and verification tag (in DECIMAL).\n"
1485 " Automatically prepends Ethernet & IP headers as well.\n"
1486 " Example: -s 30,40,34\n"
1487 " -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1488 " source/dest ports and verification tag 0.\n"
1489 " Automatically prepends a dummy SCTP DATA\n"
1490 " chunk header with payload protocol identifier ppi.\n"
1491 " Example: -S 30,40,34\n"
1494 " -h display this help and exit.\n"
1495 " -d show detailed debug of parser states.\n"
1496 " -q generate no output at all (automatically disables -d).\n"
1497 " -n use PCAP-NG instead of PCAP as output format.\n"
1503 get_text2pcap_compiled_info(GString *str)
1506 g_string_append(str, ", ");
1508 g_string_append(str, "with libz ");
1510 g_string_append(str, ZLIB_VERSION);
1511 #else /* ZLIB_VERSION */
1512 g_string_append(str, "(version unknown)");
1513 #endif /* ZLIB_VERSION */
1514 #else /* HAVE_LIBZ */
1515 g_string_append(str, "without libz");
1516 #endif /* HAVE_LIBZ */
1520 get_text2pcap_runtime_info(GString *str)
1523 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1524 g_string_append_printf(str, ", with libz %s", zlibVersion());
1528 /*----------------------------------------------------------------------
1532 parse_options (int argc, char *argv[])
1534 GString *comp_info_str;
1535 GString *runtime_info_str;
1539 static const struct option long_options[] = {
1540 {(char *)"help", no_argument, NULL, 'h'},
1541 {(char *)"version", no_argument, NULL, 'v'},
1547 arg_list_utf_16to8(argc, argv);
1548 create_app_running_mutex();
1551 /* Get the compile-time version information string */
1552 comp_info_str = get_compiled_version_info(NULL, get_text2pcap_compiled_info);
1554 /* get the run-time version information string */
1555 runtime_info_str = get_runtime_version_info(get_text2pcap_runtime_info);
1557 /* Add it to the information to be reported on a crash. */
1558 ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1563 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1565 /* Scan CLI parameters */
1566 while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1569 printf("Text2pcap (Wireshark) %s\n"
1570 "Generate a capture file from an ASCII hexdump of packets.\n"
1571 "See http://www.wireshark.org for more information.\n",
1572 get_ws_vcs_version_info());
1573 print_usage(stdout);
1576 case 'd': if (!quiet) debug++; break;
1577 case 'D': has_direction = TRUE; break;
1578 case 'q': quiet = TRUE; debug = FALSE; break;
1579 case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1580 case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1581 case 'n': use_pcapng = TRUE; break;
1583 if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1584 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1585 print_usage(stderr);
1588 switch (optarg[0]) {
1589 case 'o': offset_base = 8; break;
1590 case 'h': offset_base = 16; break;
1591 case 'd': offset_base = 10; break;
1595 hdr_ethernet = TRUE;
1596 if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1597 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1598 print_usage(stderr);
1605 hdr_ip_proto = strtol(optarg, &p, 10);
1606 if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1607 hdr_ip_proto > 255) {
1608 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1609 print_usage(stderr);
1612 hdr_ethernet = TRUE;
1613 hdr_ethernet_proto = 0x800;
1618 hdr_data_chunk = FALSE;
1621 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1622 if (p == optarg || (*p != ',' && *p != '\0')) {
1623 fprintf(stderr, "Bad src port for '-%c'\n", c);
1624 print_usage(stderr);
1628 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1629 print_usage(stderr);
1634 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1635 if (p == optarg || (*p != ',' && *p != '\0')) {
1636 fprintf(stderr, "Bad dest port for '-s'\n");
1637 print_usage(stderr);
1641 fprintf(stderr, "No tag specified for '-%c'\n", c);
1642 print_usage(stderr);
1647 hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1648 if (p == optarg || *p != '\0') {
1649 fprintf(stderr, "Bad tag for '-%c'\n", c);
1650 print_usage(stderr);
1656 hdr_ethernet = TRUE;
1657 hdr_ethernet_proto = 0x800;
1661 hdr_data_chunk = TRUE;
1664 hdr_sctp_src = (guint32)strtol(optarg, &p, 10);
1665 if (p == optarg || (*p != ',' && *p != '\0')) {
1666 fprintf(stderr, "Bad src port for '-%c'\n", c);
1667 print_usage(stderr);
1671 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1672 print_usage(stderr);
1677 hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1678 if (p == optarg || (*p != ',' && *p != '\0')) {
1679 fprintf(stderr, "Bad dest port for '-s'\n");
1680 print_usage(stderr);
1684 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1685 print_usage(stderr);
1690 hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1691 if (p == optarg || *p != '\0') {
1692 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1693 print_usage(stderr);
1699 hdr_ethernet = TRUE;
1700 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 '-u'\n");
1715 print_usage(stderr);
1719 fprintf(stderr, "No dest port specified for '-u'\n");
1720 print_usage(stderr);
1725 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1726 if (p == optarg || *p != '\0') {
1727 fprintf(stderr, "Bad dest port for '-u'\n");
1728 print_usage(stderr);
1733 hdr_ethernet = TRUE;
1734 hdr_ethernet_proto = 0x800;
1741 hdr_data_chunk = FALSE;
1742 hdr_src_port = (guint32)strtol(optarg, &p, 10);
1743 if (p == optarg || (*p != ',' && *p != '\0')) {
1744 fprintf(stderr, "Bad src port for '-T'\n");
1745 print_usage(stderr);
1749 fprintf(stderr, "No dest port specified for '-u'\n");
1750 print_usage(stderr);
1755 hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1756 if (p == optarg || *p != '\0') {
1757 fprintf(stderr, "Bad dest port for '-T'\n");
1758 print_usage(stderr);
1763 hdr_ethernet = TRUE;
1764 hdr_ethernet_proto = 0x800;
1768 identify_ascii = TRUE;
1772 show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1773 g_string_free(comp_info_str, TRUE);
1774 g_string_free(runtime_info_str, TRUE);
1780 p = strchr(optarg, ',');
1783 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1784 print_usage(stderr);
1792 hdr_ethernet_proto = 0x86DD;
1797 hdr_ethernet_proto = 0x800;
1799 hdr_ethernet = TRUE;
1801 if (hdr_ipv6 == TRUE) {
1802 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1803 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1804 print_usage(stderr);
1808 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1809 fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1810 print_usage(stderr);
1817 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1818 print_usage(stderr);
1822 if (hdr_ipv6 == TRUE) {
1823 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1824 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1825 print_usage(stderr);
1829 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1830 fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1831 print_usage(stderr);
1840 print_usage(stderr);
1845 if (optind >= argc || argc-optind < 2) {
1846 fprintf(stderr, "Must specify input and output filename\n");
1847 print_usage(stderr);
1851 if (strcmp(argv[optind], "-")) {
1852 input_filename = g_strdup(argv[optind]);
1853 input_file = ws_fopen(input_filename, "rb");
1855 fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1856 input_filename, g_strerror(errno));
1860 input_filename = "Standard input";
1864 if (strcmp(argv[optind+1], "-")) {
1865 output_filename = g_strdup(argv[optind+1]);
1866 output_file = ws_fopen(output_filename, "wb");
1868 fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1869 output_filename, g_strerror(errno));
1873 output_filename = "Standard output";
1874 output_file = stdout;
1877 /* Some validation */
1878 if (pcap_link_type != 1 && hdr_ethernet) {
1879 fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1883 /* Set up our variables */
1886 input_filename = "Standard input";
1889 output_file = stdout;
1890 output_filename = "Standard output";
1893 ts_sec = time(0); /* initialize to current time */
1894 timecode_default = *localtime(&ts_sec);
1895 timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1897 /* Display summary of our state */
1899 fprintf(stderr, "Input from: %s\n", input_filename);
1900 fprintf(stderr, "Output to: %s\n", output_filename);
1901 fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1903 if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1904 hdr_ethernet_proto);
1905 if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1907 if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1908 hdr_src_port, hdr_dest_port);
1909 if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1910 hdr_src_port, hdr_dest_port);
1911 if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1912 hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1913 if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1914 hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1919 main(int argc, char *argv[])
1921 parse_options(argc, argv);
1923 assert(input_file != NULL);
1924 assert(output_file != NULL);
1926 write_file_header();
1930 header_length += (int)sizeof(HDR_ETHERNET);
1933 ip_offset = header_length;
1934 header_length += (int)sizeof(HDR_IP);
1935 } else if (hdr_ipv6) {
1936 ip_offset = header_length;
1937 header_length += (int)sizeof(HDR_IPv6);
1940 header_length += (int)sizeof(HDR_SCTP);
1942 if (hdr_data_chunk) {
1943 header_length += (int)sizeof(HDR_DATA_CHUNK);
1946 header_length += (int)sizeof(HDR_TCP);
1949 header_length += (int)sizeof(HDR_UDP);
1951 curr_offset = header_length;
1956 write_current_packet(FALSE);
1957 write_file_trailer();
1959 fclose(output_file);
1961 fprintf(stderr, "\n-------------------------\n");
1963 fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1964 num_packets_read, (num_packets_read == 1) ? "" : "s",
1965 num_packets_written, (num_packets_written == 1) ? "" : "s",
1966 bytes_written, (bytes_written == 1) ? "" : "s");
1972 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1977 * indent-tabs-mode: nil
1980 * vi: set shiftwidth=4 tabstop=8 expandtab:
1981 * :indentSize=4:tabSize=8:noTabs=true: