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