*
* (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
*
- * $Id: text2pcap.c,v 1.23 2002/10/10 01:45:25 jmayer Exp $
+ * $Id: text2pcap.c,v 1.30 2004/07/04 17:36:53 tuexen Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
*
* The output is a libpcap packet containing Ethernet frames by
* default. This program takes options which allow the user to add
- * dummy Ethernet, IP and UDP headers to the packets in order to allow
- * dumps of L3 or higher protocols to be decoded.
+ * dummy Ethernet, IP and UDP or TCP headers to the packets in order
+ * to allow dumps of L3 or higher protocols to be decoded.
*
* Considerable flexibility is built into this code to read hexdumps
* of slightly different formats. For example, any text prefixing the
/* Dummy IP header */
static int hdr_ip = FALSE;
-static unsigned long hdr_ip_proto = 0;
+static long hdr_ip_proto = 0;
/* Dummy UDP header */
static int hdr_udp = FALSE;
-static unsigned long hdr_udp_dest = 0;
-static unsigned long hdr_udp_src = 0;
+static unsigned long hdr_dest_port = 0;
+static unsigned long hdr_src_port = 0;
+
+/* Dummy TCP header */
+static int hdr_tcp = FALSE;
/* Dummy SCTP header */
static int hdr_sctp = FALSE;
#define MAX_PACKET 64000
static unsigned char packet_buf[MAX_PACKET];
static unsigned long curr_offset = 0;
+static unsigned long max_offset = MAX_PACKET;
+static unsigned long packet_start = 0;
+static void start_new_packet (void);
/* This buffer contains strings present before the packet offset 0 */
#define PACKET_PREAMBLE_MAX_LEN 2048
static unsigned long num_packets_written = 0;
/* Time code of packet, derived from packet_preamble */
-static unsigned long ts_sec = 0;
-static unsigned long ts_usec = 0;
+static gint32 ts_sec = 0;
+static guint32 ts_usec = 0;
static char *ts_fmt = NULL;
/* Input file */
START_OF_LINE, /* Starting from beginning of line */
READ_OFFSET, /* Just read the offset */
READ_BYTE, /* Just read a byte */
- READ_TEXT, /* Just read text - ignore until EOL */
+ READ_TEXT /* Just read text - ignore until EOL */
} parser_state_t;
static parser_state_t state = INIT;
/* ----- Skeleton Packet Headers --------------------------------------------------*/
typedef struct {
- unsigned char src_addr[6];
- unsigned char dest_addr[6];
- unsigned short l3pid;
+ guint8 dest_addr[6];
+ guint8 src_addr[6];
+ guint16 l3pid;
} hdr_ethernet_t;
static hdr_ethernet_t HDR_ETHERNET = {
- {0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
{0x02, 0x02, 0x02, 0x02, 0x02, 0x02},
+ {0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
0};
typedef struct {
- unsigned char ver_hdrlen;
- unsigned char dscp;
- unsigned short packet_length;
- unsigned short identification;
- unsigned char flags;
- unsigned char fragment;
- unsigned char ttl;
- unsigned char protocol;
- unsigned short hdr_checksum;
- unsigned long src_addr;
- unsigned long dest_addr;
+ guint8 ver_hdrlen;
+ guint8 dscp;
+ guint16 packet_length;
+ guint16 identification;
+ guint8 flags;
+ guint8 fragment;
+ guint8 ttl;
+ guint8 protocol;
+ guint16 hdr_checksum;
+ guint32 src_addr;
+ guint32 dest_addr;
} hdr_ip_t;
static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0, 0x01010101, 0x02020202};
+static struct { /* pseudo header for checksum calculation */
+ guint32 src_addr;
+ guint32 dest_addr;
+ guint8 zero;
+ guint8 protocol;
+ guint16 length;
+} pseudoh;
+
typedef struct {
- unsigned short source_port;
- unsigned short dest_port;
- unsigned short length;
- unsigned short checksum;
+ guint16 source_port;
+ guint16 dest_port;
+ guint16 length;
+ guint16 checksum;
} hdr_udp_t;
static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
typedef struct {
- unsigned short src_port;
- unsigned short dest_port;
- unsigned long tag;
- unsigned long checksum;
+ guint16 source_port;
+ guint16 dest_port;
+ guint32 seq_num;
+ guint32 ack_num;
+ guint8 hdr_length;
+ guint8 flags;
+ guint16 window;
+ guint16 checksum;
+ guint16 urg;
+} hdr_tcp_t;
+
+static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
+
+typedef struct {
+ guint16 src_port;
+ guint16 dest_port;
+ guint32 tag;
+ guint32 checksum;
} hdr_sctp_t;
static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
typedef struct {
- unsigned char type;
- unsigned char bits;
- unsigned short length;
- unsigned long tsn;
- unsigned short sid;
- unsigned short ssn;
- unsigned long ppid;
+ guint8 type;
+ guint8 bits;
+ guint16 length;
+ guint32 tsn;
+ guint16 sid;
+ guint16 ssn;
+ guint32 ppid;
} hdr_data_chunk_t;
static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
/* "libpcap" file header (minus magic number). */
struct pcap_hdr {
- unsigned long magic; /* magic */
- unsigned short version_major; /* major version number */
- unsigned short version_minor; /* minor version number */
- unsigned long thiszone; /* GMT to local correction */
- unsigned long sigfigs; /* accuracy of timestamps */
- unsigned long snaplen; /* max length of captured packets, in octets */
- unsigned long network; /* data link type */
+ guint32 magic; /* magic */
+ guint16 version_major; /* major version number */
+ guint16 version_minor; /* minor version number */
+ guint32 thiszone; /* GMT to local correction */
+ guint32 sigfigs; /* accuracy of timestamps */
+ guint32 snaplen; /* max length of captured packets, in octets */
+ guint32 network; /* data link type */
};
/* "libpcap" record header. */
struct pcaprec_hdr {
- unsigned long ts_sec; /* timestamp seconds */
- unsigned long ts_usec; /* timestamp microseconds */
- unsigned long incl_len; /* number of octets of packet saved in file */
- unsigned long orig_len; /* actual length of packet */
+ gint32 ts_sec; /* timestamp seconds */
+ guint32 ts_usec; /* timestamp microseconds */
+ guint32 incl_len; /* number of octets of packet saved in file */
+ guint32 orig_len; /* actual length of packet */
};
/* Link-layer type; see net/bpf.h for details */
unsigned long num;
num = parse_num(str, FALSE);
- packet_buf[curr_offset] = num;
+ packet_buf[curr_offset] = (unsigned char) num;
curr_offset ++;
+ if (curr_offset >= max_offset) /* packet full */
+ start_new_packet();
}
/*----------------------------------------------------------------------
/*----------------------------------------------------------------------
* Compute one's complement checksum (from RFC1071)
*/
-static unsigned short
+static guint16
in_checksum (void *buf, unsigned long count)
{
unsigned long sum = 0;
- unsigned short *addr = buf;
+ guint16 *addr = buf;
while( count > 1 ) {
/* This is the inner loop */
- sum += g_ntohs(* (unsigned short *) addr);
+ sum += g_ntohs(* (guint16 *) addr);
addr++;
count -= 2;
}
/* Add left-over byte, if any */
if( count > 0 )
- sum += * (unsigned char *) addr;
+ sum += g_ntohs(* (guint8 *) addr);
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
*/
#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
-static unsigned long crc_c[256] =
+static guint32 crc_c[256] =
{
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
};
-static unsigned long
-crc32c(const unsigned char* buf, unsigned int len, unsigned long crc32_init)
+static guint32
+crc32c(const guint8* buf, unsigned int len, guint32 crc32_init)
{
unsigned int i;
- unsigned long crc32;
+ guint32 crc32;
crc32 = crc32_init;
for (i = 0; i < len; i++)
return ( crc32 );
}
-static unsigned long
-finalize_crc32c(unsigned long crc32)
+static guint32
+finalize_crc32c(guint32 crc32)
{
- unsigned long result;
- unsigned char byte0,byte1,byte2,byte3;
+ guint32 result;
+ guint8 byte0,byte1,byte2,byte3;
result = ~crc32;
byte0 = result & 0xff;
write_current_packet (void)
{
int length = 0;
- int udp_length = 0;
+ int proto_length = 0;
int ip_length = 0;
int eth_trailer_length = 0;
int i, padding_length;
+ guint32 u;
struct pcaprec_hdr ph;
if (curr_offset > 0) {
length = curr_offset;
if (hdr_data_chunk) { length += sizeof(HDR_DATA_CHUNK) + number_of_padding_bytes(curr_offset); }
if (hdr_sctp) { length += sizeof(HDR_SCTP); }
- if (hdr_udp) { length += sizeof(HDR_UDP); udp_length = length; }
+ if (hdr_udp) { length += sizeof(HDR_UDP); proto_length = length; }
+ if (hdr_tcp) { length += sizeof(HDR_TCP); proto_length = length; }
if (hdr_ip) { length += sizeof(HDR_IP); ip_length = length; }
if (hdr_ethernet) {
length += sizeof(HDR_ETHERNET);
/* Write PCap header */
ph.ts_sec = ts_sec;
ph.ts_usec = ts_usec;
+ if (ts_fmt == NULL) { ts_usec++; } /* fake packet counter */
ph.incl_len = length;
ph.orig_len = length;
fwrite(&ph, sizeof(ph), 1, output_file);
/* Write IP header */
if (hdr_ip) {
HDR_IP.packet_length = g_htons(ip_length);
- HDR_IP.protocol = hdr_ip_proto;
+ HDR_IP.protocol = (guint8) hdr_ip_proto;
HDR_IP.hdr_checksum = 0;
HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
fwrite(&HDR_IP, sizeof(HDR_IP), 1, output_file);
}
+ /* initialize pseudo header for checksum calculation */
+ pseudoh.src_addr = HDR_IP.src_addr;
+ pseudoh.dest_addr = HDR_IP.dest_addr;
+ pseudoh.zero = 0;
+ pseudoh.protocol = (guint8) hdr_ip_proto;
+ pseudoh.length = g_htons(proto_length);
+
/* Write UDP header */
if (hdr_udp) {
- HDR_UDP.source_port = g_htons(hdr_udp_src);
- HDR_UDP.dest_port = g_htons(hdr_udp_dest);
- HDR_UDP.length = g_htons(udp_length);
+ HDR_UDP.source_port = g_htons(hdr_src_port);
+ HDR_UDP.dest_port = g_htons(hdr_dest_port);
+ HDR_UDP.length = g_htons(proto_length);
+
+ HDR_UDP.checksum = 0;
+ u = g_ntohs(in_checksum(&pseudoh, sizeof(pseudoh))) +
+ g_ntohs(in_checksum(&HDR_UDP, sizeof(HDR_UDP))) +
+ g_ntohs(in_checksum(packet_buf, curr_offset));
+ HDR_UDP.checksum = g_htons((u & 0xffff) + (u>>16));
+ if (HDR_UDP.checksum == 0) /* differenciate between 'none' and 0 */
+ HDR_UDP.checksum = g_htons(1);
fwrite(&HDR_UDP, sizeof(HDR_UDP), 1, output_file);
}
+ /* Write TCP header */
+ if (hdr_tcp) {
+ HDR_TCP.source_port = g_htons(hdr_src_port);
+ HDR_TCP.dest_port = g_htons(hdr_dest_port);
+ /* HDR_TCP.seq_num already correct */
+ HDR_TCP.window = g_htons(0x2000);
+
+ HDR_TCP.checksum = 0;
+ u = g_ntohs(in_checksum(&pseudoh, sizeof(pseudoh))) +
+ g_ntohs(in_checksum(&HDR_TCP, sizeof(HDR_TCP))) +
+ g_ntohs(in_checksum(packet_buf, curr_offset));
+ HDR_TCP.checksum = g_htons((u & 0xffff) + (u>>16));
+ if (HDR_TCP.checksum == 0) /* differenciate between 'none' and 0 */
+ HDR_TCP.checksum = g_htons(1);
+
+ fwrite(&HDR_TCP, sizeof(HDR_TCP), 1, output_file);
+ }
+
/* Compute DATA chunk header and append padding */
if (hdr_data_chunk) {
HDR_DATA_CHUNK.type = hdr_data_chunk_type;
HDR_SCTP.dest_port = g_htons(hdr_sctp_dest);
HDR_SCTP.tag = g_htonl(hdr_sctp_tag);
HDR_SCTP.checksum = g_htonl(0);
- HDR_SCTP.checksum = crc32c((unsigned char *)&HDR_SCTP, sizeof(HDR_SCTP), ~0L);
+ HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0L);
if (hdr_data_chunk)
- HDR_SCTP.checksum = crc32c((unsigned char *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
+ HDR_SCTP.checksum = crc32c((guint8 *)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
HDR_SCTP.checksum = g_htonl(finalize_crc32c(crc32c(packet_buf, curr_offset, HDR_SCTP.checksum)));
fwrite(&HDR_SCTP, sizeof(HDR_SCTP), 1, output_file);
}
if (!quiet)
- fprintf(stderr, "Wrote packet of %lu bytes\n", curr_offset);
+ fprintf(stderr, "Wrote packet of %lu bytes at %u\n", curr_offset, g_ntohl(HDR_TCP.seq_num));
num_packets_written ++;
}
+
+ HDR_TCP.seq_num = g_htonl(g_ntohl(HDR_TCP.seq_num) + curr_offset);
+
+ packet_start += curr_offset;
curr_offset = 0;
}
subsecs = strptime( packet_preamble, ts_fmt, &timecode );
if (subsecs != NULL) {
/* Get the long time from the tm structure */
- ts_sec = (unsigned long)mktime( &timecode );
+ ts_sec = (gint32)mktime( &timecode );
} else
ts_sec = -1; /* we failed to parse it */
/* This will ensure incorrectly parsed dates get set to zero */
- if ( -1L == (long)ts_sec )
+ if ( -1 == ts_sec )
{
ts_sec = 0;
ts_usec = 0;
/* Write out the current packet, if required */
write_current_packet();
- curr_offset = 0;
num_packets_read ++;
/* Ensure we parse the packet preamble as it may contain the time */
if (num==0) {
/* New packet starts here */
start_new_packet();
+ packet_start = 0;
state = READ_OFFSET;
- } else if (num != curr_offset) {
+ } else if ((num - packet_start) != curr_offset) {
/*
* The offset we read isn't the one we expected.
* This may only mean that we mistakenly interpreted
fprintf(stderr,
"\n"
"Usage: %s [-h] [-d] [-q] [-o h|o] [-l typenum] [-e l3pid] [-i proto] \n"
- " [-u srcp,destp] [-s srcp,destp,tag] [-S srcp,destp,tag] [-t timefmt]\n"
- " <input-filename> <output-filename>\n"
+ " [-m max-packet] [-u srcp,destp] [-T srcp,destp] [-s srcp,destp,tag]\n"
+ " [-S srcp,destp,ppi] [-t timefmt] <input-filename> <output-filename>\n"
"\n"
"where <input-filename> specifies input filename (use - for standard input)\n"
" <output-filename> specifies output filename (use - for standard output)\n"
" DECIMAL). \n"
" Automatically prepends Ethernet header as well.\n"
" Example: -i 46\n"
+ " -m max-packet : Max packet length in output, default is %d\n"
" -u srcp,destp : Prepend dummy UDP header with specified dest and source ports\n"
" (in DECIMAL).\n"
" Automatically prepends Ethernet and IP headers as well\n"
" Example: -u 30,40\n"
+ " -T srcp,destp : Prepend dummy TCP header with specified dest and source ports\n"
+ " (in DECIMAL).\n"
+ " Automatically prepends Ethernet and IP headers as well\n"
+ " Example: -T 50,60\n"
" -s srcp,dstp,tag: Prepend dummy SCTP header with specified dest/source ports\n"
" and verification tag (in DECIMAL).\n"
" Automatically prepends Ethernet and IP headers as well\n"
" (.) but no pattern is required; the remaining number\n"
" is assumed to be fractions of a second.\n"
"",
- progname);
+ progname, MAX_PACKET);
exit(-1);
}
char *p;
/* Scan CLI parameters */
- while ((c = getopt(argc, argv, "dhqe:i:l:o:u:s:S:t:")) != -1) {
+ while ((c = getopt(argc, argv, "dhqe:i:l:m:o:u:s:S:t:T:")) != -1) {
switch(c) {
case '?': help(argv[0]); break;
case 'h': help(argv[0]); break;
case 'd': if (!quiet) debug++; break;
case 'q': quiet = TRUE; debug = FALSE; break;
- case 'l': pcap_link_type = atoi(optarg); break;
+ case 'l': pcap_link_type = strtol(optarg, NULL, 0); break;
+ case 'm': max_offset = strtol(optarg, NULL, 0); break;
case 'o':
if (optarg[0]!='h' && optarg[0] != 'o') {
fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
case 'i':
hdr_ip = TRUE;
- if (sscanf(optarg, "%ld", &hdr_ip_proto) < 1) {
+ hdr_ip_proto = strtol(optarg, &p, 10);
+ if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
+ hdr_ip_proto > 255) {
fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
help(argv[0]);
}
case 'u':
hdr_udp = TRUE;
- hdr_udp_src = strtol(optarg, &p, 10);
+ hdr_tcp = FALSE;
+ hdr_src_port = strtol(optarg, &p, 10);
if (p == optarg || (*p != ',' && *p != '\0')) {
fprintf(stderr, "Bad src port for '-u'\n");
help(argv[0]);
}
p++;
optarg = p;
- hdr_udp_dest = strtol(optarg, &p, 10);
+ hdr_dest_port = strtol(optarg, &p, 10);
if (p == optarg || *p != '\0') {
fprintf(stderr, "Bad dest port for '-u'\n");
help(argv[0]);
hdr_ethernet_proto = 0x800;
break;
+ case 'T':
+ hdr_tcp = TRUE;
+ hdr_udp = FALSE;
+ hdr_src_port = strtol(optarg, &p, 10);
+ if (p == optarg || (*p != ',' && *p != '\0')) {
+ fprintf(stderr, "Bad src port for '-T'\n");
+ help(argv[0]);
+ }
+ if (*p == '\0') {
+ fprintf(stderr, "No dest port specified for '-u'\n");
+ help(argv[0]);
+ }
+ p++;
+ optarg = p;
+ hdr_dest_port = strtol(optarg, &p, 10);
+ if (p == optarg || *p != '\0') {
+ fprintf(stderr, "Bad dest port for '-T'\n");
+ help(argv[0]);
+ }
+ hdr_ip = TRUE;
+ hdr_ip_proto = 6;
+ hdr_ethernet = TRUE;
+ hdr_ethernet_proto = 0x800;
+ break;
+
default:
help(argv[0]);
}
/* Some validation */
if (pcap_link_type != 1 && hdr_ethernet) {
- fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S) cannot be specified with link type override (-l)\n");
+ fprintf(stderr, "Dummy headers (-e, -i, -u, -s, -S -T) cannot be specified with link type override (-l)\n");
exit(-1);
}
output_filename = "Standard output";
}
+ ts_sec = time(0); /* initialize to current time */
+
/* Display summary of our state */
if (!quiet) {
fprintf(stderr, "Input from: %s\n", input_filename);
if (hdr_ip) fprintf(stderr, "Generate dummy IP header: Protocol: %ld\n",
hdr_ip_proto);
if (hdr_udp) fprintf(stderr, "Generate dummy UDP header: Source port: %ld. Dest port: %ld\n",
- hdr_udp_src, hdr_udp_dest);
+ hdr_src_port, hdr_dest_port);
+ if (hdr_tcp) fprintf(stderr, "Generate dummy TCP header: Source port: %ld. Dest port: %ld\n",
+ hdr_src_port, hdr_dest_port);
if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %ld. Dest port: %ld. Tag: %ld\n",
hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %lu. SID: %d. SSN: %d. PPID: %lu\n",