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