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