From 74254aff4cbe024c4f84c599408b2a8515f913a8 Mon Sep 17 00:00:00 2001 From: Scott Mace Date: Fri, 31 May 2002 17:06:25 +0000 Subject: Fix multi-nic support for freebsd Make several features actually work This generation of tcpreplay is being obsoleted and the author is no longer maintaining it. A new development effort has been started at sourceforge. --- net/tcpreplay/files/patch-Makefile.in | 26 +++- net/tcpreplay/files/patch-tcpreplay.8 | 83 +++++++++++ net/tcpreplay/files/patch-tcpreplay.c | 268 ++++++++++++++++++++++++++++++++++ net/tcpreplay/pkg-messages | 3 + 4 files changed, 377 insertions(+), 3 deletions(-) create mode 100644 net/tcpreplay/files/patch-tcpreplay.8 create mode 100644 net/tcpreplay/files/patch-tcpreplay.c create mode 100644 net/tcpreplay/pkg-messages (limited to 'net/tcpreplay') diff --git a/net/tcpreplay/files/patch-Makefile.in b/net/tcpreplay/files/patch-Makefile.in index e8b98ef6efc1..ef32a8a017bc 100644 --- a/net/tcpreplay/files/patch-Makefile.in +++ b/net/tcpreplay/files/patch-Makefile.in @@ -1,6 +1,6 @@ ---- Makefile.in.orig Mon Apr 15 14:13:06 2002 -+++ Makefile.in Mon Apr 15 14:15:49 2002 -@@ -10,10 +10,11 @@ +--- Makefile.in.orig Sat May 11 12:07:44 2002 ++++ Makefile.in Sat May 11 13:11:51 2002 +@@ -10,15 +10,16 @@ CFLAGS = @CFLAGS@ #CFLAGS = -ggdb -pipe -Wall LDFLAGS = @LDFLAGS@ @@ -13,6 +13,26 @@ INCS = @LNETINC@ @REDBLACKINC@ @PCAPINC@ LIBRARIES = tree cache cidr + # tcpreplay objects +-ROBJ = cache.o ++ROBJ = cache.o cidr.o + + # tcpprep objects + POBJ = cache.o tree.o cidr.o +@@ -40,11 +41,11 @@ + + tcpreplay: $(PCAPDEP) $(LNETDEP) tcpreplay.c + rm -f tcpreplay +- $(CC) $(CFLAGS) $(DEFS) $(INCS) -o $@ tcpreplay.c $(LDFLAGS) $(LIBS) $(ROBJ) ++ $(CC) $(CFLAGS) $(DEFS) $(INCS) -o $@ tcpreplay.c $(ROBJ) $(LDFLAGS) $(LIBS) + + tcpprep: $(PCAPDEP) tcpprep.c + rm -f tcpprep +- $(CC) $(CFLAGS) $(DEFS) $(INCS) -o $@ tcpprep.c $(LDFLAGS) $(LIBS) $(POBJ) ++ $(CC) $(CFLAGS) $(DEFS) $(INCS) -o $@ tcpprep.c $(POBJ) $(LDFLAGS) $(LIBS) + + clean: + rm -f *~ *.o *core $(PROGRAMS) @@ -53,12 +54,10 @@ rm -f Makefile config.h config.status config.cache config.log diff --git a/net/tcpreplay/files/patch-tcpreplay.8 b/net/tcpreplay/files/patch-tcpreplay.8 new file mode 100644 index 000000000000..79af4476e296 --- /dev/null +++ b/net/tcpreplay/files/patch-tcpreplay.8 @@ -0,0 +1,83 @@ +--- tcpreplay.8.orig Fri May 17 17:55:47 2002 ++++ tcpreplay.8 Fri May 31 11:49:46 2002 +@@ -1,5 +1,5 @@ + .\" yo there. +-.TH TCPREPLAY 8 "2 December 20001" ++.TH TCPREPLAY 8 "2 December 2001" + .SH NAME + tcpreplay \- replay traffic from a saved tcpdump file + .SH SYNOPSIS +@@ -30,6 +30,9 @@ + .B \-l + .I loop count + ] [ ++.B \-n ++.I nomartian ++] [ + .B \-m + .I multiplier + | +@@ -39,6 +42,9 @@ + .B \-R + .I regex + ] ++.B \-C ++.I cidr1[,cidr2,cidr3] ++] + .I file + .br + .ad +@@ -67,11 +73,14 @@ + .LP + This version of + .I tcpreplay +-supports sending packets out two interfaces. Packets matching the \fIregex\fP +-are sent out the \fIprimary interface\fP and all other packets are sent out the +-\fIsecondary interface\fP. For improved performance, a tcpprep \fIcache file\fP +-can be used instead. Also supported is rewriting of the destination \fIMAC +-addresses\fP to allow routers to forward packets between interfaces. Additionally, a slice of packets matching a \fIbegin\fP and \fIend\fP range can be sent from the tcpdump file. ++supports sending packets out two interfaces. Packets are matched by using either ++a \fIregex\fP, \fICIDR list\fP, or by using the tcpprep pre-processor and associated ++\fIcache file\fP. Matching packets are sent out the \fIprimary interface\fP and all ++other packets are sent out the \fIsecondary interface\fP. For improved performance, ++use either \fICIDR list\fP matching or a tcpprep \fIcache file\fP. Also supported ++is rewriting of the destination \fIMAC addresses\fP to allow routers to forward packets ++between interfaces. Additionally, a slice of packets matching a \fIbegin\fP and \fIend\fP ++range can be sent from the tcpdump file. + .SH OPTIONS + .LP + .TP +@@ -103,6 +112,9 @@ + Resend the packets at a \fImultiple\fR of the speed at which they were + recorded. + .TP ++.B \-n ++Drop packets with \fImartian\fR destination addresses. ++.TP + .B \-r + Resend the packets at the \fIrate\fR specified (in Mbps). + .TP +@@ -111,6 +123,10 @@ + that match this regex are sent via the primary interface. Packets that do not + match this regex are sent via the secondary interface. + .TP ++.B \-C ++Specify a comma serpated list of net/masklen to match against the source IP of packets. ++Works similar to regex, but is significantly faster. ++.TP + .SH "SEE ALSO" + tcpdump(8) tcpprep(8) + .SH AUTHOR +@@ -125,8 +141,10 @@ + .I tcpreplay + can only send packets as fast as your machine's interface, + processor, and disk will allow. Use of the -R flag will \fIsignificantly\fP +-slow it down. Those worrying about peformance should use \fItcpprep\fP with the +--c flag instead. ++slow it down. Use of the -C flag will work for most systems with a fast ++processor. Those worrying about peformance should use \fItcpprep\fP with the ++-c flag instead, however, processesing time may be extremely slow for large ++capture files. + .LP + ``\fIN\fR write attempts failed from full buffers and were repeated'' + does not indicate that these packets were not sent, but that the send diff --git a/net/tcpreplay/files/patch-tcpreplay.c b/net/tcpreplay/files/patch-tcpreplay.c new file mode 100644 index 000000000000..421f62f7ff50 --- /dev/null +++ b/net/tcpreplay/files/patch-tcpreplay.c @@ -0,0 +1,268 @@ +--- tcpreplay.c.orig Fri May 17 17:55:47 2002 ++++ tcpreplay.c Fri May 31 11:42:37 2002 +@@ -65,6 +65,7 @@ + #include + #include + #include "cache.h" ++#include "cidr.h" + + #define TCPREPLAY_VERSION "1.0.1-adt9" + +@@ -85,6 +86,10 @@ + u_int start = 0; + u_int stop = 0; + int mode; ++int regex_mode; ++int cidr_mode; ++int cache_mode; ++int nomartians = 0; + int rate; + int debug; + float multiplier; +@@ -101,6 +106,9 @@ + CACHE * cachedata = NULL; + int cache_bit = 0; + int cache_byte = 0; ++struct libnet_link_int * write_if; // Primary interface -i ++struct libnet_link_int * write_if2; // Secondary interface -j ++CIDR * cidrdata = NULL; + + void usage(){ + fprintf(stderr, "Version: " TCPREPLAY_VERSION "\nUsage: tcpreplay " +@@ -244,6 +252,7 @@ + struct libnet_ethernet_hdr * eth_hdr; + #ifdef DEBUG + int regex_match = -1; ++ int cache_match = -1; + int cidr_match = -1; + #endif + size_t nmatch = 0; +@@ -257,7 +266,7 @@ + make sure we're inside that slice, or increment the cache + pointers, and return without further processing + */ +- if (start != 0) { ++ if ((start != 0) && cache_mode) { + if (!((start <= packet_num) && (packet_num <= stop))) { + if (cache_bit == 7) { + cache_bit = 0; +@@ -359,14 +368,22 @@ + if (interface2 == NULL) { + /* we're not using a second NIC so just write the packet all normal like */ + +- write_status = libnet_write_link_layer((struct libnet_link_int *)user, ++ write_status = libnet_write_link_layer((struct libnet_link_int *)write_if, + interface, data, pcap_hdr->caplen); + } + + else { /* we're in multi-nic mode, and have to figure things out */ +- if (mode == REGEX_MODE) { ++ if (regex_mode == 1) { + /* put the source ip of the packet into src_ip in x.x.x.x format */ + ip_hdr = (struct libnet_ip_hdr *) (data + LIBNET_ETH_H); ++ /* drop martians */ ++ if (nomartians == 1) { ++ switch ((ntohl(ip_hdr->ip_dst.s_addr) & 0xff000000) >> 24) { ++ case 0: case 127: case 255: ++ write_status=1; ++ continue; ++ } ++ } + memset (src_ip, '\0', 16); + strncat (src_ip, libnet_host_lookup(ip_hdr->ip_src.s_addr, RESOLVE), 15); + +@@ -384,7 +401,7 @@ + if (primary_mac != NULL) + memcpy(eth_hdr->ether_dhost, primary_mac, ETHER_ADDR_LEN); + +- write_status = libnet_write_link_layer((struct libnet_link_int *)user, ++ write_status = libnet_write_link_layer((struct libnet_link_int *)write_if, + interface, data, pcap_hdr->caplen); + } + +@@ -396,11 +413,53 @@ + if (secondary_mac != NULL) + memcpy(eth_hdr->ether_dhost, secondary_mac, ETHER_ADDR_LEN); + +- write_status = libnet_write_link_layer((struct libnet_link_int *)user, ++ write_status = libnet_write_link_layer((struct libnet_link_int *)write_if2, + interface2, data, pcap_hdr->caplen); + } + } +- ++ ++ else if (cidr_mode == 1) { ++ /* put the source ip of the packet into src_ip in x.x.x.x format */ ++ ip_hdr = (struct libnet_ip_hdr *) (data + LIBNET_ETH_H); ++ /* drop martians */ ++ if (nomartians == 1) { ++ switch ((ntohl(ip_hdr->ip_dst.s_addr) & 0xff000000) >> 24) { ++ case 0: case 127: case 255: ++ write_status=1; ++ continue; ++ } ++ } ++ /* we are using a cidr match */ ++ if (check_ip_CIDR(ip_hdr->ip_src.s_addr)) { ++#ifdef DEBUG ++ /* in debug mode we need to set this flag */ ++ cidr_match = 1; ++#endif ++ /* ++ To support routing packets through a device on either side ++ of the interfaces, we need to rewrite the dst MAC address ++ so that the router will pick them off the wire. ++ */ ++ if (primary_mac != NULL) ++ memcpy(eth_hdr->ether_dhost, primary_mac, ETHER_ADDR_LEN); ++ ++ write_status = libnet_write_link_layer((struct libnet_link_int *)write_if, ++ interface, data, pcap_hdr->caplen); ++ } ++ ++ else { ++#ifdef DEBUG ++ cidr_match = 0; ++#endif ++ /* do the mac rewrite thingy */ ++ if (secondary_mac != NULL) ++ memcpy(eth_hdr->ether_dhost, secondary_mac, ETHER_ADDR_LEN); ++ ++ write_status = libnet_write_link_layer((struct libnet_link_int *)write_if2, ++ interface2, data, pcap_hdr->caplen); ++ } ++ } ++ + else { /* looks like we're using a cache file */ + /* + test to see if we have a match by applying a mask to the current byte +@@ -408,7 +467,7 @@ + */ + if (cachedata->data[cache_byte] & (char)pow((long)2, (long)cache_bit) ) { + #ifdef DEBUG +- cidr_match = 1; ++ cache_match = 1; + #endif + /* do the mac rewrite thingy */ + if (primary_mac != NULL) +@@ -420,7 +479,7 @@ + + else { + #ifdef DEBUG +- cidr_match = 0; ++ cache_match = 0; + #endif + /* do the mac rewrite thingy */ + if (secondary_mac != NULL) +@@ -456,20 +515,30 @@ + + if (regex_match == 0) { + fprintf(stderr, "Regex: No Match (%s)\n", regex); +- fprintf(stderr, "Interface: %s\n", interface); ++ fprintf(stderr, "Interface: %s\n", interface2); + } else if (regex_match == 1) { + fprintf(stderr, "Regex: Match (%s)\n", regex); +- fprintf(stderr, "Interface: %s\n", interface2); +- } else if (cidr_match == 1) { +- fprintf(stderr, "CIDR: Match\n"); ++ fprintf(stderr, "Interface: %s\n", interface); ++ } else if (cache_match == 1) { ++ fprintf(stderr, "Cache: Match\n"); + fprintf(stderr, "Byte/Bit: %d/%d -> primary\n", cache_byte, cache_bit); +- } else if (cidr_match == 0) { +- fprintf(stderr, "CIDR: No Match\n"); ++ } else if (cache_match == 0) { ++ fprintf(stderr, "Cache: No Match\n"); + fprintf(stderr, "Byte/Bit: %d/%d -> secondary\n", cache_byte, cache_bit); +- } else { ++ } else if (cidr_match == 0) { ++ fprintf(stderr, "CIDR: No Match\n"); ++ fprintf(stderr, "Interface: %s\n", interface2); ++ } else if (cidr_match == 1) { ++ fprintf(stderr, "CIDR: Match\n"); ++ fprintf(stderr, "Interface: %s\n", interface); ++ } else { + fprintf(stderr, "No CIDR/Regex Match Attempted\n"); + } +- ++ ++ if (cidr_mode == 1) { ++ memset (src_ip, '\0', 16); ++ strncat (src_ip, libnet_host_lookup(ip_hdr->ip_src.s_addr, RESOLVE), 15); ++ } + fprintf(stderr, "Source IP: %s\n", src_ip); + memcpy(mac, eth_hdr->ether_dhost, MAC_SIZE-1); + fprintf(stderr, "Dest MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +@@ -506,8 +575,6 @@ + { + pcap_t * in_file; + char * cache_file = NULL; +- struct libnet_link_int * write_if; // Primary interface -i +- struct libnet_link_int * write_if2; // Secondary interface -j + float Mrate = 0; // + double starttime_local, startusec; + char ebuf[EBUF_SIZE]; // Error buffer +@@ -539,15 +606,16 @@ + } + + #ifdef DEBUG +- while ((ch = getopt(argc, argv, "b:e:d:i:j:l:r:c:m:hR:I:J:")) != -1) ++ while ((ch = getopt(argc, argv, "nb:e:d:i:j:l:r:c:m:h:R:I:J:C:")) != -1) + #else +- while ((ch = getopt(argc, argv, "b:e:i:j:l:r:c:m:hR:I:J:")) != -1) ++ while ((ch = getopt(argc, argv, "nb:e:i:j:l:r:c:m:h:R:I:J:C:")) != -1) + #endif + switch(ch) { + case 'b': + start = atoi(optarg); + break; + case 'c': ++ cache_mode = 1; + cache_file = optarg; + cache_packets = read_cache(cache_file); + break; +@@ -578,7 +646,11 @@ + case 'h': + usage(); + break; ++ case 'n': ++ nomartians = 1; ++ break; + case 'R': ++ regex_mode = 1; + regex = optarg; + if ((regex_error = regcomp(preg, regex, regex_flags))) { + if (regerror(regex_error, preg, ebuf, EBUF_SIZE) != -1) { +@@ -595,6 +667,12 @@ + case 'J': + secondary_mac = mac2hex(optarg, "Secondary MAC"); + break; ++ case 'C': ++ cidr_mode = 1; ++ if (! parse_cidr(optarg)) { ++ usage(); ++ } ++ break; + default: + usage(); + } +@@ -616,8 +694,8 @@ + exit (1); + } + +- if (((regex == NULL) && (cache_file == NULL)) && (interface2 != NULL)) { +- fprintf(stderr, "Needs regex/cache with secondary interface\n"); ++ if (((regex == NULL) && (cache_file == NULL) && (cidrdata == NULL)) && (interface2 != NULL)) { ++ fprintf(stderr, "Needs regex/cache/cidr with secondary interface\n"); + exit (1); + } + +@@ -712,7 +790,7 @@ + exit (1); + } + if (pcap_dispatch(in_file, 0,(void *)&write_packet, +- (u_char *) write_if) == -1) { ++ NULL) == -1) { + pcap_perror(in_file, argv[1]); + } + pcap_close(in_file); diff --git a/net/tcpreplay/pkg-messages b/net/tcpreplay/pkg-messages new file mode 100644 index 000000000000..0f8a16597ace --- /dev/null +++ b/net/tcpreplay/pkg-messages @@ -0,0 +1,3 @@ +This is a patched version of tcpreplay that seems to work well enough +for some applications. A new development effort for tcpreplay has been +started, see http://www.sf.net/projects/tcpreplay. -- cgit v1.2.3