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