diff --git a/src/tcpedit/edit_packet.c b/src/tcpedit/edit_packet.c index c5d7b0b4..8cd69851 100644 --- a/src/tcpedit/edit_packet.c +++ b/src/tcpedit/edit_packet.c @@ -1162,3 +1162,61 @@ is_multicast_ipv6(tcpedit_t *tcpedit, struct tcpr_in6_addr *addr) return 0; } + +/** + * based on which is generated via the range_[src/dst] and range. + * return 1 since we changed one or more IP addresses + */ +int +range_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, + u_char *pktdata, ipv4_hdr_t *ip_hdr, int len) +{ +#ifdef DEBUG + char srcip[16], dstip[16]; +#endif + assert(tcpedit); + assert(pkthdr); + assert(pktdata); + assert(ip_hdr); + +#ifdef DEBUG + strlcpy(srcip, get_addr2name4(tcpedit->range_src_ipv4, RESOLVE), 16); + strlcpy(dstip, get_addr2name4(tcpedit->range_dst_ipv4, RESOLVE), 16); +#endif + + /* ranged IP addresses based on the value of range_[src/dst]_ipv4 */ + dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip); + + /* don't rewrite broadcast addresses */ + if (tcpedit->range_count_dst){ + if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_dst.s_addr)) + || !tcpedit->skip_broadcast) { + uint32_t old_ip = ip_hdr->ip_dst.s_addr; + ip_hdr->ip_dst.s_addr = htonl(ntohl(tcpedit->range_dst_ipv4) + tcpedit->range_pos_dst); + ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_dst.s_addr, len); + } + } + if (tcpedit->range_count_src){ + if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_src.s_addr)) + || !tcpedit->skip_broadcast) { + uint32_t old_ip = ip_hdr->ip_src.s_addr; + ip_hdr->ip_src.s_addr = htonl(ntohl(tcpedit->range_src_ipv4) + tcpedit->range_pos_src); + ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_src.s_addr, len); + } + } + if ((++tcpedit->range_pos_dst) >= tcpedit->range_count_dst){ + tcpedit->range_pos_dst = 0; + } + if ((++tcpedit->range_pos_src) >= tcpedit->range_count_src){ + tcpedit->range_pos_src = 0; + } + +#ifdef DEBUG + strlcpy(srcip, get_addr2name4(ip_hdr->ip_src.s_addr, RESOLVE), 16); + strlcpy(dstip, get_addr2name4(ip_hdr->ip_dst.s_addr, RESOLVE), 16); +#endif + + dbgx(1, "New Src IP: %s\tNew Dst IP: %s\n", srcip, dstip); + + return 0; +} diff --git a/src/tcpedit/edit_packet.h b/src/tcpedit/edit_packet.h index 99218116..b3dd68d1 100644 --- a/src/tcpedit/edit_packet.h +++ b/src/tcpedit/edit_packet.h @@ -61,6 +61,10 @@ int rewrite_ipv4_ttl(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr); int rewrite_ipv6_hlim(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr); +int range_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pktdhr, + u_char *pktdata, ipv4_hdr_t *ip_hdr, int len); + + #define BROADCAST_IP 4294967295 #endif diff --git a/src/tcpedit/parse_args.c b/src/tcpedit/parse_args.c index 3f0f7b34..7ab105d6 100644 --- a/src/tcpedit/parse_args.c +++ b/src/tcpedit/parse_args.c @@ -247,6 +247,43 @@ tcpedit_post_args(tcpedit_t *tcpedit) { return -1; } } + /* --rangecount */ + tcpedit->range_count_src = 0; + tcpedit->range_count_dst = 0; + tcpedit->range_pos_src = 0; + tcpedit->range_pos_dst = 0; + tcpedit->range_src_ipv4 = htonl(0xC6123202); + tcpedit->range_dst_ipv4 = htonl(0xC6130001); + if (HAVE_OPT(RANGE_COUNT_SRC)) { + tcpedit->rewrite_ip = true; + tcpedit->range_count_src = OPT_VALUE_RANGE_COUNT_SRC; + } + if (HAVE_OPT(RANGE_COUNT_DST)) { + tcpedit->rewrite_ip = true; + tcpedit->range_count_dst = OPT_VALUE_RANGE_COUNT_DST; + } + + if (HAVE_OPT(RANGE_ADDRESS)) { + unsigned ip1[4] = {0},ip2[4] = {0}; + int r; + /* ipv4 only */ + if ((r = sscanf(OPT_ARG(RANGE_ADDRESS), "%u.%u.%u.%u:%u.%u.%u.%u", + &ip1[0], &ip1[1], &ip1[2], &ip1[3], + &ip2[0], &ip2[1], &ip2[2], &ip2[3])) != 8){ + tcpedit_seterr(tcpedit, + "Unable to parse --range_address=%s(%d)", OPT_ARG(RANGE_ADDRESS), r); + return -1; + } + tcpedit->range_src_ipv4 = htonl(((uint8_t)ip1[0])<<24 | + ((uint8_t)ip1[1])<<16 | + ((uint8_t)ip1[2])<<8 | + ((uint8_t)ip1[3])<<0); + tcpedit->range_dst_ipv4 = htonl(((uint8_t)ip2[0])<<24 | + ((uint8_t)ip2[1])<<16 | + ((uint8_t)ip2[2])<<8 | + ((uint8_t)ip2[3])<<0); + + } /* parse the tcpedit dlt args */ rcode = tcpedit_dlt_post_args(tcpedit); diff --git a/src/tcpedit/tcpedit.c b/src/tcpedit/tcpedit.c index 2f48719c..2349f5a3 100644 --- a/src/tcpedit/tcpedit.c +++ b/src/tcpedit/tcpedit.c @@ -343,6 +343,16 @@ tcpedit_packet(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr, } } } + /* range ip address (ipv4 only) */ + if (tcpedit->range_count_src || tcpedit->range_count_dst) { + /* only IPv4 Packets */ + if (ip_hdr != NULL) { + if ((retval = range_ipv4(tcpedit, *pkthdr, packet, + ip_hdr, (*pkthdr)->caplen - l2len)) < 0) + return TCPEDIT_ERROR; + } + } + /* do we need to fix checksums? -- must always do this last! */ if ((tcpedit->fixcsum || needtorecalc)) { diff --git a/src/tcpedit/tcpedit_opts.def b/src/tcpedit/tcpedit_opts.def index 1a274304..c6222fa8 100644 --- a/src/tcpedit/tcpedit_opts.def +++ b/src/tcpedit/tcpedit_opts.def @@ -58,6 +58,49 @@ you can reuse the same seed value to recreate the traffic. EOText; }; +flag = { + name = range_count_src; + descrip = "Set the count of source ip address range"; + arg-type = number; + arg-range = "1->1048575"; + arg-default = 1; + max = 1; + doc = <<- EOText +Increament source ip address (ipv4) within specified range. +EOText; +}; + +flag = { + name = range_count_dst; + descrip = "Set the count of destination ip address range"; + arg-type = number; + arg-range = "1->1048575"; + arg-default = 1; + max = 1; + doc = <<- EOText +Increament destination ip address (ipv4) within specified range. +EOText; +}; + + +flag = { + name = range_address; + arg-type = string; + max = 1; + descrip = "Rewrite IP addresses to be src/dst"; + doc = <<- EOText +Takes a pair of colon delimited IPv4 addresses which will be used to rewrite +all traffic to appear to be based on the src/dst IP addresses. + +IPv4 Example: +@example +--endpoints=198.18.50.2:198.19.0.2 +@end example + +EOText; +}; + + flag = { name = pnat; value = N; diff --git a/src/tcpedit/tcpedit_types.h b/src/tcpedit/tcpedit_types.h index d3210458..4a92afec 100644 --- a/src/tcpedit/tcpedit_types.h +++ b/src/tcpedit/tcpedit_types.h @@ -151,7 +151,7 @@ typedef struct { /* pseudo-randomize IP addresses using a seed */ uint32_t seed; - + /* rewrite tcp/udp ports */ tcpedit_portmap_t *portmap; @@ -161,6 +161,13 @@ typedef struct { uint32_t fuzz_seed; uint32_t fuzz_factor; + + uint32_t range_count_src; + uint32_t range_count_dst; + uint32_t range_pos_src; + uint32_t range_pos_dst; + uint32_t range_src_ipv4; + uint32_t range_dst_ipv4; } tcpedit_t;