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