qt: add missing initializers (CID 1325722)
[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_diag_control.h>
116 #include <wsutil/ws_version_info.h>
117
118 #include <time.h>
119 #include <glib.h>
120
121 #ifdef HAVE_UNISTD_H
122 # include <unistd.h>
123 #endif
124
125 #ifdef HAVE_GETOPT_H
126 #include <getopt.h>
127 #endif
128
129 #include <errno.h>
130 #include <assert.h>
131
132 #ifdef HAVE_LIBZ
133 #include <zlib.h>      /* to get the libz version number */
134 #endif
135
136 #ifndef HAVE_GETOPT_LONG
137 #include "wsutil/wsgetopt.h"
138 #endif
139
140 #ifndef HAVE_STRPTIME
141 # include "wsutil/strptime.h"
142 #endif
143
144 #include "pcapio.h"
145 #include "text2pcap.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         char *appname;
925         char *comment;
926
927         appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
928         comment = g_strdup_printf("Generated from input file %s.", input_filename);
929         success = pcapng_write_session_header_block(output_file,
930                                                     comment,
931                                                     NULL,    /* HW */
932                                                     NULL,    /* OS */
933                                                     appname,
934                                                     -1,      /* section_length */
935                                                     &bytes_written,
936                                                     &err);
937         g_free(appname);
938         g_free(comment);
939         if (success) {
940             success = pcapng_write_interface_description_block(output_file,
941                                                                NULL,
942                                                                NULL,
943                                                                NULL,
944                                                                "",
945                                                                NULL,
946                                                                pcap_link_type,
947                                                                PCAP_SNAPLEN,
948                                                                &bytes_written,
949                                                                0,
950                                                                9,
951                                                                &err);
952         }
953     } else {
954         success = libpcap_write_file_header(output_file, pcap_link_type,
955                                             PCAP_SNAPLEN, FALSE,
956                                             &bytes_written, &err);
957     }
958     if (!success) {
959         fprintf(stderr, "File write error [%s] : %s\n",
960                 output_filename, g_strerror(err));
961         exit(1);
962     }
963 }
964
965 static void
966 write_file_trailer (void)
967 {
968     int      err;
969     gboolean success;
970
971     if (use_pcapng) {
972         success = pcapng_write_interface_statistics_block(output_file,
973                                                           0,
974                                                           &bytes_written,
975                                                           "Counters provided by text2pcap",
976                                                           0,
977                                                           0,
978                                                           num_packets_written,
979                                                           num_packets_written - num_packets_written,
980                                                           &err);
981
982     } else {
983         success = TRUE;
984     }
985     if (!success) {
986         fprintf(stderr, "File write error [%s] : %s\n",
987                 output_filename, g_strerror(err));
988         exit(1);
989     }
990    return;
991 }
992
993 /*----------------------------------------------------------------------
994  * Append a token to the packet preamble.
995  */
996 static void
997 append_to_preamble (char *str)
998 {
999     size_t toklen;
1000
1001     if (packet_preamble_len != 0) {
1002         if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
1003             return; /* no room to add more preamble */
1004         /* Add a blank separator between the previous token and this token. */
1005         packet_preamble[packet_preamble_len++] = ' ';
1006     }
1007     toklen = strlen(str);
1008     if (toklen != 0) {
1009         if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
1010             return; /* no room to add the token to the preamble */
1011         g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
1012         packet_preamble_len += (int) toklen;
1013         if (debug >= 2) {
1014             char *c;
1015             char xs[PACKET_PREAMBLE_MAX_LEN];
1016             g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
1017             while ((c = strchr(xs, '\r')) != NULL) *c=' ';
1018             fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
1019         }
1020     }
1021 }
1022
1023 /*----------------------------------------------------------------------
1024  * Parse the preamble to get the timecode.
1025  */
1026
1027 static void
1028 parse_preamble (void)
1029 {
1030     struct tm  timecode;
1031     char      *subsecs;
1032     char      *p;
1033     int        subseclen;
1034     int        i;
1035
1036      /*
1037      * Null-terminate the preamble.
1038      */
1039     packet_preamble[packet_preamble_len] = '\0';
1040     if (debug > 0)
1041         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1042
1043     if (has_direction) {
1044         switch (packet_preamble[0]) {
1045         case 'i':
1046         case 'I':
1047             direction = 0x00000001;
1048             packet_preamble[0] = ' ';
1049             break;
1050         case 'o':
1051         case 'O':
1052             direction = 0x00000002;
1053             packet_preamble[0] = ' ';
1054             break;
1055         default:
1056             direction = 0x00000000;
1057             break;
1058         }
1059         i = 0;
1060         while (packet_preamble[i] == ' ' ||
1061                packet_preamble[i] == '\r' ||
1062                packet_preamble[i] == '\t') {
1063             i++;
1064         }
1065         packet_preamble_len -= i;
1066         /* Also move the trailing '\0'. */
1067         memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1068     }
1069
1070
1071     /*
1072      * If no "-t" flag was specified, don't attempt to parse the packet
1073      * preamble to extract a time stamp.
1074      */
1075     if (ts_fmt == NULL) {
1076         /* Clear Preamble */
1077         packet_preamble_len = 0;
1078         return;
1079     }
1080
1081     /*
1082      * Initialize to today localtime, just in case not all fields
1083      * of the date and time are specified.
1084      */
1085
1086     timecode = timecode_default;
1087     ts_nsec = 0;
1088
1089     /* Ensure preamble has more than two chars before attempting to parse.
1090      * This should cover line breaks etc that get counted.
1091      */
1092     if (strlen(packet_preamble) > 2) {
1093         /* Get Time leaving subseconds */
1094         subsecs = strptime( packet_preamble, ts_fmt, &timecode );
1095         if (subsecs != NULL) {
1096             /* Get the long time from the tm structure */
1097             /*  (will return -1 if failure)            */
1098             ts_sec  = mktime( &timecode );
1099         } else
1100             ts_sec = -1;    /* we failed to parse it */
1101
1102         /* This will ensure incorrectly parsed dates get set to zero */
1103         if (-1 == ts_sec) {
1104             /* Sanitize - remove all '\r' */
1105             char *c;
1106             while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1107             fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n   (defaulting to Jan 1,1970 00:00:00 GMT)\n",
1108                  packet_preamble, ts_fmt);
1109             if (debug >= 2) {
1110                 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
1111                     timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
1112                     timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
1113             }
1114             ts_sec  = 0;  /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
1115             ts_nsec = 0;
1116         } else {
1117             /* Parse subseconds */
1118             ts_nsec = (guint32)strtol(subsecs, &p, 10);
1119             if (subsecs == p) {
1120                 /* Error */
1121                 ts_nsec = 0;
1122             } else {
1123                 /*
1124                  * Convert that number to a number
1125                  * of microseconds; if it's N digits
1126                  * long, it's in units of 10^(-N) seconds,
1127                  * so, to convert it to units of
1128                  * 10^-9 seconds, we multiply by
1129                  * 10^(9-N).
1130                  */
1131                 subseclen = (int) (p - subsecs);
1132                 if (subseclen > 9) {
1133                     /*
1134                      * *More* than 9 digits; 9-N is
1135                      * negative, so we divide by
1136                      * 10^(N-9).
1137                      */
1138                     for (i = subseclen - 9; i != 0; i--)
1139                         ts_nsec /= 10;
1140                 } else if (subseclen < 9) {
1141                     for (i = 9 - subseclen; i != 0; i--)
1142                         ts_nsec *= 10;
1143                 }
1144             }
1145         }
1146     }
1147     if (debug >= 2) {
1148         char *c;
1149         while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1150         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1151         fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
1152     }
1153
1154
1155     /* Clear Preamble */
1156     packet_preamble_len = 0;
1157 }
1158
1159 /*----------------------------------------------------------------------
1160  * Start a new packet
1161  */
1162 static void
1163 start_new_packet (gboolean cont)
1164 {
1165     if (debug >= 1)
1166         fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1167
1168     /* Write out the current packet, if required */
1169     write_current_packet(cont);
1170     num_packets_read++;
1171
1172     /* Ensure we parse the packet preamble as it may contain the time */
1173     parse_preamble();
1174 }
1175
1176 /*----------------------------------------------------------------------
1177  * Process a directive
1178  */
1179 static void
1180 process_directive (char *str)
1181 {
1182     fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1183 }
1184
1185 /*----------------------------------------------------------------------
1186  * Parse a single token (called from the scanner)
1187  */
1188 void
1189 parse_token (token_t token, char *str)
1190 {
1191     guint32  num;
1192     int      by_eol;
1193     int      rollback = 0;
1194     int      line_size;
1195     int      i;
1196     char    *s2;
1197     char     tmp_str[3];
1198
1199     /*
1200      * This is implemented as a simple state machine of five states.
1201      * State transitions are caused by tokens being received from the
1202      * scanner. The code should be self-documenting.
1203      */
1204
1205     if (debug >= 2) {
1206         /* Sanitize - remove all '\r' */
1207         char *c;
1208         if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1209
1210         fprintf(stderr, "(%s, %s \"%s\") -> (",
1211                 state_str[state], token_str[token], str ? str : "");
1212     }
1213
1214     switch (state) {
1215
1216     /* ----- Waiting for new packet -------------------------------------------*/
1217     case INIT:
1218         if (!str && token != T_EOL) goto fail_null_str;
1219         switch (token) {
1220         case T_TEXT:
1221             append_to_preamble(str);
1222             break;
1223         case T_DIRECTIVE:
1224             process_directive(str);
1225             break;
1226         case T_OFFSET:
1227             num = parse_num(str, TRUE);
1228             if (num == 0) {
1229                 /* New packet starts here */
1230                 start_new_packet(FALSE);
1231                 state = READ_OFFSET;
1232                 pkt_lnstart = packet_buf + num;
1233             }
1234             break;
1235         case T_EOL:
1236             /* Some describing text may be parsed as offset, but the invalid
1237                offset will be checked in the state of START_OF_LINE, so
1238                we add this transition to gain flexibility */
1239             state = START_OF_LINE;
1240             break;
1241         default:
1242             break;
1243         }
1244         break;
1245
1246     /* ----- Processing packet, start of new line -----------------------------*/
1247     case START_OF_LINE:
1248         if (!str && token != T_EOL) goto fail_null_str;
1249         switch (token) {
1250         case T_TEXT:
1251             append_to_preamble(str);
1252             break;
1253         case T_DIRECTIVE:
1254             process_directive(str);
1255             break;
1256         case T_OFFSET:
1257             num = parse_num(str, TRUE);
1258             if (num == 0) {
1259                 /* New packet starts here */
1260                 start_new_packet(FALSE);
1261                 packet_start = 0;
1262                 state = READ_OFFSET;
1263             } else if ((num - packet_start) != curr_offset - header_length) {
1264                 /*
1265                  * The offset we read isn't the one we expected.
1266                  * This may only mean that we mistakenly interpreted
1267                  * some text as byte values (e.g., if the text dump
1268                  * of packet data included a number with spaces around
1269                  * it).  If the offset is less than what we expected,
1270                  * assume that's the problem, and throw away the putative
1271                  * extra byte values.
1272                  */
1273                 if (num < curr_offset) {
1274                     unwrite_bytes(curr_offset - num);
1275                     state = READ_OFFSET;
1276                 } else {
1277                     /* Bad offset; switch to INIT state */
1278                     if (debug >= 1)
1279                         fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1280                                 curr_offset, num);
1281                     write_current_packet(FALSE);
1282                     state = INIT;
1283                 }
1284             } else
1285                 state = READ_OFFSET;
1286                 pkt_lnstart = packet_buf + num;
1287             break;
1288         case T_EOL:
1289             state = START_OF_LINE;
1290             break;
1291         default:
1292             break;
1293         }
1294         break;
1295
1296     /* ----- Processing packet, read offset -----------------------------------*/
1297     case READ_OFFSET:
1298         switch (token) {
1299         case T_BYTE:
1300             /* Record the byte */
1301             state = READ_BYTE;
1302             if (!str) goto fail_null_str;
1303             write_byte(str);
1304             break;
1305         case T_TEXT:
1306         case T_DIRECTIVE:
1307         case T_OFFSET:
1308             state = READ_TEXT;
1309             break;
1310         case T_EOL:
1311             state = START_OF_LINE;
1312             break;
1313         default:
1314             break;
1315         }
1316         break;
1317
1318     /* ----- Processing packet, read byte -------------------------------------*/
1319     case READ_BYTE:
1320         switch (token) {
1321         case T_BYTE:
1322             /* Record the byte */
1323             write_byte(str);
1324             break;
1325         case T_TEXT:
1326         case T_DIRECTIVE:
1327         case T_OFFSET:
1328         case T_EOL:
1329             by_eol = 0;
1330             state = READ_TEXT;
1331             if (token == T_EOL) {
1332                 by_eol = 1;
1333                 state = START_OF_LINE;
1334             }
1335             if (identify_ascii) {
1336                 /* Here a line of pkt bytes reading is finished
1337                    compare the ascii and hex to avoid such situation:
1338                    "61 62 20 ab ", when ab is ascii dump then it should
1339                    not be treat as byte */
1340                 rollback = 0;
1341                 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1342                    s2 = "ab ", s1 = "616220"
1343                    we should find out the largest tail of s1 matches the head
1344                    of s2, it means the matched part in tail is the ASCII dump
1345                    of the head byte. These matched should be rollback */
1346                 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1347                 s2 = (char*)g_malloc((line_size+1)/4+1);
1348                 /* gather the possible pattern */
1349                 for (i = 0; i < (line_size+1)/4; i++) {
1350                     tmp_str[0] = pkt_lnstart[i*3];
1351                     tmp_str[1] = pkt_lnstart[i*3+1];
1352                     tmp_str[2] = '\0';
1353                     /* it is a valid convertable string */
1354                     if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
1355                         break;
1356                     }
1357                     s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1358                     rollback++;
1359                     /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1360                     if (!(pkt_lnstart[i*3+2] == ' ')) {
1361                         if (by_eol != 1)
1362                             rollback--;
1363                         break;
1364                     }
1365                 }
1366                 /* If packet line start contains possible byte pattern, the line end
1367                    should contain the matched pattern if the user open the -a flag.
1368                    The packet will be possible invalid if the byte pattern cannot find
1369                    a matched one in the line of packet buffer.*/
1370                 if (rollback > 0) {
1371                     if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1372                         unwrite_bytes(rollback);
1373                     }
1374                     /* Not matched. This line contains invalid packet bytes, so
1375                        discard the whole line */
1376                     else {
1377                         unwrite_bytes(line_size);
1378                     }
1379                 }
1380                 g_free(s2);
1381             }
1382             break;
1383         default:
1384             break;
1385         }
1386         break;
1387
1388     /* ----- Processing packet, read text -------------------------------------*/
1389     case READ_TEXT:
1390         switch (token) {
1391         case T_EOL:
1392             state = START_OF_LINE;
1393             break;
1394         default:
1395             break;
1396         }
1397         break;
1398
1399     default:
1400         fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1401         exit(1);
1402     }
1403
1404     if (debug >= 2)
1405         fprintf(stderr, ", %s)\n", state_str[state]);
1406
1407     return;
1408
1409 fail_null_str:
1410     fprintf(stderr, "FATAL ERROR: got NULL str pointer in state (%d)", state);
1411     exit(1);
1412
1413 }
1414
1415 /*----------------------------------------------------------------------
1416  * Print usage string and exit
1417  */
1418 static void
1419 print_usage (FILE *output)
1420 {
1421     fprintf(output,
1422             "\n"
1423             "Usage: text2pcap [options] <infile> <outfile>\n"
1424             "\n"
1425             "where  <infile> specifies input  filename (use - for standard input)\n"
1426             "      <outfile> specifies output filename (use - for standard output)\n"
1427             "\n"
1428             "Input:\n"
1429             "  -o hex|oct|dec         parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1430             "                         default is hex.\n"
1431             "  -t <timefmt>           treat the text before the packet as a date/time code;\n"
1432             "                         the specified argument is a format string of the sort\n"
1433             "                         supported by strptime.\n"
1434             "                         Example: The time \"10:15:14.5476\" has the format code\n"
1435             "                         \"%%H:%%M:%%S.\"\n"
1436             "                         NOTE: The subsecond component delimiter, '.', must be\n"
1437             "                         given, but no pattern is required; the remaining\n"
1438             "                         number is assumed to be fractions of a second.\n"
1439             "                         NOTE: Date/time fields from the current date/time are\n"
1440             "                         used as the default for unspecified fields.\n"
1441             "  -D                     the text before the packet starts with an I or an O,\n"
1442             "                         indicating that the packet is inbound or outbound.\n"
1443             "                         This is only stored if the output format is PCAP-NG.\n"
1444             "  -a                     enable ASCII text dump identification.\n"
1445             "                         The start of the ASCII text dump can be identified\n"
1446             "                         and excluded from the packet data, even if it looks\n"
1447             "                         like a HEX dump.\n"
1448             "                         NOTE: Do not enable it if the input file does not\n"
1449             "                         contain the ASCII text dump.\n"
1450             "\n"
1451             "Output:\n"
1452             "  -l <typenum>           link-layer type number; default is 1 (Ethernet).  See\n"
1453             "                         http://www.tcpdump.org/linktypes.html for a list of\n"
1454             "                         numbers.  Use this option if your dump is a complete\n"
1455             "                         hex dump of an encapsulated packet and you wish to\n"
1456             "                         specify the exact type of encapsulation.\n"
1457             "                         Example: -l 7 for ARCNet packets.\n"
1458             "  -m <max-packet>        max packet length in output; default is %d\n"
1459             "\n"
1460             "Prepend dummy header:\n"
1461             "  -e <l3pid>             prepend dummy Ethernet II header with specified L3PID\n"
1462             "                         (in HEX).\n"
1463             "                         Example: -e 0x806 to specify an ARP packet.\n"
1464             "  -i <proto>             prepend dummy IP header with specified IP protocol\n"
1465             "                         (in DECIMAL).\n"
1466             "                         Automatically prepends Ethernet header as well.\n"
1467             "                         Example: -i 46\n"
1468             "  -4 <srcip>,<destip>    prepend dummy IPv4 header with specified\n"
1469             "                         dest and source address.\n"
1470             "                         Example: -4 10.0.0.1,10.0.0.2\n"
1471             "  -6 <srcip>,<destip>    replace IPv6 header with specified\n"
1472             "                         dest and source address.\n"
1473             "                         Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
1474             "  -u <srcp>,<destp>      prepend dummy UDP header with specified\n"
1475             "                         source and destination ports (in DECIMAL).\n"
1476             "                         Automatically prepends Ethernet & IP headers as well.\n"
1477             "                         Example: -u 1000,69 to make the packets look like\n"
1478             "                         TFTP/UDP packets.\n"
1479             "  -T <srcp>,<destp>      prepend dummy TCP header with specified\n"
1480             "                         source and destination ports (in DECIMAL).\n"
1481             "                         Automatically prepends Ethernet & IP headers as well.\n"
1482             "                         Example: -T 50,60\n"
1483             "  -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1484             "                         source/dest ports and verification tag (in DECIMAL).\n"
1485             "                         Automatically prepends Ethernet & IP headers as well.\n"
1486             "                         Example: -s 30,40,34\n"
1487             "  -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1488             "                         source/dest ports and verification tag 0.\n"
1489             "                         Automatically prepends a dummy SCTP DATA\n"
1490             "                         chunk header with payload protocol identifier ppi.\n"
1491             "                         Example: -S 30,40,34\n"
1492             "\n"
1493             "Miscellaneous:\n"
1494             "  -h                     display this help and exit.\n"
1495             "  -d                     show detailed debug of parser states.\n"
1496             "  -q                     generate no output at all (automatically disables -d).\n"
1497             "  -n                     use PCAP-NG instead of PCAP as output format.\n"
1498             "",
1499             MAX_PACKET);
1500 }
1501
1502 static void
1503 get_text2pcap_compiled_info(GString *str)
1504 {
1505     /* LIBZ */
1506     g_string_append(str, ", ");
1507 #ifdef HAVE_LIBZ
1508     g_string_append(str, "with libz ");
1509 #ifdef ZLIB_VERSION
1510     g_string_append(str, ZLIB_VERSION);
1511 #else /* ZLIB_VERSION */
1512     g_string_append(str, "(version unknown)");
1513 #endif /* ZLIB_VERSION */
1514 #else /* HAVE_LIBZ */
1515     g_string_append(str, "without libz");
1516 #endif /* HAVE_LIBZ */
1517 }
1518
1519 static void
1520 get_text2pcap_runtime_info(GString *str)
1521 {
1522     /* zlib */
1523 #if defined(HAVE_LIBZ) && !defined(_WIN32)
1524     g_string_append_printf(str, ", with libz %s", zlibVersion());
1525 #endif
1526 }
1527
1528 /*----------------------------------------------------------------------
1529  * Parse CLI options
1530  */
1531 static void
1532 parse_options (int argc, char *argv[])
1533 {
1534     GString *comp_info_str;
1535     GString *runtime_info_str;
1536     int   c;
1537     char *p;
1538 DIAG_OFF(cast-qual)
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 DIAG_ON(cast-qual)
1545
1546 #ifdef _WIN32
1547     arg_list_utf_16to8(argc, argv);
1548     create_app_running_mutex();
1549 #endif /* _WIN32 */
1550
1551     /* Get the compile-time version information string */
1552     comp_info_str = get_compiled_version_info(NULL, get_text2pcap_compiled_info);
1553
1554     /* get the run-time version information string */
1555     runtime_info_str = get_runtime_version_info(get_text2pcap_runtime_info);
1556
1557     /* Add it to the information to be reported on a crash. */
1558     ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1559          "\n"
1560          "%s"
1561          "\n"
1562          "%s",
1563       get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1564
1565     /* Scan CLI parameters */
1566     while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1567         switch (c) {
1568         case 'h':
1569             printf("Text2pcap (Wireshark) %s\n"
1570                    "Generate a capture file from an ASCII hexdump of packets.\n"
1571                    "See http://www.wireshark.org for more information.\n",
1572                    get_ws_vcs_version_info());
1573             print_usage(stdout);
1574             exit(0);
1575             break;
1576         case 'd': if (!quiet) debug++; break;
1577         case 'D': has_direction = TRUE; break;
1578         case 'q': quiet = TRUE; debug = FALSE; break;
1579         case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1580         case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1581         case 'n': use_pcapng = TRUE; break;
1582         case 'o':
1583             if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1584                 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1585                 print_usage(stderr);
1586                 exit(1);
1587             }
1588             switch (optarg[0]) {
1589             case 'o': offset_base =  8; break;
1590             case 'h': offset_base = 16; break;
1591             case 'd': offset_base = 10; break;
1592             }
1593             break;
1594         case 'e':
1595             hdr_ethernet = TRUE;
1596             if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1597                 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1598                 print_usage(stderr);
1599                 exit(1);
1600             }
1601             break;
1602
1603         case 'i':
1604             hdr_ip = TRUE;
1605             hdr_ip_proto = strtol(optarg, &p, 10);
1606             if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1607                   hdr_ip_proto > 255) {
1608                 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1609                 print_usage(stderr);
1610                 exit(1);
1611             }
1612             hdr_ethernet = TRUE;
1613             hdr_ethernet_proto = 0x800;
1614             break;
1615
1616         case 's':
1617             hdr_sctp = TRUE;
1618             hdr_data_chunk = FALSE;
1619             hdr_tcp = FALSE;
1620             hdr_udp = FALSE;
1621             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1622             if (p == optarg || (*p != ',' && *p != '\0')) {
1623                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1624                 print_usage(stderr);
1625                 exit(1);
1626             }
1627             if (*p == '\0') {
1628                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1629                 print_usage(stderr);
1630                 exit(1);
1631             }
1632             p++;
1633             optarg = p;
1634             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1635             if (p == optarg || (*p != ',' && *p != '\0')) {
1636                 fprintf(stderr, "Bad dest port for '-s'\n");
1637                 print_usage(stderr);
1638                 exit(1);
1639             }
1640             if (*p == '\0') {
1641                 fprintf(stderr, "No tag specified for '-%c'\n", c);
1642                 print_usage(stderr);
1643                 exit(1);
1644             }
1645             p++;
1646             optarg = p;
1647             hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1648             if (p == optarg || *p != '\0') {
1649                 fprintf(stderr, "Bad tag for '-%c'\n", c);
1650                 print_usage(stderr);
1651                 exit(1);
1652             }
1653
1654             hdr_ip = TRUE;
1655             hdr_ip_proto = 132;
1656             hdr_ethernet = TRUE;
1657             hdr_ethernet_proto = 0x800;
1658             break;
1659         case 'S':
1660             hdr_sctp = TRUE;
1661             hdr_data_chunk = TRUE;
1662             hdr_tcp = FALSE;
1663             hdr_udp = FALSE;
1664             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1665             if (p == optarg || (*p != ',' && *p != '\0')) {
1666                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1667                 print_usage(stderr);
1668                 exit(1);
1669             }
1670             if (*p == '\0') {
1671                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1672                 print_usage(stderr);
1673                 exit(1);
1674             }
1675             p++;
1676             optarg = p;
1677             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1678             if (p == optarg || (*p != ',' && *p != '\0')) {
1679                 fprintf(stderr, "Bad dest port for '-s'\n");
1680                 print_usage(stderr);
1681                 exit(1);
1682             }
1683             if (*p == '\0') {
1684                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1685                 print_usage(stderr);
1686                 exit(1);
1687             }
1688             p++;
1689             optarg = p;
1690             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1691             if (p == optarg || *p != '\0') {
1692                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1693                 print_usage(stderr);
1694                 exit(1);
1695             }
1696
1697             hdr_ip = TRUE;
1698             hdr_ip_proto = 132;
1699             hdr_ethernet = TRUE;
1700             hdr_ethernet_proto = 0x800;
1701             break;
1702
1703         case 't':
1704             ts_fmt = optarg;
1705             break;
1706
1707         case 'u':
1708             hdr_udp = TRUE;
1709             hdr_tcp = FALSE;
1710             hdr_sctp = FALSE;
1711             hdr_data_chunk = FALSE;
1712             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1713             if (p == optarg || (*p != ',' && *p != '\0')) {
1714                 fprintf(stderr, "Bad src port for '-u'\n");
1715                 print_usage(stderr);
1716                 exit(1);
1717             }
1718             if (*p == '\0') {
1719                 fprintf(stderr, "No dest port specified for '-u'\n");
1720                 print_usage(stderr);
1721                 exit(1);
1722             }
1723             p++;
1724             optarg = p;
1725             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1726             if (p == optarg || *p != '\0') {
1727                 fprintf(stderr, "Bad dest port for '-u'\n");
1728                 print_usage(stderr);
1729                 exit(1);
1730             }
1731             hdr_ip = TRUE;
1732             hdr_ip_proto = 17;
1733             hdr_ethernet = TRUE;
1734             hdr_ethernet_proto = 0x800;
1735             break;
1736
1737         case 'T':
1738             hdr_tcp = TRUE;
1739             hdr_udp = FALSE;
1740             hdr_sctp = FALSE;
1741             hdr_data_chunk = FALSE;
1742             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1743             if (p == optarg || (*p != ',' && *p != '\0')) {
1744                 fprintf(stderr, "Bad src port for '-T'\n");
1745                 print_usage(stderr);
1746                 exit(1);
1747             }
1748             if (*p == '\0') {
1749                 fprintf(stderr, "No dest port specified for '-u'\n");
1750                 print_usage(stderr);
1751                 exit(1);
1752             }
1753             p++;
1754             optarg = p;
1755             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1756             if (p == optarg || *p != '\0') {
1757                 fprintf(stderr, "Bad dest port for '-T'\n");
1758                 print_usage(stderr);
1759                 exit(1);
1760             }
1761             hdr_ip = TRUE;
1762             hdr_ip_proto = 6;
1763             hdr_ethernet = TRUE;
1764             hdr_ethernet_proto = 0x800;
1765             break;
1766
1767         case 'a':
1768             identify_ascii = TRUE;
1769             break;
1770
1771         case 'v':
1772             show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1773             g_string_free(comp_info_str, TRUE);
1774             g_string_free(runtime_info_str, TRUE);
1775             exit(0);
1776             break;
1777
1778         case '4':
1779         case '6':
1780             p = strchr(optarg, ',');
1781
1782             if (!p) {
1783                 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1784                 print_usage(stderr);
1785                 exit(1);
1786             }
1787
1788             *p = '\0';
1789             if (c == '6')
1790             {
1791                 hdr_ipv6 = TRUE;
1792                 hdr_ethernet_proto = 0x86DD;
1793             }
1794             else
1795             {
1796                 hdr_ip = TRUE;
1797                 hdr_ethernet_proto = 0x800;
1798             }
1799             hdr_ethernet = TRUE;
1800
1801             if (hdr_ipv6 == TRUE) {
1802                 if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
1803                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1804                         print_usage(stderr);
1805                         exit(1);
1806                 }
1807             } else {
1808                 if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
1809                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1810                         print_usage(stderr);
1811                         exit(1);
1812                 }
1813             }
1814
1815             p++;
1816             if (*p == '\0') {
1817                 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1818                 print_usage(stderr);
1819                 exit(1);
1820             }
1821
1822             if (hdr_ipv6 == TRUE) {
1823                 if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
1824                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1825                         print_usage(stderr);
1826                         exit(1);
1827                 }
1828             } else {
1829                 if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
1830                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1831                         print_usage(stderr);
1832                         exit(1);
1833                 }
1834             }
1835             break;
1836
1837
1838         case '?':
1839         default:
1840             print_usage(stderr);
1841             exit(1);
1842         }
1843     }
1844
1845     if (optind >= argc || argc-optind < 2) {
1846         fprintf(stderr, "Must specify input and output filename\n");
1847         print_usage(stderr);
1848         exit(1);
1849     }
1850
1851     if (strcmp(argv[optind], "-")) {
1852         input_filename = g_strdup(argv[optind]);
1853         input_file = ws_fopen(input_filename, "rb");
1854         if (!input_file) {
1855             fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1856                     input_filename, g_strerror(errno));
1857             exit(1);
1858         }
1859     } else {
1860         input_filename = "Standard input";
1861         input_file = stdin;
1862     }
1863
1864     if (strcmp(argv[optind+1], "-")) {
1865         output_filename = g_strdup(argv[optind+1]);
1866         output_file = ws_fopen(output_filename, "wb");
1867         if (!output_file) {
1868             fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1869                     output_filename, g_strerror(errno));
1870             exit(1);
1871         }
1872     } else {
1873         output_filename = "Standard output";
1874         output_file = stdout;
1875     }
1876
1877     /* Some validation */
1878     if (pcap_link_type != 1 && hdr_ethernet) {
1879         fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1880         exit(1);
1881     }
1882
1883     /* Set up our variables */
1884     if (!input_file) {
1885         input_file = stdin;
1886         input_filename = "Standard input";
1887     }
1888     if (!output_file) {
1889         output_file = stdout;
1890         output_filename = "Standard output";
1891     }
1892
1893     ts_sec = time(0);               /* initialize to current time */
1894     timecode_default = *localtime(&ts_sec);
1895     timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1896
1897     /* Display summary of our state */
1898     if (!quiet) {
1899         fprintf(stderr, "Input from: %s\n", input_filename);
1900         fprintf(stderr, "Output to: %s\n",  output_filename);
1901         fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1902
1903         if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1904                                   hdr_ethernet_proto);
1905         if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1906                             hdr_ip_proto);
1907         if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1908                              hdr_src_port, hdr_dest_port);
1909         if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1910                              hdr_src_port, hdr_dest_port);
1911         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1912                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1913         if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1914                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1915     }
1916 }
1917
1918 int
1919 main(int argc, char *argv[])
1920 {
1921     parse_options(argc, argv);
1922
1923     assert(input_file  != NULL);
1924     assert(output_file != NULL);
1925
1926     write_file_header();
1927
1928     header_length = 0;
1929     if (hdr_ethernet) {
1930         header_length += (int)sizeof(HDR_ETHERNET);
1931     }
1932     if (hdr_ip) {
1933         ip_offset = header_length;
1934         header_length += (int)sizeof(HDR_IP);
1935     } else if (hdr_ipv6) {
1936         ip_offset = header_length;
1937         header_length += (int)sizeof(HDR_IPv6);
1938     }
1939     if (hdr_sctp) {
1940         header_length += (int)sizeof(HDR_SCTP);
1941     }
1942     if (hdr_data_chunk) {
1943         header_length += (int)sizeof(HDR_DATA_CHUNK);
1944     }
1945     if (hdr_tcp) {
1946         header_length += (int)sizeof(HDR_TCP);
1947     }
1948     if (hdr_udp) {
1949         header_length += (int)sizeof(HDR_UDP);
1950     }
1951     curr_offset = header_length;
1952
1953     yyin = input_file;
1954     yylex();
1955
1956     write_current_packet(FALSE);
1957     write_file_trailer();
1958     fclose(input_file);
1959     fclose(output_file);
1960     if (debug)
1961         fprintf(stderr, "\n-------------------------\n");
1962     if (!quiet) {
1963         fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1964                 num_packets_read, (num_packets_read == 1) ? "" : "s",
1965                 num_packets_written, (num_packets_written == 1) ? "" : "s",
1966                 bytes_written, (bytes_written == 1) ? "" : "s");
1967     }
1968     return 0;
1969 }
1970
1971 /*
1972  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1973  *
1974  * Local variables:
1975  * c-basic-offset: 4
1976  * tab-width: 8
1977  * indent-tabs-mode: nil
1978  * End:
1979  *
1980  * vi: set shiftwidth=4 tabstop=8 expandtab:
1981  * :indentSize=4:tabSize=8:noTabs=true:
1982  */
1983