Fix the fuzz failure reported (by me) in https://bugs.wireshark.org/bugzilla/show_bug...
[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  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28  *
29  *******************************************************************************/
30
31 /*******************************************************************************
32  *
33  * This utility reads in an ASCII hexdump of this common format:
34  *
35  * 00000000  00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
36  * 00000010  03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3...\7f..
37  * 00000020  03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
38  * 00000030  01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
39  *
40  * Each bytestring line consists of an offset, one or more bytes, and
41  * text at the end. An offset is defined as a hex string of more than
42  * two characters. A byte is defined as a hex string of exactly two
43  * characters. The text at the end is ignored, as is any text before
44  * the offset. Bytes read from a bytestring line are added to the
45  * current packet only if all the following conditions are satisfied:
46  *
47  * - No text appears between the offset and the bytes (any bytes appearing after
48  *   such text would be ignored)
49  *
50  * - The offset must be arithmetically correct, i.e. if the offset is 00000020, then
51  *   exactly 32 bytes must have been read into this packet before this. If the offset
52  *   is wrong, the packet is immediately terminated
53  *
54  * A packet start is signaled by a zero offset.
55  *
56  * Lines starting with #TEXT2PCAP are directives. These allow the user
57  * to embed instructions into the capture file which allows text2pcap
58  * to take some actions (e.g. specifying the encapsulation
59  * etc.). Currently no directives are implemented.
60  *
61  * Lines beginning with # which are not directives are ignored as
62  * comments. Currently all non-hexdump text is ignored by text2pcap;
63  * in the future, text processing may be added, but lines prefixed
64  * with '#' will still be ignored.
65  *
66  * The output is a libpcap packet containing Ethernet frames by
67  * default. This program takes options which allow the user to add
68  * dummy Ethernet, IP and UDP or TCP headers to the packets in order
69  * to allow dumps of L3 or higher protocols to be decoded.
70  *
71  * Considerable flexibility is built into this code to read hexdumps
72  * of slightly different formats. For example, any text prefixing the
73  * hexdump line is dropped (including mail forwarding '>'). The offset
74  * can be any hex number of four digits or greater.
75  *
76  * This converter cannot read a single packet greater than 64KiB-1. Packet
77  * snaplength is automatically set to 64KiB-1.
78  */
79
80 #include "config.h"
81
82 /*
83  * Just make sure we include the prototype for strptime as well
84  * (needed for glibc 2.2) but make sure we do this only if not
85  * yet defined.
86  */
87 #ifndef __USE_XOPEN
88 #  define __USE_XOPEN
89 #endif
90 #ifndef _XOPEN_SOURCE
91 #  ifndef __sun
92 #    define _XOPEN_SOURCE 600
93 #  endif
94 #endif
95
96 /*
97  * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms
98  * using glibc, to expand the set of things system header files define.
99  *
100  * Unfortunately, on other platforms, such as some versions of Solaris
101  * (including Solaris 10), it *reduces* that set as well, causing
102  * strptime() not to be declared, presumably because the version of the
103  * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and
104  * blah blah blah namespace pollution blah blah blah.
105  *
106  * So we define __EXTENSIONS__ so that "strptime()" is declared.
107  */
108 #ifndef __EXTENSIONS__
109 #  define __EXTENSIONS__
110 #endif
111
112 #include <ctype.h>
113 #include <stdio.h>
114 #include <stdlib.h>
115 #include <string.h>
116 #include <wsutil/file_util.h>
117
118 #include <time.h>
119 #include <glib.h>
120
121 #ifdef HAVE_UNISTD_H
122 # include <unistd.h>
123 #endif
124
125 #include <errno.h>
126 #include <assert.h>
127
128 #ifndef HAVE_GETOPT
129 #include "wsutil/wsgetopt.h"
130 #endif
131
132 #ifdef NEED_STRPTIME_H
133 # include "wsutil/strptime.h"
134 #endif
135
136 #include "pcapio.h"
137 #include "text2pcap.h"
138 #include "svnversion.h"
139
140 #ifdef _WIN32
141 #include <wsutil/unicode-utils.h>
142 #endif /* _WIN32 */
143
144 /*--- Options --------------------------------------------------------------------*/
145
146 /* File format */
147 static gboolean use_pcapng = FALSE;
148
149 /* Debug level */
150 static int debug = 0;
151 /* Be quiet */
152 static int quiet = FALSE;
153
154 /* Dummy Ethernet header */
155 static int hdr_ethernet = FALSE;
156 static guint32 hdr_ethernet_proto = 0;
157
158 /* Dummy IP header */
159 static int hdr_ip = FALSE;
160 static long hdr_ip_proto = 0;
161
162 /* Dummy UDP header */
163 static int hdr_udp = FALSE;
164 static guint32 hdr_dest_port = 0;
165 static guint32 hdr_src_port = 0;
166
167 /* Dummy TCP header */
168 static int hdr_tcp = FALSE;
169
170 /* Dummy SCTP header */
171 static int hdr_sctp = FALSE;
172 static guint32 hdr_sctp_src  = 0;
173 static guint32 hdr_sctp_dest = 0;
174 static guint32 hdr_sctp_tag  = 0;
175
176 /* Dummy DATA chunk header */
177 static int hdr_data_chunk = FALSE;
178 static guint8  hdr_data_chunk_type = 0;
179 static guint8  hdr_data_chunk_bits = 0;
180 static guint32 hdr_data_chunk_tsn  = 0;
181 static guint16 hdr_data_chunk_sid  = 0;
182 static guint16 hdr_data_chunk_ssn  = 0;
183 static guint32 hdr_data_chunk_ppid = 0;
184
185 /* ASCII text dump identification */
186 static int identify_ascii = FALSE;
187
188 static gboolean has_direction = FALSE;
189 static guint32 direction = 0;
190
191 /*--- Local date -----------------------------------------------------------------*/
192
193 /* This is where we store the packet currently being built */
194 #define MAX_PACKET 65535
195 static guint8 packet_buf[MAX_PACKET];
196 static guint32 header_length;
197 static guint32 ip_offset;
198 static guint32 curr_offset;
199 static guint32 max_offset = MAX_PACKET;
200 static guint32 packet_start = 0;
201 static void start_new_packet(gboolean);
202
203 /* This buffer contains strings present before the packet offset 0 */
204 #define PACKET_PREAMBLE_MAX_LEN     2048
205 static guint8 packet_preamble[PACKET_PREAMBLE_MAX_LEN+1];
206 static int packet_preamble_len = 0;
207
208 /* Number of packets read and written */
209 static guint32 num_packets_read = 0;
210 static guint32 num_packets_written = 0;
211 static guint64 bytes_written = 0;
212
213 /* Time code of packet, derived from packet_preamble */
214 static time_t ts_sec  = 0;
215 static guint32 ts_usec = 0;
216 static char *ts_fmt = NULL;
217 static struct tm timecode_default;
218
219 static guint8* pkt_lnstart;
220
221 /* Input file */
222 static const char *input_filename;
223 static FILE *input_file = NULL;
224 /* Output file */
225 static const char *output_filename;
226 static FILE *output_file = NULL;
227
228 /* Offset base to parse */
229 static guint32 offset_base = 16;
230
231 extern FILE *yyin;
232
233 /* ----- State machine -----------------------------------------------------------*/
234
235 /* Current state of parser */
236 typedef enum {
237     INIT,             /* Waiting for start of new packet */
238     START_OF_LINE,    /* Starting from beginning of line */
239     READ_OFFSET,      /* Just read the offset */
240     READ_BYTE,        /* Just read a byte */
241     READ_TEXT         /* Just read text - ignore until EOL */
242 } parser_state_t;
243 static parser_state_t state = INIT;
244
245 static const char *state_str[] = {"Init",
246                            "Start-of-line",
247                            "Offset",
248                            "Byte",
249                            "Text"
250 };
251
252 static const char *token_str[] = {"",
253                            "Byte",
254                            "Offset",
255                            "Directive",
256                            "Text",
257                            "End-of-line"
258 };
259
260 /* ----- Skeleton Packet Headers --------------------------------------------------*/
261
262 typedef struct {
263     guint8  dest_addr[6];
264     guint8  src_addr[6];
265     guint16 l3pid;
266 } hdr_ethernet_t;
267
268 static hdr_ethernet_t HDR_ETHERNET = {
269     {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02},
270     {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01},
271     0};
272
273 typedef struct {
274     guint8  ver_hdrlen;
275     guint8  dscp;
276     guint16 packet_length;
277     guint16 identification;
278     guint8  flags;
279     guint8  fragment;
280     guint8  ttl;
281     guint8  protocol;
282     guint16 hdr_checksum;
283     guint32 src_addr;
284     guint32 dest_addr;
285 } hdr_ip_t;
286
287 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0,
288 #ifdef WORDS_BIGENDIAN
289 0x0a010101, 0x0a020202
290 #else
291 0x0101010a, 0x0202020a
292 #endif
293 };
294
295 static struct {         /* pseudo header for checksum calculation */
296     guint32 src_addr;
297     guint32 dest_addr;
298     guint8  zero;
299     guint8  protocol;
300     guint16 length;
301 } pseudoh;
302
303 typedef struct {
304     guint16 source_port;
305     guint16 dest_port;
306     guint16 length;
307     guint16 checksum;
308 } hdr_udp_t;
309
310 static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
311
312 typedef struct {
313     guint16 source_port;
314     guint16 dest_port;
315     guint32 seq_num;
316     guint32 ack_num;
317     guint8  hdr_length;
318     guint8  flags;
319     guint16 window;
320     guint16 checksum;
321     guint16 urg;
322 } hdr_tcp_t;
323
324 static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
325
326 typedef struct {
327     guint16 src_port;
328     guint16 dest_port;
329     guint32 tag;
330     guint32 checksum;
331 } hdr_sctp_t;
332
333 static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
334
335 typedef struct {
336     guint8  type;
337     guint8  bits;
338     guint16 length;
339     guint32 tsn;
340     guint16 sid;
341     guint16 ssn;
342     guint32 ppid;
343 } hdr_data_chunk_t;
344
345 static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
346
347 static char tempbuf[64];
348
349 /*----------------------------------------------------------------------
350  * Stuff for writing a PCap file
351  */
352 #define PCAP_MAGIC          0xa1b2c3d4
353 #define PCAP_SNAPLEN        0xffff
354
355 /* "libpcap" file header (minus magic number). */
356 struct pcap_hdr {
357     guint32 magic;          /* magic */
358     guint16 version_major;  /* major version number */
359     guint16 version_minor;  /* minor version number */
360     guint32 thiszone;       /* GMT to local correction */
361     guint32 sigfigs;        /* accuracy of timestamps */
362     guint32 snaplen;        /* max length of captured packets, in octets */
363     guint32 network;        /* data link type */
364 };
365
366 /* "libpcap" record header. */
367 struct pcaprec_hdr {
368     guint32 ts_sec;         /* timestamp seconds */
369     guint32 ts_usec;        /* timestamp microseconds */
370     guint32 incl_len;       /* number of octets of packet saved in file */
371     guint32 orig_len;       /* actual length of packet */
372 };
373
374 /* Link-layer type; see net/bpf.h for details */
375 static guint32 pcap_link_type = 1;   /* Default is DLT-EN10MB */
376
377 /*----------------------------------------------------------------------
378  * Parse a single hex number
379  * Will abort the program if it can't parse the number
380  * Pass in TRUE if this is an offset, FALSE if not
381  */
382 static guint32
383 parse_num (const char *str, int offset)
384 {
385     guint32 num;
386     char *c;
387
388     num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
389     if (c==str) {
390         fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
391         exit(-1);
392     }
393     return num;
394 }
395
396 /*----------------------------------------------------------------------
397  * Write this byte into current packet
398  */
399 static void
400 write_byte (const char *str)
401 {
402     guint32 num;
403
404     num = parse_num(str, FALSE);
405     packet_buf[curr_offset] = (guint8) num;
406     curr_offset ++;
407     if (curr_offset - header_length >= max_offset) /* packet full */
408         start_new_packet(TRUE);
409 }
410
411 /*----------------------------------------------------------------------
412  * Write a number of bytes into current packet
413  */
414
415 static void
416 write_bytes(const char bytes[], guint32 nbytes)
417 {
418     guint32 i;
419
420     if (curr_offset + nbytes < MAX_PACKET) {
421         for (i = 0; i < nbytes; i++) {
422             packet_buf[curr_offset] = bytes[i];
423             curr_offset++;
424         }
425     }
426 }
427
428 /*----------------------------------------------------------------------
429  * Remove bytes from the current packet
430  */
431 static void
432 unwrite_bytes (guint32 nbytes)
433 {
434     curr_offset -= nbytes;
435 }
436
437 /*----------------------------------------------------------------------
438  * Compute one's complement checksum (from RFC1071)
439  */
440 static guint16
441 in_checksum (void *buf, guint32 count)
442 {
443     guint32 sum = 0;
444     guint16 *addr = (guint16 *)buf;
445
446     while (count > 1) {
447         /*  This is the inner loop */
448         sum += g_ntohs(* (guint16 *) addr);
449         addr++;
450         count -= 2;
451     }
452
453     /*  Add left-over byte, if any */
454     if (count > 0)
455         sum += g_ntohs(* (guint8 *) addr);
456
457     /*  Fold 32-bit sum to 16 bits */
458     while (sum>>16)
459         sum = (sum & 0xffff) + (sum >> 16);
460
461     sum = ~sum;
462     return g_htons(sum);
463 }
464
465 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
466  * That code is copyrighted by D. Otis and has been modified.
467  */
468
469 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
470 static guint32 crc_c[256] =
471 {
472 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
473 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
474 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
475 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
476 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
477 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
478 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
479 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
480 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
481 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
482 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
483 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
484 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
485 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
486 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
487 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
488 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
489 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
490 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
491 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
492 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
493 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
494 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
495 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
496 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
497 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
498 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
499 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
500 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
501 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
502 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
503 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
504 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
505 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
506 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
507 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
508 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
509 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
510 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
511 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
512 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
513 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
514 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
515 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
516 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
517 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
518 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
519 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
520 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
521 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
522 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
523 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
524 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
525 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
526 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
527 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
528 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
529 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
530 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
531 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
532 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
533 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
534 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
535 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
536 };
537
538 static guint32
539 crc32c(const guint8* buf, unsigned int len, guint32 crc32_init)
540 {
541     unsigned int i;
542     guint32 crc32;
543
544     crc32 = crc32_init;
545     for (i = 0; i < len; i++)
546         CRC32C(crc32, buf[i]);
547
548     return ( crc32 );
549 }
550
551 static guint32
552 finalize_crc32c(guint32 crc32)
553 {
554     guint32 result;
555     guint8 byte0,byte1,byte2,byte3;
556
557     result = ~crc32;
558     byte0 = result & 0xff;
559     byte1 = (result>>8) & 0xff;
560     byte2 = (result>>16) & 0xff;
561     byte3 = (result>>24) & 0xff;
562     result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
563     return ( result );
564 }
565
566 static guint16
567 number_of_padding_bytes (guint32 length)
568 {
569     guint16 remainder;
570
571     remainder = length % 4;
572
573     if (remainder == 0)
574         return 0;
575     else
576         return 4 - remainder;
577 }
578
579 /*----------------------------------------------------------------------
580  * Write current packet out
581  */
582 static void
583 write_current_packet(gboolean cont)
584 {
585     guint32 length = 0;
586     guint16 padding_length = 0;
587     int err;
588     gboolean success;
589
590     if (curr_offset > header_length) {
591         /* Write the packet */
592
593         /* Compute packet length */
594         length = curr_offset;
595         if (hdr_sctp) {
596             padding_length = number_of_padding_bytes(length - header_length );
597         } else {
598             padding_length = 0;
599         }
600         /* Reset curr_offset, since we now write the headers */
601         curr_offset = 0;
602
603         /* Write Ethernet header */
604         if (hdr_ethernet) {
605             HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
606             write_bytes((const char *)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
607         }
608
609         /* Write IP header */
610         if (hdr_ip) {
611             HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
612             HDR_IP.protocol = (guint8) hdr_ip_proto;
613             HDR_IP.hdr_checksum = 0;
614             HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
615             write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
616         }
617
618         /* Write UDP header */
619         if (hdr_udp) {
620             guint16 x16;
621             guint32 u;
622
623             /* initialize pseudo header for checksum calculation */
624             pseudoh.src_addr    = HDR_IP.src_addr;
625             pseudoh.dest_addr   = HDR_IP.dest_addr;
626             pseudoh.zero        = 0;
627             pseudoh.protocol    = (guint8) hdr_ip_proto;
628             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_UDP));
629             /* initialize the UDP header */
630             HDR_UDP.source_port = g_htons(hdr_src_port);
631             HDR_UDP.dest_port = g_htons(hdr_dest_port);
632             HDR_UDP.length = g_htons(length - header_length + sizeof(HDR_UDP));
633             HDR_UDP.checksum = 0;
634             /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
635             x16  = in_checksum(&pseudoh, sizeof(pseudoh));
636             u    = g_ntohs(x16);
637             x16  = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
638             u   += g_ntohs(x16);
639             x16  = in_checksum(packet_buf + header_length, length - header_length);
640             u   += g_ntohs(x16);
641             x16  = (u & 0xffff) + (u>>16);
642             HDR_UDP.checksum = g_htons(x16);
643             if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */
644                 HDR_UDP.checksum = g_htons(1);
645             write_bytes((const char *)&HDR_UDP, sizeof(HDR_UDP));
646         }
647
648         /* Write TCP header */
649         if (hdr_tcp) {
650             guint16 x16;
651             guint32 u;
652
653              /* initialize pseudo header for checksum calculation */
654             pseudoh.src_addr    = HDR_IP.src_addr;
655             pseudoh.dest_addr   = HDR_IP.dest_addr;
656             pseudoh.zero        = 0;
657             pseudoh.protocol    = (guint8) hdr_ip_proto;
658             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_TCP));
659             /* initialize the TCP header */
660             HDR_TCP.source_port = g_htons(hdr_src_port);
661             HDR_TCP.dest_port = g_htons(hdr_dest_port);
662             /* HDR_TCP.seq_num already correct */
663             HDR_TCP.window = g_htons(0x2000);
664             HDR_TCP.checksum = 0;
665             /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
666             x16  = in_checksum(&pseudoh, sizeof(pseudoh));
667             u    = g_ntohs(x16);
668             x16  = in_checksum(&HDR_TCP, sizeof(HDR_TCP));
669             u   += g_ntohs(x16);
670             x16  = in_checksum(packet_buf + header_length, length - header_length);
671             u   += g_ntohs(x16);
672             x16  = (u & 0xffff) + (u>>16);
673             HDR_TCP.checksum = g_htons(x16);
674             if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */
675                 HDR_TCP.checksum = g_htons(1);
676             write_bytes((const char *)&HDR_TCP, sizeof(HDR_TCP));
677             HDR_TCP.seq_num = g_ntohl(HDR_TCP.seq_num) + length - header_length;
678             HDR_TCP.seq_num = g_htonl(HDR_TCP.seq_num);
679         }
680
681         /* Compute DATA chunk header */
682         if (hdr_data_chunk) {
683             hdr_data_chunk_bits = 0;
684             if (packet_start == 0) {
685                 hdr_data_chunk_bits |= 0x02;
686             }
687             if (!cont) {
688                 hdr_data_chunk_bits |= 0x01;
689             }
690             HDR_DATA_CHUNK.type   = hdr_data_chunk_type;
691             HDR_DATA_CHUNK.bits   = hdr_data_chunk_bits;
692             HDR_DATA_CHUNK.length = g_htons(length - header_length + sizeof(HDR_DATA_CHUNK));
693             HDR_DATA_CHUNK.tsn    = g_htonl(hdr_data_chunk_tsn);
694             HDR_DATA_CHUNK.sid    = g_htons(hdr_data_chunk_sid);
695             HDR_DATA_CHUNK.ssn    = g_htons(hdr_data_chunk_ssn);
696             HDR_DATA_CHUNK.ppid   = g_htonl(hdr_data_chunk_ppid);
697             hdr_data_chunk_tsn++;
698             if (!cont) {
699                 hdr_data_chunk_ssn++;
700             }
701         }
702
703         /* Write SCTP common header */
704         if (hdr_sctp) {
705             guint32 zero = 0;
706
707             HDR_SCTP.src_port  = g_htons(hdr_sctp_src);
708             HDR_SCTP.dest_port = g_htons(hdr_sctp_dest);
709             HDR_SCTP.tag       = g_htonl(hdr_sctp_tag);
710             HDR_SCTP.checksum  = g_htonl(0);
711             HDR_SCTP.checksum  = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0L);
712             if (hdr_data_chunk) {
713                 HDR_SCTP.checksum  = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
714                 HDR_SCTP.checksum  = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
715                 HDR_SCTP.checksum  = crc32c((guint8 *)&zero, padding_length, HDR_SCTP.checksum);
716             } else {
717                 HDR_SCTP.checksum  = crc32c((guint8 *)packet_buf + header_length, length - header_length, HDR_SCTP.checksum);
718             }
719             HDR_SCTP.checksum = finalize_crc32c(HDR_SCTP.checksum);
720             HDR_SCTP.checksum  = g_htonl(HDR_SCTP.checksum);
721             write_bytes((const char *)&HDR_SCTP, sizeof(HDR_SCTP));
722         }
723
724         /* Write DATA chunk header */
725         if (hdr_data_chunk) {
726             write_bytes((const char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
727         }
728
729         /* Reset curr_offset, since we now write the trailers */
730         curr_offset = length;
731
732         /* Write DATA chunk padding */
733         if (hdr_data_chunk && (padding_length > 0)) {
734             memset(tempbuf, 0, padding_length);
735             write_bytes((const char *)&tempbuf, padding_length);
736             length += padding_length;
737         }
738
739         /* Write Ethernet trailer */
740         if (hdr_ethernet && (length < 60)) {
741             memset(tempbuf, 0, 60 - length);
742             write_bytes((const char *)&tempbuf, 60 - length);
743             length = 60;
744         }
745         if (use_pcapng) {
746             success = libpcap_write_enhanced_packet_block(libpcap_write_to_file, output_file,
747                                                           NULL,
748                                                           ts_sec, ts_usec,
749                                                           length, length,
750                                                           0,
751                                                           1000000,
752                                                           packet_buf, direction,
753                                                           &bytes_written, &err);
754         } else {
755             success = libpcap_write_packet(libpcap_write_to_file, output_file,
756                                            ts_sec, ts_usec,
757                                            length, length,
758                                            packet_buf,
759                                            &bytes_written, &err);
760         }
761         if (!success) {
762             fprintf(stderr, "File write error [%s] : %s\n",
763                     output_filename, g_strerror(err));
764             exit(-1);
765         }
766         if (ts_fmt == NULL) {
767             /* fake packet counter */
768             ts_usec++;
769         }
770         if (!quiet) {
771             fprintf(stderr, "Wrote packet of %u bytes.\n", length);
772         }
773         num_packets_written ++;
774     }
775
776     packet_start += curr_offset - header_length;
777     curr_offset = header_length;
778     return;
779 }
780
781 /*----------------------------------------------------------------------
782  * Write file header and trailer
783  */
784 static void
785 write_file_header (void)
786 {
787     int err;
788     gboolean success;
789
790     if (use_pcapng) {
791 #ifdef SVNVERSION
792         const char *appname = "text2pcap (" SVNVERSION " from " SVNPATH ")";
793 #else
794         const char *appname = "text2pcap";
795 #endif
796         char comment[100];
797
798         g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
799         success = libpcap_write_session_header_block(libpcap_write_to_file, output_file,
800                                                      comment,
801                                                      NULL,
802                                                      NULL,
803                                                      appname,
804                                                      -1,
805                                                      &bytes_written,
806                                                      &err);
807         if (success) {
808             success = libpcap_write_interface_description_block(libpcap_write_to_file, output_file,
809                                                                 NULL,
810                                                                 NULL,
811                                                                 NULL,
812                                                                 "",
813                                                                 NULL,
814                                                                 pcap_link_type,
815                                                                 PCAP_SNAPLEN,
816                                                                 &bytes_written,
817                                                                 0,
818                                                                 6,
819                                                                 &err);
820         }
821     } else {
822         success = libpcap_write_file_header(libpcap_write_to_file, output_file, pcap_link_type, PCAP_SNAPLEN,
823                                             FALSE, &bytes_written, &err);
824     }
825     if (!success) {
826         fprintf(stderr, "File write error [%s] : %s\n",
827                 output_filename, g_strerror(err));
828         exit(-1);
829     }
830 }
831
832 static void
833 write_file_trailer (void)
834 {
835     int err;
836     gboolean success;
837
838     if (use_pcapng) {
839         success = libpcap_write_interface_statistics_block(libpcap_write_to_file, output_file,
840                                                            0,
841                                                            &bytes_written,
842                                                            "Counters provided by text2pcap",
843                                                            0,
844                                                            0,
845                                                            num_packets_written,
846                                                            num_packets_written - num_packets_written,
847                                                            &err);
848
849     } else {
850         success = TRUE;
851     }
852     if (!success) {
853         fprintf(stderr, "File write error [%s] : %s\n",
854                 output_filename, g_strerror(err));
855         exit(-1);
856     }
857    return;
858 }
859
860 /*----------------------------------------------------------------------
861  * Append a token to the packet preamble.
862  */
863 static void
864 append_to_preamble(char *str)
865 {
866     size_t toklen;
867
868     if (packet_preamble_len != 0) {
869         if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN)
870             return; /* no room to add more preamble */
871         /* Add a blank separator between the previous token and this token. */
872         packet_preamble[packet_preamble_len++] = ' ';
873     }
874     toklen = strlen(str);
875     if (toklen != 0) {
876         if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN)
877             return; /* no room to add the token to the preamble */
878         g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN);
879         packet_preamble_len += (int) toklen;
880         if (debug >= 2) {
881             char *c;
882             char xs[PACKET_PREAMBLE_MAX_LEN];
883             g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN);
884             while ((c = strchr(xs, '\r')) != NULL) *c=' ';
885             fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs);
886         }
887     }
888 }
889
890 /*----------------------------------------------------------------------
891  * Parse the preamble to get the timecode.
892  */
893
894 static void
895 parse_preamble (void)
896 {
897     struct tm timecode;
898     char *subsecs;
899     char *p;
900     int  subseclen;
901     int  i;
902
903      /*
904      * Null-terminate the preamble.
905      */
906     packet_preamble[packet_preamble_len] = '\0';
907     if (debug > 0)
908         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
909
910     if (has_direction) {
911         switch (packet_preamble[0]) {
912         case 'i':
913         case 'I':
914             direction = 0x00000001;
915             packet_preamble[0] = ' ';
916             break;
917         case 'o':
918         case 'O':
919             direction = 0x00000002;
920             packet_preamble[0] = ' ';
921             break;
922         default:
923             direction = 0x00000000;
924             break;
925         }
926         i = 0;
927         while (packet_preamble[i] == ' ' ||
928                packet_preamble[i] == '\r' ||
929                packet_preamble[i] == '\t') {
930             i++;
931         }
932         packet_preamble_len -= i;
933         /* Also move the trailing '\0'. */
934         memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
935     }
936
937
938     /*
939      * If no "-t" flag was specified, don't attempt to parse the packet
940      * preamble to extract a time stamp.
941      */
942     if (ts_fmt == NULL) {
943         /* Clear Preamble */
944         packet_preamble_len = 0;
945         return;
946     }
947
948     /*
949      * Initialize to today localtime, just in case not all fields
950      * of the date and time are specified.
951      */
952
953     timecode = timecode_default;
954     ts_usec = 0;
955
956     /* Ensure preamble has more than two chars before attempting to parse.
957      * This should cover line breaks etc that get counted.
958      */
959     if (strlen(packet_preamble) > 2) {
960         /* Get Time leaving subseconds */
961         subsecs = strptime( packet_preamble, ts_fmt, &timecode );
962         if (subsecs != NULL) {
963             /* Get the long time from the tm structure */
964             /*  (will return -1 if failure)            */
965             ts_sec  = mktime( &timecode );
966         } else
967             ts_sec = -1;    /* we failed to parse it */
968
969         /* This will ensure incorrectly parsed dates get set to zero */
970         if (-1 == ts_sec) {
971             /* Sanitize - remove all '\r' */
972             char *c;
973             while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
974             fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n   (defaulting to Jan 1,1970 00:00:00 GMT)\n",
975                  packet_preamble, ts_fmt);
976             if (debug >= 2) {
977                 fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n",
978                     timecode.tm_mday, timecode.tm_mon, timecode.tm_year,
979                     timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
980             }
981             ts_sec  = 0;  /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
982             ts_usec = 0;
983         } else {
984             /* Parse subseconds */
985             ts_usec = (guint32)strtol(subsecs, &p, 10);
986             if (subsecs == p) {
987                 /* Error */
988                 ts_usec = 0;
989             } else {
990                 /*
991                  * Convert that number to a number
992                  * of microseconds; if it's N digits
993                  * long, it's in units of 10^(-N) seconds,
994                  * so, to convert it to units of
995                  * 10^-6 seconds, we multiply by
996                  * 10^(6-N).
997                  */
998                 subseclen = (int) (p - subsecs);
999                 if (subseclen > 6) {
1000                     /*
1001                      * *More* than 6 digits; 6-N is
1002                      * negative, so we divide by
1003                      * 10^(N-6).
1004                      */
1005                     for (i = subseclen - 6; i != 0; i--)
1006                         ts_usec /= 10;
1007                 } else if (subseclen < 6) {
1008                     for (i = 6 - subseclen; i != 0; i--)
1009                         ts_usec *= 10;
1010                 }
1011             }
1012         }
1013     }
1014     if (debug >= 2) {
1015         char *c;
1016         while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
1017         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
1018         fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_usec);
1019     }
1020
1021
1022     /* Clear Preamble */
1023     packet_preamble_len = 0;
1024 }
1025
1026 /*----------------------------------------------------------------------
1027  * Start a new packet
1028  */
1029 static void
1030 start_new_packet(gboolean cont)
1031 {
1032     if (debug >= 1)
1033         fprintf(stderr, "Start new packet (cont = %s).\n", cont ? "TRUE" : "FALSE");
1034
1035     /* Write out the current packet, if required */
1036     write_current_packet(cont);
1037     num_packets_read ++;
1038
1039     /* Ensure we parse the packet preamble as it may contain the time */
1040     parse_preamble();
1041 }
1042
1043 /*----------------------------------------------------------------------
1044  * Process a directive
1045  */
1046 static void
1047 process_directive (char *str)
1048 {
1049     fprintf(stderr, "\n--- Directive [%s] currently unsupported ---\n", str + 10);
1050 }
1051
1052 /*----------------------------------------------------------------------
1053  * Parse a single token (called from the scanner)
1054  */
1055 void
1056 parse_token (token_t token, char *str)
1057 {
1058     guint32 num;
1059     int by_eol;
1060     int rollback = 0;
1061     int line_size;
1062     int i;
1063     char* s2;
1064     char tmp_str[3];
1065
1066     /*
1067      * This is implemented as a simple state machine of five states.
1068      * State transitions are caused by tokens being received from the
1069      * scanner. The code should be self_documenting.
1070      */
1071
1072     if (debug >= 2) {
1073         /* Sanitize - remove all '\r' */
1074         char *c;
1075         if (str!=NULL) { while ((c = strchr(str, '\r')) != NULL) *c=' '; }
1076
1077         fprintf(stderr, "(%s, %s \"%s\") -> (",
1078                 state_str[state], token_str[token], str ? str : "");
1079     }
1080
1081     switch(state) {
1082
1083     /* ----- Waiting for new packet -------------------------------------------*/
1084     case INIT:
1085         switch(token) {
1086         case T_TEXT:
1087             append_to_preamble(str);
1088             break;
1089         case T_DIRECTIVE:
1090             process_directive(str);
1091             break;
1092         case T_OFFSET:
1093             num = parse_num(str, TRUE);
1094             if (num == 0) {
1095                 /* New packet starts here */
1096                 start_new_packet(FALSE);
1097                 state = READ_OFFSET;
1098                 pkt_lnstart = packet_buf + num;
1099             }
1100             break;
1101         case T_EOL:
1102             /* Some describing text may be parsed as offset, but the invalid
1103                offset will be checked in the state of START_OF_LINE, so
1104                we add this transition to gain flexibility */
1105             state = START_OF_LINE;
1106             break;
1107         default:
1108             break;
1109         }
1110         break;
1111
1112     /* ----- Processing packet, start of new line -----------------------------*/
1113     case START_OF_LINE:
1114         switch(token) {
1115         case T_TEXT:
1116             append_to_preamble(str);
1117             break;
1118         case T_DIRECTIVE:
1119             process_directive(str);
1120             break;
1121         case T_OFFSET:
1122             num = parse_num(str, TRUE);
1123             if (num == 0) {
1124                 /* New packet starts here */
1125                 start_new_packet(FALSE);
1126                 packet_start = 0;
1127                 state = READ_OFFSET;
1128             } else if ((num - packet_start) != curr_offset - header_length) {
1129                 /*
1130                  * The offset we read isn't the one we expected.
1131                  * This may only mean that we mistakenly interpreted
1132                  * some text as byte values (e.g., if the text dump
1133                  * of packet data included a number with spaces around
1134                  * it).  If the offset is less than what we expected,
1135                  * assume that's the problem, and throw away the putative
1136                  * extra byte values.
1137                  */
1138                 if (num < curr_offset) {
1139                     unwrite_bytes(curr_offset - num);
1140                     state = READ_OFFSET;
1141                 } else {
1142                     /* Bad offset; switch to INIT state */
1143                     if (debug >= 1)
1144                         fprintf(stderr, "Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet\n",
1145                                 curr_offset, num);
1146                     write_current_packet(FALSE);
1147                     state = INIT;
1148                 }
1149             } else
1150                 state = READ_OFFSET;
1151                 pkt_lnstart = packet_buf + num;
1152             break;
1153         case T_EOL:
1154             state = START_OF_LINE;
1155             break;
1156         default:
1157             break;
1158         }
1159         break;
1160
1161     /* ----- Processing packet, read offset -----------------------------------*/
1162     case READ_OFFSET:
1163         switch(token) {
1164         case T_BYTE:
1165             /* Record the byte */
1166             state = READ_BYTE;
1167             write_byte(str);
1168             break;
1169         case T_TEXT:
1170         case T_DIRECTIVE:
1171         case T_OFFSET:
1172             state = READ_TEXT;
1173             break;
1174         case T_EOL:
1175             state = START_OF_LINE;
1176             break;
1177         default:
1178             break;
1179         }
1180         break;
1181
1182     /* ----- Processing packet, read byte -------------------------------------*/
1183     case READ_BYTE:
1184         switch(token) {
1185         case T_BYTE:
1186             /* Record the byte */
1187             write_byte(str);
1188             break;
1189         case T_TEXT:
1190         case T_DIRECTIVE:
1191         case T_OFFSET:
1192         case T_EOL:
1193             by_eol = 0;
1194             state = READ_TEXT;
1195             if (token == T_EOL) {
1196                 by_eol = 1;
1197                 state = START_OF_LINE;
1198             }
1199             if (identify_ascii) {
1200                 /* Here a line of pkt bytes reading is finished
1201                    compare the ascii and hex to avoid such situation:
1202                    "61 62 20 ab ", when ab is ascii dump then it should
1203                    not be treat as byte */
1204                 rollback = 0;
1205                 /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1206                    s2 = "ab ", s1 = "616220"
1207                    we should find out the largest tail of s1 matches the head
1208                    of s2, it means the matched part in tail is the ASCII dump
1209                    of the head byte. These matched should be rollback */
1210                 line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1211                 s2 = (char*)g_malloc((line_size+1)/4+1);
1212                 /* gather the possible pattern */
1213                 for (i = 0; i < (line_size+1)/4; i++) {
1214                     tmp_str[0] = pkt_lnstart[i*3];
1215                     tmp_str[1] = pkt_lnstart[i*3+1];
1216                     tmp_str[2] = '\0';
1217                     /* it is a valid convertable string */
1218                     if (!isxdigit(tmp_str[0]) || !isxdigit(tmp_str[0])) {
1219                         break;
1220                     }
1221                     s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
1222                     rollback++;
1223                     /* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
1224                     if (!(pkt_lnstart[i*3+2] == ' ')) {
1225                         if (by_eol != 1)
1226                             rollback--;
1227                         break;
1228                     }
1229                 }
1230                 /* If packet line start contains possible byte pattern, the line end
1231                    should contain the matched pattern if the user open the -a flag.
1232                    The packet will be possible invalid if the byte pattern cannot find
1233                    a matched one in the line of packet buffer.*/
1234                 if (rollback > 0) {
1235                     if (strncmp(pkt_lnstart+line_size-rollback, s2, rollback) == 0) {
1236                         unwrite_bytes(rollback);
1237                     }
1238                     /* Not matched. This line contains invalid packet bytes, so
1239                        discard the whole line */
1240                     else {
1241                         unwrite_bytes(line_size);
1242                     }
1243                 }
1244                 g_free(s2);
1245             }
1246             break;
1247         default:
1248             break;
1249         }
1250         break;
1251
1252     /* ----- Processing packet, read text -------------------------------------*/
1253     case READ_TEXT:
1254         switch(token) {
1255         case T_EOL:
1256             state = START_OF_LINE;
1257             break;
1258         default:
1259             break;
1260         }
1261         break;
1262
1263     default:
1264         fprintf(stderr, "FATAL ERROR: Bad state (%d)", state);
1265         exit(-1);
1266     }
1267
1268     if (debug>=2)
1269         fprintf(stderr, ", %s)\n", state_str[state]);
1270
1271 }
1272
1273 /*----------------------------------------------------------------------
1274  * Print usage string and exit
1275  */
1276 static void
1277 usage (void)
1278 {
1279     fprintf(stderr,
1280             "Text2pcap %s"
1281 #ifdef SVNVERSION
1282             " (" SVNVERSION " from " SVNPATH ")"
1283 #endif
1284             "\n"
1285             "Generate a capture file from an ASCII hexdump of packets.\n"
1286             "See http://www.wireshark.org for more information.\n"
1287             "\n"
1288             "Usage: text2pcap [options] <infile> <outfile>\n"
1289             "\n"
1290             "where  <infile> specifies input  filename (use - for standard input)\n"
1291             "      <outfile> specifies output filename (use - for standard output)\n"
1292             "\n"
1293             "Input:\n"
1294             "  -o hex|oct|dec         parse offsets as (h)ex, (o)ctal or (d)ecimal;\n"
1295             "                         default is hex.\n"
1296             "  -t <timefmt>           treat the text before the packet as a date/time code;\n"
1297             "                         the specified argument is a format string of the sort\n"
1298             "                         supported by strptime.\n"
1299             "                         Example: The time \"10:15:14.5476\" has the format code\n"
1300             "                         \"%%H:%%M:%%S.\"\n"
1301             "                         NOTE: The subsecond component delimiter, '.', must be\n"
1302             "                         given, but no pattern is required; the remaining\n"
1303             "                         number is assumed to be fractions of a second.\n"
1304             "                         NOTE: Date/time fields from the current date/time are\n"
1305             "                         used as the default for unspecified fields.\n"
1306             "  -D                     the text before the packet starts with an I or an O,\n"
1307             "                         indicating that the packet is inbound or outbound.\n"
1308             "                         This is only stored if the output format is PCAP-NG.\n"
1309             "  -a                     enable ASCII text dump identification.\n"
1310             "                         The start of the ASCII text dump can be identified\n"
1311             "                         and excluded from the packet data, even if it looks\n"
1312             "                         like a HEX dump.\n"
1313             "                         NOTE: Do not enable it if the input file does not\n"
1314             "                         contain the ASCII text dump.\n"
1315             "\n"
1316             "Output:\n"
1317             "  -l <typenum>           link-layer type number; default is 1 (Ethernet).  See\n"
1318             "                         http://www.tcpdump.org/linktypes.html for a list of\n"
1319             "                         numbers.  Use this option if your dump is a complete\n"
1320             "                         hex dump of an encapsulated packet and you wish to\n"
1321             "                         specify the exact type of encapsulation.\n"
1322             "                         Example: -l 7 for ARCNet packets.\n"
1323             "  -m <max-packet>        max packet length in output; default is %d\n"
1324             "\n"
1325             "Prepend dummy header:\n"
1326             "  -e <l3pid>             prepend dummy Ethernet II header with specified L3PID\n"
1327             "                         (in HEX).\n"
1328             "                         Example: -e 0x806 to specify an ARP packet.\n"
1329             "  -i <proto>             prepend dummy IP header with specified IP protocol\n"
1330             "                         (in DECIMAL).\n"
1331             "                         Automatically prepends Ethernet header as well.\n"
1332             "                         Example: -i 46\n"
1333             "  -u <srcp>,<destp>      prepend dummy UDP header with specified\n"
1334             "                         source and destination ports (in DECIMAL).\n"
1335             "                         Automatically prepends Ethernet & IP headers as well.\n"
1336             "                         Example: -u 1000,69 to make the packets look like\n"
1337             "                         TFTP/UDP packets.\n"
1338             "  -T <srcp>,<destp>      prepend dummy TCP header with specified\n"
1339             "                         source and destination ports (in DECIMAL).\n"
1340             "                         Automatically prepends Ethernet & IP headers as well.\n"
1341             "                         Example: -T 50,60\n"
1342             "  -s <srcp>,<dstp>,<tag> prepend dummy SCTP header with specified\n"
1343             "                         source/dest ports and verification tag (in DECIMAL).\n"
1344             "                         Automatically prepends Ethernet & IP headers as well.\n"
1345             "                         Example: -s 30,40,34\n"
1346             "  -S <srcp>,<dstp>,<ppi> prepend dummy SCTP header with specified\n"
1347             "                         source/dest ports and verification tag 0.\n"
1348             "                         Automatically prepends a dummy SCTP DATA\n"
1349             "                         chunk header with payload protocol identifier ppi.\n"
1350             "                         Example: -S 30,40,34\n"
1351             "\n"
1352             "Miscellaneous:\n"
1353             "  -h                     display this help and exit.\n"
1354             "  -d                     show detailed debug of parser states.\n"
1355             "  -q                     generate no output at all (automatically disables -d).\n"
1356             "  -n                     use PCAP-NG instead of PCAP as output format.\n"
1357             "",
1358             VERSION, MAX_PACKET);
1359
1360     exit(-1);
1361 }
1362
1363 /*----------------------------------------------------------------------
1364  * Parse CLI options
1365  */
1366 static void
1367 parse_options (int argc, char *argv[])
1368 {
1369     int c;
1370     char *p;
1371
1372 #ifdef _WIN32
1373     arg_list_utf_16to8(argc, argv);
1374     create_app_running_mutex();
1375 #endif /* _WIN32 */
1376
1377     /* Scan CLI parameters */
1378     while ((c = getopt(argc, argv, "Ddhqe:i:l:m:no:u:s:S:t:T:a")) != -1) {
1379         switch(c) {
1380         case '?': usage(); break;
1381         case 'h': usage(); break;
1382         case 'd': if (!quiet) debug++; break;
1383         case 'D': has_direction = TRUE; break;
1384         case 'q': quiet = TRUE; debug = FALSE; break;
1385         case 'l': pcap_link_type = (guint32)strtol(optarg, NULL, 0); break;
1386         case 'm': max_offset = (guint32)strtol(optarg, NULL, 0); break;
1387         case 'n': use_pcapng = TRUE; break;
1388         case 'o':
1389             if (optarg[0]!='h' && optarg[0] != 'o' && optarg[0] != 'd') {
1390                 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
1391                 usage();
1392             }
1393             switch(optarg[0]) {
1394             case 'o': offset_base = 8; break;
1395             case 'h': offset_base = 16; break;
1396             case 'd': offset_base = 10; break;
1397             }
1398             break;
1399         case 'e':
1400             hdr_ethernet = TRUE;
1401             if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
1402                 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
1403                 usage();
1404             }
1405             break;
1406
1407         case 'i':
1408             hdr_ip = TRUE;
1409             hdr_ip_proto = strtol(optarg, &p, 10);
1410             if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
1411                   hdr_ip_proto > 255) {
1412                 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
1413                 usage();
1414             }
1415             hdr_ethernet = TRUE;
1416             hdr_ethernet_proto = 0x800;
1417             break;
1418
1419         case 's':
1420             hdr_sctp = TRUE;
1421             hdr_data_chunk = FALSE;
1422             hdr_tcp = FALSE;
1423             hdr_udp = FALSE;
1424             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1425             if (p == optarg || (*p != ',' && *p != '\0')) {
1426                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1427                 usage();
1428             }
1429             if (*p == '\0') {
1430                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1431                 usage();
1432             }
1433             p++;
1434             optarg = p;
1435             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1436             if (p == optarg || (*p != ',' && *p != '\0')) {
1437                 fprintf(stderr, "Bad dest port for '-s'\n");
1438                 usage();
1439             }
1440             if (*p == '\0') {
1441                 fprintf(stderr, "No tag specified for '-%c'\n", c);
1442                 usage();
1443             }
1444             p++;
1445             optarg = p;
1446             hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
1447             if (p == optarg || *p != '\0') {
1448                 fprintf(stderr, "Bad tag for '-%c'\n", c);
1449                 usage();
1450             }
1451
1452             hdr_ip = TRUE;
1453             hdr_ip_proto = 132;
1454             hdr_ethernet = TRUE;
1455             hdr_ethernet_proto = 0x800;
1456             break;
1457         case 'S':
1458             hdr_sctp = TRUE;
1459             hdr_data_chunk = TRUE;
1460             hdr_tcp = FALSE;
1461             hdr_udp = FALSE;
1462             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
1463             if (p == optarg || (*p != ',' && *p != '\0')) {
1464                 fprintf(stderr, "Bad src port for '-%c'\n", c);
1465                 usage();
1466             }
1467             if (*p == '\0') {
1468                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
1469                 usage();
1470             }
1471             p++;
1472             optarg = p;
1473             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
1474             if (p == optarg || (*p != ',' && *p != '\0')) {
1475                 fprintf(stderr, "Bad dest port for '-s'\n");
1476                 usage();
1477             }
1478             if (*p == '\0') {
1479                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
1480                 usage();
1481             }
1482             p++;
1483             optarg = p;
1484             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
1485             if (p == optarg || *p != '\0') {
1486                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
1487                 usage();
1488             }
1489
1490             hdr_ip = TRUE;
1491             hdr_ip_proto = 132;
1492             hdr_ethernet = TRUE;
1493             hdr_ethernet_proto = 0x800;
1494             break;
1495
1496         case 't':
1497             ts_fmt = optarg;
1498             break;
1499
1500         case 'u':
1501             hdr_udp = TRUE;
1502             hdr_tcp = FALSE;
1503             hdr_sctp = FALSE;
1504             hdr_data_chunk = FALSE;
1505             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1506             if (p == optarg || (*p != ',' && *p != '\0')) {
1507                 fprintf(stderr, "Bad src port for '-u'\n");
1508                 usage();
1509             }
1510             if (*p == '\0') {
1511                 fprintf(stderr, "No dest port specified for '-u'\n");
1512                 usage();
1513             }
1514             p++;
1515             optarg = p;
1516             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1517             if (p == optarg || *p != '\0') {
1518                 fprintf(stderr, "Bad dest port for '-u'\n");
1519                 usage();
1520             }
1521             hdr_ip = TRUE;
1522             hdr_ip_proto = 17;
1523             hdr_ethernet = TRUE;
1524             hdr_ethernet_proto = 0x800;
1525             break;
1526
1527         case 'T':
1528             hdr_tcp = TRUE;
1529             hdr_udp = FALSE;
1530             hdr_sctp = FALSE;
1531             hdr_data_chunk = FALSE;
1532             hdr_src_port = (guint32)strtol(optarg, &p, 10);
1533             if (p == optarg || (*p != ',' && *p != '\0')) {
1534                 fprintf(stderr, "Bad src port for '-T'\n");
1535                 usage();
1536             }
1537             if (*p == '\0') {
1538                 fprintf(stderr, "No dest port specified for '-u'\n");
1539                 usage();
1540             }
1541             p++;
1542             optarg = p;
1543             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
1544             if (p == optarg || *p != '\0') {
1545                 fprintf(stderr, "Bad dest port for '-T'\n");
1546                 usage();
1547             }
1548             hdr_ip = TRUE;
1549             hdr_ip_proto = 6;
1550             hdr_ethernet = TRUE;
1551             hdr_ethernet_proto = 0x800;
1552             break;
1553
1554         case 'a':
1555             identify_ascii = TRUE;
1556             break;
1557
1558         default:
1559             usage();
1560         }
1561     }
1562
1563     if (optind >= argc || argc-optind < 2) {
1564         fprintf(stderr, "Must specify input and output filename\n");
1565         usage();
1566     }
1567
1568     if (strcmp(argv[optind], "-")) {
1569         input_filename = g_strdup(argv[optind]);
1570         input_file = ws_fopen(input_filename, "rb");
1571         if (!input_file) {
1572             fprintf(stderr, "Cannot open file [%s] for reading: %s\n",
1573                     input_filename, g_strerror(errno));
1574             exit(-1);
1575         }
1576     } else {
1577         input_filename = "Standard input";
1578         input_file = stdin;
1579     }
1580
1581     if (strcmp(argv[optind+1], "-")) {
1582         output_filename = g_strdup(argv[optind+1]);
1583         output_file = ws_fopen(output_filename, "wb");
1584         if (!output_file) {
1585             fprintf(stderr, "Cannot open file [%s] for writing: %s\n",
1586                     output_filename, g_strerror(errno));
1587             exit(-1);
1588         }
1589     } else {
1590         output_filename = "Standard output";
1591         output_file = stdout;
1592     }
1593
1594     /* Some validation */
1595     if (pcap_link_type != 1 && hdr_ethernet) {
1596         fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
1597         exit(-1);
1598     }
1599
1600     /* Set up our variables */
1601     if (!input_file) {
1602         input_file = stdin;
1603         input_filename = "Standard input";
1604     }
1605     if (!output_file) {
1606         output_file = stdout;
1607         output_filename = "Standard output";
1608     }
1609
1610     ts_sec = time(0);               /* initialize to current time */
1611     timecode_default = *localtime(&ts_sec);
1612     timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1613
1614     /* Display summary of our state */
1615     if (!quiet) {
1616         fprintf(stderr, "Input from: %s\n", input_filename);
1617         fprintf(stderr, "Output to: %s\n", output_filename);
1618         fprintf(stderr, "Output format: %s\n", use_pcapng ? "PCAP-NG" : "PCAP");
1619
1620         if (hdr_ethernet) fprintf(stderr, "Generate dummy Ethernet header: Protocol: 0x%0X\n",
1621                                   hdr_ethernet_proto);
1622         if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
1623                             hdr_ip_proto);
1624         if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %u. Dest port: %u\n",
1625                              hdr_src_port, hdr_dest_port);
1626         if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %u. Dest port: %u\n",
1627                              hdr_src_port, hdr_dest_port);
1628         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
1629                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
1630         if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
1631                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
1632     }
1633 }
1634
1635 int
1636 main(int argc, char *argv[])
1637 {
1638     parse_options(argc, argv);
1639
1640     assert(input_file != NULL);
1641     assert(output_file != NULL);
1642
1643     write_file_header();
1644
1645     header_length = 0;
1646     if (hdr_ethernet) {
1647         header_length += (int)sizeof(HDR_ETHERNET);
1648     }
1649     if (hdr_ip) {
1650         ip_offset = header_length;
1651         header_length += (int)sizeof(HDR_IP);
1652     }
1653     if (hdr_sctp) {
1654         header_length += (int)sizeof(HDR_SCTP);
1655     }
1656     if (hdr_data_chunk) {
1657         header_length += (int)sizeof(HDR_DATA_CHUNK);
1658     }
1659     if (hdr_tcp) {
1660         header_length += (int)sizeof(HDR_TCP);
1661     }
1662     if (hdr_udp) {
1663         header_length += (int)sizeof(HDR_UDP);
1664     }
1665     curr_offset = header_length;
1666
1667     yyin = input_file;
1668     yylex();
1669
1670     write_current_packet(FALSE);
1671     write_file_trailer();
1672     fclose(input_file);
1673     fclose(output_file);
1674     if (debug)
1675         fprintf(stderr, "\n-------------------------\n");
1676     if (!quiet) {
1677         fprintf(stderr, "Read %u potential packet%s, wrote %u packet%s (%" G_GINT64_MODIFIER "u byte%s).\n",
1678                 num_packets_read, (num_packets_read == 1) ? "" : "s",
1679                 num_packets_written, (num_packets_written == 1) ? "" : "s",
1680                 bytes_written, (bytes_written == 1) ? "" : "s");
1681     }
1682     return 0;
1683 }
1684
1685 /*
1686  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1687  *
1688  * Local variables:
1689  * c-basic-offset: 4
1690  * tab-width: 4
1691  * indent-tabs-mode: nil
1692  * End:
1693  *
1694  * vi: set shiftwidth=4 tabstop=4 expandtab:
1695  * :indentSize=4:tabSize=4:noTabs=true:
1696  */
1697