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