From 4941ee4a2accc1d1a5d38148ec1378487b9e1cf0 Mon Sep 17 00:00:00 2001 From: maxim Date: Wed, 9 May 2007 18:31:49 +0000 Subject: o Teach get_mac_addr_mask() to not silently accept incorrect MAC addresses. o Swap a couple of magic 6s by ETHER_ADDR_LEN. PR: bin/80913 Submitted by: Andrey V. Elsukov MFC after: 1 month --- sbin/ipfw/ipfw2.c | 60 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 22 deletions(-) (limited to 'sbin') diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index bb40006..f83c4bb 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -4373,36 +4374,50 @@ end_mask: } static void -get_mac_addr_mask(char *p, uint8_t *addr, uint8_t *mask) +get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask) { int i, l; + char *ap, *ptr, *optr; + struct ether_addr *mac; + const char *macset = "0123456789abcdefABCDEF:"; - for (i=0; i<6; i++) - addr[i] = mask[i] = 0; - if (strcmp(p, "any") == 0) + if (strcmp(p, "any") == 0) { + for (i = 0; i < ETHER_ADDR_LEN; i++) + addr[i] = mask[i] = 0; return; - - for (i=0; *p && i<6;i++, p++) { - addr[i] = strtol(p, &p, 16); - if (*p != ':') /* we start with the mask */ - break; } - if (*p == '/') { /* mask len */ - l = strtol(p+1, &p, 0); - for (i=0; l>0; l -=8, i++) - mask[i] = (l >=8) ? 0xff : (~0) << (8-l); - } else if (*p == '&') { /* mask */ - for (i=0, p++; *p && i<6;i++, p++) { - mask[i] = strtol(p, &p, 16); - if (*p != ':') - break; + + optr = ptr = strdup(p); + if ((ap = strsep(&ptr, "&/")) != NULL && *ap != 0) { + l = strlen(ap); + if (strspn(ap, macset) != l || (mac = ether_aton(ap)) == NULL) + errx(EX_DATAERR, "Incorrect MAC address"); + bcopy(mac, addr, ETHER_ADDR_LEN); + } else + errx(EX_DATAERR, "Incorrect MAC address"); + + if (ptr != NULL) { /* we have mask? */ + if (p[ptr - optr - 1] == '/') { /* mask len */ + l = strtol(ptr, &ap, 10); + if (*ap != 0 || l > ETHER_ADDR_LEN * 8 || l < 0) + errx(EX_DATAERR, "Incorrect mask length"); + for (i = 0; l > 0 && i < ETHER_ADDR_LEN; l -= 8, i++) + mask[i] = (l >= 8) ? 0xff: (~0) << (8 - l); + } else { /* mask */ + l = strlen(ptr); + if (strspn(ptr, macset) != l || + (mac = ether_aton(ptr)) == NULL) + errx(EX_DATAERR, "Incorrect mask"); + bcopy(mac, mask, ETHER_ADDR_LEN); } - } else if (*p == '\0') { - for (i=0; i<6; i++) + } else { /* default mask: ff:ff:ff:ff:ff:ff */ + for (i = 0; i < ETHER_ADDR_LEN; i++) mask[i] = 0xff; } - for (i=0; i<6; i++) + for (i = 0; i < ETHER_ADDR_LEN; i++) addr[i] &= mask[i]; + + free(optr); } /* @@ -4477,7 +4492,8 @@ add_mac(ipfw_insn *cmd, int ac, char *av[]) mac = (ipfw_insn_mac *)cmd; get_mac_addr_mask(av[0], mac->addr, mac->mask); /* dst */ - get_mac_addr_mask(av[1], &(mac->addr[6]), &(mac->mask[6])); /* src */ + get_mac_addr_mask(av[1], &(mac->addr[ETHER_ADDR_LEN]), + &(mac->mask[ETHER_ADDR_LEN])); /* src */ return cmd; } -- cgit v1.1