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