summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTommy Beadle <tbeadle@gmail.com>2016-02-29 09:29:48 -0500
committerTobias Klauser <tklauser@distanz.ch>2016-03-29 10:08:38 +0200
commit196fc0351c1e5b39697091c845c73d04510e070e (patch)
treed4fe5100574e7ac58733b103fcdcf579bd926f40
parent070337f8cb27c1c4d77217879a3e1a1f193cef8f (diff)
mausezahn: Allow IPv6 ranges to be specified for source and dest addresses
This allows a user to pass a range of IPv6 addresses, either like: fec0:5000::1-fec0:5000::100 or in CIDR notation: fec0:5000::0/112 These can be used for the -A and/or -B command-line options. The largest range that can be used is a /64. In other words, if using CIDR notation, the masklen must be <= 128 and >= 64. Signed-off-by: Tommy Beadle <tbeadle@gmail.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r--staging/mausezahn.c95
-rw-r--r--staging/modifications.c82
-rw-r--r--staging/mz.h11
-rw-r--r--staging/send.c36
-rw-r--r--staging/tools.c254
5 files changed, 444 insertions, 34 deletions
diff --git a/staging/mausezahn.c b/staging/mausezahn.c
index 5051bcb..70f1e72 100644
--- a/staging/mausezahn.c
+++ b/staging/mausezahn.c
@@ -276,9 +276,13 @@ int reset(void)
tx.ip_src_isrange = 0;
tx.ip_src_start = 0;
tx.ip_src_stop = 0;
+ memset(&tx.ip6_src_start, 0, sizeof(tx.ip6_src_start));
+ memset(&tx.ip6_src_stop, 0, sizeof(tx.ip6_src_stop));
tx.ip_dst_start = 0;
tx.ip_dst_stop = 0;
+ memset(&tx.ip6_dst_start, 0, sizeof(tx.ip6_dst_start));
+ memset(&tx.ip6_dst_stop, 0, sizeof(tx.ip6_dst_stop));
tx.ip_dst_isrange = 0;
tx.ip_ttl = 0;
@@ -658,12 +662,24 @@ int getopts (int argc, char *argv[])
// Set source IP address:
if (strlen(tx.ip_src_txt)) { // option -A has been specified
if (mz_strcmp(tx.ip_src_txt, "bcast", 2)==0) {
+ if (ipv6_mode) {
+ fprintf(stderr, "Option -A does not support 'bcast' when in IPv6 mode.\n");
+ return 1;
+ }
tx.ip_src = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
} else if (strcmp(tx.ip_src_txt, "rand") == 0) {
+ if (ipv6_mode) {
+ fprintf(stderr, "Option -A does not support 'rand' when in IPv6 mode.\n");
+ return 1;
+ }
tx.ip_src_rand = 1;
tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0
}
- else if (get_ip_range_src(tx.ip_src_txt)) { // returns 1 when no range has been specified
+ else if (
+ (ipv6_mode && get_ip6_range_src(tx.ip_src_txt, l)) || // returns 1 when no range has been specified
+ (!ipv6_mode && get_ip_range_src(tx.ip_src_txt))
+ )
+ {
// name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
if (ipv6_mode)
tx.ip6_src = libnet_name2addr6 (l, tx.ip_src_txt, LIBNET_RESOLVE);
@@ -689,8 +705,15 @@ int getopts (int argc, char *argv[])
}
if (mz_strcmp(tx.ip_dst_txt, "bcast", 2)==0) {
- tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
- } else if (get_ip_range_dst(tx.ip_dst_txt)) { // returns 1 when no range has been specified
+ if (ipv6_mode) {
+ fprintf(stderr, "Option -B does not support 'bcast' when in IPv6 mode.\n");
+ return 1;
+ }
+ tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
+ } else if (
+ (ipv6_mode && get_ip6_range_dst(tx.ip_dst_txt, l)) || // returns 1 when no range has been specified
+ (!ipv6_mode && get_ip_range_dst(tx.ip_dst_txt)))
+ {
// name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
if (ipv6_mode)
tx.ip6_dst = libnet_name2addr6 (l, tx.ip_dst_txt, LIBNET_RESOLVE);
@@ -699,7 +722,13 @@ int getopts (int argc, char *argv[])
}
}
else { // no destination IP specified: by default use broadcast
- tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
+ if (ipv6_mode) {
+ // XXX I think we want to use a link-local
+ // broadcast address instead.
+ tx.ip6_dst = libnet_name2addr6 (l, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", LIBNET_DONT_RESOLVE);
+ } else {
+ tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
+ }
}
// Initialize tx.ip_src_h and tx.ip_dst_h which are used by 'print_frame_details()'
@@ -710,28 +739,40 @@ int getopts (int argc, char *argv[])
dum2 = (unsigned char*) &tx.ip_src;
}
else { // ip_src already given, convert to ip_src_h
- dum1 = (unsigned char*) &tx.ip_src;
- dum2 = (unsigned char*) &tx.ip_src_h;
+ if (ipv6_mode) {
+ if (tx.ip_src_isrange) {
+ tx.ip6_src = tx.ip6_src_start;
+ }
+ } else {
+ dum1 = (unsigned char*) &tx.ip_src;
+ dum2 = (unsigned char*) &tx.ip_src_h;
+ }
}
- *dum2 = *(dum1+3);
- dum2++;
- *dum2 = *(dum1+2);
- dum2++;
- *dum2 = *(dum1+1);
- dum2++;
- *dum2 = *dum1;
-
- dum1 = (unsigned char*) &tx.ip_dst;
- dum2 = (unsigned char*) &tx.ip_dst_h;
-
- *dum2 = *(dum1+3);
- dum2++;
- *dum2 = *(dum1+2);
- dum2++;
- *dum2 = *(dum1+1);
- dum2++;
- *dum2 = *dum1;
+ if (ipv6_mode) {
+ if (tx.ip_dst_isrange) {
+ tx.ip6_dst = tx.ip6_dst_start;
+ }
+ } else {
+ *dum2 = *(dum1+3);
+ dum2++;
+ *dum2 = *(dum1+2);
+ dum2++;
+ *dum2 = *(dum1+1);
+ dum2++;
+ *dum2 = *dum1;
+
+ dum1 = (unsigned char*) &tx.ip_dst;
+ dum2 = (unsigned char*) &tx.ip_dst_h;
+
+ *dum2 = *(dum1+3);
+ dum2++;
+ *dum2 = *(dum1+2);
+ dum2++;
+ *dum2 = *(dum1+1);
+ dum2++;
+ *dum2 = *dum1;
+ }
libnet_destroy(l);
}
@@ -911,8 +952,6 @@ int main(int argc, char **argv)
l = get_link_context();
t4 = create_icmp6_packet(l); // t4 can be used for later header changes
t3 = create_ip_packet(l); // t3 can be used for later header changes
- if (ipv6_mode)
- update_ISUM(l, t4);
if (!quiet) complexity();
if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
@@ -925,8 +964,6 @@ int main(int argc, char **argv)
l = get_link_context();
t4 = create_udp_packet(l); // t4 can be used for later header changes
t3 = create_ip_packet(l); // t3 can be used for later header changes
- if (ipv6_mode)
- update_USUM(l, t4);
if (!quiet) complexity();
if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
@@ -939,8 +976,6 @@ int main(int argc, char **argv)
l = get_link_context();
t4 = create_tcp_packet(l); // t4 can be used for later header changes
t3 = create_ip_packet(l); // t3 can be used for later header changes
- if (ipv6_mode)
- update_TSUM(l, t4);
if (!quiet) complexity();
if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
diff --git a/staging/modifications.c b/staging/modifications.c
index e11ba0e..1affbbb 100644
--- a/staging/modifications.c
+++ b/staging/modifications.c
@@ -27,6 +27,8 @@
// int update_Eth_SA (libnet_t *l, libnet_ptag_t t)
// int update_IP_SA (libnet_t *l, libnet_ptag_t t)
// int update_IP_DA (libnet_t *l, libnet_ptag_t t)
+// int update_IP6_SA (libnet_t *l, libnet_ptag_t t)
+// int update_IP6_DA (libnet_t *l, libnet_ptag_t t)
// int update_DPORT (libnet_t *l, libnet_ptag_t t)
// int update_SPORT (libnet_t *l, libnet_ptag_t t)
// int update_TCP_SQNR (libnet_t *l, libnet_ptag_t t)
@@ -135,6 +137,10 @@ int update_IP_SA (libnet_t *l, libnet_ptag_t t)
u_int8_t *x, *y;
int i=0;
+ if (ipv6_mode) {
+ return update_IP6_SA(l, t);
+ }
+
if (tx.ip_src_rand)
{
tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0
@@ -190,6 +196,41 @@ int update_IP_SA (libnet_t *l, libnet_ptag_t t)
}
+int
+update_IP6_SA(libnet_t *l, libnet_ptag_t t)
+{
+ int i = 0;
+ if (tx.ip_src_rand) {
+ fprintf(stderr, "Random source addresses are not supported in IPv6 mode.\n");
+ exit(1);
+ } else if (tx.ip_src_isrange) {
+ if (incr_in6_addr(tx.ip6_src, &tx.ip6_src)
+ || (in6_addr_cmp(tx.ip6_src, tx.ip6_src_stop) > 0))
+ {
+ tx.ip6_src = tx.ip6_src_start;
+ i = 1;
+ }
+ }
+
+ t = libnet_build_ipv6(tx.ip_tos,
+ tx.ip_flow,
+ tx.ip_len,
+ tx.ip_proto,
+ tx.ip_ttl,
+ tx.ip6_src,
+ tx.ip6_dst,
+ (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL,
+ (mode==IP) ? tx.ip_payload_s : 0,
+ l,
+ t);
+
+ if (t == -1) {
+ fprintf(stderr," mz/update_IP6_SA: IP address manipulation failed!\n");
+ exit (1);
+ }
+
+ return i;
+}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -208,6 +249,9 @@ int update_IP_DA(libnet_t *l, libnet_ptag_t t)
u_int8_t *x, *y;
int i=0;
+ if (ipv6_mode) {
+ return update_IP6_DA(l, t);
+ }
if (tx.ip_dst_isrange)
{
@@ -262,6 +306,39 @@ int update_IP_DA(libnet_t *l, libnet_ptag_t t)
}
+int
+update_IP6_DA(libnet_t *l, libnet_ptag_t t)
+{
+ int i = 0;
+ if (tx.ip_dst_isrange) {
+ if (incr_in6_addr(tx.ip6_dst, &tx.ip6_dst)
+ || (in6_addr_cmp(tx.ip6_dst, tx.ip6_dst_stop) > 0))
+ {
+ tx.ip6_dst = tx.ip6_dst_start;
+ i = 1;
+ }
+ }
+
+ t = libnet_build_ipv6(tx.ip_tos,
+ tx.ip_flow,
+ tx.ip_len,
+ tx.ip_proto,
+ tx.ip_ttl,
+ tx.ip6_src,
+ tx.ip6_dst,
+ (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL,
+ (mode==IP) ? tx.ip_payload_s : 0,
+ l,
+ t);
+
+ if (t == -1) {
+ fprintf(stderr," mz/update_IP6_DA: IP address manipulation failed!\n");
+ exit (1);
+ }
+
+ return i;
+}
+
///////////////////////////////////////////////////////////////////////////////////////
@@ -399,7 +476,7 @@ int update_SPORT(libnet_t *l, libnet_ptag_t t)
if (t == -1)
{
- fprintf(stderr, " mz/update_DPORT: Can't build TCP header: %s\n", libnet_geterror(l));
+ fprintf(stderr, " mz/update_SPORT: Can't build TCP header: %s\n", libnet_geterror(l));
exit (0);
}
}
@@ -448,6 +525,7 @@ int update_USUM(libnet_t *l, libnet_ptag_t t)
tx.udp_payload_s,
l,
t);
+ tx.udp_sum = 0;
return t;
}
@@ -504,6 +582,7 @@ int update_TSUM(libnet_t *l, libnet_ptag_t t)
tx.tcp_payload_s,
l,
t);
+ tx.tcp_sum = 0;
return t;
}
@@ -544,6 +623,7 @@ int update_ISUM(libnet_t *l, libnet_ptag_t t)
tx.icmp_payload_s,
l,
t);
+ tx.icmp_chksum = 0;
return t;
}
diff --git a/staging/mz.h b/staging/mz.h
index 339be31..5ed05a7 100644
--- a/staging/mz.h
+++ b/staging/mz.h
@@ -402,6 +402,8 @@ struct tx_struct
u_int32_t ip_src_h; // mirror of ip_src (NOT network byte order => easy to count)
u_int32_t ip_src_start; // start of range (NOT network byte order => easy to count)
u_int32_t ip_src_stop; // stop of range (NOT network byte order => easy to count)
+ struct libnet_in6_addr ip6_src_start; // start of IPv6 range
+ struct libnet_in6_addr ip6_src_stop; // stop of IPv6 range
int ip_src_isrange; // if set to 1 then the start/stop values above are valid.
u_int32_t ip_dst; // has always network byte order(!)
struct libnet_in6_addr ip6_dst;
@@ -409,6 +411,8 @@ struct tx_struct
u_int32_t ip_dst_h; // mirror of ip_dst (NOT network byte order => easy to count)
u_int32_t ip_dst_start; // start of range (NOT network byte order => easy to count)
u_int32_t ip_dst_stop; // stop of range (NOT network byte order => easy to count)
+ struct libnet_in6_addr ip6_dst_start; // start of IPv6 range
+ struct libnet_in6_addr ip6_dst_stop; // stop of IPv6 range
int ip_dst_isrange; // if set to 1 then the start/stop values above are valid.
u_int16_t
ip_len,
@@ -653,6 +657,8 @@ int type2str(u_int16_t type, char *str);
//
int get_ip_range_dst (char *arg);
int get_ip_range_src (char *arg);
+int get_ip6_range_src (char *arg, libnet_t *l);
+int get_ip6_range_dst (char *arg, libnet_t *l);
// Sets a random SA for a given IP packet.
// Return value: 0 upon success, 1 upon failure
@@ -740,6 +746,7 @@ int update_RTP(libnet_t *l, libnet_ptag_t t);
//
// RETURNS '1' if tx.ip_src restarts
int update_IP_SA (libnet_t *l, libnet_ptag_t t);
+int update_IP6_SA (libnet_t *l, libnet_ptag_t t);
// Applies another DESTINATION IP address from a specified range (tx.ip_dst_isrange==1)
@@ -750,6 +757,7 @@ int update_IP_SA (libnet_t *l, libnet_ptag_t t);
//
// RETURN VALUE: '1' if tx.ip_dst restarts
int update_IP_DA(libnet_t *l, libnet_ptag_t t);
+int update_IP6_DA (libnet_t *l, libnet_ptag_t t);
// Applies another DESTINATION PORT from a specified range to a given UDP- or TCP-PTAG.
@@ -784,6 +792,9 @@ int update_TSUM(libnet_t *l, libnet_ptag_t t);
//
int print_frame_details(void);
+int in6_addr_cmp(struct libnet_in6_addr addr1, struct libnet_in6_addr addr2);
+int incr_in6_addr(struct libnet_in6_addr src, struct libnet_in6_addr *dst);
+uint64_t get_ip6_range_count(struct libnet_in6_addr start, struct libnet_in6_addr stop);
// Calculates the number of frames to be sent.
// Should be used as standard output except the
diff --git a/staging/send.c b/staging/send.c
index ef76512..5d5adea 100644
--- a/staging/send.c
+++ b/staging/send.c
@@ -90,13 +90,27 @@ int complexity(void)
if (tx.ip_dst_isrange)
{
- nr_da = tx.ip_dst_stop - tx.ip_dst_start + 1;
- //fprintf(stderr,"DA Range = %lu\n",nr_da);
+ if (ipv6_mode)
+ {
+ nr_da = get_ip6_range_count(tx.ip6_dst_start, tx.ip6_dst_stop);
+ }
+ else
+ {
+ nr_da = tx.ip_dst_stop - tx.ip_dst_start + 1;
+ }
+ //fprintf(stderr,"DA Range = %lu\n",nr_da);
}
if (tx.ip_src_isrange)
{
- nr_sa = tx.ip_src_stop - tx.ip_src_start + 1;
+ if (ipv6_mode)
+ {
+ nr_sa = get_ip6_range_count(tx.ip6_src_start, tx.ip6_src_stop);
+ }
+ else
+ {
+ nr_sa = tx.ip_src_stop - tx.ip_src_start + 1;
+ }
//fprintf(stderr,"SA Range = %lu\n",nr_sa);
}
@@ -195,6 +209,22 @@ int send_frame (libnet_t *l, libnet_ptag_t t3, libnet_ptag_t t4)
{
AGAIN:
+ if (ipv6_mode) {
+ switch (mode) {
+ case ICMP6:
+ update_ISUM(l, t4);
+ break;
+ case UDP:
+ case DNS:
+ case RTP:
+ case SYSLOG:
+ update_USUM(l, t4);
+ break;
+ case TCP:
+ update_TSUM(l, t4);
+ break;
+ }
+ }
if (verbose) (void) print_frame_details();
libnet_write(l);
diff --git a/staging/tools.c b/staging/tools.c
index be8eace..9d2d1be 100644
--- a/staging/tools.c
+++ b/staging/tools.c
@@ -29,6 +29,8 @@
// xstr2lint ........... Same as above but returns an unsigned long long int
// get_ip_range_dst .... Parses string for an IP range and sets start/stop addresses
// get_ip_range_src .... Same for source addresses
+// get_ip6_range_dst ... Parses string for an IPv6 range and sets start/stop addresses
+// get_ip6_range_src ... Same for source addresses
// check_eth_mac_txt ... Scans tx.eth_dst|src_txt and sets tx.eth_dst|src appropriately
// get_port_range ...... Parses string for a dst|src-port range and sets start/stop values
// get_tcp_flags ....... Parses string for TCP arguments and sets tx.tcp_control
@@ -54,7 +56,11 @@
#include "mz.h"
+#define CMP_INT(a, b) ((a) < (b) ? -1 : (a) > (b))
+#define IPV6_MAX_RANGE_LEN strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128")
+#define IPV6_MIN_RANGE_LEN strlen("::/0")
+static int in6_range_too_big(struct libnet_in6_addr start, struct libnet_in6_addr stop);
// Scan 'str' for an argument 'arg_name' and returns its value in arg_value
// Return value: number of occurences of arg_name
@@ -188,6 +194,91 @@ unsigned long long int xstr2lint(char *str)
}
+/*
+ * Return the IPv6 broadcast address for the given network/mask.
+ */
+struct libnet_in6_addr
+in6_addr_bcast(struct libnet_in6_addr addr, unsigned int masklen)
+{
+ struct libnet_in6_addr bcast;
+ uint32_t mask = 0;
+ int i = 3;
+ if (masklen > 128) {
+ fprintf(stderr, "Invalid IPv6 masklen: %u\n", masklen);
+ exit(1);
+ }
+ masklen = 128 - masklen;
+
+ bcast = addr;
+
+ for (i = 3; i >= 0; i--, masklen -= 32) {
+ if (masklen <= 32) {
+ bcast.__u6_addr.__u6_addr32[i] = htonl(ntohl(bcast.__u6_addr.__u6_addr32[i]) | ((uint32_t) (~0) >> (32 - masklen)));
+ break;
+ }
+ bcast.__u6_addr.__u6_addr32[i] = (uint32_t) (~0);
+ }
+ return bcast;
+}
+
+/*
+ * Returns 0 if the given IPv6 addresses are equal,
+ * -1 if addr1 is lower than addr2,
+ * 1 if addr2 is lower than addr1.
+ */
+int in6_addr_cmp(struct libnet_in6_addr addr1,
+ struct libnet_in6_addr addr2)
+{
+ uint32_t *p1 = addr1.__u6_addr.__u6_addr32,
+ *p2 = addr2.__u6_addr.__u6_addr32;
+ int i, val = 0;
+
+ for (i = 0; i < 4; i++) {
+ val = CMP_INT(ntohl(*p1++), ntohl(*p2++));
+ if (val) {
+ break;
+ }
+ }
+ return val;
+}
+
+/*
+ * Calculate the address that comes immediately after the one given.
+ * Store the result in *dst.
+ * Returns 1 if an overflow occurred. Otherwise, returns 0.
+ */
+int
+incr_in6_addr(struct libnet_in6_addr src, struct libnet_in6_addr *dst)
+{
+ uint32_t i = 16, carry = 1;
+ uint8_t *addr;
+ *dst = src;
+ addr = dst->__u6_addr.__u6_addr8;
+ while (carry && i) {
+ addr[i - 1] += carry;
+ if (addr[i - 1] > 0xff || !addr[i - 1]) {
+ addr[i - 1] &= 0xff;
+ } else {
+ carry = 0;
+ }
+ i--;
+ }
+ return (int)carry;
+}
+
+
+/*
+ * Return 1 if the number of addresses that are in the range from start to stop
+ * is greater than what can be stored in a uint64_t. Otherwise, return 0.
+ */
+static int
+in6_range_too_big(struct libnet_in6_addr start, struct libnet_in6_addr stop)
+{
+ return (
+ (start.__u6_addr.__u6_addr32[0] != stop.__u6_addr.__u6_addr32[0])
+ || (start.__u6_addr.__u6_addr32[1] != stop.__u6_addr.__u6_addr32[1])
+ );
+}
// Parses string 'arg' for an IP range and finds start and stop IP addresses.
@@ -383,6 +474,169 @@ int get_ip_range_src (char *arg)
}
+/*
+ * Return the number of IPv6 addresses in the range from start to stop or
+ * UINT64_MAX, whichever is smaller.
+ */
+uint64_t get_ip6_range_count(struct libnet_in6_addr start, struct libnet_in6_addr stop)
+{
+ uint64_t retval = 0;
+ if (in6_range_too_big(start, stop)) {
+ return UINT64_MAX;
+ }
+ retval = ((uint64_t)(ntohl(stop.__u6_addr.__u6_addr32[2]) - ntohl(start.__u6_addr.__u6_addr32[2])) << 32)
+ + (ntohl(stop.__u6_addr.__u6_addr32[3]) - ntohl(start.__u6_addr.__u6_addr32[3]));
+ if (retval < UINT64_MAX) {
+ retval++;
+ }
+ return retval;
+}
+
+int get_ip6_range_src (char *arg, libnet_t *l)
+{
+
+ int
+ i, len,
+ found_slash=0, found_dash=0;
+
+ unsigned int q;
+ struct libnet_in6_addr tmp_in6_addr;
+ uint32_t mask, invmask;
+ char *start_str, *stop_str;
+
+ len = strnlen(arg, IPV6_MAX_RANGE_LEN);
+
+ if ( (len > IPV6_MAX_RANGE_LEN) || (len < IPV6_MIN_RANGE_LEN) )
+ return 1; // ERROR: no range
+
+ // Find "-" or "/"
+ for (i=0; i<len; i++)
+ {
+ if (arg[i]=='/') found_slash=1;
+ if (arg[i]=='-') found_dash=1;
+ }
+
+ if ((found_slash) && (found_dash))
+ exit (1); // ERROR: Wrong range string syntax (cannot use both "/" and "-" !!!
+
+ if (found_dash)
+ {
+ start_str = strtok (arg, "-");
+ stop_str = strtok (NULL, "-");
+
+ // These are the start and stop IP addresses of the range:
+ tx.ip6_src_start = libnet_name2addr6 (l, start_str, LIBNET_DONT_RESOLVE);
+ tx.ip6_src_stop = libnet_name2addr6 (l, stop_str, LIBNET_DONT_RESOLVE);
+ //XXX Not sure if this needs to be modified
+ //tx.ip_src_h = tx.ip_src_start;
+ //tx.ip_src = str2ip32_rev (start_str);
+
+ if (in6_addr_cmp(tx.ip6_src_start, tx.ip6_src_stop) < 0)
+ {
+ // Set range flag:
+ tx.ip_src_isrange = 1;
+ if (in6_range_too_big(tx.ip6_src_start, tx.ip6_src_stop)) {
+ fprintf(stderr, "The IPv6 range is too big. It must be smaller than a /64.\n");
+ exit (1);
+ }
+ return 0;
+ }
+ else
+ {
+ tx.ip_src_isrange = 0;
+ return 1; // ERROR: stop value must be greater than start value !!!
+ }
+ }
+ else if (found_slash)
+ {
+ start_str = strtok (arg, "/");
+ stop_str = strtok (NULL, "/"); // Actually contains the prefix length, e. g. "24"
+
+ q = (unsigned int) str2int (stop_str);
+
+ tmp_in6_addr = libnet_name2addr6 (l, start_str, LIBNET_DONT_RESOLVE);
+ tx.ip6_src_stop = in6_addr_bcast(tmp_in6_addr, q);
+ incr_in6_addr(tmp_in6_addr, &tx.ip6_src_start), // ensure that we do not start with the net-id
+ // TODO decrement the bcast address so it's not included in the range.
+ tx.ip_src_isrange = 1;
+ if (in6_range_too_big(tx.ip6_src_start, tx.ip6_src_stop)) {
+ fprintf(stderr, "The IPv6 range is too big. It must be smaller than a /64.\n");
+ exit (1);
+ }
+ return 0;
+ }
+
+ return 1; // ERROR: The specified argument string is not a range!
+}
+
+int get_ip6_range_dst (char *arg, libnet_t *l)
+{
+
+ int
+ i, len,
+ found_slash=0, found_dash=0;
+
+ unsigned int q;
+ uint32_t mask, invmask;
+ struct libnet_in6_addr tmp_in6_addr;
+ char *start_str, *stop_str;
+
+ len = strnlen(arg,IPV6_MAX_RANGE_LEN);
+
+ if ( (len > IPV6_MAX_RANGE_LEN) || (len < IPV6_MIN_RANGE_LEN) )
+ return 1; // ERROR: no range
+
+ // Find "-" or "/"
+ for (i=0; i<len; i++)
+ {
+ if (arg[i]=='/') found_slash=1;
+ if (arg[i]=='-') found_dash=1;
+ }
+
+ if ((found_slash) && (found_dash))
+ exit (1); // ERROR: Wrong range string syntax (cannot use both "/" and "-" !!!
+
+ if (found_dash)
+ {
+ start_str = strtok (arg, "-");
+ stop_str = strtok (NULL, "-");
+
+ // These are the start and stop IP addresses of the range:
+ tx.ip6_dst_start = libnet_name2addr6 (l, start_str, LIBNET_DONT_RESOLVE);
+ tx.ip6_dst_stop = libnet_name2addr6 (l, stop_str, LIBNET_DONT_RESOLVE);
+ //XXX Not sure if this needs to be modified
+ //tx.ip_dst_h = tx.ip_dst_start;
+ //tx.ip_dst = str2ip32_rev (start_str);
+
+ if (in6_addr_cmp(tx.ip6_dst_start, tx.ip6_dst_stop) < 0)
+ {
+ // Set range flag:
+ tx.ip_dst_isrange = 1;
+ return 0;
+ }
+ else
+ {
+ tx.ip_dst_isrange = 0;
+ return 1; // ERROR: stop value must be greater than start value !!!
+ }
+ }
+ else if (found_slash)
+ {
+ start_str = strtok (arg, "/");
+ stop_str = strtok (NULL, "/"); // Actually contains the prefix length, e. g. "24"
+
+ q = (unsigned int) str2int (stop_str);
+
+ tmp_in6_addr = libnet_name2addr6 (l, start_str, LIBNET_DONT_RESOLVE);
+ tx.ip6_dst_stop = in6_addr_bcast(tmp_in6_addr, q);
+ incr_in6_addr(tmp_in6_addr, &tx.ip6_dst_start), // ensure that we do not start with the net-id
+ // TODO decrement the bcast address so it's not included in the range.
+ tx.ip_dst_isrange = 1;
+ return 0;
+ }
+
+ return 1; // ERROR: The specified argument string is not a range!
+}
// Scans tx.eth_dst_txt or tx.eth_src_txt and sets the corresponding
// MAC addresses (tx.eth_dst or tx.eth_src) accordingly.