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