--- userspace/extensions/libipt_mac.c~ 2002-10-15 17:12:27.000000000 +0200 +++ userspace/extensions/libipt_mac.c 2002-10-15 20:52:33.000000000 +0200 @@ -20,11 +20,14 @@ "MAC v%s options:\n" " --mac-source [!] XX:XX:XX:XX:XX:XX\n" " Match source MAC address\n" +" --mac-mask XX:XX:XX:XX:XX:XX\n" +" Apply mask to source MAC address\n" "\n", IPTABLES_VERSION); } static struct option opts[] = { { "mac-source", 1, 0, '1' }, + { "mac-mask", 1, 0, '2' }, {0} }; @@ -37,12 +40,13 @@ } static void -parse_mac(const char *mac, struct ipt_mac_info *info) +parse_mac(const char *mac, unsigned char macaddress[ETH_ALEN], + char *errmsg) { unsigned int i = 0; if (strlen(mac) != ETH_ALEN*3-1) - exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac); + exit_error(PARAMETER_PROBLEM, "%s `%s'", errmsg, mac); for (i = 0; i < ETH_ALEN; i++) { long number; @@ -53,10 +57,10 @@ if (end == mac + i*3 + 2 && number >= 0 && number <= 255) - info->srcaddr[i] = number; + macaddress[i] = number; else exit_error(PARAMETER_PROBLEM, - "Bad mac address `%s'", mac); + "%s `%s'", errmsg, mac); } } @@ -69,15 +73,40 @@ struct ipt_entry_match **match) { struct ipt_mac_info *macinfo = (struct ipt_mac_info *)(*match)->data; + static int mask_parsed = 0; + int i; switch (c) { case '1': check_inverse(optarg, &invert, &optind, 0); - parse_mac(argv[optind-1], macinfo); + parse_mac(argv[optind-1], macinfo->srcaddr, "Bad mac address"); if (invert) macinfo->invert = 1; + if (!mask_parsed) { + macinfo->is_mask = 0; + } else if (macinfo->is_mask) { + for (i = 0; i < ETH_ALEN; i++) + macinfo->srcaddr[i] &= macinfo->mask[i]; + } *flags = 1; break; + + case '2': + check_inverse(optarg, &invert, &optind, 0); + if (invert) + exit_error(PARAMETER_PROBLEM, + "mac-mask: unexpected `!'"); + parse_mac(argv[optind-1], macinfo->mask, + "Bad mac mask"); + macinfo->is_mask = 0; + mask_parsed = 1; + for (i = 0; i < ETH_ALEN; i++) { + macinfo->srcaddr[i] &= macinfo->mask[i]; + if (macinfo->mask[i] != 0xFF) { + macinfo->is_mask = 1; + } + } + break; default: return 0; @@ -86,13 +115,20 @@ return 1; } -static void print_mac(unsigned char macaddress[ETH_ALEN], int invert) +static void print_mac(unsigned char macaddress[ETH_ALEN], + unsigned char macmask[ETH_ALEN], + int invert) { unsigned int i; - + printf("%s%02X", invert ? "! " : "", macaddress[0]); for (i = 1; i < ETH_ALEN; i++) printf(":%02X", macaddress[i]); + if (macmask != NULL) { + printf("/%02X", macmask[0]); + for (i = 1; i < ETH_ALEN; i++) + printf(":%02X", macmask[i]); + } printf(" "); } @@ -112,6 +148,8 @@ { printf("MAC "); print_mac(((struct ipt_mac_info *)match->data)->srcaddr, + ((struct ipt_mac_info *)match->data)->is_mask ? + ((struct ipt_mac_info *)match->data)->mask : NULL, ((struct ipt_mac_info *)match->data)->invert); } @@ -120,7 +158,11 @@ { printf("--mac-source "); print_mac(((struct ipt_mac_info *)match->data)->srcaddr, - ((struct ipt_mac_info *)match->data)->invert); + NULL, ((struct ipt_mac_info *)match->data)->invert); + if (((struct ipt_mac_info *)match->data)->is_mask) { + printf("--mac-mask "); + print_mac(((struct ipt_mac_info *)match->data)->mask, NULL, 0); + } } static