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