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