Qt: Support search without a selected packet
[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 #ifdef _WIN32
1463     arg_list_utf_16to8(argc, argv);
1464     create_app_running_mutex();
1465 #endif /* _WIN32 */
1466
1467     /* Get the compile-time version information string */
1468     comp_info_str = get_compiled_version_info(NULL, NULL);
1469
1470     /* get the run-time version information string */
1471     runtime_info_str = get_runtime_version_info(NULL);
1472
1473     /* Add it to the information to be reported on a crash. */
1474     ws_add_crash_info("Text2pcap (Wireshark) %s\n"
1475          "\n"
1476          "%s"
1477          "\n"
1478          "%s",
1479       get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
1480     g_string_free(comp_info_str, TRUE);
1481     g_string_free(runtime_info_str, TRUE);
1482
1483     /* Scan CLI parameters */
1484     while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
1485         switch (c) {
1486         case 'h':
1487             printf("Text2pcap (Wireshark) %s\n"
1488                    "Generate a capture file from an ASCII hexdump of packets.\n"
1489                    "See https://www.wireshark.org for more information.\n",
1490                    get_ws_vcs_version_info());
1491             print_usage(stdout);
1492             exit(0);
1493             break;
1494         case 'd': if (!quiet) debug++; break;
1495         case 'D': has_direction = TRUE; break;
1496         case 'q': quiet = TRUE; debug = FALSE; break;
1497         case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1498         case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1499         case 'n': use_pcapng = TRUE; break;
1500         case 'o':
1501             if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
1502                 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1503                 print_usage(stderr);
1504                 return EXIT_FAILURE;
1505             }
1506             switch (optarg[0]) {
1507             case 'o': offset_base =  8; break;
1508             case 'h': offset_base = 16; break;
1509             case 'd': offset_base = 10; break;
1510             }
1511             break;
1512         case 'e':
1513             hdr_ethernet = TRUE;
1514             if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1515                 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1516                 print_usage(stderr);
1517                 return EXIT_FAILURE;
1518             }
1519             break;
1520
1521         case 'i':
1522             hdr_ip = TRUE;
1523             hdr_ip_proto = strtol(optarg, &p, 10);
1524             if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1525                   hdr_ip_proto > 255) {
1526                 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1527                 print_usage(stderr);
1528                 return EXIT_FAILURE;
1529             }
1530             hdr_ethernet = TRUE;
1531             hdr_ethernet_proto = 0x800;
1532             break;
1533
1534         case 's':
1535             hdr_sctp = TRUE;
1536             hdr_data_chunk = FALSE;
1537             hdr_tcp = FALSE;
1538             hdr_udp = FALSE;
1539             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1540             if (p == optarg || (*p != ',' && *p != '\0')) {
1541                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1542                 print_usage(stderr);
1543                 return EXIT_FAILURE;
1544             }
1545             if (*p == '\0') {
1546                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1547                 print_usage(stderr);
1548                 return EXIT_FAILURE;
1549             }
1550             p++;
1551             optarg = p;
1552             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1553             if (p == optarg || (*p != ',' && *p != '\0')) {
1554                 fprintf(stderr, "Bad dest port for '-s'\n");
1555                 print_usage(stderr);
1556                 return EXIT_FAILURE;
1557             }
1558             if (*p == '\0') {
1559                 fprintf(stderr, "No tag specified for '-%c'\n", c);
1560                 print_usage(stderr);
1561                 return EXIT_FAILURE;
1562             }
1563             p++;
1564             optarg = p;
1565             hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1566             if (p == optarg || *p != '\0') {
1567                 fprintf(stderr, "Bad tag for '-%c'\n", c);
1568                 print_usage(stderr);
1569                 return EXIT_FAILURE;
1570             }
1571
1572             hdr_ip = TRUE;
1573             hdr_ip_proto = 132;
1574             hdr_ethernet = TRUE;
1575             hdr_ethernet_proto = 0x800;
1576             break;
1577         case 'S':
1578             hdr_sctp = TRUE;
1579             hdr_data_chunk = TRUE;
1580             hdr_tcp = FALSE;
1581             hdr_udp = FALSE;
1582             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1583             if (p == optarg || (*p != ',' && *p != '\0')) {
1584                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1585                 print_usage(stderr);
1586                 return EXIT_FAILURE;
1587             }
1588             if (*p == '\0') {
1589                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1590                 print_usage(stderr);
1591                 return EXIT_FAILURE;
1592             }
1593             p++;
1594             optarg = p;
1595             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1596             if (p == optarg || (*p != ',' && *p != '\0')) {
1597                 fprintf(stderr, "Bad dest port for '-s'\n");
1598                 print_usage(stderr);
1599                 return EXIT_FAILURE;
1600             }
1601             if (*p == '\0') {
1602                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1603                 print_usage(stderr);
1604                 return EXIT_FAILURE;
1605             }
1606             p++;
1607             optarg = p;
1608             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1609             if (p == optarg || *p != '\0') {
1610                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1611                 print_usage(stderr);
1612                 return EXIT_FAILURE;
1613             }
1614
1615             hdr_ip = TRUE;
1616             hdr_ip_proto = 132;
1617             hdr_ethernet = TRUE;
1618             hdr_ethernet_proto = 0x800;
1619             break;
1620
1621         case 't':
1622             ts_fmt = optarg;
1623             break;
1624
1625         case 'u':
1626             hdr_udp = TRUE;
1627             hdr_tcp = FALSE;
1628             hdr_sctp = FALSE;
1629             hdr_data_chunk = FALSE;
1630             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1631             if (p == optarg || (*p != ',' && *p != '\0')) {
1632                 fprintf(stderr, "Bad src port for '-u'\n");
1633                 print_usage(stderr);
1634                 return EXIT_FAILURE;
1635             }
1636             if (*p == '\0') {
1637                 fprintf(stderr, "No dest port specified for '-u'\n");
1638                 print_usage(stderr);
1639                 return EXIT_FAILURE;
1640             }
1641             p++;
1642             optarg = p;
1643             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1644             if (p == optarg || *p != '\0') {
1645                 fprintf(stderr, "Bad dest port for '-u'\n");
1646                 print_usage(stderr);
1647                 return EXIT_FAILURE;
1648             }
1649             hdr_ip = TRUE;
1650             hdr_ip_proto = 17;
1651             hdr_ethernet = TRUE;
1652             hdr_ethernet_proto = 0x800;
1653             break;
1654
1655         case 'T':
1656             hdr_tcp = TRUE;
1657             hdr_udp = FALSE;
1658             hdr_sctp = FALSE;
1659             hdr_data_chunk = FALSE;
1660             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1661             if (p == optarg || (*p != ',' && *p != '\0')) {
1662                 fprintf(stderr, "Bad src port for '-T'\n");
1663                 print_usage(stderr);
1664                 return EXIT_FAILURE;
1665             }
1666             if (*p == '\0') {
1667                 fprintf(stderr, "No dest port specified for '-u'\n");
1668                 print_usage(stderr);
1669                 return EXIT_FAILURE;
1670             }
1671             p++;
1672             optarg = p;
1673             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1674             if (p == optarg || *p != '\0') {
1675                 fprintf(stderr, "Bad dest port for '-T'\n");
1676                 print_usage(stderr);
1677                 return EXIT_FAILURE;
1678             }
1679             hdr_ip = TRUE;
1680             hdr_ip_proto = 6;
1681             hdr_ethernet = TRUE;
1682             hdr_ethernet_proto = 0x800;
1683             break;
1684
1685         case 'a':
1686             identify_ascii = TRUE;
1687             break;
1688
1689         case 'v':
1690             comp_info_str = get_compiled_version_info(NULL, NULL);
1691             runtime_info_str = get_runtime_version_info(NULL);
1692             show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
1693             g_string_free(comp_info_str, TRUE);
1694             g_string_free(runtime_info_str, TRUE);
1695             exit(0);
1696             break;
1697
1698         case '4':
1699         case '6':
1700             p = strchr(optarg, ',');
1701
1702             if (!p) {
1703                 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
1704                 print_usage(stderr);
1705                 return EXIT_FAILURE;
1706             }
1707
1708             *p = '\0';
1709             if (c == '6')
1710             {
1711                 hdr_ipv6 = TRUE;
1712                 hdr_ethernet_proto = 0x86DD;
1713             }
1714             else
1715             {
1716                 hdr_ip = TRUE;
1717                 hdr_ethernet_proto = 0x800;
1718             }
1719             hdr_ethernet = TRUE;
1720
1721             if (hdr_ipv6 == TRUE) {
1722                 if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
1723                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1724                         print_usage(stderr);
1725                         return EXIT_FAILURE;
1726                 }
1727             } else {
1728                 if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
1729                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
1730                         print_usage(stderr);
1731                         return EXIT_FAILURE;
1732                 }
1733             }
1734
1735             p++;
1736             if (*p == '\0') {
1737                 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
1738                 print_usage(stderr);
1739                 return EXIT_FAILURE;
1740             }
1741
1742             if (hdr_ipv6 == TRUE) {
1743                 if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
1744                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1745                         print_usage(stderr);
1746                         return EXIT_FAILURE;
1747                 }
1748             } else {
1749                 if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
1750                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
1751                         print_usage(stderr);
1752                         return EXIT_FAILURE;
1753                 }
1754             }
1755             break;
1756
1757
1758         case '?':
1759         default:
1760             print_usage(stderr);
1761             return EXIT_FAILURE;
1762         }
1763     }
1764
1765     if (optind >= argc || argc-optind < 2) {
1766         fprintf(stderr, "Must specify input and output filename\n");
1767         print_usage(stderr);
1768         return EXIT_FAILURE;
1769     }
1770
1771     if (max_offset > WTAP_MAX_PACKET_SIZE_STANDARD) {
1772         fprintf(stderr, "Maximum packet length cannot be more than %d bytes\n",
1773                 WTAP_MAX_PACKET_SIZE_STANDARD);
1774         return EXIT_FAILURE;
1775     }
1776
1777     if (strcmp(argv[optind], "-") != 0) {
1778         input_filename = argv[optind];
1779         input_file = ws_fopen(input_filename, "rb");
1780         if (!input_file) {
1781             fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1782                     input_filename, g_strerror(errno));
1783             return EXIT_FAILURE;
1784         }
1785     } else {
1786         input_filename = "Standard input";
1787         input_file = stdin;
1788     }
1789
1790     if (strcmp(argv[optind+1], "-") != 0) {
1791         /* Write to a file.  Open the file, in binary mode. */
1792         output_filename = argv[optind+1];
1793         output_file = ws_fopen(output_filename, "wb");
1794         if (!output_file) {
1795             fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1796                     output_filename, g_strerror(errno));
1797             return EXIT_FAILURE;
1798         }
1799     } else {
1800         /* Write to the standard output. */
1801 #ifdef _WIN32
1802         /* Put the standard output in binary mode. */
1803         if (_setmode(1, O_BINARY) == -1) {
1804             /* "Should not happen" */
1805             fprintf(stderr, "Cannot put standard output in binary mode: %s\n",
1806                     g_strerror(errno));
1807             return EXIT_FAILURE;
1808         }
1809 #endif
1810         output_filename = "Standard output";
1811         output_file = stdout;
1812     }
1813
1814     /* Some validation */
1815     if (pcap_link_type != 1 && hdr_ethernet) {
1816         fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1817         return EXIT_FAILURE;
1818     }
1819
1820     /* Set up our variables */
1821     if (!input_file) {
1822         input_file = stdin;
1823         input_filename = "Standard input";
1824     }
1825     if (!output_file) {
1826         output_file = stdout;
1827         output_filename = "Standard output";
1828     }
1829
1830     ts_sec = time(0);               /* initialize to current time */
1831     now_tm = localtime(&ts_sec);
1832     if (now_tm == NULL) {
1833         /*
1834          * This shouldn't happen - on UN*X, this should Just Work, and
1835          * on Windows, it won't work if ts_sec is before the Epoch,
1836          * but it's long after 1970, so....
1837          */
1838         fprintf(stderr, "localtime(right now) failed\n");
1839         return EXIT_FAILURE;
1840     }
1841     timecode_default = *now_tm;
1842     timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1843
1844     /* Display summary of our state */
1845     if (!quiet) {
1846         fprintf(stderr, "Input from: %s\n", input_filename);
1847         fprintf(stderr, "Output to: %s\n",  output_filename);
1848         fprintf(stderr, "Output format: %s\n", use_pcapng ? "pcapng" : "pcap");
1849
1850         if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1851                                   hdr_ethernet_proto);
1852         if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1853                             hdr_ip_proto);
1854         if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1855                              hdr_src_port, hdr_dest_port);
1856         if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1857                              hdr_src_port, hdr_dest_port);
1858         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1859                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1860         if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
1861                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1862     }
1863
1864     return EXIT_SUCCESS;
1865 }
1866
1867 int
1868 main(int argc, char *argv[])
1869 {
1870     int ret = EXIT_SUCCESS;
1871
1872     if (parse_options(argc, argv) != EXIT_SUCCESS) {
1873         ret = EXIT_FAILURE;
1874         goto clean_exit;
1875     }
1876
1877     assert(input_file  != NULL);
1878     assert(output_file != NULL);
1879
1880     if (write_file_header() != EXIT_SUCCESS) {
1881         ret = EXIT_FAILURE;
1882         goto clean_exit;
1883     }
1884
1885     header_length = 0;
1886     if (hdr_ethernet) {
1887         header_length += (int)sizeof(HDR_ETHERNET);
1888     }
1889     if (hdr_ip) {
1890         ip_offset = header_length;
1891         header_length += (int)sizeof(HDR_IP);
1892     } else if (hdr_ipv6) {
1893         ip_offset = header_length;
1894         header_length += (int)sizeof(HDR_IPv6);
1895     }
1896     if (hdr_sctp) {
1897         header_length += (int)sizeof(HDR_SCTP);
1898     }
1899     if (hdr_data_chunk) {
1900         header_length += (int)sizeof(HDR_DATA_CHUNK);
1901     }
1902     if (hdr_tcp) {
1903         header_length += (int)sizeof(HDR_TCP);
1904     }
1905     if (hdr_udp) {
1906         header_length += (int)sizeof(HDR_UDP);
1907     }
1908     curr_offset = header_length;
1909
1910     text2pcap_in = input_file;
1911     if (text2pcap_scan() == EXIT_SUCCESS) {
1912         if (write_current_packet(FALSE) != EXIT_SUCCESS)
1913             ret = EXIT_FAILURE;
1914     } else {
1915         ret = EXIT_FAILURE;
1916     }
1917     if (debug)
1918         fprintf(stderr, "\n-------------------------\n");
1919     if (!quiet) {
1920         fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1921                 num_packets_read, (num_packets_read == 1) ? "" : "s",
1922                 num_packets_written, (num_packets_written == 1) ? "" : "s",
1923                 bytes_written, (bytes_written == 1) ? "" : "s");
1924     }
1925 clean_exit:
1926     if (input_file) {
1927         fclose(input_file);
1928     }
1929     if (output_file) {
1930         fclose(output_file);
1931     }
1932     return ret;
1933 }
1934
1935 /*
1936  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1937  *
1938  * Local variables:
1939  * c-basic-offset: 4
1940  * tab-width: 8
1941  * indent-tabs-mode: nil
1942  * End:
1943  *
1944  * vi: set shiftwidth=4 tabstop=8 expandtab:
1945  * :indentSize=4:tabSize=8:noTabs=true:
1946  */
1947