Ethereal-dev: [Ethereal-dev] tcp added to text2pcap
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Matthijs Melchior <mmelchior@xxxxxxxxx>
Date: Sat, 26 Apr 2003 18:01:35 +0200
Hi, here is a patch to text2pcap and its documentation. It adds the following features: - option -m to set maximum packet length - option -T to generate TCP headers - UDP headers now have a correct checksum - default capture timestamp is current time, usec field counts packets - UDP and TCP headers are mutual exclusive - changed etherenet addresses, now sends from 1 -> 2 .... ? I suspect the IP header checksum needs to avoid sending checksum 'none', just as the udp and tcp checksums do. Devising a test case for this is too difficult, so I have not changed that code... [if so, then 'in_checksum()' can be changed to do this] I would like this to be included in the ethereal release, although an incompatible change would be appreciated: use -t for tcp headers and -T for timestamp format. Thanks, -- Regards, ---------------------------------------------------------------- -o) Matthijs Melchior Maarssen /\\ mmelchior@xxxxxxxxx Netherlands _\_v ---------------------------------------------------------------- ----
--- text2pcap.c-ORG Sat Mar 1 06:09:58 2003 +++ text2pcap.c Sat Apr 26 17:44:33 2003 @@ -65,8 +65,8 @@ * * 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 @@ -129,8 +129,11 @@ /* 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; @@ -154,6 +157,9 @@ #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 @@ -217,8 +223,8 @@ } 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 { @@ -237,6 +243,14 @@ 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; @@ -247,6 +261,20 @@ 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; guint32 tag; @@ -326,6 +354,8 @@ num = parse_num(str, FALSE); packet_buf[curr_offset] = num; curr_offset ++; + if (curr_offset >= max_offset) /* packet full */ + start_new_packet(); } /*---------------------------------------------------------------------- @@ -355,7 +385,7 @@ /* 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) @@ -485,10 +515,11 @@ 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) { @@ -498,7 +529,8 @@ 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); @@ -512,6 +544,7 @@ /* 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); @@ -531,15 +564,48 @@ 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 = 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; @@ -583,9 +649,13 @@ } 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; } @@ -741,7 +811,6 @@ /* 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 */ @@ -819,8 +888,9 @@ 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 @@ -920,8 +990,8 @@ 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,tag] [-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" @@ -941,10 +1011,15 @@ " 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" @@ -962,7 +1037,7 @@ " (.) but no pattern is required; the remaining number\n" " is assumed to be fractions of a second.\n" "", - progname); + progname, MAX_PACKET); exit(-1); } @@ -977,13 +1052,14 @@ 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); @@ -1086,7 +1162,8 @@ 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]); @@ -1097,7 +1174,7 @@ } 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]); @@ -1108,6 +1185,31 @@ 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]); } @@ -1146,7 +1248,7 @@ /* 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); } @@ -1160,6 +1262,8 @@ 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); @@ -1170,7 +1274,9 @@ 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", --- doc/text2pcap.pod-ORG Mon Mar 10 05:30:00 2003 +++ doc/text2pcap.pod Sat Apr 26 16:43:03 2003 @@ -13,7 +13,9 @@ S<[ B<-l> typenum ]> S<[ B<-e> l3pid ]> S<[ B<-i> proto ]> +S<[ B<-m> max-packet ]> S<[ B<-u> srcport,destport ]> +S<[ B<-T> srcport,destport ]> S<[ B<-s> srcport,destport,tag ]> S<[ B<-S> srcport,destport,ppi ]> S<[ B<-t> timefmt ]> @@ -26,7 +28,7 @@ the data described into a B<libpcap>-style capture file. B<text2pcap> can read hexdumps with multiple packets in them, and build a capture file of multiple packets. B<text2pcap> is also capable of generating -dummy Ethernet, IP and UDP headers, in order to build fully +dummy Ethernet, IP and UDP or TCP headers, in order to build fully processable packet dumps from hexdumps of application-level data only. @@ -75,7 +77,7 @@ B<Text2pcap> also allows the user to read in dumps of application-level data, by inserting dummy L2, L3 and L4 headers before each packet. The user can elect to insert Ethernet headers, -Ethernet and IP, or Ethernet, IP and UDP headers before each +Ethernet and IP, or Ethernet, IP and UDP/TCP headers before each packet. This allows Ethereal or any other full-packet decoder to handle these dumps. @@ -131,6 +133,15 @@ Ethernet header as well. Example: I<-i 46> to specify an RSVP packet (IP protocol 46). +=item -m max-packet + +Set the maximum packet length, default is 64000. +Usefull for testing various packet boundaries when only an application +level datastream is available. Example: + od -Ax -tx1 stream | text2pcap -m1460 -T1234,1234 - stream.pcap + will convert from plain datastream format to a sequence of ethernet +TCP packets. + =item -u srcport,destport Include dummy UDP headers before each packet. Specify the source and @@ -139,6 +150,15 @@ IP or Ethernet headers. Note that this automatically includes appropriate Ethernet and IP headers with each packet. Example: I<-u 1000,69> to make the packets look like TFTP/UDP packets. + +=item -T srcport,destport + +Include dummy TCP headers before each packet. Specify the source and +destination TCP ports for the packet in decimal. Use this option if +your dump is the TCP payload of a packet but does not include any TCP, +IP or Ethernet headers. Note that this automatically includes +appropriate Ethernet and IP headers with each packet. + Sequence numbers will start a 0. =item -s srcport,destport,tag
- Follow-Ups:
- Re: [Ethereal-dev] tcp added to text2pcap
- From: Guy Harris
- Re: [Ethereal-dev] tcp added to text2pcap
- Prev by Date: [Ethereal-dev] General problem for reassembling WTP packets
- Next by Date: Re: [Ethereal-dev] tcp added to text2pcap
- Previous by thread: Re: [Ethereal-dev] General problem for reassembling WTP packets
- Next by thread: Re: [Ethereal-dev] tcp added to text2pcap
- Index(es):