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