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