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