Enhanced text2pcap so that if direction is specified on the command line, "-D",
[metze/wireshark/wip.git] / text2pcap.c
1 /**-*-C-*-**********************************************************************
2  *
3  * text2pcap.c
4  *
5  * Utility to convert an ASCII hexdump into a libpcap-format capture file
6  *
7  * (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
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.
17  *
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.
22  *
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.
26  *
27  *******************************************************************************/
28
29 /*******************************************************************************
30  *
31  * This utility reads in an ASCII hexdump of this common format:
32  *
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......
37  *
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:
44  *
45  * - No text appears between the offset and the bytes (any bytes appearing after
46  *   such text would be ignored)
47  *
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
51  *
52  * A packet start is signaled by a zero offset.
53  *
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.
58  *
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.
63  *
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.
68  *
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.
73  *
74  * This converter cannot read a single packet greater than 64KiB-1. Packet
75  * snaplength is automatically set to 64KiB-1.
76  */
77
78 #include "config.h"
79
80 /*
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
83  * yet defined.
84  */
85 #ifndef __USE_XOPEN
86 #  define __USE_XOPEN
87 #endif
88 #ifndef _XOPEN_SOURCE
89 #  ifndef __sun
90 #    define _XOPEN_SOURCE 600
91 #  endif
92 #endif
93
94 /*
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.
97  *
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.
103  *
104  * So we define __EXTENSIONS__ so that "strptime()" is declared.
105  */
106 #ifndef __EXTENSIONS__
107 #  define __EXTENSIONS__
108 #endif
109
110 #include <ctype.h>
111 #include <stdio.h>
112 #include <stdlib.h>
113 #include <string.h>
114 #include <wsutil/file_util.h>
115
116 #include <time.h>
117 #include <glib.h>
118
119 #ifdef HAVE_UNISTD_H
120 # include <unistd.h>
121 #endif
122
123 #include <errno.h>
124 #include <assert.h>
125
126 #ifndef HAVE_GETOPT
127 #include "wsutil/wsgetopt.h"
128 #endif
129
130 #ifdef NEED_STRPTIME_H
131 # include "wsutil/strptime.h"
132 #endif
133
134 #include "pcapio.h"
135 #include "text2pcap.h"
136 #include "version.h"
137
138 #ifdef _WIN32
139 #include <wsutil/unicode-utils.h>
140 #endif /* _WIN32 */
141
142 #ifdef HAVE_ARPA_INET_H
143 #include <arpa/inet.h>
144 #endif
145
146 #ifdef HAVE_WINSOCK2_H
147 #include <winsock2.h>       /* needed to define AF_ values on Windows */
148 #endif
149
150 #ifndef HAVE_INET_ATON_H
151 # include "wsutil/inet_aton.h"
152 #endif
153
154 #ifdef HAVE_SYS_SOCKET_H
155 #include <sys/socket.h>
156 #endif
157
158 #ifdef NEED_INET_V6DEFS_H
159 # include "wsutil/inet_v6defs.h"
160 #endif
161
162 /*--- Options --------------------------------------------------------------------*/
163
164 /* File format */
165 static gboolean use_pcapng = FALSE;
166
167 /* Debug level */
168 static int debug = 0;
169 /* Be quiet */
170 static int quiet = FALSE;
171
172 /* Dummy Ethernet header */
173 static int hdr_ethernet = FALSE;
174 static guint32 hdr_ethernet_proto = 0;
175
176 /* Dummy IP header */
177 static int hdr_ip = FALSE;
178 static int hdr_ipv6 = FALSE;
179 static long hdr_ip_proto = 0;
180
181 /* Destination and source addresses for IP header */
182 static guint32 hdr_ip_dest_addr = 0;
183 static guint32 hdr_ip_src_addr = 0;
184 static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
185 static guint8 hdr_ipv6_src_addr[16]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
186 static guint8 NO_IPv6_ADDRESS[16]    = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
187
188 /* Dummy UDP header */
189 static int     hdr_udp       = FALSE;
190 static guint32 hdr_dest_port = 0;
191 static guint32 hdr_src_port  = 0;
192
193 /* Dummy TCP header */
194 static int hdr_tcp = FALSE;
195
196 /* TCP sequence numbers when has_direction is true */
197 static guint32 tcp_in_seq_num = 0;
198 static guint32 tcp_out_seq_num = 0;
199
200 /* Dummy SCTP header */
201 static int hdr_sctp = FALSE;
202 static guint32 hdr_sctp_src  = 0;
203 static guint32 hdr_sctp_dest = 0;
204 static guint32 hdr_sctp_tag  = 0;
205
206 /* Dummy DATA chunk header */
207 static int hdr_data_chunk = FALSE;
208 static guint8  hdr_data_chunk_type = 0;
209 static guint8  hdr_data_chunk_bits = 0;
210 static guint32 hdr_data_chunk_tsn  = 0;
211 static guint16 hdr_data_chunk_sid  = 0;
212 static guint16 hdr_data_chunk_ssn  = 0;
213 static guint32 hdr_data_chunk_ppid = 0;
214
215 /* ASCII text dump identification */
216 static int identify_ascii = FALSE;
217
218 static gboolean has_direction = FALSE;
219 static guint32 direction = 0;
220
221 /*--- Local date -----------------------------------------------------------------*/
222
223 /* This is where we store the packet currently being built */
224 #define MAX_PACKET 65535
225 static guint8  packet_buf[MAX_PACKET];
226 static guint32 header_length;
227 static guint32 ip_offset;
228 static guint32 curr_offset;
229 static guint32 max_offset = MAX_PACKET;
230 static guint32 packet_start = 0;
231
232 static void start_new_packet(gboolean);
233
234 /* This buffer contains strings present before the packet offset 0 */
235 #define PACKET_PREAMBLE_MAX_LEN     2048
236 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
237 static int    packet_preamble_len = 0;
238
239 /* Number of packets read and written */
240 static guint32 num_packets_read    = 0;
241 static guint32 num_packets_written = 0;
242 static guint64 bytes_written       = 0;
243
244 /* Time code of packet, derived from packet_preamble */
245 static time_t   ts_sec  = 0;
246 static guint32  ts_usec = 0;
247 static char    *ts_fmt  = NULL;
248 static struct tm timecode_default;
249
250 static guint8* pkt_lnstart;
251
252 /* Input file */
253 static const char *input_filename;
254 static FILE       *input_file  = NULL;
255 /* Output file */
256 static const char *output_filename;
257 static FILE       *output_file = NULL;
258
259 /* Offset base to parse */
260 static guint32 offset_base = 16;
261
262 extern FILE *yyin;
263
264 /* ----- State machine -----------------------------------------------------------*/
265
266 /* Current state of parser */
267 typedef enum {
268     INIT,             /* Waiting for start of new packet */
269     START_OF_LINE,    /* Starting from beginning of line */
270     READ_OFFSET,      /* Just read the offset */
271     READ_BYTE,        /* Just read a byte */
272     READ_TEXT         /* Just read text - ignore until EOL */
273 } parser_state_t;
274 static parser_state_t state = INIT;
275
276 static const char *state_str[] = {"Init",
277                            "Start-of-line",
278                            "Offset",
279                            "Byte",
280                            "Text"
281 };
282
283 static const char *token_str[] = {"",
284                            "Byte",
285                            "Offset",
286                            "Directive",
287                            "Text",
288                            "End-of-line"
289 };
290
291 /* ----- Skeleton Packet Headers --------------------------------------------------*/
292
293 typedef struct {
294     guint8  dest_addr[6];
295     guint8  src_addr[6];
296     guint16 l3pid;
297 } hdr_ethernet_t;
298
299 static hdr_ethernet_t HDR_ETHERNET = {
300     {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
301     {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
302     0};
303
304 typedef struct {
305     guint8  ver_hdrlen;
306     guint8  dscp;
307     guint16 packet_length;
308     guint16 identification;
309     guint8  flags;
310     guint8  fragment;
311     guint8  ttl;
312     guint8  protocol;
313     guint16 hdr_checksum;
314     guint32 src_addr;
315     guint32 dest_addr;
316 } hdr_ip_t;
317
318 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
319 #ifdef WORDS_BIGENDIAN
320 0x0a010101, 0x0a020202
321 #else
322 0x0101010a, 0x0202020a
323 #endif
324 };
325
326 /* Fixed IP address values */
327 #ifdef WORDS_BIGENDIAN
328 #define IP_SRC 0x0a010101
329 #define IP_DST 0x0a020202
330 #else
331 #define IP_SRC 0x0101010a
332 #define IP_DST 0x0202020a
333 #endif
334
335 static struct {         /* pseudo header for checksum calculation */
336     guint32 src_addr;
337     guint32 dest_addr;
338     guint8  zero;
339     guint8  protocol;
340     guint16 length;
341 } pseudoh;
342
343
344 /* headers taken from glibc */
345
346 /* IPv6 address */
347 struct hdr_in6_addr
348 {
349     union
350     {
351        guint8  __u6_addr8[16];
352        guint16 __u6_addr16[8];
353        guint32 __u6_addr32[4];
354     } __in6_u;
355 };
356
357 typedef struct {
358     union  {
359         struct ip6_hdrctl {
360             guint32 ip6_un1_flow;   /* 24 bits of flow-ID */
361             guint16 ip6_un1_plen;   /* payload length */
362             guint8  ip6_un1_nxt;    /* next header */
363             guint8  ip6_un1_hlim;   /* hop limit */
364         } ip6_un1;
365         guint8 ip6_un2_vfc;       /* 4 bits version, 4 bits priority */
366     } ip6_ctlun;
367     struct hdr_in6_addr ip6_src;      /* source address */
368     struct hdr_in6_addr ip6_dst;      /* destination address */
369 } hdr_ipv6_t;
370
371 static hdr_ipv6_t HDR_IPv6;
372
373 static struct {                 /* pseudo header ipv6 for checksum calculation */
374     struct  hdr_in6_addr src_addr6;
375     struct  hdr_in6_addr dst_addr6;
376     guint32 protocol;
377     guint32 zero;
378 } pseudoh6;
379
380
381 typedef struct {
382     guint16 source_port;
383     guint16 dest_port;
384     guint16 length;
385     guint16 checksum;
386 } hdr_udp_t;
387
388 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
389
390 typedef struct {
391     guint16 source_port;
392     guint16 dest_port;
393     guint32 seq_num;
394     guint32 ack_num;
395     guint8  hdr_length;
396     guint8  flags;
397     guint16 window;
398     guint16 checksum;
399     guint16 urg;
400 } hdr_tcp_t;
401
402 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
403
404 typedef struct {
405     guint16 src_port;
406     guint16 dest_port;
407     guint32 tag;
408     guint32 checksum;
409 } hdr_sctp_t;
410
411 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
412
413 typedef struct {
414     guint8  type;
415     guint8  bits;
416     guint16 length;
417     guint32 tsn;
418     guint16 sid;
419     guint16 ssn;
420     guint32 ppid;
421 } hdr_data_chunk_t;
422
423 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
424
425 static char tempbuf[64];
426
427 /*----------------------------------------------------------------------
428  * Stuff for writing a PCap file
429  */
430 #define PCAP_MAGIC          0xa1b2c3d4
431 #define PCAP_SNAPLEN        0xffff
432
433 /* "libpcap" file header (minus magic number). */
434 struct pcap_hdr {
435     guint32 magic;          /* magic */
436     guint16 version_major;  /* major version number */
437     guint16 version_minor;  /* minor version number */
438     guint32 thiszone;       /* GMT to local correction */
439     guint32 sigfigs;        /* accuracy of timestamps */
440     guint32 snaplen;        /* max length of captured packets, in octets */
441     guint32 network;        /* data link type */
442 };
443
444 /* "libpcap" record header. */
445 struct pcaprec_hdr {
446     guint32 ts_sec;         /* timestamp seconds */
447     guint32 ts_usec;        /* timestamp microseconds */
448     guint32 incl_len;       /* number of octets of packet saved in file */
449     guint32 orig_len;       /* actual length of packet */
450 };
451
452 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
453 static guint32 pcap_link_type = 1;   /* Default is LINKTYPE_ETHERNET */
454
455 /*----------------------------------------------------------------------
456  * Parse a single hex number
457  * Will abort the program if it can't parse the number
458  * Pass in TRUE if this is an offset, FALSE if not
459  */
460 static guint32
461 parse_num (const char *str, int offset)
462 {
463     guint32  num;
464     char    *c;
465
466     num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
467     if (c == str) {
468         fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
469         exit(1);
470     }
471     return num;
472 }
473
474 /*----------------------------------------------------------------------
475  * Write this byte into current packet
476  */
477 static void
478 write_byte (const char *str)
479 {
480     guint32 num;
481
482     num = parse_num(str, FALSE);
483     packet_buf[curr_offset] = (guint8) num;
484     curr_offset++;
485     if (curr_offset - header_length >= max_offset) /* packet full */
486         start_new_packet(TRUE);
487 }
488
489 /*----------------------------------------------------------------------
490  * Write a number of bytes into current packet
491  */
492
493 static void
494 write_bytes (const char bytes[], guint32 nbytes)
495 {
496     guint32 i;
497
498     if (curr_offset + nbytes < MAX_PACKET) {
499         for (i = 0; i < nbytes; i++) {
500             packet_buf[curr_offset] = bytes[i];
501             curr_offset++;
502         }
503     }
504 }
505
506 /*----------------------------------------------------------------------
507  * Remove bytes from the current packet
508  */
509 static void
510 unwrite_bytes (guint32 nbytes)
511 {
512     curr_offset -= nbytes;
513 }
514
515 /*----------------------------------------------------------------------
516  * Compute one's complement checksum (from RFC1071)
517  */
518 static guint16
519 in_checksum (void *buf, guint32 count)
520 {
521     guint32 sum = 0;
522     guint16 *addr = (guint16 *)buf;
523
524     while (count > 1) {
525         /*  This is the inner loop */
526         sum += g_ntohs(* (guint16 *) addr);
527         addr++;
528         count -= 2;
529     }
530
531     /*  Add left-over byte, if any */
532     if (count > 0)
533         sum += g_ntohs(* (guint8 *) addr);
534
535     /*  Fold 32-bit sum to 16 bits */
536     while (sum>>16)
537         sum = (sum & 0xffff) + (sum >> 16);
538
539     sum = ~sum;
540     return g_htons(sum);
541 }
542
543 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
544  * That code is copyrighted by D. Otis and has been modified.
545  */
546
547 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
548 static guint32 crc_c[256] =
549 {
550 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
551 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
552 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
553 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
554 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
555 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
556 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
557 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
558 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
559 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
560 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
561 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
562 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
563 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
564 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
565 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
566 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
567 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
568 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
569 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
570 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
571 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
572 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
573 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
574 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
575 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
576 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
577 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
578 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
579 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
580 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
581 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
582 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
583 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
584 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
585 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
586 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
587 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
588 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
589 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
590 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
591 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
592 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
593 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
594 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
595 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
596 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
597 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
598 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
599 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
600 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
601 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
602 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
603 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
604 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
605 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
606 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
607 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
608 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
609 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
610 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
611 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
612 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
613 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
614 };
615
616 static guint32
617 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
618 {
619     unsigned int i;
620     guint32 crc32;
621
622     crc32 = crc32_init;
623     for (i = 0; i < len; i++)
624         CRC32C(crc32, buf[i]);
625
626     return crc32;
627 }
628
629 static guint32
630 finalize_crc32c (guint32 crc32)
631 {
632     guint32 result;
633     guint8 byte0,byte1,byte2,byte3;
634
635     result = ~crc32;
636     byte0 = result & 0xff;
637     byte1 = (result>>8) & 0xff;
638     byte2 = (result>>16) & 0xff;
639     byte3 = (result>>24) & 0xff;
640     result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
641     return result;
642 }
643
644 static guint16
645 number_of_padding_bytes (guint32 length)
646 {
647     guint16 remainder;
648
649     remainder = length % 4;
650
651     if (remainder == 0)
652         return 0;
653     else
654         return 4 - remainder;
655 }
656
657 /*----------------------------------------------------------------------
658  * Write current packet out
659  */
660 static void
661 write_current_packet (gboolean cont)
662 {
663     guint32  length         = 0;
664     guint16  padding_length = 0;
665     int      err;
666     guint16  ihatemacros;
667     gboolean success;
668
669     if (curr_offset > header_length) {
670         /* Write the packet */
671
672         /* Is direction indication on with an inbound packet? */
673         gboolean isInbound = has_direction && (direction == 2);
674
675         /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
676         if (hdr_ipv6) {
677             hdr_ethernet_proto = 0x86DD;
678             hdr_ip = FALSE;
679         }
680
681         /* Compute packet length */
682         length = curr_offset;
683         if (hdr_sctp) {
684             padding_length = number_of_padding_bytes(length - header_length );
685         } else {
686             padding_length = 0;
687         }
688         /* Reset curr_offset, since we now write the headers */
689         curr_offset = 0;
690
691         /* Write Ethernet header */
692         if (hdr_ethernet) {
693             HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
694             write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
695         }
696
697         /* Write IP header */
698         if (hdr_ip) {
699             if (isInbound) {
700                 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
701                 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
702             }
703             else {
704                 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
705                 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
706             }
707
708             HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
709             HDR_IP.protocol = (guint8) hdr_ip_proto;
710             HDR_IP.hdr_checksum = 0;
711             HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
712             write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
713         } else if (hdr_ipv6) {
714             if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
715                 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
716             if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
717                 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
718
719             HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
720             HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
721             HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
722             HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt  = (guint8) hdr_ip_proto;
723             HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
724             write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
725
726             /* initialize pseudo ipv6 header for checksum calculation */
727             pseudoh6.src_addr6  = HDR_IPv6.ip6_src;
728             pseudoh6.dst_addr6  = HDR_IPv6.ip6_dst;
729             pseudoh6.zero       = 0;
730             pseudoh6.protocol   = (guint8) hdr_ip_proto;
731             ihatemacros         = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
732             pseudoh.length      = g_htons(length - ihatemacros + sizeof(HDR_UDP));
733         }
734
735         if (!hdr_ipv6) {
736             /* initialize pseudo header for checksum calculation */
737             pseudoh.src_addr    = HDR_IP.src_addr;
738             pseudoh.dest_addr   = HDR_IP.dest_addr;
739             pseudoh.zero        = 0;
740             pseudoh.protocol    = (guint8) hdr_ip_proto;
741             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_UDP));
742         }
743
744         /* Write UDP header */
745         if (hdr_udp) {
746             guint16 x16;
747             guint32 u;
748
749             /* initialize the UDP header */
750             HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
751             HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
752             HDR_UDP.length      = pseudoh.length;
753             HDR_UDP.checksum = 0;
754             /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
755             x16  = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
756             u    = g_ntohs(x16);
757             x16  = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
758             u   += g_ntohs(x16);
759             x16  = in_checksum(packet_buf + header_length, length - header_length);
760             u   += g_ntohs(x16);
761             x16  = (u & 0xffff) + (u>>16);
762             HDR_UDP.checksum = g_htons(x16);
763             if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
764                 HDR_UDP.checksum = g_htons(1);
765             write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
766         }
767
768         /* Write TCP header */
769         if (hdr_tcp) {
770             guint16 x16;
771             guint32 u;
772
773              /* initialize pseudo header for checksum calculation */
774             pseudoh.src_addr    = HDR_IP.src_addr;
775             pseudoh.dest_addr   = HDR_IP.dest_addr;
776             pseudoh.zero        = 0;
777             pseudoh.protocol    = (guint8) hdr_ip_proto;
778             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_TCP));
779             /* initialize the TCP header */
780             HDR_TCP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
781             HDR_TCP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
782             /* set ack number if we have direction */
783             if (has_direction) {
784                 HDR_TCP.flags = 0x10;
785                 HDR_TCP.ack_num = g_ntohl(isInbound ? tcp_out_seq_num : tcp_in_seq_num);
786                 HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num);
787             }
788             else {
789                 HDR_TCP.flags = 0;
790                 HDR_TCP.ack_num = 0;
791             }
792             HDR_TCP.seq_num = isInbound ? tcp_in_seq_num : tcp_out_seq_num;
793             HDR_TCP.window = g_htons(0x2000);
794             HDR_TCP.checksum = 0;
795             /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
796             x16  = in_checksum(&pseudoh, sizeof(pseudoh));
797             u    = g_ntohs(x16);
798             x16  = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
799             u   += g_ntohs(x16);
800             x16  = in_checksum(packet_buf + header_length, length - header_length);
801             u   += g_ntohs(x16);
802             x16  = (u & 0xffff) + (u>>16);
803             HDR_TCP.checksum = g_htons(x16);
804             if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
805                 HDR_TCP.checksum = g_htons(1);
806             write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
807             if (isInbound) {
808                 tcp_in_seq_num = g_ntohl(tcp_in_seq_num) + length - header_length;
809                 tcp_in_seq_num = g_htonl(tcp_in_seq_num);
810             }
811             else {
812                 tcp_out_seq_num = g_ntohl(tcp_out_seq_num) + length - header_length;
813                 tcp_out_seq_num = g_htonl(tcp_out_seq_num);
814             }
815         }
816
817         /* Compute DATA chunk header */
818         if (hdr_data_chunk) {
819             hdr_data_chunk_bits = 0;
820             if (packet_start == 0) {
821                 hdr_data_chunk_bits |= 0x02;
822             }
823             if (!cont) {
824                 hdr_data_chunk_bits |= 0x01;
825             }
826             HDR_DATA_CHUNK.type   = hdr_data_chunk_type;
827             HDR_DATA_CHUNK.bits   = hdr_data_chunk_bits;
828             HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
829             HDR_DATA_CHUNK.tsn    = g_htonl(hdr_data_chunk_tsn);
830             HDR_DATA_CHUNK.sid    = g_htons(hdr_data_chunk_sid);
831             HDR_DATA_CHUNK.ssn    = g_htons(hdr_data_chunk_ssn);
832             HDR_DATA_CHUNK.ppid   = g_htonl(hdr_data_chunk_ppid);
833             hdr_data_chunk_tsn++;
834             if (!cont) {
835                 hdr_data_chunk_ssn++;
836             }
837         }
838
839         /* Write SCTP common header */
840         if (hdr_sctp) {
841             guint32 zero = 0;
842
843             HDR_SCTP.src_port  = isInbound ? g_htons(hdr_sctp_dest): g_htons(hdr_sctp_src);
844             HDR_SCTP.dest_port = isInbound ? g_htons(hdr_sctp_src) : g_htons(hdr_sctp_dest);
845             HDR_SCTP.tag       = g_htonl(hdr_sctp_tag);
846             HDR_SCTP.checksum  = g_htonl(0);
847             HDR_SCTP.checksum  = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0);
848             if (hdr_data_chunk) {
849                 HDR_SCTP.checksum  = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
850                 HDR_SCTP.checksum  = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
851                 HDR_SCTP.checksum  = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
852             } else {
853                 HDR_SCTP.checksum  = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
854             }
855             HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
856             HDR_SCTP.checksum  = g_htonl(HDR_SCTP.checksum);
857             write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
858         }
859
860         /* Write DATA chunk header */
861         if (hdr_data_chunk) {
862             write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
863         }
864
865         /* Reset curr_offset, since we now write the trailers */
866         curr_offset = length;
867
868         /* Write DATA chunk padding */
869         if (hdr_data_chunk && (padding_length > 0)) {
870             memset(tempbuf, 0, padding_length);
871             write_bytes((const char *)&tempbuf, padding_length);
872             length += padding_length;
873         }
874
875         /* Write Ethernet trailer */
876         if (hdr_ethernet && (length < 60)) {
877             memset(tempbuf, 0, 60 - length);
878             write_bytes((const char *)&tempbuf, 60 - length);
879             length = 60;
880         }
881         if (use_pcapng) {
882             success = pcapng_write_enhanced_packet_block(output_file,
883                                                          NULL,
884                                                          ts_sec, ts_usec,
885                                                          length, length,
886                                                          0,
887                                                          1000000,
888                                                          packet_buf, direction,
889                                                          &bytes_written, &err);
890         } else {
891             success = libpcap_write_packet(output_file,
892                                            ts_sec, ts_usec,
893                                            length, length,
894                                            packet_buf,
895                                            &bytes_written, &err);
896         }
897         if (!success) {
898             fprintf(stderr, "File write error [%s] : %s\n",
899                     output_filename, g_strerror(err));
900             exit(1);
901         }
902         if (ts_fmt == NULL) {
903             /* fake packet counter */
904             ts_usec++;
905         }
906         if (!quiet) {
907             fprintf(stderr, "Wrote packet of %u bytes.\n", length);
908         }
909         num_packets_written++;
910     }
911
912     packet_start += curr_offset - header_length;
913     curr_offset = header_length;
914     return;
915 }
916
917 /*----------------------------------------------------------------------
918  * Write file header and trailer
919  */
920 static void
921 write_file_header (void)
922 {
923     int      err;
924     gboolean success;
925
926     if (use_pcapng) {
927 #ifdef GITVERSION
928         const char *appname = "text2pcap (" GITVERSION " from " GITBRANCH ")";
929 #else
930         const char *appname = "text2pcap";
931 #endif
932         char comment[100];
933
934         g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
935         success = pcapng_write_session_header_block(output_file,
936                                                     comment,
937                                                     NULL,
938                                                     NULL,
939                                                     appname,
940                                                     -1,
941                                                     &bytes_written,
942                                                     &err);
943         if (success) {
944             success = pcapng_write_interface_description_block(output_file,
945                                                                NULL,
946                                                                NULL,
947                                                                NULL,
948                                                                "",
949                                                                NULL,
950                                                                pcap_link_type,
951                                                                PCAP_SNAPLEN,
952                                                                &bytes_written,
953                                                                0,
954                                                                6,
955                                                                &err);
956         }
957     } else {
958         success = libpcap_write_file_header(output_file, pcap_link_type, PCAP_SNAPLEN,
959                                             FALSE, &bytes_written, &err);
960     }
961     if (!success) {
962         fprintf(stderr, "File write error [%s] : %s\n",
963                 output_filename, g_strerror(err));
964         exit(1);
965     }
966 }
967
968 static void
969 write_file_trailer (void)
970 {
971     int      err;
972     gboolean success;
973
974     if (use_pcapng) {
975         success = pcapng_write_interface_statistics_block(output_file,
976                                                           0,
977                                                           &bytes_written,
978                                                           "Counters provided by text2pcap",
979                                                           0,
980                                                           0,
981                                                           num_packets_written,
982                                                           num_packets_written - num_packets_written,
983                                                           &err);
984
985     } else {
986         success = TRUE;
987     }
988     if (!success) {
989         fprintf(stderr, "File write error [%s] : %s\n",
990                 output_filename, g_strerror(err));
991         exit(1);
992     }
993    return;
994 }
995
996 /*----------------------------------------------------------------------
997  * Append a token to the packet preamble.
998  */
999 static void
1000 append_to_preamble (char *str)
1001 {
1002     size_t toklen;
1003
1004     if (packet_preamble_len != 0) {
1005         if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1006             return; /* no room to add more preamble */
1007         /* Add a blank separator between the previous token and this token. */
1008         packet_preamble[packet_preamble_len++] = ' ';
1009     }
1010     toklen = strlen(str);
1011     if (toklen != 0) {
1012         if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1013             return; /* no room to add the token to the preamble */
1014         g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1015         packet_preamble_len += (int) toklen;
1016         if (debug >= 2) {
1017             char *c;
1018             char xs[PACKET_PREAMBLE_MAX_LEN];
1019             g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1020             while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1021             fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1022         }
1023     }
1024 }
1025
1026 /*----------------------------------------------------------------------
1027  * Parse the preamble to get the timecode.
1028  */
1029
1030 static void
1031 parse_preamble (void)
1032 {
1033     struct tm  timecode;
1034     char      *subsecs;
1035     char      *p;
1036     int        subseclen;
1037     int        i;
1038
1039      /*
1040      * Null-terminate the preamble.
1041      */
1042     packet_preamble[packet_preamble_len] = '\0';
1043     if (debug > 0)
1044         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1045
1046     if (has_direction) {
1047         switch (packet_preamble[0]) {
1048         case 'i':
1049         case 'I':
1050             direction = 0x00000001;
1051             packet_preamble[0] = ' ';
1052             break;
1053         case 'o':
1054         case 'O':
1055             direction = 0x00000002;
1056             packet_preamble[0] = ' ';
1057             break;
1058         default:
1059             direction = 0x00000000;
1060             break;
1061         }
1062         i = 0;
1063         while (packet_preamble[i] == ' ' ||
1064                packet_preamble[i] == '\r' ||
1065                packet_preamble[i] == '\t') {
1066             i++;
1067         }
1068         packet_preamble_len -= i;
1069         /* Also move the trailing '\0'. */
1070         memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1071     }
1072
1073
1074     /*
1075      * If no "-t" flag was specified, don't attempt to parse the packet
1076      * preamble to extract a time stamp.
1077      */
1078     if (ts_fmt == NULL) {
1079         /* Clear Preamble */
1080         packet_preamble_len = 0;
1081         return;
1082     }
1083
1084     /*
1085      * Initialize to today localtime, just in case not all fields
1086      * of the date and time are specified.
1087      */
1088
1089     timecode = timecode_default;
1090     ts_usec = 0;
1091
1092     /* Ensure preamble has more than two chars before attempting to parse.
1093      * This should cover line breaks etc that get counted.
1094      */
1095     if (strlen(packet_preamble) > 2) {
1096         /* Get Time leaving subseconds */
1097         subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1098         if (subsecs != NULL) {
1099             /* Get the long time from the tm structure */
1100             /*  (will return -1 if failure)            */
1101             ts_sec  = mktime( &timecode );
1102         } else
1103             ts_sec = -1;    /* we failed to parse it */
1104
1105         /* This will ensure incorrectly parsed dates get set to zero */
1106         if (-1 == ts_sec) {
1107             /* Sanitize - remove all '\r' */
1108             char *c;
1109             while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1110             fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n   (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1111                  packet_preamble, ts_fmt);
1112             if (debug >= 2) {
1113                 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1114                     timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1115                     timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1116             }
1117             ts_sec  = 0;  /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1118             ts_usec = 0;
1119         } else {
1120             /* Parse subseconds */
1121             ts_usec = (guint32)strtol(subsecs, &p, 10);
1122             if (subsecs == p) {
1123                 /* Error */
1124                 ts_usec = 0;
1125             } else {
1126                 /*
1127                  * Convert that number to a number
1128                  * of microseconds; if it's N digits
1129                  * long, it's in units of 10^(-N) seconds,
1130                  * so, to convert it to units of
1131                  * 10^-6 seconds, we multiply by
1132                  * 10^(6-N).
1133                  */
1134                 subseclen = (int) (p - subsecs);
1135                 if (subseclen > 6) {
1136                     /*
1137                      * *More* than 6 digits; 6-N is
1138                      * negative, so we divide by
1139                      * 10^(N-6).
1140                      */
1141                     for (i = subseclen - 6; i != 0; i--)
1142                         ts_usec /= 10;
1143                 } else if (subseclen < 6) {
1144                     for (i = 6 - subseclen; i != 0; i--)
1145                         ts_usec *= 10;
1146                 }
1147             }
1148         }
1149     }
1150     if (debug >= 2) {
1151         char *c;
1152         while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1153         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1154         fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_usec);
1155     }
1156
1157
1158     /* Clear Preamble */
1159     packet_preamble_len = 0;
1160 }
1161
1162 /*----------------------------------------------------------------------
1163  * Start a new packet
1164  */
1165 static void
1166 start_new_packet (gboolean cont)
1167 {
1168     if (debug >= 1)
1169         fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1170
1171     /* Write out the current packet, if required */
1172     write_current_packet(cont);
1173     num_packets_read++;
1174
1175     /* Ensure we parse the packet preamble as it may contain the time */
1176     parse_preamble();
1177 }
1178
1179 /*----------------------------------------------------------------------
1180  * Process a directive
1181  */
1182 static void
1183 process_directive (char *str)
1184 {
1185     fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1186 }
1187
1188 /*----------------------------------------------------------------------
1189  * Parse a single token (called from the scanner)
1190  */
1191 void
1192 parse_token (token_t token, char *str)
1193 {
1194     guint32  num;
1195     int      by_eol;
1196     int      rollback = 0;
1197     int      line_size;
1198     int      i;
1199     char    *s2;
1200     char     tmp_str[3];
1201
1202     /*
1203      * This is implemented as a simple state machine of five states.
1204      * State transitions are caused by tokens being received from the
1205      * scanner. The code should be self-documenting.
1206      */
1207
1208     if (debug >= 2) {
1209         /* Sanitize - remove all '\r' */
1210         char *c;
1211         if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1212
1213         fprintf(stderr, "(%s, %s \"%s\") -> (",
1214                 state_str[state], token_str[token], str ? str : "");
1215     }
1216
1217     switch (state) {
1218
1219     /* ----- Waiting for new packet -------------------------------------------*/
1220     case INIT:
1221         if (!str && token != T_EOL) goto fail_null_str;
1222         switch (token) {
1223         case T_TEXT:
1224             append_to_preamble(str);
1225             break;
1226         case T_DIRECTIVE:
1227             process_directive(str);
1228             break;
1229         case T_OFFSET:
1230             num = parse_num(str, TRUE);
1231             if (num == 0) {
1232                 /* New packet starts here */
1233                 start_new_packet(FALSE);
1234                 state = READ_OFFSET;
1235                 pkt_lnstart = packet_buf + num;
1236             }
1237             break;
1238         case T_EOL:
1239             /* Some describing text may be parsed as offset, but the invalid
1240                offset will be checked in the state of START_OF_LINE, so
1241                we add this transition to gain flexibility */
1242             state = START_OF_LINE;
1243             break;
1244         default:
1245             break;
1246         }
1247         break;
1248
1249     /* ----- Processing packet, start of new line -----------------------------*/
1250     case START_OF_LINE:
1251         if (!str && token != T_EOL) goto fail_null_str;
1252         switch (token) {
1253         case T_TEXT:
1254             append_to_preamble(str);
1255             break;
1256         case T_DIRECTIVE:
1257             process_directive(str);
1258             break;
1259         case T_OFFSET:
1260             num = parse_num(str, TRUE);
1261             if (num == 0) {
1262                 /* New packet starts here */
1263                 start_new_packet(FALSE);
1264                 packet_start = 0;
1265                 state = READ_OFFSET;
1266             } else if ((num - packet_start) != curr_offset - header_length) {
1267                 /*
1268                  * The offset we read isn't the one we expected.
1269                  * This may only mean that we mistakenly interpreted
1270                  * some text as byte values (e.g., if the text dump
1271                  * of packet data included a number with spaces around
1272                  * it).  If the offset is less than what we expected,
1273                  * assume that's the problem, and throw away the putative
1274                  * extra byte values.
1275                  */
1276                 if (num < curr_offset) {
1277                     unwrite_bytes(curr_offset - num);
1278                     state = READ_OFFSET;
1279                 } else {
1280                     /* Bad offset; switch to INIT state */
1281                     if (debug >= 1)
1282                         fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1283                                 curr_offset, num);
1284                     write_current_packet(FALSE);
1285                     state = INIT;
1286                 }
1287             } else
1288                 state = READ_OFFSET;
1289                 pkt_lnstart = packet_buf + num;
1290             break;
1291         case T_EOL:
1292             state = START_OF_LINE;
1293             break;
1294         default:
1295             break;
1296         }
1297         break;
1298
1299     /* ----- Processing packet, read offset -----------------------------------*/
1300     case READ_OFFSET:
1301         switch (token) {
1302         case T_BYTE:
1303             /* Record the byte */
1304             state = READ_BYTE;
1305             if (!str) goto fail_null_str;
1306             write_byte(str);
1307             break;
1308         case T_TEXT:
1309         case T_DIRECTIVE:
1310         case T_OFFSET:
1311             state = READ_TEXT;
1312             break;
1313         case T_EOL:
1314             state = START_OF_LINE;
1315             break;
1316         default:
1317             break;
1318         }
1319         break;
1320
1321     /* ----- Processing packet, read byte -------------------------------------*/
1322     case READ_BYTE:
1323         switch (token) {
1324         case T_BYTE:
1325             /* Record the byte */
1326             write_byte(str);
1327             break;
1328         case T_TEXT:
1329         case T_DIRECTIVE:
1330         case T_OFFSET:
1331         case T_EOL:
1332             by_eol = 0;
1333             state = READ_TEXT;
1334             if (token == T_EOL) {
1335                 by_eol = 1;
1336                 state = START_OF_LINE;
1337             }
1338             if (identify_ascii) {
1339                 /* Here a line of pkt bytes reading is finished
1340                    compare the ascii and hex to avoid such situation:
1341                    "61 62 20 ab ", when ab is ascii dump then it should
1342                    not be treat as byte */
1343                 rollback = 0;
1344                 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1345                    s2 = "ab ", s1 = "616220"
1346                    we should find out the largest tail of s1 matches the head
1347                    of s2, it means the matched part in tail is the ASCII dump
1348                    of the head byte. These matched should be rollback */
1349                 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1350                 s2 = (char*)g_malloc((line_size+1)/4+1);
1351                 /* gather the possible pattern */
1352                 for (i = 0; i < (line_size+1)/4; i++) {
1353                     tmp_str[0] = pkt_lnstart[i*3];
1354                     tmp_str[1] = pkt_lnstart[i*3+1];
1355                     tmp_str[2] = '\0';
1356                     /* it is a valid convertable string */
1357                     if (!isxdigit(tmp_str[0]) || !isxdigit(tmp_str[0])) {
1358                         break;
1359                     }
1360                     s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1361                     rollback++;
1362                     /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1363                     if (!(pkt_lnstart[i*3+2] == ' ')) {
1364                         if (by_eol != 1)
1365                             rollback--;
1366                         break;
1367                     }
1368                 }
1369                 /* If packet line start contains possible byte pattern, the line end
1370                    should contain the matched pattern if the user open the -a flag.
1371                    The packet will be possible invalid if the byte pattern cannot find
1372                    a matched one in the line of packet buffer.*/
1373                 if (rollback > 0) {
1374                     if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1375                         unwrite_bytes(rollback);
1376                     }
1377                     /* Not matched. This line contains invalid packet bytes, so
1378                        discard the whole line */
1379                     else {
1380                         unwrite_bytes(line_size);
1381                     }
1382                 }
1383                 g_free(s2);
1384             }
1385             break;
1386         default:
1387             break;
1388         }
1389         break;
1390
1391     /* ----- Processing packet, read text -------------------------------------*/
1392     case READ_TEXT:
1393         switch (token) {
1394         case T_EOL:
1395             state = START_OF_LINE;
1396             break;
1397         default:
1398             break;
1399         }
1400         break;
1401
1402     default:
1403         fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1404         exit(1);
1405     }
1406
1407     if (debug >= 2)
1408         fprintf(stderr, ", %s)\n", state_str[state]);
1409
1410     return;
1411
1412 fail_null_str:
1413     fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1414     exit(1);
1415
1416 }
1417
1418 /*----------------------------------------------------------------------
1419  * Print usage string and exit
1420  */
1421 static void
1422 usage (gboolean is_error)
1423 {
1424     FILE *output;
1425
1426     if (!is_error) {
1427         output = stdout;
1428     }
1429     else {
1430         output = stderr;
1431     }
1432
1433     fprintf(output,
1434             "Text2pcap %s"
1435 #ifdef GITVERSION
1436             " (" GITVERSION " from " GITBRANCH ")"
1437 #endif
1438             "\n"
1439             "Generate a capture file from an ASCII hexdump of packets.\n"
1440             "See http://www.wireshark.org for more information.\n"
1441             "\n"
1442             "Usage: text2pcap [options] <infile> <outfile>\n"
1443             "\n"
1444             "where  <infile> specifies input  filename (use - for standard input)\n"
1445             "      <outfile> specifies output filename (use - for standard output)\n"
1446             "\n"
1447             "Input:\n"
1448             "  -o hex|oct|dec         parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1449             "                         default is hex.\n"
1450             "  -t <timefmt>           treat the text before the packet as a date/time code;\n"
1451             "                         the specified argument is a format string of the sort\n"
1452             "                         supported by strptime.\n"
1453             "                         Example: The time \"10:15:14.5476\" has the format code\n"
1454             "                         \"%%H:%%M:%%S.\"\n"
1455             "                         NOTE: The subsecond component delimiter, '.', must be\n"
1456             "                         given, but no pattern is required; the remaining\n"
1457             "                         number is assumed to be fractions of a second.\n"
1458             "                         NOTE: Date/time fields from the current date/time are\n"
1459             "                         used as the default for unspecified fields.\n"
1460             "  -D                     the text before the packet starts with an I or an O,\n"
1461             "                         indicating that the packet is inbound or outbound.\n"
1462             "                         This is only stored if the output format is PCAP-NG.\n"
1463             "  -a                     enable ASCII text dump identification.\n"
1464             "                         The start of the ASCII text dump can be identified\n"
1465             "                         and excluded from the packet data, even if it looks\n"
1466             "                         like a HEX dump.\n"
1467             "                         NOTE: Do not enable it if the input file does not\n"
1468             "                         contain the ASCII text dump.\n"
1469             "\n"
1470             "Output:\n"
1471             "  -l <typenum>           link-layer type number; default is 1 (Ethernet).  See\n"
1472             "                         http://www.tcpdump.org/linktypes.html for a list of\n"
1473             "                         numbers.  Use this option if your dump is a complete\n"
1474             "                         hex dump of an encapsulated packet and you wish to\n"
1475             "                         specify the exact type of encapsulation.\n"
1476             "                         Example: -l 7 for ARCNet packets.\n"
1477             "  -m <max-packet>        max packet length in output; default is %d\n"
1478             "\n"
1479             "Prepend dummy header:\n"
1480             "  -e <l3pid>             prepend dummy Ethernet II header with specified L3PID\n"
1481             "                         (in HEX).\n"
1482             "                         Example: -e 0x806 to specify an ARP packet.\n"
1483             "  -i <proto>             prepend dummy IP header with specified IP protocol\n"
1484             "                         (in DECIMAL).\n"
1485             "                         Automatically prepends Ethernet header as well.\n"
1486             "                         Example: -i 46\n"
1487             "  -4 <srcip>,<destip>    prepend dummy IPv4 header with specified\n"
1488             "                         dest and source address.\n"
1489             "                         Example: -4 10.0.0.1,10.0.0.2\n"
1490             "  -6 <srcip>,<destip>    replace IPv6 header with specified\n"
1491             "                         dest and source address.\n"
1492             "                         Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1493             "  -u <srcp>,<destp>      prepend dummy UDP header with specified\n"
1494             "                         source and destination ports (in DECIMAL).\n"
1495             "                         Automatically prepends Ethernet & IP headers as well.\n"
1496             "                         Example: -u 1000,69 to make the packets look like\n"
1497             "                         TFTP/UDP packets.\n"
1498             "  -T <srcp>,<destp>      prepend dummy TCP header with specified\n"
1499             "                         source and destination ports (in DECIMAL).\n"
1500             "                         Automatically prepends Ethernet & IP headers as well.\n"
1501             "                         Example: -T 50,60\n"
1502             "  -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1503             "                         source/dest ports and verification tag (in DECIMAL).\n"
1504             "                         Automatically prepends Ethernet & IP headers as well.\n"
1505             "                         Example: -s 30,40,34\n"
1506             "  -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1507             "                         source/dest ports and verification tag 0.\n"
1508             "                         Automatically prepends a dummy SCTP DATA\n"
1509             "                         chunk header with payload protocol identifier ppi.\n"
1510             "                         Example: -S 30,40,34\n"
1511             "\n"
1512             "Miscellaneous:\n"
1513             "  -h                     display this help and exit.\n"
1514             "  -d                     show detailed debug of parser states.\n"
1515             "  -q                     generate no output at all (automatically disables -d).\n"
1516             "  -n                     use PCAP-NG instead of PCAP as output format.\n"
1517             "",
1518             VERSION, MAX_PACKET);
1519
1520     exit(is_error ? 1 : 0);
1521 }
1522
1523 /*----------------------------------------------------------------------
1524  * Parse CLI options
1525  */
1526 static void
1527 parse_options (int argc, char *argv[])
1528 {
1529     int   c;
1530     char *p;
1531
1532 #ifdef _WIN32
1533     arg_list_utf_16to8(argc, argv);
1534     create_app_running_mutex();
1535 #endif /* _WIN32 */
1536
1537     /* Scan CLI parameters */
1538     while ((c = getopt(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:4:6:")) != -1) {
1539         switch (c) {
1540         case '?': usage(TRUE); break;
1541         case 'h': usage(FALSE); break;
1542         case 'd': if (!quiet) debug++; break;
1543         case 'D': has_direction = TRUE; break;
1544         case 'q': quiet = TRUE; debug = FALSE; break;
1545         case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1546         case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1547         case 'n': use_pcapng = TRUE; break;
1548         case 'o':
1549             if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1550                 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1551                 usage(TRUE);
1552             }
1553             switch (optarg[0]) {
1554             case 'o': offset_base =  8; break;
1555             case 'h': offset_base = 16; break;
1556             case 'd': offset_base = 10; break;
1557             }
1558             break;
1559         case 'e':
1560             hdr_ethernet = TRUE;
1561             if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1562                 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1563                 usage(TRUE);
1564             }
1565             break;
1566
1567         case 'i':
1568             hdr_ip = TRUE;
1569             hdr_ip_proto = strtol(optarg, &p, 10);
1570             if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1571                   hdr_ip_proto > 255) {
1572                 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1573                 usage(TRUE);
1574             }
1575             hdr_ethernet = TRUE;
1576             hdr_ethernet_proto = 0x800;
1577             break;
1578
1579         case 's':
1580             hdr_sctp = TRUE;
1581             hdr_data_chunk = FALSE;
1582             hdr_tcp = FALSE;
1583             hdr_udp = FALSE;
1584             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1585             if (p == optarg || (*p != ',' && *p != '\0')) {
1586                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1587                 usage(TRUE);
1588             }
1589             if (*p == '\0') {
1590                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1591                 usage(TRUE);
1592             }
1593             p++;
1594             optarg = p;
1595             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1596             if (p == optarg || (*p != ',' && *p != '\0')) {
1597                 fprintf(stderr, "Bad dest port for '-s'\n");
1598                 usage(TRUE);
1599             }
1600             if (*p == '\0') {
1601                 fprintf(stderr, "No tag specified for '-%c'\n", c);
1602                 usage(TRUE);
1603             }
1604             p++;
1605             optarg = p;
1606             hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1607             if (p == optarg || *p != '\0') {
1608                 fprintf(stderr, "Bad tag for '-%c'\n", c);
1609                 usage(TRUE);
1610             }
1611
1612             hdr_ip = TRUE;
1613             hdr_ip_proto = 132;
1614             hdr_ethernet = TRUE;
1615             hdr_ethernet_proto = 0x800;
1616             break;
1617         case 'S':
1618             hdr_sctp = TRUE;
1619             hdr_data_chunk = TRUE;
1620             hdr_tcp = FALSE;
1621             hdr_udp = FALSE;
1622             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1623             if (p == optarg || (*p != ',' && *p != '\0')) {
1624                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1625                 usage(TRUE);
1626             }
1627             if (*p == '\0') {
1628                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1629                 usage(TRUE);
1630             }
1631             p++;
1632             optarg = p;
1633             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1634             if (p == optarg || (*p != ',' && *p != '\0')) {
1635                 fprintf(stderr, "Bad dest port for '-s'\n");
1636                 usage(TRUE);
1637             }
1638             if (*p == '\0') {
1639                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1640                 usage(TRUE);
1641             }
1642             p++;
1643             optarg = p;
1644             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1645             if (p == optarg || *p != '\0') {
1646                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1647                 usage(TRUE);
1648             }
1649
1650             hdr_ip = TRUE;
1651             hdr_ip_proto = 132;
1652             hdr_ethernet = TRUE;
1653             hdr_ethernet_proto = 0x800;
1654             break;
1655
1656         case 't':
1657             ts_fmt = optarg;
1658             break;
1659
1660         case 'u':
1661             hdr_udp = TRUE;
1662             hdr_tcp = FALSE;
1663             hdr_sctp = FALSE;
1664             hdr_data_chunk = FALSE;
1665             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1666             if (p == optarg || (*p != ',' && *p != '\0')) {
1667                 fprintf(stderr, "Bad src port for '-u'\n");
1668                 usage(TRUE);
1669             }
1670             if (*p == '\0') {
1671                 fprintf(stderr, "No dest port specified for '-u'\n");
1672                 usage(TRUE);
1673             }
1674             p++;
1675             optarg = p;
1676             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1677             if (p == optarg || *p != '\0') {
1678                 fprintf(stderr, "Bad dest port for '-u'\n");
1679                 usage(TRUE);
1680             }
1681             hdr_ip = TRUE;
1682             hdr_ip_proto = 17;
1683             hdr_ethernet = TRUE;
1684             hdr_ethernet_proto = 0x800;
1685             break;
1686
1687         case 'T':
1688             hdr_tcp = TRUE;
1689             hdr_udp = FALSE;
1690             hdr_sctp = FALSE;
1691             hdr_data_chunk = FALSE;
1692             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1693             if (p == optarg || (*p != ',' && *p != '\0')) {
1694                 fprintf(stderr, "Bad src port for '-T'\n");
1695                 usage(TRUE);
1696             }
1697             if (*p == '\0') {
1698                 fprintf(stderr, "No dest port specified for '-u'\n");
1699                 usage(TRUE);
1700             }
1701             p++;
1702             optarg = p;
1703             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1704             if (p == optarg || *p != '\0') {
1705                 fprintf(stderr, "Bad dest port for '-T'\n");
1706                 usage(TRUE);
1707             }
1708             hdr_ip = TRUE;
1709             hdr_ip_proto = 6;
1710             hdr_ethernet = TRUE;
1711             hdr_ethernet_proto = 0x800;
1712             break;
1713
1714         case 'a':
1715             identify_ascii = TRUE;
1716             break;
1717
1718         case '4':
1719         case '6':
1720             p = strchr(optarg, ',');
1721
1722             if (!p) {
1723                 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1724                 usage(TRUE);
1725             }
1726
1727             *p = '\0';
1728             if (c == '6')
1729             {
1730                 hdr_ipv6 = TRUE;
1731                 hdr_ethernet_proto = 0x86DD;
1732             }
1733             else
1734             {
1735                 hdr_ip = TRUE;
1736                 hdr_ethernet_proto = 0x800;
1737             }
1738             hdr_ethernet = TRUE;
1739
1740             if (hdr_ipv6 == TRUE) {
1741                 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1742                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1743                         usage(TRUE);
1744                 }
1745             } else {
1746                 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1747                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1748                         usage(TRUE);
1749                 }
1750             }
1751
1752             p++;
1753             if (*p == '\0') {
1754                 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1755                 usage(TRUE);
1756             }
1757
1758             if (hdr_ipv6 == TRUE) {
1759                 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1760                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1761                         usage(TRUE);
1762                 }
1763             } else {
1764                 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1765                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1766                         usage(TRUE);
1767                 }
1768             }
1769             break;
1770
1771
1772         default:
1773             usage(TRUE);
1774         }
1775     }
1776
1777     if (optind >= argc || argc-optind < 2) {
1778         fprintf(stderr, "Must specify input and output filename\n");
1779         usage(TRUE);
1780     }
1781
1782     if (strcmp(argv[optind], "-")) {
1783         input_filename = g_strdup(argv[optind]);
1784         input_file = ws_fopen(input_filename, "rb");
1785         if (!input_file) {
1786             fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1787                     input_filename, g_strerror(errno));
1788             exit(1);
1789         }
1790     } else {
1791         input_filename = "Standard input";
1792         input_file = stdin;
1793     }
1794
1795     if (strcmp(argv[optind+1], "-")) {
1796         output_filename = g_strdup(argv[optind+1]);
1797         output_file = ws_fopen(output_filename, "wb");
1798         if (!output_file) {
1799             fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1800                     output_filename, g_strerror(errno));
1801             exit(1);
1802         }
1803     } else {
1804         output_filename = "Standard output";
1805         output_file = stdout;
1806     }
1807
1808     /* Some validation */
1809     if (pcap_link_type != 1 && hdr_ethernet) {
1810         fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1811         exit(1);
1812     }
1813
1814     /* Set up our variables */
1815     if (!input_file) {
1816         input_file = stdin;
1817         input_filename = "Standard input";
1818     }
1819     if (!output_file) {
1820         output_file = stdout;
1821         output_filename = "Standard output";
1822     }
1823
1824     ts_sec = time(0);               /* initialize to current time */
1825     timecode_default = *localtime(&ts_sec);
1826     timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1827
1828     /* Display summary of our state */
1829     if (!quiet) {
1830         fprintf(stderr, "Input from: %s\n", input_filename);
1831         fprintf(stderr, "Output to: %s\n",  output_filename);
1832         fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1833
1834         if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1835                                   hdr_ethernet_proto);
1836         if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1837                             hdr_ip_proto);
1838         if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1839                              hdr_src_port, hdr_dest_port);
1840         if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1841                              hdr_src_port, hdr_dest_port);
1842         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1843                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1844         if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
1845                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1846     }
1847 }
1848
1849 int
1850 main(int argc, char *argv[])
1851 {
1852     parse_options(argc, argv);
1853
1854     assert(input_file  != NULL);
1855     assert(output_file != NULL);
1856
1857     write_file_header();
1858
1859     header_length = 0;
1860     if (hdr_ethernet) {
1861         header_length += (int)sizeof(HDR_ETHERNET);
1862     }
1863     if (hdr_ip) {
1864         ip_offset = header_length;
1865         header_length += (int)sizeof(HDR_IP);
1866     } else if (hdr_ipv6) {
1867         ip_offset = header_length;
1868         header_length += (int)sizeof(HDR_IPv6);
1869     }
1870     if (hdr_sctp) {
1871         header_length += (int)sizeof(HDR_SCTP);
1872     }
1873     if (hdr_data_chunk) {
1874         header_length += (int)sizeof(HDR_DATA_CHUNK);
1875     }
1876     if (hdr_tcp) {
1877         header_length += (int)sizeof(HDR_TCP);
1878     }
1879     if (hdr_udp) {
1880         header_length += (int)sizeof(HDR_UDP);
1881     }
1882     curr_offset = header_length;
1883
1884     yyin = input_file;
1885     yylex();
1886
1887     write_current_packet(FALSE);
1888     write_file_trailer();
1889     fclose(input_file);
1890     fclose(output_file);
1891     if (debug)
1892         fprintf(stderr, "\n-------------------------\n");
1893     if (!quiet) {
1894         fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1895                 num_packets_read, (num_packets_read == 1) ? "" : "s",
1896                 num_packets_written, (num_packets_written == 1) ? "" : "s",
1897                 bytes_written, (bytes_written == 1) ? "" : "s");
1898     }
1899     return 0;
1900 }
1901
1902 /*
1903  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1904  *
1905  * Local variables:
1906  * c-basic-offset: 4
1907  * tab-width: 8
1908  * indent-tabs-mode: nil
1909  * End:
1910  *
1911  * vi: set shiftwidth=4 tabstop=8 expandtab:
1912  * :indentSize=4:tabSize=8:noTabs=true:
1913  */
1914