Only include <wsutil/os_version_info.h> if we need it.
[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 <stdio.h>
111 #include <stdlib.h>
112 #include <string.h>
113 #include <wsutil/file_util.h>
114 #include <wsutil/crash_info.h>
115 #include <wsutil/ws_version_info.h>
116
117 #include <time.h>
118 #include <glib.h>
119
120 #ifdef HAVE_UNISTD_H
121 # include <unistd.h>
122 #endif
123
124 #ifdef HAVE_GETOPT_H
125 #include <getopt.h>
126 #endif
127
128 #include <errno.h>
129 #include <assert.h>
130
131 #ifdef HAVE_LIBZ
132 #include <zlib.h>      /* to get the libz version number */
133 #endif
134
135 #ifndef HAVE_GETOPT_LONG
136 #include "wsutil/wsgetopt.h"
137 #endif
138
139 #ifndef HAVE_STRPTIME
140 # include "wsutil/strptime.h"
141 #endif
142
143 #include "pcapio.h"
144 #include "text2pcap.h"
145 #include "version_info.h"
146
147 #ifdef _WIN32
148 #include <wsutil/unicode-utils.h>
149 #endif /* _WIN32 */
150
151 #ifdef HAVE_ARPA_INET_H
152 #include <arpa/inet.h>
153 #endif
154
155 #ifdef HAVE_WINSOCK2_H
156 #include <winsock2.h>       /* needed to define AF_ values on Windows */
157 #endif
158
159 #ifndef HAVE_INET_ATON
160 # include "wsutil/inet_aton.h"
161 #endif
162
163 #ifdef HAVE_SYS_SOCKET_H
164 #include <sys/socket.h>
165 #endif
166
167 #ifdef NEED_INET_V6DEFS_H
168 # include "wsutil/inet_v6defs.h"
169 #endif
170
171 /*--- Options --------------------------------------------------------------------*/
172
173 /* File format */
174 static gboolean use_pcapng = FALSE;
175
176 /* Debug level */
177 static int debug = 0;
178 /* Be quiet */
179 static int quiet = FALSE;
180
181 /* Dummy Ethernet header */
182 static int hdr_ethernet = FALSE;
183 static guint32 hdr_ethernet_proto = 0;
184
185 /* Dummy IP header */
186 static int hdr_ip = FALSE;
187 static int hdr_ipv6 = FALSE;
188 static long hdr_ip_proto = 0;
189
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};
196
197 /* Dummy UDP header */
198 static int     hdr_udp       = FALSE;
199 static guint32 hdr_dest_port = 0;
200 static guint32 hdr_src_port  = 0;
201
202 /* Dummy TCP header */
203 static int hdr_tcp = FALSE;
204
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;
208
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;
214
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;
223
224 /* ASCII text dump identification */
225 static int identify_ascii = FALSE;
226
227 static gboolean has_direction = FALSE;
228 static guint32 direction = 0;
229
230 /*--- Local date -----------------------------------------------------------------*/
231
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;
240
241 static void start_new_packet(gboolean);
242
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;
247
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;
252
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;
258
259 static guint8* pkt_lnstart;
260
261 /* Input file */
262 static const char *input_filename;
263 static FILE       *input_file  = NULL;
264 /* Output file */
265 static const char *output_filename;
266 static FILE       *output_file = NULL;
267
268 /* Offset base to parse */
269 static guint32 offset_base = 16;
270
271 extern FILE *yyin;
272
273 /* ----- State machine -----------------------------------------------------------*/
274
275 /* Current state of parser */
276 typedef enum {
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 */
282 } parser_state_t;
283 static parser_state_t state = INIT;
284
285 static const char *state_str[] = {"Init",
286                            "Start-of-line",
287                            "Offset",
288                            "Byte",
289                            "Text"
290 };
291
292 static const char *token_str[] = {"",
293                            "Byte",
294                            "Offset",
295                            "Directive",
296                            "Text",
297                            "End-of-line"
298 };
299
300 /* ----- Skeleton Packet Headers --------------------------------------------------*/
301
302 typedef struct {
303     guint8  dest_addr[6];
304     guint8  src_addr[6];
305     guint16 l3pid;
306 } hdr_ethernet_t;
307
308 static hdr_ethernet_t HDR_ETHERNET = {
309     {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
310     {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
311     0};
312
313 typedef struct {
314     guint8  ver_hdrlen;
315     guint8  dscp;
316     guint16 packet_length;
317     guint16 identification;
318     guint8  flags;
319     guint8  fragment;
320     guint8  ttl;
321     guint8  protocol;
322     guint16 hdr_checksum;
323     guint32 src_addr;
324     guint32 dest_addr;
325 } hdr_ip_t;
326
327 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
328 #ifdef WORDS_BIGENDIAN
329 0x0a010101, 0x0a020202
330 #else
331 0x0101010a, 0x0202020a
332 #endif
333 };
334
335 /* Fixed IP address values */
336 #ifdef WORDS_BIGENDIAN
337 #define IP_SRC 0x0a010101
338 #define IP_DST 0x0a020202
339 #else
340 #define IP_SRC 0x0101010a
341 #define IP_DST 0x0202020a
342 #endif
343
344 static struct {         /* pseudo header for checksum calculation */
345     guint32 src_addr;
346     guint32 dest_addr;
347     guint8  zero;
348     guint8  protocol;
349     guint16 length;
350 } pseudoh;
351
352
353 /* headers taken from glibc */
354
355 /* IPv6 address */
356 struct hdr_in6_addr
357 {
358     union
359     {
360        guint8  __u6_addr8[16];
361        guint16 __u6_addr16[8];
362        guint32 __u6_addr32[4];
363     } __in6_u;
364 };
365
366 typedef struct {
367     union  {
368         struct ip6_hdrctl {
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 */
373         } ip6_un1;
374         guint8 ip6_un2_vfc;       /* 4 bits version, 4 bits priority */
375     } ip6_ctlun;
376     struct hdr_in6_addr ip6_src;      /* source address */
377     struct hdr_in6_addr ip6_dst;      /* destination address */
378 } hdr_ipv6_t;
379
380 static hdr_ipv6_t HDR_IPv6;
381
382 static struct {                 /* pseudo header ipv6 for checksum calculation */
383     struct  hdr_in6_addr src_addr6;
384     struct  hdr_in6_addr dst_addr6;
385     guint32 protocol;
386     guint32 zero;
387 } pseudoh6;
388
389
390 typedef struct {
391     guint16 source_port;
392     guint16 dest_port;
393     guint16 length;
394     guint16 checksum;
395 } hdr_udp_t;
396
397 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
398
399 typedef struct {
400     guint16 source_port;
401     guint16 dest_port;
402     guint32 seq_num;
403     guint32 ack_num;
404     guint8  hdr_length;
405     guint8  flags;
406     guint16 window;
407     guint16 checksum;
408     guint16 urg;
409 } hdr_tcp_t;
410
411 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
412
413 typedef struct {
414     guint16 src_port;
415     guint16 dest_port;
416     guint32 tag;
417     guint32 checksum;
418 } hdr_sctp_t;
419
420 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
421
422 typedef struct {
423     guint8  type;
424     guint8  bits;
425     guint16 length;
426     guint32 tsn;
427     guint16 sid;
428     guint16 ssn;
429     guint32 ppid;
430 } hdr_data_chunk_t;
431
432 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
433
434 static char tempbuf[64];
435
436 /*----------------------------------------------------------------------
437  * Stuff for writing a PCap file
438  */
439 #define PCAP_SNAPLEN        0xffff
440
441 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
442 static guint32 pcap_link_type = 1;   /* Default is LINKTYPE_ETHERNET */
443
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
448  */
449 static guint32
450 parse_num (const char *str, int offset)
451 {
452     guint32  num;
453     char    *c;
454
455     if (str == NULL) {
456         fprintf(stderr, "FATAL ERROR: str is NULL\n");
457         exit(1);
458     }
459
460     num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
461     if (c == str) {
462         fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
463         exit(1);
464     }
465     return num;
466 }
467
468 /*----------------------------------------------------------------------
469  * Write this byte into current packet
470  */
471 static void
472 write_byte (const char *str)
473 {
474     guint32 num;
475
476     num = parse_num(str, FALSE);
477     packet_buf[curr_offset] = (guint8) num;
478     curr_offset++;
479     if (curr_offset - header_length >= max_offset) /* packet full */
480         start_new_packet(TRUE);
481 }
482
483 /*----------------------------------------------------------------------
484  * Write a number of bytes into current packet
485  */
486
487 static void
488 write_bytes (const char bytes[], guint32 nbytes)
489 {
490     guint32 i;
491
492     if (curr_offset + nbytes < MAX_PACKET) {
493         for (i = 0; i < nbytes; i++) {
494             packet_buf[curr_offset] = bytes[i];
495             curr_offset++;
496         }
497     }
498 }
499
500 /*----------------------------------------------------------------------
501  * Remove bytes from the current packet
502  */
503 static void
504 unwrite_bytes (guint32 nbytes)
505 {
506     curr_offset -= nbytes;
507 }
508
509 /*----------------------------------------------------------------------
510  * Compute one's complement checksum (from RFC1071)
511  */
512 static guint16
513 in_checksum (void *buf, guint32 count)
514 {
515     guint32 sum = 0;
516     guint16 *addr = (guint16 *)buf;
517
518     while (count > 1) {
519         /*  This is the inner loop */
520         sum += g_ntohs(* (guint16 *) addr);
521         addr++;
522         count -= 2;
523     }
524
525     /*  Add left-over byte, if any */
526     if (count > 0)
527         sum += g_ntohs(* (guint8 *) addr);
528
529     /*  Fold 32-bit sum to 16 bits */
530     while (sum>>16)
531         sum = (sum & 0xffff) + (sum >> 16);
532
533     sum = ~sum;
534     return g_htons(sum);
535 }
536
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.
539  */
540
541 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
542 static guint32 crc_c[256] =
543 {
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,
608 };
609
610 static guint32
611 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
612 {
613     unsigned int i;
614     guint32 crc;
615
616     crc = crc32_init;
617     for (i = 0; i < len; i++)
618         CRC32C(crc, buf[i]);
619
620     return crc;
621 }
622
623 static guint32
624 finalize_crc32c (guint32 crc)
625 {
626     guint32 result;
627     guint8 byte0,byte1,byte2,byte3;
628
629     result = ~crc;
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);
635     return result;
636 }
637
638 static guint16
639 number_of_padding_bytes (guint32 length)
640 {
641     guint16 remainder;
642
643     remainder = length % 4;
644
645     if (remainder == 0)
646         return 0;
647     else
648         return 4 - remainder;
649 }
650
651 /*----------------------------------------------------------------------
652  * Write current packet out
653  */
654 static void
655 write_current_packet (gboolean cont)
656 {
657     guint32  length         = 0;
658     guint16  padding_length = 0;
659     int      err;
660     guint16  ihatemacros;
661     gboolean success;
662
663     if (curr_offset > header_length) {
664         /* Write the packet */
665
666         /* Is direction indication on with an inbound packet? */
667         gboolean isInbound = has_direction && (direction == 2);
668
669         /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
670         if (hdr_ipv6) {
671             hdr_ethernet_proto = 0x86DD;
672             hdr_ip = FALSE;
673         }
674
675         /* Compute packet length */
676         length = curr_offset;
677         if (hdr_sctp) {
678             padding_length = number_of_padding_bytes(length - header_length );
679         } else {
680             padding_length = 0;
681         }
682         /* Reset curr_offset, since we now write the headers */
683         curr_offset = 0;
684
685         /* Write Ethernet header */
686         if (hdr_ethernet) {
687             HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
688             write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
689         }
690
691         /* Write IP header */
692         if (hdr_ip) {
693             if (isInbound) {
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;
696             }
697             else {
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;
700             }
701
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));
712
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));
719
720             /* initialize pseudo ipv6 header for checksum calculation */
721             pseudoh6.src_addr6  = HDR_IPv6.ip6_src;
722             pseudoh6.dst_addr6  = HDR_IPv6.ip6_dst;
723             pseudoh6.zero       = 0;
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));
727         }
728
729         if (!hdr_ipv6) {
730             /* initialize pseudo header for checksum calculation */
731             pseudoh.src_addr    = HDR_IP.src_addr;
732             pseudoh.dest_addr   = HDR_IP.dest_addr;
733             pseudoh.zero        = 0;
734             pseudoh.protocol    = (guint8) hdr_ip_proto;
735             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_UDP));
736         }
737
738         /* Write UDP header */
739         if (hdr_udp) {
740             guint16 x16;
741             guint32 u;
742
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));
750             u    = g_ntohs(x16);
751             x16  = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
752             u   += g_ntohs(x16);
753             x16  = in_checksum(packet_buf + header_length, length - header_length);
754             u   += g_ntohs(x16);
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));
760         }
761
762         /* Write TCP header */
763         if (hdr_tcp) {
764             guint16 x16;
765             guint32 u;
766
767              /* initialize pseudo header for checksum calculation */
768             pseudoh.src_addr    = HDR_IP.src_addr;
769             pseudoh.dest_addr   = HDR_IP.dest_addr;
770             pseudoh.zero        = 0;
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 */
777             if (has_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);
781             }
782             else {
783                 HDR_TCP.flags = 0;
784                 HDR_TCP.ack_num = 0;
785             }
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));
791             u    = g_ntohs(x16);
792             x16  = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
793             u   += g_ntohs(x16);
794             x16  = in_checksum(packet_buf + header_length, length - header_length);
795             u   += g_ntohs(x16);
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));
801             if (isInbound) {
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);
804             }
805             else {
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);
808             }
809         }
810
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;
816             }
817             if (!cont) {
818                 hdr_data_chunk_bits |= 0x01;
819             }
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++;
828             if (!cont) {
829                 hdr_data_chunk_ssn++;
830             }
831         }
832
833         /* Write SCTP common header */
834         if (hdr_sctp) {
835             guint32 zero = 0;
836
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);
846             } else {
847                 HDR_SCTP.checksum  = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
848             }
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));
852         }
853
854         /* Write DATA chunk header */
855         if (hdr_data_chunk) {
856             write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
857         }
858
859         /* Reset curr_offset, since we now write the trailers */
860         curr_offset = length;
861
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;
867         }
868
869         /* Write Ethernet trailer */
870         if (hdr_ethernet && (length < 60)) {
871             memset(tempbuf, 0, 60 - length);
872             write_bytes((const char *)&tempbuf, 60 - length);
873             length = 60;
874         }
875         if (use_pcapng) {
876             success = pcapng_write_enhanced_packet_block(output_file,
877                                                          NULL,
878                                                          ts_sec, ts_nsec,
879                                                          length, length,
880                                                          0,
881                                                          1000000000,
882                                                          packet_buf, direction,
883                                                          &bytes_written, &err);
884         } else {
885             success = libpcap_write_packet(output_file,
886                                            ts_sec, ts_nsec/1000,
887                                            length, length,
888                                            packet_buf,
889                                            &bytes_written, &err);
890         }
891         if (!success) {
892             fprintf(stderr, "File write error [%s] : %s\n",
893                     output_filename, g_strerror(err));
894             exit(1);
895         }
896         if (ts_fmt == NULL) {
897             /* fake packet counter */
898             if (use_pcapng)
899                 ts_nsec++;
900             else
901                 ts_nsec += 1000;
902         }
903         if (!quiet) {
904             fprintf(stderr, "Wrote packet of %u bytes.\n", length);
905         }
906         num_packets_written++;
907     }
908
909     packet_start += curr_offset - header_length;
910     curr_offset = header_length;
911     return;
912 }
913
914 /*----------------------------------------------------------------------
915  * Write file header and trailer
916  */
917 static void
918 write_file_header (void)
919 {
920     int      err;
921     gboolean success;
922
923     if (use_pcapng) {
924 #ifdef GITVERSION
925         const char *appname = "text2pcap (" GITVERSION " from " GITBRANCH ")";
926 #else
927         const char *appname = "text2pcap";
928 #endif
929         char comment[100];
930
931         g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
932         success = pcapng_write_session_header_block(output_file,
933                                                     comment,
934                                                     NULL,
935                                                     NULL,
936                                                     appname,
937                                                     -1,
938                                                     &bytes_written,
939                                                     &err);
940         if (success) {
941             success = pcapng_write_interface_description_block(output_file,
942                                                                NULL,
943                                                                NULL,
944                                                                NULL,
945                                                                "",
946                                                                NULL,
947                                                                pcap_link_type,
948                                                                PCAP_SNAPLEN,
949                                                                &bytes_written,
950                                                                0,
951                                                                9,
952                                                                &err);
953         }
954     } else {
955         success = libpcap_write_file_header(output_file, pcap_link_type,
956                                             PCAP_SNAPLEN, FALSE,
957                                             &bytes_written, &err);
958     }
959     if (!success) {
960         fprintf(stderr, "File write error [%s] : %s\n",
961                 output_filename, g_strerror(err));
962         exit(1);
963     }
964 }
965
966 static void
967 write_file_trailer (void)
968 {
969     int      err;
970     gboolean success;
971
972     if (use_pcapng) {
973         success = pcapng_write_interface_statistics_block(output_file,
974                                                           0,
975                                                           &bytes_written,
976                                                           "Counters provided by text2pcap",
977                                                           0,
978                                                           0,
979                                                           num_packets_written,
980                                                           num_packets_written - num_packets_written,
981                                                           &err);
982
983     } else {
984         success = TRUE;
985     }
986     if (!success) {
987         fprintf(stderr, "File write error [%s] : %s\n",
988                 output_filename, g_strerror(err));
989         exit(1);
990     }
991    return;
992 }
993
994 /*----------------------------------------------------------------------
995  * Append a token to the packet preamble.
996  */
997 static void
998 append_to_preamble (char *str)
999 {
1000     size_t toklen;
1001
1002     if (packet_preamble_len != 0) {
1003         if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1004             return; /* no room to add more preamble */
1005         /* Add a blank separator between the previous token and this token. */
1006         packet_preamble[packet_preamble_len++] = ' ';
1007     }
1008     toklen = strlen(str);
1009     if (toklen != 0) {
1010         if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1011             return; /* no room to add the token to the preamble */
1012         g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1013         packet_preamble_len += (int) toklen;
1014         if (debug >= 2) {
1015             char *c;
1016             char xs[PACKET_PREAMBLE_MAX_LEN];
1017             g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1018             while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1019             fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1020         }
1021     }
1022 }
1023
1024 /*----------------------------------------------------------------------
1025  * Parse the preamble to get the timecode.
1026  */
1027
1028 static void
1029 parse_preamble (void)
1030 {
1031     struct tm  timecode;
1032     char      *subsecs;
1033     char      *p;
1034     int        subseclen;
1035     int        i;
1036
1037      /*
1038      * Null-terminate the preamble.
1039      */
1040     packet_preamble[packet_preamble_len] = '\0';
1041     if (debug > 0)
1042         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1043
1044     if (has_direction) {
1045         switch (packet_preamble[0]) {
1046         case 'i':
1047         case 'I':
1048             direction = 0x00000001;
1049             packet_preamble[0] = ' ';
1050             break;
1051         case 'o':
1052         case 'O':
1053             direction = 0x00000002;
1054             packet_preamble[0] = ' ';
1055             break;
1056         default:
1057             direction = 0x00000000;
1058             break;
1059         }
1060         i = 0;
1061         while (packet_preamble[i] == ' ' ||
1062                packet_preamble[i] == '\r' ||
1063                packet_preamble[i] == '\t') {
1064             i++;
1065         }
1066         packet_preamble_len -= i;
1067         /* Also move the trailing '\0'. */
1068         memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1069     }
1070
1071
1072     /*
1073      * If no "-t" flag was specified, don't attempt to parse the packet
1074      * preamble to extract a time stamp.
1075      */
1076     if (ts_fmt == NULL) {
1077         /* Clear Preamble */
1078         packet_preamble_len = 0;
1079         return;
1080     }
1081
1082     /*
1083      * Initialize to today localtime, just in case not all fields
1084      * of the date and time are specified.
1085      */
1086
1087     timecode = timecode_default;
1088     ts_nsec = 0;
1089
1090     /* Ensure preamble has more than two chars before attempting to parse.
1091      * This should cover line breaks etc that get counted.
1092      */
1093     if (strlen(packet_preamble) > 2) {
1094         /* Get Time leaving subseconds */
1095         subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1096         if (subsecs != NULL) {
1097             /* Get the long time from the tm structure */
1098             /*  (will return -1 if failure)            */
1099             ts_sec  = mktime( &timecode );
1100         } else
1101             ts_sec = -1;    /* we failed to parse it */
1102
1103         /* This will ensure incorrectly parsed dates get set to zero */
1104         if (-1 == ts_sec) {
1105             /* Sanitize - remove all '\r' */
1106             char *c;
1107             while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1108             fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n   (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1109                  packet_preamble, ts_fmt);
1110             if (debug >= 2) {
1111                 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1112                     timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1113                     timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1114             }
1115             ts_sec  = 0;  /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1116             ts_nsec = 0;
1117         } else {
1118             /* Parse subseconds */
1119             ts_nsec = (guint32)strtol(subsecs, &p, 10);
1120             if (subsecs == p) {
1121                 /* Error */
1122                 ts_nsec = 0;
1123             } else {
1124                 /*
1125                  * Convert that number to a number
1126                  * of microseconds; if it's N digits
1127                  * long, it's in units of 10^(-N) seconds,
1128                  * so, to convert it to units of
1129                  * 10^-9 seconds, we multiply by
1130                  * 10^(9-N).
1131                  */
1132                 subseclen = (int) (p - subsecs);
1133                 if (subseclen > 9) {
1134                     /*
1135                      * *More* than 9 digits; 9-N is
1136                      * negative, so we divide by
1137                      * 10^(N-9).
1138                      */
1139                     for (i = subseclen - 9; i != 0; i--)
1140                         ts_nsec /= 10;
1141                 } else if (subseclen < 9) {
1142                     for (i = 9 - subseclen; i != 0; i--)
1143                         ts_nsec *= 10;
1144                 }
1145             }
1146         }
1147     }
1148     if (debug >= 2) {
1149         char *c;
1150         while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1151         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1152         fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1153     }
1154
1155
1156     /* Clear Preamble */
1157     packet_preamble_len = 0;
1158 }
1159
1160 /*----------------------------------------------------------------------
1161  * Start a new packet
1162  */
1163 static void
1164 start_new_packet (gboolean cont)
1165 {
1166     if (debug >= 1)
1167         fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1168
1169     /* Write out the current packet, if required */
1170     write_current_packet(cont);
1171     num_packets_read++;
1172
1173     /* Ensure we parse the packet preamble as it may contain the time */
1174     parse_preamble();
1175 }
1176
1177 /*----------------------------------------------------------------------
1178  * Process a directive
1179  */
1180 static void
1181 process_directive (char *str)
1182 {
1183     fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1184 }
1185
1186 /*----------------------------------------------------------------------
1187  * Parse a single token (called from the scanner)
1188  */
1189 void
1190 parse_token (token_t token, char *str)
1191 {
1192     guint32  num;
1193     int      by_eol;
1194     int      rollback = 0;
1195     int      line_size;
1196     int      i;
1197     char    *s2;
1198     char     tmp_str[3];
1199
1200     /*
1201      * This is implemented as a simple state machine of five states.
1202      * State transitions are caused by tokens being received from the
1203      * scanner. The code should be self-documenting.
1204      */
1205
1206     if (debug >= 2) {
1207         /* Sanitize - remove all '\r' */
1208         char *c;
1209         if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1210
1211         fprintf(stderr, "(%s, %s \"%s\") -> (",
1212                 state_str[state], token_str[token], str ? str : "");
1213     }
1214
1215     switch (state) {
1216
1217     /* ----- Waiting for new packet -------------------------------------------*/
1218     case INIT:
1219         if (!str && token != T_EOL) goto fail_null_str;
1220         switch (token) {
1221         case T_TEXT:
1222             append_to_preamble(str);
1223             break;
1224         case T_DIRECTIVE:
1225             process_directive(str);
1226             break;
1227         case T_OFFSET:
1228             num = parse_num(str, TRUE);
1229             if (num == 0) {
1230                 /* New packet starts here */
1231                 start_new_packet(FALSE);
1232                 state = READ_OFFSET;
1233                 pkt_lnstart = packet_buf + num;
1234             }
1235             break;
1236         case T_EOL:
1237             /* Some describing text may be parsed as offset, but the invalid
1238                offset will be checked in the state of START_OF_LINE, so
1239                we add this transition to gain flexibility */
1240             state = START_OF_LINE;
1241             break;
1242         default:
1243             break;
1244         }
1245         break;
1246
1247     /* ----- Processing packet, start of new line -----------------------------*/
1248     case START_OF_LINE:
1249         if (!str && token != T_EOL) goto fail_null_str;
1250         switch (token) {
1251         case T_TEXT:
1252             append_to_preamble(str);
1253             break;
1254         case T_DIRECTIVE:
1255             process_directive(str);
1256             break;
1257         case T_OFFSET:
1258             num = parse_num(str, TRUE);
1259             if (num == 0) {
1260                 /* New packet starts here */
1261                 start_new_packet(FALSE);
1262                 packet_start = 0;
1263                 state = READ_OFFSET;
1264             } else if ((num - packet_start) != curr_offset - header_length) {
1265                 /*
1266                  * The offset we read isn't the one we expected.
1267                  * This may only mean that we mistakenly interpreted
1268                  * some text as byte values (e.g., if the text dump
1269                  * of packet data included a number with spaces around
1270                  * it).  If the offset is less than what we expected,
1271                  * assume that's the problem, and throw away the putative
1272                  * extra byte values.
1273                  */
1274                 if (num < curr_offset) {
1275                     unwrite_bytes(curr_offset - num);
1276                     state = READ_OFFSET;
1277                 } else {
1278                     /* Bad offset; switch to INIT state */
1279                     if (debug >= 1)
1280                         fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1281                                 curr_offset, num);
1282                     write_current_packet(FALSE);
1283                     state = INIT;
1284                 }
1285             } else
1286                 state = READ_OFFSET;
1287                 pkt_lnstart = packet_buf + num;
1288             break;
1289         case T_EOL:
1290             state = START_OF_LINE;
1291             break;
1292         default:
1293             break;
1294         }
1295         break;
1296
1297     /* ----- Processing packet, read offset -----------------------------------*/
1298     case READ_OFFSET:
1299         switch (token) {
1300         case T_BYTE:
1301             /* Record the byte */
1302             state = READ_BYTE;
1303             if (!str) goto fail_null_str;
1304             write_byte(str);
1305             break;
1306         case T_TEXT:
1307         case T_DIRECTIVE:
1308         case T_OFFSET:
1309             state = READ_TEXT;
1310             break;
1311         case T_EOL:
1312             state = START_OF_LINE;
1313             break;
1314         default:
1315             break;
1316         }
1317         break;
1318
1319     /* ----- Processing packet, read byte -------------------------------------*/
1320     case READ_BYTE:
1321         switch (token) {
1322         case T_BYTE:
1323             /* Record the byte */
1324             write_byte(str);
1325             break;
1326         case T_TEXT:
1327         case T_DIRECTIVE:
1328         case T_OFFSET:
1329         case T_EOL:
1330             by_eol = 0;
1331             state = READ_TEXT;
1332             if (token == T_EOL) {
1333                 by_eol = 1;
1334                 state = START_OF_LINE;
1335             }
1336             if (identify_ascii) {
1337                 /* Here a line of pkt bytes reading is finished
1338                    compare the ascii and hex to avoid such situation:
1339                    "61 62 20 ab ", when ab is ascii dump then it should
1340                    not be treat as byte */
1341                 rollback = 0;
1342                 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1343                    s2 = "ab ", s1 = "616220"
1344                    we should find out the largest tail of s1 matches the head
1345                    of s2, it means the matched part in tail is the ASCII dump
1346                    of the head byte. These matched should be rollback */
1347                 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1348                 s2 = (char*)g_malloc((line_size+1)/4+1);
1349                 /* gather the possible pattern */
1350                 for (i = 0; i < (line_size+1)/4; i++) {
1351                     tmp_str[0] = pkt_lnstart[i*3];
1352                     tmp_str[1] = pkt_lnstart[i*3+1];
1353                     tmp_str[2] = '\0';
1354                     /* it is a valid convertable string */
1355                     if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[0])) {
1356                         break;
1357                     }
1358                     s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1359                     rollback++;
1360                     /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1361                     if (!(pkt_lnstart[i*3+2] == ' ')) {
1362                         if (by_eol != 1)
1363                             rollback--;
1364                         break;
1365                     }
1366                 }
1367                 /* If packet line start contains possible byte pattern, the line end
1368                    should contain the matched pattern if the user open the -a flag.
1369                    The packet will be possible invalid if the byte pattern cannot find
1370                    a matched one in the line of packet buffer.*/
1371                 if (rollback > 0) {
1372                     if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1373                         unwrite_bytes(rollback);
1374                     }
1375                     /* Not matched. This line contains invalid packet bytes, so
1376                        discard the whole line */
1377                     else {
1378                         unwrite_bytes(line_size);
1379                     }
1380                 }
1381                 g_free(s2);
1382             }
1383             break;
1384         default:
1385             break;
1386         }
1387         break;
1388
1389     /* ----- Processing packet, read text -------------------------------------*/
1390     case READ_TEXT:
1391         switch (token) {
1392         case T_EOL:
1393             state = START_OF_LINE;
1394             break;
1395         default:
1396             break;
1397         }
1398         break;
1399
1400     default:
1401         fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1402         exit(1);
1403     }
1404
1405     if (debug >= 2)
1406         fprintf(stderr, ", %s)\n", state_str[state]);
1407
1408     return;
1409
1410 fail_null_str:
1411     fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1412     exit(1);
1413
1414 }
1415
1416 /*----------------------------------------------------------------------
1417  * Print usage string and exit
1418  */
1419 static void
1420 print_usage (FILE *output)
1421 {
1422     fprintf(output,
1423             "\n"
1424             "Usage: text2pcap [options] <infile> <outfile>\n"
1425             "\n"
1426             "where  <infile> specifies input  filename (use - for standard input)\n"
1427             "      <outfile> specifies output filename (use - for standard output)\n"
1428             "\n"
1429             "Input:\n"
1430             "  -o hex|oct|dec         parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1431             "                         default is hex.\n"
1432             "  -t <timefmt>           treat the text before the packet as a date/time code;\n"
1433             "                         the specified argument is a format string of the sort\n"
1434             "                         supported by strptime.\n"
1435             "                         Example: The time \"10:15:14.5476\" has the format code\n"
1436             "                         \"%%H:%%M:%%S.\"\n"
1437             "                         NOTE: The subsecond component delimiter, '.', must be\n"
1438             "                         given, but no pattern is required; the remaining\n"
1439             "                         number is assumed to be fractions of a second.\n"
1440             "                         NOTE: Date/time fields from the current date/time are\n"
1441             "                         used as the default for unspecified fields.\n"
1442             "  -D                     the text before the packet starts with an I or an O,\n"
1443             "                         indicating that the packet is inbound or outbound.\n"
1444             "                         This is only stored if the output format is PCAP-NG.\n"
1445             "  -a                     enable ASCII text dump identification.\n"
1446             "                         The start of the ASCII text dump can be identified\n"
1447             "                         and excluded from the packet data, even if it looks\n"
1448             "                         like a HEX dump.\n"
1449             "                         NOTE: Do not enable it if the input file does not\n"
1450             "                         contain the ASCII text dump.\n"
1451             "\n"
1452             "Output:\n"
1453             "  -l <typenum>           link-layer type number; default is 1 (Ethernet).  See\n"
1454             "                         http://www.tcpdump.org/linktypes.html for a list of\n"
1455             "                         numbers.  Use this option if your dump is a complete\n"
1456             "                         hex dump of an encapsulated packet and you wish to\n"
1457             "                         specify the exact type of encapsulation.\n"
1458             "                         Example: -l 7 for ARCNet packets.\n"
1459             "  -m <max-packet>        max packet length in output; default is %d\n"
1460             "\n"
1461             "Prepend dummy header:\n"
1462             "  -e <l3pid>             prepend dummy Ethernet II header with specified L3PID\n"
1463             "                         (in HEX).\n"
1464             "                         Example: -e 0x806 to specify an ARP packet.\n"
1465             "  -i <proto>             prepend dummy IP header with specified IP protocol\n"
1466             "                         (in DECIMAL).\n"
1467             "                         Automatically prepends Ethernet header as well.\n"
1468             "                         Example: -i 46\n"
1469             "  -4 <srcip>,<destip>    prepend dummy IPv4 header with specified\n"
1470             "                         dest and source address.\n"
1471             "                         Example: -4 10.0.0.1,10.0.0.2\n"
1472             "  -6 <srcip>,<destip>    replace IPv6 header with specified\n"
1473             "                         dest and source address.\n"
1474             "                         Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1475             "  -u <srcp>,<destp>      prepend dummy UDP header with specified\n"
1476             "                         source and destination ports (in DECIMAL).\n"
1477             "                         Automatically prepends Ethernet & IP headers as well.\n"
1478             "                         Example: -u 1000,69 to make the packets look like\n"
1479             "                         TFTP/UDP packets.\n"
1480             "  -T <srcp>,<destp>      prepend dummy TCP header with specified\n"
1481             "                         source and destination ports (in DECIMAL).\n"
1482             "                         Automatically prepends Ethernet & IP headers as well.\n"
1483             "                         Example: -T 50,60\n"
1484             "  -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1485             "                         source/dest ports and verification tag (in DECIMAL).\n"
1486             "                         Automatically prepends Ethernet & IP headers as well.\n"
1487             "                         Example: -s 30,40,34\n"
1488             "  -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1489             "                         source/dest ports and verification tag 0.\n"
1490             "                         Automatically prepends a dummy SCTP DATA\n"
1491             "                         chunk header with payload protocol identifier ppi.\n"
1492             "                         Example: -S 30,40,34\n"
1493             "\n"
1494             "Miscellaneous:\n"
1495             "  -h                     display this help and exit.\n"
1496             "  -d                     show detailed debug of parser states.\n"
1497             "  -q                     generate no output at all (automatically disables -d).\n"
1498             "  -n                     use PCAP-NG instead of PCAP as output format.\n"
1499             "",
1500             MAX_PACKET);
1501 }
1502
1503 static void
1504 get_text2pcap_compiled_info(GString *str)
1505 {
1506     /* LIBZ */
1507     g_string_append(str, ", ");
1508 #ifdef HAVE_LIBZ
1509     g_string_append(str, "with libz ");
1510 #ifdef ZLIB_VERSION
1511     g_string_append(str, ZLIB_VERSION);
1512 #else /* ZLIB_VERSION */
1513     g_string_append(str, "(version unknown)");
1514 #endif /* ZLIB_VERSION */
1515 #else /* HAVE_LIBZ */
1516     g_string_append(str, "without libz");
1517 #endif /* HAVE_LIBZ */
1518 }
1519
1520 static void
1521 get_text2pcap_runtime_info(GString *str)
1522 {
1523     /* zlib */
1524 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1525     g_string_append_printf(str, ", with libz %s", zlibVersion());
1526 #endif
1527 }
1528
1529 /*----------------------------------------------------------------------
1530  * Parse CLI options
1531  */
1532 static void
1533 parse_options (int argc, char *argv[])
1534 {
1535     GString *comp_info_str;
1536     GString *runtime_info_str;
1537     int   c;
1538     char *p;
1539     static const struct option long_options[] = {
1540         {(char *)"help", no_argument, NULL, 'h'},
1541         {(char *)"version", no_argument, NULL, 'v'},
1542         {0, 0, 0, 0 }
1543     };
1544
1545 #ifdef _WIN32
1546     arg_list_utf_16to8(argc, argv);
1547     create_app_running_mutex();
1548 #endif /* _WIN32 */
1549
1550     /* Assemble the compile-time version information string */
1551     comp_info_str = g_string_new("Compiled ");
1552     get_compiled_version_info(comp_info_str, NULL, get_text2pcap_compiled_info);
1553
1554     /* Assemble the run-time version information string */
1555     runtime_info_str = g_string_new("Running ");
1556     get_runtime_version_info(runtime_info_str, get_text2pcap_runtime_info);
1557
1558     /* Add it to the information to be reported on a crash. */
1559     ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1560          "\n"
1561          "%s"
1562          "\n"
1563          "%s",
1564       get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1565
1566     /* Scan CLI parameters */
1567     while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1568         switch (c) {
1569         case 'h':
1570             printf("Text2pcap (Wireshark) %s\n"
1571                    "Generate a capture file from an ASCII hexdump of packets.\n"
1572                    "See http://www.wireshark.org for more information.\n",
1573                    get_ws_vcs_version_info());
1574             print_usage(stdout);
1575             exit(0);
1576             break;
1577         case 'd': if (!quiet) debug++; break;
1578         case 'D': has_direction = TRUE; break;
1579         case 'q': quiet = TRUE; debug = FALSE; break;
1580         case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1581         case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1582         case 'n': use_pcapng = TRUE; break;
1583         case 'o':
1584             if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1585                 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1586                 print_usage(stderr);
1587                 exit(1);
1588             }
1589             switch (optarg[0]) {
1590             case 'o': offset_base =  8; break;
1591             case 'h': offset_base = 16; break;
1592             case 'd': offset_base = 10; break;
1593             }
1594             break;
1595         case 'e':
1596             hdr_ethernet = TRUE;
1597             if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1598                 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1599                 print_usage(stderr);
1600                 exit(1);
1601             }
1602             break;
1603
1604         case 'i':
1605             hdr_ip = TRUE;
1606             hdr_ip_proto = strtol(optarg, &p, 10);
1607             if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1608                   hdr_ip_proto > 255) {
1609                 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1610                 print_usage(stderr);
1611                 exit(1);
1612             }
1613             hdr_ethernet = TRUE;
1614             hdr_ethernet_proto = 0x800;
1615             break;
1616
1617         case 's':
1618             hdr_sctp = TRUE;
1619             hdr_data_chunk = FALSE;
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                 print_usage(stderr);
1626                 exit(1);
1627             }
1628             if (*p == '\0') {
1629                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1630                 print_usage(stderr);
1631                 exit(1);
1632             }
1633             p++;
1634             optarg = p;
1635             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1636             if (p == optarg || (*p != ',' && *p != '\0')) {
1637                 fprintf(stderr, "Bad dest port for '-s'\n");
1638                 print_usage(stderr);
1639                 exit(1);
1640             }
1641             if (*p == '\0') {
1642                 fprintf(stderr, "No tag specified for '-%c'\n", c);
1643                 print_usage(stderr);
1644                 exit(1);
1645             }
1646             p++;
1647             optarg = p;
1648             hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1649             if (p == optarg || *p != '\0') {
1650                 fprintf(stderr, "Bad tag for '-%c'\n", c);
1651                 print_usage(stderr);
1652                 exit(1);
1653             }
1654
1655             hdr_ip = TRUE;
1656             hdr_ip_proto = 132;
1657             hdr_ethernet = TRUE;
1658             hdr_ethernet_proto = 0x800;
1659             break;
1660         case 'S':
1661             hdr_sctp = TRUE;
1662             hdr_data_chunk = TRUE;
1663             hdr_tcp = FALSE;
1664             hdr_udp = FALSE;
1665             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1666             if (p == optarg || (*p != ',' && *p != '\0')) {
1667                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1668                 print_usage(stderr);
1669                 exit(1);
1670             }
1671             if (*p == '\0') {
1672                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1673                 print_usage(stderr);
1674                 exit(1);
1675             }
1676             p++;
1677             optarg = p;
1678             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1679             if (p == optarg || (*p != ',' && *p != '\0')) {
1680                 fprintf(stderr, "Bad dest port for '-s'\n");
1681                 print_usage(stderr);
1682                 exit(1);
1683             }
1684             if (*p == '\0') {
1685                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1686                 print_usage(stderr);
1687                 exit(1);
1688             }
1689             p++;
1690             optarg = p;
1691             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1692             if (p == optarg || *p != '\0') {
1693                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1694                 print_usage(stderr);
1695                 exit(1);
1696             }
1697
1698             hdr_ip = TRUE;
1699             hdr_ip_proto = 132;
1700             hdr_ethernet = TRUE;
1701             hdr_ethernet_proto = 0x800;
1702             break;
1703
1704         case 't':
1705             ts_fmt = optarg;
1706             break;
1707
1708         case 'u':
1709             hdr_udp = TRUE;
1710             hdr_tcp = FALSE;
1711             hdr_sctp = FALSE;
1712             hdr_data_chunk = FALSE;
1713             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1714             if (p == optarg || (*p != ',' && *p != '\0')) {
1715                 fprintf(stderr, "Bad src port for '-u'\n");
1716                 print_usage(stderr);
1717                 exit(1);
1718             }
1719             if (*p == '\0') {
1720                 fprintf(stderr, "No dest port specified for '-u'\n");
1721                 print_usage(stderr);
1722                 exit(1);
1723             }
1724             p++;
1725             optarg = p;
1726             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1727             if (p == optarg || *p != '\0') {
1728                 fprintf(stderr, "Bad dest port for '-u'\n");
1729                 print_usage(stderr);
1730                 exit(1);
1731             }
1732             hdr_ip = TRUE;
1733             hdr_ip_proto = 17;
1734             hdr_ethernet = TRUE;
1735             hdr_ethernet_proto = 0x800;
1736             break;
1737
1738         case 'T':
1739             hdr_tcp = TRUE;
1740             hdr_udp = FALSE;
1741             hdr_sctp = FALSE;
1742             hdr_data_chunk = FALSE;
1743             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1744             if (p == optarg || (*p != ',' && *p != '\0')) {
1745                 fprintf(stderr, "Bad src port for '-T'\n");
1746                 print_usage(stderr);
1747                 exit(1);
1748             }
1749             if (*p == '\0') {
1750                 fprintf(stderr, "No dest port specified for '-u'\n");
1751                 print_usage(stderr);
1752                 exit(1);
1753             }
1754             p++;
1755             optarg = p;
1756             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1757             if (p == optarg || *p != '\0') {
1758                 fprintf(stderr, "Bad dest port for '-T'\n");
1759                 print_usage(stderr);
1760                 exit(1);
1761             }
1762             hdr_ip = TRUE;
1763             hdr_ip_proto = 6;
1764             hdr_ethernet = TRUE;
1765             hdr_ethernet_proto = 0x800;
1766             break;
1767
1768         case 'a':
1769             identify_ascii = TRUE;
1770             break;
1771
1772         case 'v':
1773             show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1774             g_string_free(comp_info_str, TRUE);
1775             g_string_free(runtime_info_str, TRUE);
1776             exit(0);
1777             break;
1778
1779         case '4':
1780         case '6':
1781             p = strchr(optarg, ',');
1782
1783             if (!p) {
1784                 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1785                 print_usage(stderr);
1786                 exit(1);
1787             }
1788
1789             *p = '\0';
1790             if (c == '6')
1791             {
1792                 hdr_ipv6 = TRUE;
1793                 hdr_ethernet_proto = 0x86DD;
1794             }
1795             else
1796             {
1797                 hdr_ip = TRUE;
1798                 hdr_ethernet_proto = 0x800;
1799             }
1800             hdr_ethernet = TRUE;
1801
1802             if (hdr_ipv6 == TRUE) {
1803                 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1804                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1805                         print_usage(stderr);
1806                         exit(1);
1807                 }
1808             } else {
1809                 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1810                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1811                         print_usage(stderr);
1812                         exit(1);
1813                 }
1814             }
1815
1816             p++;
1817             if (*p == '\0') {
1818                 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1819                 print_usage(stderr);
1820                 exit(1);
1821             }
1822
1823             if (hdr_ipv6 == TRUE) {
1824                 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1825                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1826                         print_usage(stderr);
1827                         exit(1);
1828                 }
1829             } else {
1830                 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1831                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1832                         print_usage(stderr);
1833                         exit(1);
1834                 }
1835             }
1836             break;
1837
1838
1839         case '?':
1840         default:
1841             print_usage(stderr);
1842             exit(1);
1843         }
1844     }
1845
1846     if (optind >= argc || argc-optind < 2) {
1847         fprintf(stderr, "Must specify input and output filename\n");
1848         print_usage(stderr);
1849         exit(1);
1850     }
1851
1852     if (strcmp(argv[optind], "-")) {
1853         input_filename = g_strdup(argv[optind]);
1854         input_file = ws_fopen(input_filename, "rb");
1855         if (!input_file) {
1856             fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1857                     input_filename, g_strerror(errno));
1858             exit(1);
1859         }
1860     } else {
1861         input_filename = "Standard input";
1862         input_file = stdin;
1863     }
1864
1865     if (strcmp(argv[optind+1], "-")) {
1866         output_filename = g_strdup(argv[optind+1]);
1867         output_file = ws_fopen(output_filename, "wb");
1868         if (!output_file) {
1869             fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1870                     output_filename, g_strerror(errno));
1871             exit(1);
1872         }
1873     } else {
1874         output_filename = "Standard output";
1875         output_file = stdout;
1876     }
1877
1878     /* Some validation */
1879     if (pcap_link_type != 1 && hdr_ethernet) {
1880         fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1881         exit(1);
1882     }
1883
1884     /* Set up our variables */
1885     if (!input_file) {
1886         input_file = stdin;
1887         input_filename = "Standard input";
1888     }
1889     if (!output_file) {
1890         output_file = stdout;
1891         output_filename = "Standard output";
1892     }
1893
1894     ts_sec = time(0);               /* initialize to current time */
1895     timecode_default = *localtime(&ts_sec);
1896     timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1897
1898     /* Display summary of our state */
1899     if (!quiet) {
1900         fprintf(stderr, "Input from: %s\n", input_filename);
1901         fprintf(stderr, "Output to: %s\n",  output_filename);
1902         fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1903
1904         if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1905                                   hdr_ethernet_proto);
1906         if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1907                             hdr_ip_proto);
1908         if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1909                              hdr_src_port, hdr_dest_port);
1910         if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1911                              hdr_src_port, hdr_dest_port);
1912         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1913                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1914         if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
1915                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1916     }
1917 }
1918
1919 int
1920 main(int argc, char *argv[])
1921 {
1922     parse_options(argc, argv);
1923
1924     assert(input_file  != NULL);
1925     assert(output_file != NULL);
1926
1927     write_file_header();
1928
1929     header_length = 0;
1930     if (hdr_ethernet) {
1931         header_length += (int)sizeof(HDR_ETHERNET);
1932     }
1933     if (hdr_ip) {
1934         ip_offset = header_length;
1935         header_length += (int)sizeof(HDR_IP);
1936     } else if (hdr_ipv6) {
1937         ip_offset = header_length;
1938         header_length += (int)sizeof(HDR_IPv6);
1939     }
1940     if (hdr_sctp) {
1941         header_length += (int)sizeof(HDR_SCTP);
1942     }
1943     if (hdr_data_chunk) {
1944         header_length += (int)sizeof(HDR_DATA_CHUNK);
1945     }
1946     if (hdr_tcp) {
1947         header_length += (int)sizeof(HDR_TCP);
1948     }
1949     if (hdr_udp) {
1950         header_length += (int)sizeof(HDR_UDP);
1951     }
1952     curr_offset = header_length;
1953
1954     yyin = input_file;
1955     yylex();
1956
1957     write_current_packet(FALSE);
1958     write_file_trailer();
1959     fclose(input_file);
1960     fclose(output_file);
1961     if (debug)
1962         fprintf(stderr, "\n-------------------------\n");
1963     if (!quiet) {
1964         fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1965                 num_packets_read, (num_packets_read == 1) ? "" : "s",
1966                 num_packets_written, (num_packets_written == 1) ? "" : "s",
1967                 bytes_written, (bytes_written == 1) ? "" : "s");
1968     }
1969     return 0;
1970 }
1971
1972 /*
1973  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1974  *
1975  * Local variables:
1976  * c-basic-offset: 4
1977  * tab-width: 8
1978  * indent-tabs-mode: nil
1979  * End:
1980  *
1981  * vi: set shiftwidth=4 tabstop=8 expandtab:
1982  * :indentSize=4:tabSize=8:noTabs=true:
1983  */
1984