LTE RRC: add missing lte_rrc.bcch_bch.nb.tdd dissector
[metze/wireshark/wip.git] / text2pcap.c
1 /**-*-C-*-**********************************************************************
2  *
3  * text2pcap.c
4  *
5  * Utility to convert an ASCII hexdump into a libpcap-format capture file
6  *
7  * (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * 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 = TRUE;
1568             hdr_ip_proto = 132;
1569             hdr_ethernet = TRUE;
1570             hdr_ethernet_proto = 0x800;
1571             break;
1572         case 'S':
1573             hdr_sctp = TRUE;
1574             hdr_data_chunk = TRUE;
1575             hdr_tcp = FALSE;
1576             hdr_udp = FALSE;
1577             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1578             if (p == optarg || (*p != ',' && *p != '\0')) {
1579                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1580                 print_usage(stderr);
1581                 return EXIT_FAILURE;
1582             }
1583             if (*p == '\0') {
1584                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1585                 print_usage(stderr);
1586                 return EXIT_FAILURE;
1587             }
1588             p++;
1589             optarg = p;
1590             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1591             if (p == optarg || (*p != ',' && *p != '\0')) {
1592                 fprintf(stderr, "Bad dest port for '-s'\n");
1593                 print_usage(stderr);
1594                 return EXIT_FAILURE;
1595             }
1596             if (*p == '\0') {
1597                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1598                 print_usage(stderr);
1599                 return EXIT_FAILURE;
1600             }
1601             p++;
1602             optarg = p;
1603             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1604             if (p == optarg || *p != '\0') {
1605                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1606                 print_usage(stderr);
1607                 return EXIT_FAILURE;
1608             }
1609
1610             hdr_ip = TRUE;
1611             hdr_ip_proto = 132;
1612             hdr_ethernet = TRUE;
1613             hdr_ethernet_proto = 0x800;
1614             break;
1615
1616         case 't':
1617             ts_fmt = optarg;
1618             break;
1619
1620         case 'u':
1621             hdr_udp = TRUE;
1622             hdr_tcp = FALSE;
1623             hdr_sctp = FALSE;
1624             hdr_data_chunk = FALSE;
1625             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1626             if (p == optarg || (*p != ',' && *p != '\0')) {
1627                 fprintf(stderr, "Bad src port for '-u'\n");
1628                 print_usage(stderr);
1629                 return EXIT_FAILURE;
1630             }
1631             if (*p == '\0') {
1632                 fprintf(stderr, "No dest port specified for '-u'\n");
1633                 print_usage(stderr);
1634                 return EXIT_FAILURE;
1635             }
1636             p++;
1637             optarg = p;
1638             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1639             if (p == optarg || *p != '\0') {
1640                 fprintf(stderr, "Bad dest port for '-u'\n");
1641                 print_usage(stderr);
1642                 return EXIT_FAILURE;
1643             }
1644             hdr_ip = TRUE;
1645             hdr_ip_proto = 17;
1646             hdr_ethernet = TRUE;
1647             hdr_ethernet_proto = 0x800;
1648             break;
1649
1650         case 'T':
1651             hdr_tcp = TRUE;
1652             hdr_udp = FALSE;
1653             hdr_sctp = FALSE;
1654             hdr_data_chunk = FALSE;
1655             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1656             if (p == optarg || (*p != ',' && *p != '\0')) {
1657                 fprintf(stderr, "Bad src port for '-T'\n");
1658                 print_usage(stderr);
1659                 return EXIT_FAILURE;
1660             }
1661             if (*p == '\0') {
1662                 fprintf(stderr, "No dest port specified for '-u'\n");
1663                 print_usage(stderr);
1664                 return EXIT_FAILURE;
1665             }
1666             p++;
1667             optarg = p;
1668             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1669             if (p == optarg || *p != '\0') {
1670                 fprintf(stderr, "Bad dest port for '-T'\n");
1671                 print_usage(stderr);
1672                 return EXIT_FAILURE;
1673             }
1674             hdr_ip = TRUE;
1675             hdr_ip_proto = 6;
1676             hdr_ethernet = TRUE;
1677             hdr_ethernet_proto = 0x800;
1678             break;
1679
1680         case 'a':
1681             identify_ascii = TRUE;
1682             break;
1683
1684         case 'v':
1685             comp_info_str = get_compiled_version_info(NULL, NULL);
1686             runtime_info_str = get_runtime_version_info(NULL);
1687             show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1688             g_string_free(comp_info_str, TRUE);
1689             g_string_free(runtime_info_str, TRUE);
1690             exit(0);
1691             break;
1692
1693         case '4':
1694         case '6':
1695             p = strchr(optarg, ',');
1696
1697             if (!p) {
1698                 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1699                 print_usage(stderr);
1700                 return EXIT_FAILURE;
1701             }
1702
1703             *p = '\0';
1704             if (c == '6')
1705             {
1706                 hdr_ipv6 = TRUE;
1707                 hdr_ethernet_proto = 0x86DD;
1708             }
1709             else
1710             {
1711                 hdr_ip = TRUE;
1712                 hdr_ethernet_proto = 0x800;
1713             }
1714             hdr_ethernet = TRUE;
1715
1716             if (hdr_ipv6 == TRUE) {
1717                 if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
1718                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1719                         print_usage(stderr);
1720                         return EXIT_FAILURE;
1721                 }
1722             } else {
1723                 if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
1724                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1725                         print_usage(stderr);
1726                         return EXIT_FAILURE;
1727                 }
1728             }
1729
1730             p++;
1731             if (*p == '\0') {
1732                 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1733                 print_usage(stderr);
1734                 return EXIT_FAILURE;
1735             }
1736
1737             if (hdr_ipv6 == TRUE) {
1738                 if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
1739                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1740                         print_usage(stderr);
1741                         return EXIT_FAILURE;
1742                 }
1743             } else {
1744                 if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
1745                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1746                         print_usage(stderr);
1747                         return EXIT_FAILURE;
1748                 }
1749             }
1750             break;
1751
1752
1753         case '?':
1754         default:
1755             print_usage(stderr);
1756             return EXIT_FAILURE;
1757         }
1758     }
1759
1760     if (optind >= argc || argc-optind < 2) {
1761         fprintf(stderr, "Must specify input and output filename\n");
1762         print_usage(stderr);
1763         return EXIT_FAILURE;
1764     }
1765
1766     if (max_offset > WTAP_MAX_PACKET_SIZE_STANDARD) {
1767         fprintf(stderr, "Maximum packet length cannot be more than %d bytes\n",
1768                 WTAP_MAX_PACKET_SIZE_STANDARD);
1769         return EXIT_FAILURE;
1770     }
1771
1772     if (strcmp(argv[optind], "-") != 0) {
1773         input_filename = argv[optind];
1774         input_file = ws_fopen(input_filename, "rb");
1775         if (!input_file) {
1776             fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1777                     input_filename, g_strerror(errno));
1778             return EXIT_FAILURE;
1779         }
1780     } else {
1781         input_filename = "Standard input";
1782         input_file = stdin;
1783     }
1784
1785     if (strcmp(argv[optind+1], "-") != 0) {
1786         /* Write to a file.  Open the file, in binary mode. */
1787         output_filename = argv[optind+1];
1788         output_file = ws_fopen(output_filename, "wb");
1789         if (!output_file) {
1790             fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1791                     output_filename, g_strerror(errno));
1792             return EXIT_FAILURE;
1793         }
1794     } else {
1795         /* Write to the standard output. */
1796 #ifdef _WIN32
1797         /* Put the standard output in binary mode. */
1798         if (_setmode(1, O_BINARY) == -1) {
1799             /* "Should not happen" */
1800             fprintf(stderr, "Cannot put standard output in binary mode: %s\n",
1801                     g_strerror(errno));
1802             return EXIT_FAILURE;
1803         }
1804 #endif
1805         output_filename = "Standard output";
1806         output_file = stdout;
1807     }
1808
1809     /* Some validation */
1810     if (pcap_link_type != 1 && hdr_ethernet) {
1811         fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1812         return EXIT_FAILURE;
1813     }
1814
1815     /* Set up our variables */
1816     if (!input_file) {
1817         input_file = stdin;
1818         input_filename = "Standard input";
1819     }
1820     if (!output_file) {
1821         output_file = stdout;
1822         output_filename = "Standard output";
1823     }
1824
1825     ts_sec = time(0);               /* initialize to current time */
1826     now_tm = localtime(&ts_sec);
1827     if (now_tm == NULL) {
1828         /*
1829          * This shouldn't happen - on UN*X, this should Just Work, and
1830          * on Windows, it won't work if ts_sec is before the Epoch,
1831          * but it's long after 1970, so....
1832          */
1833         fprintf(stderr, "localtime(right now) failed\n");
1834         return EXIT_FAILURE;
1835     }
1836     timecode_default = *now_tm;
1837     timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1838
1839     /* Display summary of our state */
1840     if (!quiet) {
1841         fprintf(stderr, "Input from: %s\n", input_filename);
1842         fprintf(stderr, "Output to: %s\n",  output_filename);
1843         fprintf(stderr, "Output format: %s\n", use_pcapng ? "pcapng" : "pcap");
1844
1845         if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1846                                   hdr_ethernet_proto);
1847         if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1848                             hdr_ip_proto);
1849         if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1850                              hdr_src_port, hdr_dest_port);
1851         if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1852                              hdr_src_port, hdr_dest_port);
1853         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1854                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1855         if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1856                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1857     }
1858
1859     return EXIT_SUCCESS;
1860 }
1861
1862 static int
1863 real_main(int argc, char *argv[])
1864 {
1865     int ret = EXIT_SUCCESS;
1866
1867 #ifdef _WIN32
1868     create_app_running_mutex();
1869 #endif /* _WIN32 */
1870
1871     if (parse_options(argc, argv) != EXIT_SUCCESS) {
1872         ret = EXIT_FAILURE;
1873         goto clean_exit;
1874     }
1875
1876     assert(input_file  != NULL);
1877     assert(output_file != NULL);
1878
1879     if (write_file_header() != EXIT_SUCCESS) {
1880         ret = EXIT_FAILURE;
1881         goto clean_exit;
1882     }
1883
1884     header_length = 0;
1885     if (hdr_ethernet) {
1886         header_length += (int)sizeof(HDR_ETHERNET);
1887     }
1888     if (hdr_ip) {
1889         ip_offset = header_length;
1890         header_length += (int)sizeof(HDR_IP);
1891     } else if (hdr_ipv6) {
1892         ip_offset = header_length;
1893         header_length += (int)sizeof(HDR_IPv6);
1894     }
1895     if (hdr_sctp) {
1896         header_length += (int)sizeof(HDR_SCTP);
1897     }
1898     if (hdr_data_chunk) {
1899         header_length += (int)sizeof(HDR_DATA_CHUNK);
1900     }
1901     if (hdr_tcp) {
1902         header_length += (int)sizeof(HDR_TCP);
1903     }
1904     if (hdr_udp) {
1905         header_length += (int)sizeof(HDR_UDP);
1906     }
1907     curr_offset = header_length;
1908
1909     text2pcap_in = input_file;
1910     if (text2pcap_scan() == EXIT_SUCCESS) {
1911         if (write_current_packet(FALSE) != EXIT_SUCCESS)
1912             ret = EXIT_FAILURE;
1913     } else {
1914         ret = EXIT_FAILURE;
1915     }
1916     if (debug)
1917         fprintf(stderr, "\n-------------------------\n");
1918     if (!quiet) {
1919         fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1920                 num_packets_read, (num_packets_read == 1) ? "" : "s",
1921                 num_packets_written, (num_packets_written == 1) ? "" : "s",
1922                 bytes_written, (bytes_written == 1) ? "" : "s");
1923     }
1924 clean_exit:
1925     if (input_file) {
1926         fclose(input_file);
1927     }
1928     if (output_file) {
1929         fclose(output_file);
1930     }
1931     return ret;
1932 }
1933
1934 #ifdef _WIN32
1935 int
1936 wmain(int argc, wchar_t *wc_argv[])
1937 {
1938     char **argv;
1939
1940     argv = arg_list_utf_16to8(argc, wc_argv);
1941     return real_main(argc, argv);
1942 }
1943 #else
1944 int
1945 main(int argc, char *argv[])
1946 {
1947     return real_main(argc, argv);
1948 }
1949 #endif
1950
1951 /*
1952  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1953  *
1954  * Local variables:
1955  * c-basic-offset: 4
1956  * tab-width: 8
1957  * indent-tabs-mode: nil
1958  * End:
1959  *
1960  * vi: set shiftwidth=4 tabstop=8 expandtab:
1961  * :indentSize=4:tabSize=8:noTabs=true:
1962  */