X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=text2pcap.c;h=daf1dacece82c6683efeb3a3240d7cc464cc20c1;hb=86d089a63822cd5a1cc4ec7775b94f4aecfb58ba;hp=a7349b9ce510b0b3f9bfbf1b0ce111fbe0e9dc0b;hpb=a7146246673d2016f4e0ad2caf6e6b1e4d5acc0d;p=obnox%2Fwireshark%2Fwip.git diff --git a/text2pcap.c b/text2pcap.c index a7349b9ce5..daf1dacece 100644 --- a/text2pcap.c +++ b/text2pcap.c @@ -51,7 +51,7 @@ * exactly 32 bytes must have been read into this packet before this. If the offset * is wrong, the packet is immediately terminated * - * A packet start is signalled by a zero offset. + * A packet start is signaled by a zero offset. * * Lines starting with #TEXT2PCAP are directives. These allow the user * to embed instructions into the capture file which allows text2pcap @@ -81,19 +81,39 @@ # include "config.h" #endif -#include -#include -#include -#include - /* * Just make sure we include the prototype for strptime as well * (needed for glibc 2.2) but make sure we do this only if not * yet defined. */ -#ifndef +#ifndef __USE_XOPEN # define __USE_XOPEN #endif +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE +#endif + +/* + * Defining _XOPEN_SOURCE is needed on some platforms, e.g. platforms + * using glibc, to expand the set of things system header files define. + * + * Unfortunately, on other platforms, such as some versions of Solaris + * (including Solaris 10), it *reduces* that set as well, causing + * strptime() not to be declared, presumably because the version of the + * X/Open spec that _XOPEN_SOURCE implies doesn't include strptime() and + * blah blah blah namespace pollution blah blah blah. + * + * So we define __EXTENSIONS__ so that "strptime()" is declared. + */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ +#endif + +#include +#include +#include +#include +#include #include #include @@ -105,15 +125,22 @@ #include #include -#ifdef NEED_GETOPT_H -# include "getopt.h" +#ifdef HAVE_GETOPT_H +#include +#else +#include "wsutil/wsgetopt.h" #endif #ifdef NEED_STRPTIME_H -# include "strptime.h" +# include "wsutil/strptime.h" #endif #include "text2pcap.h" +#include "svnversion.h" + +#ifdef _WIN32 +#include +#endif /* _WIN32 */ /*--- Options --------------------------------------------------------------------*/ @@ -174,9 +201,10 @@ static unsigned long num_packets_read = 0; static unsigned long num_packets_written = 0; /* Time code of packet, derived from packet_preamble */ -static gint32 ts_sec = 0; +static time_t ts_sec = 0; static guint32 ts_usec = 0; static char *ts_fmt = NULL; +static struct tm timecode_default; /* Input file */ static const char *input_filename; @@ -226,8 +254,8 @@ typedef struct { } hdr_ethernet_t; static hdr_ethernet_t HDR_ETHERNET = { - {0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, - {0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + {0x0a, 0x02, 0x02, 0x02, 0x02, 0x02}, + {0x0a, 0x01, 0x01, 0x01, 0x01, 0x01}, 0}; typedef struct { @@ -244,7 +272,7 @@ typedef struct { guint32 dest_addr; } hdr_ip_t; -static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0, 0x01010101, 0x02020202}; +static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 0, 0, 0x0101010a, 0x0202020a}; static struct { /* pseudo header for checksum calculation */ guint32 src_addr; @@ -318,7 +346,7 @@ struct pcap_hdr { /* "libpcap" record header. */ struct pcaprec_hdr { - gint32 ts_sec; /* timestamp seconds */ + guint32 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 */ @@ -394,7 +422,8 @@ in_checksum (void *buf, unsigned long count) while (sum>>16) sum = (sum & 0xffff) + (sum >> 16); - return g_htons(~sum); + sum = ~sum; + return g_htons(sum); } /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt. @@ -544,8 +573,8 @@ write_current_packet (void) } } - /* Write PCap header */ - ph.ts_sec = ts_sec; + /* Write PCAP header */ + ph.ts_sec = (guint32)ts_sec; ph.ts_usec = ts_usec; if (ts_fmt == NULL) { ts_usec++; } /* fake packet counter */ ph.incl_len = length; @@ -576,16 +605,22 @@ write_current_packet (void) /* Write UDP header */ if (hdr_udp) { + guint16 x16; 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); + /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */ 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 */ + x16 = in_checksum(&pseudoh, sizeof(pseudoh)); + u = g_ntohs(x16); + x16 = in_checksum(&HDR_UDP, sizeof(HDR_UDP)); + u += g_ntohs(x16); + x16 = in_checksum(packet_buf, curr_offset); + u += g_ntohs(x16); + x16 = (u & 0xffff) + (u>>16); + HDR_UDP.checksum = g_htons(x16); + if (HDR_UDP.checksum == 0) /* differentiate between 'none' and 0 */ HDR_UDP.checksum = g_htons(1); fwrite(&HDR_UDP, sizeof(HDR_UDP), 1, output_file); @@ -593,18 +628,24 @@ write_current_packet (void) /* Write TCP header */ if (hdr_tcp) { + guint16 x16; 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); + /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */ 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); + x16 = in_checksum(&pseudoh, sizeof(pseudoh)); + u = g_ntohs(x16); + x16 = in_checksum(&HDR_TCP, sizeof(HDR_TCP)); + u += g_ntohs(x16); + x16 = in_checksum(packet_buf, curr_offset); + u += g_ntohs(x16); + x16 = (u & 0xffff) + (u>>16); + HDR_TCP.checksum = g_htons(x16); + if (HDR_TCP.checksum == 0) /* differentiate between 'none' and 0 */ + HDR_TCP.checksum = g_htons(1); fwrite(&HDR_TCP, sizeof(HDR_TCP), 1, output_file); } @@ -626,6 +667,7 @@ write_current_packet (void) /* Write SCTP header */ if (hdr_sctp) { + guint32 x32; HDR_SCTP.src_port = g_htons(hdr_sctp_src); HDR_SCTP.dest_port = g_htons(hdr_sctp_dest); HDR_SCTP.tag = g_htonl(hdr_sctp_tag); @@ -633,7 +675,9 @@ write_current_packet (void) HDR_SCTP.checksum = crc32c((guint8 *)&HDR_SCTP, sizeof(HDR_SCTP), ~0L); if (hdr_data_chunk) 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))); + /* Note: g_ntohl() macro arg may be eval'd twice so calc value before invoking macro */ + x32 = finalize_crc32c(crc32c(packet_buf, curr_offset, HDR_SCTP.checksum)); + HDR_SCTP.checksum = g_htonl(x32); fwrite(&HDR_SCTP, sizeof(HDR_SCTP), 1, output_file); } @@ -655,8 +699,8 @@ write_current_packet (void) 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); + HDR_TCP.seq_num = g_ntohl(HDR_TCP.seq_num) + curr_offset; + HDR_TCP.seq_num = g_htonl(HDR_TCP.seq_num); packet_start += curr_offset; curr_offset = 0; @@ -699,14 +743,22 @@ append_to_preamble(char *str) if (toklen != 0) { if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN) return; /* no room to add the token to the preamble */ - strcpy(&packet_preamble[packet_preamble_len], str); - packet_preamble_len += toklen; + g_strlcpy(&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN); + packet_preamble_len += (int) toklen; + if (debug >= 2) { + char *c; + char xs[PACKET_PREAMBLE_MAX_LEN]; + g_strlcpy(xs, packet_preamble, PACKET_PREAMBLE_MAX_LEN); + while ((c = strchr(xs, '\r')) != NULL) *c=' '; + fprintf (stderr, "[[append_to_preamble: \"%s\"]]", xs); + } } } /*---------------------------------------------------------------------- * Parse the preamble to get the timecode. */ + static void parse_preamble (void) { @@ -723,7 +775,12 @@ parse_preamble (void) if (ts_fmt == NULL) return; - ts_sec = 0; + /* + * Initialize to today localtime, just in case not all fields + * of the date and time are specified. + */ + + timecode = timecode_default; ts_usec = 0; /* @@ -731,36 +788,33 @@ parse_preamble (void) */ packet_preamble[packet_preamble_len] = '\0'; - /* Ensure preamble has more than two chars before atempting to parse. + /* Ensure preamble has more than two chars before attempting to parse. * This should cover line breaks etc that get counted. */ if ( strlen(packet_preamble) > 2 ) { - /* - * Initialize to the Epoch, just in case not all fields - * of the date and time are specified. - */ - timecode.tm_sec = 0; - timecode.tm_min = 0; - timecode.tm_hour = 0; - timecode.tm_mday = 1; - timecode.tm_mon = 0; - timecode.tm_year = 70; - timecode.tm_wday = 0; - timecode.tm_yday = 0; - timecode.tm_isdst = -1; - /* Get Time leaving subseconds */ subsecs = strptime( packet_preamble, ts_fmt, &timecode ); if (subsecs != NULL) { /* Get the long time from the tm structure */ - ts_sec = (gint32)mktime( &timecode ); + /* (will return -1 if failure) */ + ts_sec = mktime( &timecode ); } else ts_sec = -1; /* we failed to parse it */ /* This will ensure incorrectly parsed dates get set to zero */ if ( -1 == ts_sec ) { - ts_sec = 0; + /* Sanitize - remove all '\r' */ + char *c; + while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' '; + fprintf (stderr, "Failure processing time \"%s\" using time format \"%s\"\n (defaulting to Jan 1,1970 00:00:00 GMT)\n", + packet_preamble, ts_fmt); + if (debug >= 2) { + fprintf(stderr, "timecode: %02d/%02d/%d %02d:%02d:%02d %d\n", + timecode.tm_mday, timecode.tm_mon, timecode.tm_year, + timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst); + } + ts_sec = 0; /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */ ts_usec = 0; } else @@ -779,7 +833,7 @@ parse_preamble (void) * 10^-6 seconds, we multiply by * 10^(6-N). */ - subseclen = p - subsecs; + subseclen = (int) (p - subsecs); if (subseclen > 6) { /* * *More* than 6 digits; 6-N is @@ -795,10 +849,14 @@ parse_preamble (void) } } } + if (debug >= 2) { + char *c; + while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' '; + fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble); + fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_usec); + } - /*printf("Format(%s), time(%u), subsecs(%u)\n\n", ts_fmt, ts_sec, ts_usec);*/ - /* Clear Preamble */ packet_preamble_len = 0; } @@ -993,63 +1051,71 @@ usage (void) fprintf(stderr, "Text2pcap %s" #ifdef SVNVERSION - " (" SVNVERSION ")" + " (" SVNVERSION " from " SVNPATH ")" #endif "\n" "Generate a capture file from an ASCII hexdump of packets.\n" "See http://www.wireshark.org for more information.\n" "\n" - "Usage: text2pcap [options] \n" + "Usage: text2pcap [options] \n" "\n" - "where specifies input filename (use - for standard input)\n" - " specifies output filename (use - for standard output)\n" + "where specifies input filename (use - for standard input)\n" + " specifies output filename (use - for standard output)\n" "\n" "Input:\n" - " -o hex|oct parse offsets as (h)ex or (o)ctal, default is hex\n" - " -t treats the text before the packet as a date/time code;\n" - " the specified argument is a format string of the sort \n" + " -o hex|oct|dec parse offsets as (h)ex, (o)ctal or (d)ecimal;\n" + " default is hex.\n" + " -t treat the text before the packet as a date/time code;\n" + " the specified argument is a format string of the sort\n" " supported by strptime.\n" " Example: The time \"10:15:14.5476\" has the format code\n" " \"%%H:%%M:%%S.\"\n" - " NOTE: The subsecond component delimiter must be given\n" - " (.) but no pattern is required; the remaining number\n" - " is assumed to be fractions of a second.\n" + " NOTE: The subsecond component delimiter, '.', must be\n" + " given, but no pattern is required; the remaining\n" + " number is assumed to be fractions of a second.\n" + " NOTE: Date/time fields from the current date/time are\n" + " used as the default for unspecified fields.\n" "\n" "Output:\n" - " -l link-layer type number. Default is 1 (Ethernet). \n" + " -l link-layer type number; default is 1 (Ethernet).\n" " See the file net/bpf.h for list of numbers.\n" - " -m max packet length in output, default is %d\n" + " Use this option if your dump is a complete hex dump\n" + " of an encapsulated packet and you wish to specify\n" + " the exact type of encapsulation.\n" + " Example: -l 7 for ARCNet packets.\n" + " -m max packet length in output; default is %d\n" "\n" "Prepend dummy header:\n" " -e prepend dummy Ethernet II header with specified L3PID\n" - " (in HEX)\n" - " Example: -e 0x800\n" + " (in HEX).\n" + " Example: -e 0x806 to specify an ARP packet.\n" " -i prepend dummy IP header with specified IP protocol\n" - " (in DECIMAL). \n" + " (in DECIMAL).\n" " Automatically prepends Ethernet header as well.\n" " Example: -i 46\n" " -u , prepend dummy UDP header with specified\n" " dest and source ports (in DECIMAL).\n" - " Automatically prepends Ethernet & IP headers as well\n" - " Example: -u 30,40\n" - " -T , prepend dummy TCP header with specified \n" + " Automatically prepends Ethernet & IP headers as well.\n" + " Example: -u 1000,69 to make the packets look like\n" + " TFTP/UDP packets.\n" + " -T , prepend dummy TCP header with specified\n" " dest and source ports (in DECIMAL).\n" - " Automatically prepends Ethernet & IP headers as well\n" + " Automatically prepends Ethernet & IP headers as well.\n" " Example: -T 50,60\n" - " -s ,, prepend dummy SCTP header with specified \n" + " -s ,, prepend dummy SCTP header with specified\n" " dest/source ports and verification tag (in DECIMAL).\n" - " Automatically prepends Ethernet & IP headers as well\n" + " Automatically prepends Ethernet & IP headers as well.\n" " Example: -s 30,40,34\n" - " -S ,, prepend dummy SCTP header with specified \n" - " dest/source ports and verification tag 0. \n" - " It also prepends a dummy SCTP DATA \n" + " -S ,, prepend dummy SCTP header with specified\n" + " dest/source ports and verification tag 0.\n" + " Automatically prepends a dummy SCTP DATA\n" " chunk header with payload protocol identifier ppi.\n" " Example: -S 30,40,34\n" "\n" "Miscellaneous:\n" - " -h display this help and exit\n" - " -d detailed debug of parser states \n" - " -q generate no output at all (automatically turns off -d)\n" + " -h display this help and exit.\n" + " -d show detailed debug of parser states.\n" + " -q generate no output at all (automatically turns off -d).\n" "", VERSION, MAX_PACKET); @@ -1065,6 +1131,10 @@ parse_options (int argc, char *argv[]) int c; char *p; +#ifdef _WIN32 + arg_list_utf_16to8(argc, argv); +#endif /* _WIN32 */ + /* Scan CLI parameters */ while ((c = getopt(argc, argv, "dhqe:i:l:m:o:u:s:S:t:T:")) != -1) { switch(c) { @@ -1075,11 +1145,15 @@ parse_options (int argc, char *argv[]) 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); + if (optarg[0]!='h' && optarg[0] != 'o' && optarg[0] != 'd') { + fprintf(stderr, "Bad argument for '-o': %s\n", optarg); usage(); } - offset_base = (optarg[0]=='o') ? 8 : 16; + switch(optarg[0]) { + case 'o': offset_base = 8; break; + case 'h': offset_base = 16; break; + case 'd': offset_base = 10; break; + } break; case 'e': hdr_ethernet = TRUE; @@ -1238,11 +1312,11 @@ parse_options (int argc, char *argv[]) } if (strcmp(argv[optind], "-")) { - input_filename = strdup(argv[optind]); - input_file = fopen(input_filename, "rb"); + input_filename = g_strdup(argv[optind]); + input_file = ws_fopen(input_filename, "rb"); if (!input_file) { fprintf(stderr, "Cannot open file [%s] for reading: %s\n", - input_filename, strerror(errno)); + input_filename, g_strerror(errno)); exit(-1); } } else { @@ -1251,11 +1325,11 @@ parse_options (int argc, char *argv[]) } if (strcmp(argv[optind+1], "-")) { - output_filename = strdup(argv[optind+1]); - output_file = fopen(output_filename, "wb"); + output_filename = g_strdup(argv[optind+1]); + output_file = ws_fopen(output_filename, "wb"); if (!output_file) { fprintf(stderr, "Cannot open file [%s] for writing: %s\n", - output_filename, strerror(errno)); + output_filename, g_strerror(errno)); exit(-1); } } else { @@ -1279,7 +1353,9 @@ parse_options (int argc, char *argv[]) output_filename = "Standard output"; } - ts_sec = (gint32) time(0); /* initialize to current time */ + ts_sec = time(0); /* initialize to current time */ + timecode_default = *localtime(&ts_sec); + timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */ /* Display summary of our state */ if (!quiet) { @@ -1301,7 +1377,8 @@ parse_options (int argc, char *argv[]) } } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { parse_options(argc, argv); @@ -1317,8 +1394,9 @@ int main(int argc, char *argv[]) if (debug) fprintf(stderr, "\n-------------------------\n"); if (!quiet) { - fprintf(stderr, "Read %ld potential packets, wrote %ld packets\n", - num_packets_read, num_packets_written); + fprintf(stderr, "Read %ld potential packet%s, wrote %ld packet%s\n", + num_packets_read, (num_packets_read==1) ?"":"s", + num_packets_written, (num_packets_written==1)?"":"s"); } return 0; }