The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / text2pcap.c @ master

History | View | Annotate | Download (63.9 KB)

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