*
* (c) Copyright 2001 Ashok Narayanan <ashokn@cisco.com>
*
- * $Id: text2pcap.c,v 1.25 2003/02/27 02:30:59 guy Exp $
+ * $Id$
*
* 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
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;
} 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 {
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 {
guint16 source_port;
guint16 dest_port;
static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
+typedef struct {
+ 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;
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();
}
/*----------------------------------------------------------------------
/* Add left-over byte, if any */
if( count > 0 )
- sum += * (guint8 *) addr;
+ sum += g_ntohs(* (guint8 *) addr);
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
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;
}
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;
}
/* 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",