decrypt
[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 = 0;
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 static struct {                 /* pseudo header ipv6 for checksum calculation */
338     struct  e_in6_addr src_addr6;
339     struct  e_in6_addr dst_addr6;
340     guint32 protocol;
341     guint32 zero;
342 } pseudoh6;
343
344
345 typedef struct {
346     guint16 source_port;
347     guint16 dest_port;
348     guint16 length;
349     guint16 checksum;
350 } hdr_udp_t;
351
352 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
353
354 typedef struct {
355     guint16 source_port;
356     guint16 dest_port;
357     guint32 seq_num;
358     guint32 ack_num;
359     guint8  hdr_length;
360     guint8  flags;
361     guint16 window;
362     guint16 checksum;
363     guint16 urg;
364 } hdr_tcp_t;
365
366 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
367
368 typedef struct {
369     guint16 src_port;
370     guint16 dest_port;
371     guint32 tag;
372     guint32 checksum;
373 } hdr_sctp_t;
374
375 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
376
377 typedef struct {
378     guint8  type;
379     guint8  bits;
380     guint16 length;
381     guint32 tsn;
382     guint16 sid;
383     guint16 ssn;
384     guint32 ppid;
385 } hdr_data_chunk_t;
386
387 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
388
389 static char tempbuf[64];
390
391 /*----------------------------------------------------------------------
392  * Stuff for writing a PCap file
393  */
394 #define PCAP_SNAPLEN        0xffff
395
396 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
397 static guint32 pcap_link_type = 1;   /* Default is LINKTYPE_ETHERNET */
398
399 /*----------------------------------------------------------------------
400  * Parse a single hex number
401  * Will abort the program if it can't parse the number
402  * Pass in TRUE if this is an offset, FALSE if not
403  */
404 static int
405 parse_num(const char *str, int offset, guint32* num)
406 {
407     char    *c;
408
409     if (str == NULL) {
410         fprintf(stderr, "FATAL ERROR: str is NULL\n");
411         return EXIT_FAILURE;
412     }
413
414     *num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
415     if (c == str) {
416         fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
417         return EXIT_FAILURE;
418     }
419     return EXIT_SUCCESS;
420 }
421
422 /*----------------------------------------------------------------------
423  * Write this byte into current packet
424  */
425 static int
426 write_byte(const char *str)
427 {
428     guint32 num;
429
430     if (parse_num(str, FALSE, &num) != EXIT_SUCCESS)
431         return EXIT_FAILURE;
432
433     packet_buf[curr_offset] = (guint8) num;
434     curr_offset++;
435     if (curr_offset - header_length >= max_offset) /* packet full */
436         if (start_new_packet(TRUE) != EXIT_SUCCESS)
437             return EXIT_FAILURE;
438
439     return EXIT_SUCCESS;
440 }
441
442 /*----------------------------------------------------------------------
443  * Write a number of bytes into current packet
444  */
445
446 static void
447 write_bytes (const char bytes[], guint32 nbytes)
448 {
449     guint32 i;
450
451     if (curr_offset + nbytes < WTAP_MAX_PACKET_SIZE_STANDARD) {
452         for (i = 0; i < nbytes; i++) {
453             packet_buf[curr_offset] = bytes[i];
454             curr_offset++;
455         }
456     }
457 }
458
459 /*----------------------------------------------------------------------
460  * Remove bytes from the current packet
461  */
462 static void
463 unwrite_bytes (guint32 nbytes)
464 {
465     curr_offset -= nbytes;
466 }
467
468 /*----------------------------------------------------------------------
469  * Compute one's complement checksum (from RFC1071)
470  */
471 static guint16
472 in_checksum (void *buf, guint32 count)
473 {
474     guint32 sum = 0;
475     guint16 *addr = (guint16 *)buf;
476
477     while (count > 1) {
478         /*  This is the inner loop */
479         sum += g_ntohs(* (guint16 *) addr);
480         addr++;
481         count -= 2;
482     }
483
484     /*  Add left-over byte, if any */
485     if (count > 0)
486         sum += g_ntohs(* (guint8 *) addr);
487
488     /*  Fold 32-bit sum to 16 bits */
489     while (sum>>16)
490         sum = (sum & 0xffff) + (sum >> 16);
491
492     sum = ~sum;
493     return g_htons(sum);
494 }
495
496 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
497  * That code is copyrighted by D. Otis and has been modified.
498  */
499
500 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
501 static guint32 crc_c[256] =
502 {
503 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U,
504 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU,
505 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU,
506 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U,
507 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
508 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U,
509 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U,
510 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU,
511 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU,
512 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
513 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U,
514 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU,
515 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U,
516 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU,
517 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
518 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U,
519 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U,
520 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U,
521 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U,
522 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
523 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U,
524 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U,
525 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U,
526 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U,
527 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
528 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U,
529 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U,
530 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U,
531 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U,
532 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
533 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U,
534 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U,
535 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU,
536 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U,
537 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
538 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU,
539 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U,
540 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU,
541 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU,
542 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
543 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U,
544 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU,
545 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU,
546 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U,
547 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
548 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U,
549 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U,
550 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU,
551 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U,
552 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
553 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU,
554 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U,
555 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU,
556 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U,
557 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
558 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU,
559 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU,
560 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U,
561 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U,
562 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
563 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U,
564 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU,
565 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU,
566 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U,
567 };
568
569 static guint32
570 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
571 {
572     unsigned int i;
573     guint32 crc;
574
575     crc = crc32_init;
576     for (i = 0; i < len; i++)
577         CRC32C(crc, buf[i]);
578
579     return crc;
580 }
581
582 static guint32
583 finalize_crc32c (guint32 crc)
584 {
585     guint32 result;
586     guint8 byte0,byte1,byte2,byte3;
587
588     result = ~crc;
589     byte0 = result & 0xff;
590     byte1 = (result>>8) & 0xff;
591     byte2 = (result>>16) & 0xff;
592     byte3 = (result>>24) & 0xff;
593     result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
594     return result;
595 }
596
597 static guint16
598 number_of_padding_bytes (guint32 length)
599 {
600     guint16 remainder;
601
602     remainder = length % 4;
603
604     if (remainder == 0)
605         return 0;
606     else
607         return 4 - remainder;
608 }
609
610 /*----------------------------------------------------------------------
611  * Write current packet out
612  */
613 static int
614 write_current_packet (gboolean cont)
615 {
616     guint32  length         = 0;
617     guint16  padding_length = 0;
618     int      err;
619     guint16  ihatemacros;
620     gboolean success;
621
622     if (curr_offset > header_length) {
623         /* Write the packet */
624
625         /* Is direction indication on with an inbound packet? */
626         gboolean isInbound = has_direction && (direction == 2);
627
628         /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
629         if (hdr_ipv6) {
630             hdr_ethernet_proto = 0x86DD;
631             hdr_ip = FALSE;
632         }
633
634         /* Compute packet length */
635         length = curr_offset;
636         if (hdr_sctp) {
637             padding_length = number_of_padding_bytes(length - header_length );
638         } else {
639             padding_length = 0;
640         }
641         /* Reset curr_offset, since we now write the headers */
642         curr_offset = 0;
643
644         /* Write Ethernet header */
645         if (hdr_ethernet) {
646             HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
647             write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
648         }
649
650         /* Write IP header */
651         if (hdr_ip) {
652             if (isInbound) {
653                 HDR_IP.src_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
654                 HDR_IP.dest_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
655             }
656             else {
657                 HDR_IP.src_addr = hdr_ip_src_addr? hdr_ip_src_addr : IP_SRC;
658                 HDR_IP.dest_addr = hdr_ip_dest_addr ? hdr_ip_dest_addr : IP_DST;
659             }
660
661             HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
662             HDR_IP.protocol = (guint8) hdr_ip_proto;
663             HDR_IP.hdr_checksum = 0;
664             HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
665             write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
666         } else if (hdr_ipv6) {
667             if (memcmp(isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr)))
668                 memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(ws_in6_addr));
669             if (memcmp(isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr)))
670                 memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(ws_in6_addr));
671
672             HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
673             HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
674             HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
675             HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt  = (guint8) hdr_ip_proto;
676             HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
677             write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
678
679             /* initialize pseudo ipv6 header for checksum calculation */
680             pseudoh6.src_addr6  = HDR_IPv6.ip6_src;
681             pseudoh6.dst_addr6  = HDR_IPv6.ip6_dst;
682             pseudoh6.zero       = 0;
683             pseudoh6.protocol   = (guint8) hdr_ip_proto;
684             ihatemacros         = g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen);
685             pseudoh.length      = g_htons(length - ihatemacros + sizeof(HDR_UDP));
686         }
687
688         if (!hdr_ipv6) {
689             /* initialize pseudo header for checksum calculation */
690             pseudoh.src_addr    = HDR_IP.src_addr;
691             pseudoh.dest_addr   = HDR_IP.dest_addr;
692             pseudoh.zero        = 0;
693             pseudoh.protocol    = (guint8) hdr_ip_proto;
694             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_UDP));
695         }
696
697         /* Write UDP header */
698         if (hdr_udp) {
699             guint16 x16;
700             guint32 u;
701
702             /* initialize the UDP header */
703             HDR_UDP.source_port = isInbound ? g_htons(hdr_dest_port): g_htons(hdr_src_port);
704             HDR_UDP.dest_port = isInbound ? g_htons(hdr_src_port) : g_htons(hdr_dest_port);
705             HDR_UDP.length      = pseudoh.length;
706             HDR_UDP.checksum = 0;
707             /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
708             x16  = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
709             u    = g_ntohs(x16);
710             x16  = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
711             u   += g_ntohs(x16);
712             x16  = in_checksum(packet_buf + header_length, length - header_length);
713             u   += g_ntohs(x16);
714             x16  = (u & 0xffff) + (u>>16);
715             HDR_UDP.checksum = g_htons(x16);
716             if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
717                 HDR_UDP.checksum = g_htons(1);
718             write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
719         }
720
721         /* Write TCP header */
722         if (hdr_tcp) {
723             guint16 x16;
724             guint32 u;
725
726              /* initialize pseudo header for checksum calculation */
727             pseudoh.src_addr    = HDR_IP.src_addr;
728             pseudoh.dest_addr   = HDR_IP.dest_addr;
729             pseudoh.zero        = 0;
730             pseudoh.protocol    = (guint8) hdr_ip_proto;
731             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_TCP));
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  = 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 = TRUE;
1518             hdr_ip_proto = strtol(optarg, &p, 10);
1519             if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1520                   hdr_ip_proto > 255) {
1521                 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1522                 print_usage(stderr);
1523                 return EXIT_FAILURE;
1524             }
1525             hdr_ethernet = TRUE;
1526             hdr_ethernet_proto = 0x800;
1527             break;
1528
1529         case 's':
1530             hdr_sctp = TRUE;
1531             hdr_data_chunk = FALSE;
1532             hdr_tcp = FALSE;
1533             hdr_udp = FALSE;
1534             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1535             if (p == optarg || (*p != ',' && *p != '\0')) {
1536                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1537                 print_usage(stderr);
1538                 return EXIT_FAILURE;
1539             }
1540             if (*p == '\0') {
1541                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1542                 print_usage(stderr);
1543                 return EXIT_FAILURE;
1544             }
1545             p++;
1546             optarg = p;
1547             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1548             if (p == optarg || (*p != ',' && *p != '\0')) {
1549                 fprintf(stderr, "Bad dest port for '-s'\n");
1550                 print_usage(stderr);
1551                 return EXIT_FAILURE;
1552             }
1553             if (*p == '\0') {
1554                 fprintf(stderr, "No tag specified for '-%c'\n", c);
1555                 print_usage(stderr);
1556                 return EXIT_FAILURE;
1557             }
1558             p++;
1559             optarg = p;
1560             hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1561             if (p == optarg || *p != '\0') {
1562                 fprintf(stderr, "Bad tag for '-%c'\n", c);
1563                 print_usage(stderr);
1564                 return EXIT_FAILURE;
1565             }
1566
1567             hdr_ip_proto = 132;
1568             hdr_ethernet = TRUE;
1569             hdr_ethernet_proto = 0x800;
1570             break;
1571         case 'S':
1572             hdr_sctp = TRUE;
1573             hdr_data_chunk = TRUE;
1574             hdr_tcp = FALSE;
1575             hdr_udp = FALSE;
1576             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1577             if (p == optarg || (*p != ',' && *p != '\0')) {
1578                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1579                 print_usage(stderr);
1580                 return EXIT_FAILURE;
1581             }
1582             if (*p == '\0') {
1583                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1584                 print_usage(stderr);
1585                 return EXIT_FAILURE;
1586             }
1587             p++;
1588             optarg = p;
1589             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1590             if (p == optarg || (*p != ',' && *p != '\0')) {
1591                 fprintf(stderr, "Bad dest port for '-s'\n");
1592                 print_usage(stderr);
1593                 return EXIT_FAILURE;
1594             }
1595             if (*p == '\0') {
1596                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1597                 print_usage(stderr);
1598                 return EXIT_FAILURE;
1599             }
1600             p++;
1601             optarg = p;
1602             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1603             if (p == optarg || *p != '\0') {
1604                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1605                 print_usage(stderr);
1606                 return EXIT_FAILURE;
1607             }
1608
1609             hdr_ip_proto = 132;
1610             hdr_ethernet = TRUE;
1611             hdr_ethernet_proto = 0x800;
1612             break;
1613
1614         case 't':
1615             ts_fmt = optarg;
1616             break;
1617
1618         case 'u':
1619             hdr_udp = TRUE;
1620             hdr_tcp = FALSE;
1621             hdr_sctp = FALSE;
1622             hdr_data_chunk = FALSE;
1623             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1624             if (p == optarg || (*p != ',' && *p != '\0')) {
1625                 fprintf(stderr, "Bad src port for '-u'\n");
1626                 print_usage(stderr);
1627                 return EXIT_FAILURE;
1628             }
1629             if (*p == '\0') {
1630                 fprintf(stderr, "No dest port specified for '-u'\n");
1631                 print_usage(stderr);
1632                 return EXIT_FAILURE;
1633             }
1634             p++;
1635             optarg = p;
1636             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1637             if (p == optarg || *p != '\0') {
1638                 fprintf(stderr, "Bad dest port for '-u'\n");
1639                 print_usage(stderr);
1640                 return EXIT_FAILURE;
1641             }
1642             hdr_ip_proto = 17;
1643             hdr_ethernet = TRUE;
1644             hdr_ethernet_proto = 0x800;
1645             break;
1646
1647         case 'T':
1648             hdr_tcp = TRUE;
1649             hdr_udp = FALSE;
1650             hdr_sctp = FALSE;
1651             hdr_data_chunk = FALSE;
1652             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1653             if (p == optarg || (*p != ',' && *p != '\0')) {
1654                 fprintf(stderr, "Bad src port for '-T'\n");
1655                 print_usage(stderr);
1656                 return EXIT_FAILURE;
1657             }
1658             if (*p == '\0') {
1659                 fprintf(stderr, "No dest port specified for '-u'\n");
1660                 print_usage(stderr);
1661                 return EXIT_FAILURE;
1662             }
1663             p++;
1664             optarg = p;
1665             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1666             if (p == optarg || *p != '\0') {
1667                 fprintf(stderr, "Bad dest port for '-T'\n");
1668                 print_usage(stderr);
1669                 return EXIT_FAILURE;
1670             }
1671             hdr_ip_proto = 6;
1672             hdr_ethernet = TRUE;
1673             hdr_ethernet_proto = 0x800;
1674             break;
1675
1676         case 'a':
1677             identify_ascii = TRUE;
1678             break;
1679
1680         case 'v':
1681             comp_info_str = get_compiled_version_info(NULL, NULL);
1682             runtime_info_str = get_runtime_version_info(NULL);
1683             show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1684             g_string_free(comp_info_str, TRUE);
1685             g_string_free(runtime_info_str, TRUE);
1686             exit(0);
1687             break;
1688
1689         case '4':
1690         case '6':
1691             p = strchr(optarg, ',');
1692
1693             if (!p) {
1694                 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1695                 print_usage(stderr);
1696                 return EXIT_FAILURE;
1697             }
1698
1699             *p = '\0';
1700             if (c == '6')
1701             {
1702                 hdr_ipv6 = TRUE;
1703                 hdr_ethernet_proto = 0x86DD;
1704             }
1705             else
1706             {
1707                 hdr_ip = TRUE;
1708                 hdr_ethernet_proto = 0x800;
1709             }
1710             hdr_ethernet = TRUE;
1711
1712             if (hdr_ipv6 == TRUE) {
1713                 if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
1714                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1715                         print_usage(stderr);
1716                         return EXIT_FAILURE;
1717                 }
1718             } else {
1719                 if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
1720                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1721                         print_usage(stderr);
1722                         return EXIT_FAILURE;
1723                 }
1724             }
1725
1726             p++;
1727             if (*p == '\0') {
1728                 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1729                 print_usage(stderr);
1730                 return EXIT_FAILURE;
1731             }
1732
1733             if (hdr_ipv6 == TRUE) {
1734                 if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
1735                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1736                         print_usage(stderr);
1737                         return EXIT_FAILURE;
1738                 }
1739             } else {
1740                 if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
1741                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1742                         print_usage(stderr);
1743                         return EXIT_FAILURE;
1744                 }
1745             }
1746             break;
1747
1748
1749         case '?':
1750         default:
1751             print_usage(stderr);
1752             return EXIT_FAILURE;
1753         }
1754     }
1755
1756     if (optind >= argc || argc-optind < 2) {
1757         fprintf(stderr, "Must specify input and output filename\n");
1758         print_usage(stderr);
1759         return EXIT_FAILURE;
1760     }
1761
1762     if (max_offset > WTAP_MAX_PACKET_SIZE_STANDARD) {
1763         fprintf(stderr, "Maximum packet length cannot be more than %d bytes\n",
1764                 WTAP_MAX_PACKET_SIZE_STANDARD);
1765         return EXIT_FAILURE;
1766     }
1767
1768     if (strcmp(argv[optind], "-") != 0) {
1769         input_filename = argv[optind];
1770         input_file = ws_fopen(input_filename, "rb");
1771         if (!input_file) {
1772             fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1773                     input_filename, g_strerror(errno));
1774             return EXIT_FAILURE;
1775         }
1776     } else {
1777         input_filename = "Standard input";
1778         input_file = stdin;
1779     }
1780
1781     if (strcmp(argv[optind+1], "-") != 0) {
1782         /* Write to a file.  Open the file, in binary mode. */
1783         output_filename = argv[optind+1];
1784         output_file = ws_fopen(output_filename, "wb");
1785         if (!output_file) {
1786             fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1787                     output_filename, g_strerror(errno));
1788             return EXIT_FAILURE;
1789         }
1790     } else {
1791         /* Write to the standard output. */
1792 #ifdef _WIN32
1793         /* Put the standard output in binary mode. */
1794         if (_setmode(1, O_BINARY) == -1) {
1795             /* "Should not happen" */
1796             fprintf(stderr, "Cannot put standard output in binary mode: %s\n",
1797                     g_strerror(errno));
1798             return EXIT_FAILURE;
1799         }
1800 #endif
1801         output_filename = "Standard output";
1802         output_file = stdout;
1803     }
1804
1805     /* Some validation */
1806     if (pcap_link_type != 1 && hdr_ethernet) {
1807         fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1808         return EXIT_FAILURE;
1809     }
1810
1811     /* Set up our variables */
1812     if (!input_file) {
1813         input_file = stdin;
1814         input_filename = "Standard input";
1815     }
1816     if (!output_file) {
1817         output_file = stdout;
1818         output_filename = "Standard output";
1819     }
1820
1821     ts_sec = time(0);               /* initialize to current time */
1822     now_tm = localtime(&ts_sec);
1823     if (now_tm == NULL) {
1824         /*
1825          * This shouldn't happen - on UN*X, this should Just Work, and
1826          * on Windows, it won't work if ts_sec is before the Epoch,
1827          * but it's long after 1970, so....
1828          */
1829         fprintf(stderr, "localtime(right now) failed\n");
1830         return EXIT_FAILURE;
1831     }
1832     timecode_default = *now_tm;
1833     timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1834
1835     if ((hdr_tcp || hdr_udp || hdr_sctp) && !(hdr_ip || hdr_ipv6)) {
1836         /*
1837          * If TCP (-T), UDP (-u) or SCTP (-s/-S) header options are specified
1838          * but none of IPv4 (-4) or IPv6 (-6) options then add an IPv4 header
1839          */
1840         hdr_ip = TRUE;
1841     }
1842
1843     /* Display summary of our state */
1844     if (!quiet) {
1845         fprintf(stderr, "Input from: %s\n", input_filename);
1846         fprintf(stderr, "Output to: %s\n",  output_filename);
1847         fprintf(stderr, "Output format: %s\n", use_pcapng ? "pcapng" : "pcap");
1848
1849         if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1850                                   hdr_ethernet_proto);
1851         if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1852                             hdr_ip_proto);
1853         if (hdr_ipv6) fprintf(stderr, "Generate dummy IPv6 header: Protocol: %ld\n",
1854                             hdr_ip_proto);
1855         if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1856                              hdr_src_port, hdr_dest_port);
1857         if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1858                              hdr_src_port, hdr_dest_port);
1859         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1860                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1861         if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1862                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1863     }
1864
1865     return EXIT_SUCCESS;
1866 }
1867
1868 static int
1869 real_main(int argc, char *argv[])
1870 {
1871     int ret = EXIT_SUCCESS;
1872
1873 #ifdef _WIN32
1874     create_app_running_mutex();
1875 #endif /* _WIN32 */
1876
1877     if (parse_options(argc, argv) != EXIT_SUCCESS) {
1878         ret = EXIT_FAILURE;
1879         goto clean_exit;
1880     }
1881
1882     assert(input_file  != NULL);
1883     assert(output_file != NULL);
1884
1885     if (write_file_header() != EXIT_SUCCESS) {
1886         ret = EXIT_FAILURE;
1887         goto clean_exit;
1888     }
1889
1890     header_length = 0;
1891     if (hdr_ethernet) {
1892         header_length += (int)sizeof(HDR_ETHERNET);
1893     }
1894     if (hdr_ip) {
1895         ip_offset = header_length;
1896         header_length += (int)sizeof(HDR_IP);
1897     } else if (hdr_ipv6) {
1898         ip_offset = header_length;
1899         header_length += (int)sizeof(HDR_IPv6);
1900     }
1901     if (hdr_sctp) {
1902         header_length += (int)sizeof(HDR_SCTP);
1903     }
1904     if (hdr_data_chunk) {
1905         header_length += (int)sizeof(HDR_DATA_CHUNK);
1906     }
1907     if (hdr_tcp) {
1908         header_length += (int)sizeof(HDR_TCP);
1909     }
1910     if (hdr_udp) {
1911         header_length += (int)sizeof(HDR_UDP);
1912     }
1913     curr_offset = header_length;
1914
1915     text2pcap_in = input_file;
1916     if (text2pcap_scan() == EXIT_SUCCESS) {
1917         if (write_current_packet(FALSE) != EXIT_SUCCESS)
1918             ret = EXIT_FAILURE;
1919     } else {
1920         ret = EXIT_FAILURE;
1921     }
1922     if (debug)
1923         fprintf(stderr, "\n-------------------------\n");
1924     if (!quiet) {
1925         fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1926                 num_packets_read, (num_packets_read == 1) ? "" : "s",
1927                 num_packets_written, (num_packets_written == 1) ? "" : "s",
1928                 bytes_written, (bytes_written == 1) ? "" : "s");
1929     }
1930 clean_exit:
1931     if (input_file) {
1932         fclose(input_file);
1933     }
1934     if (output_file) {
1935         fclose(output_file);
1936     }
1937     return ret;
1938 }
1939
1940 #ifdef _WIN32
1941 int
1942 wmain(int argc, wchar_t *wc_argv[])
1943 {
1944     char **argv;
1945
1946     argv = arg_list_utf_16to8(argc, wc_argv);
1947     return real_main(argc, argv);
1948 }
1949 #else
1950 int
1951 main(int argc, char *argv[])
1952 {
1953     return real_main(argc, argv);
1954 }
1955 #endif
1956
1957 /*
1958  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1959  *
1960  * Local variables:
1961  * c-basic-offset: 4
1962  * tab-width: 8
1963  * indent-tabs-mode: nil
1964  * End:
1965  *
1966  * vi: set shiftwidth=4 tabstop=8 expandtab:
1967  * :indentSize=4:tabSize=8:noTabs=true:
1968  */