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