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