libxt_mac.c revision d09b6d591ca7d7d7575cb6aa20384c9830f777ab
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* Shared library add-on to iptables to add MAC address support. */ 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdbool.h> 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdio.h> 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <netdb.h> 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string.h> 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdlib.h> 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <getopt.h> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(__GLIBC__) && __GLIBC__ == 2 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <net/ethernet.h> 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <linux/if_ether.h> 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <xtables.h> 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <linux/netfilter/xt_mac.h> 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void mac_help(void) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf( 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)"mac match options:\n" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)"[!] --mac-source XX:XX:XX:XX:XX:XX\n" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)" Match source MAC address\n"); 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const struct option mac_opts[] = { 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {.name = "mac-source", .has_arg = true, .val = '1'}, 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) XT_GETOPT_TABLEEND, 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)parse_mac(const char *mac, struct xt_mac_info *info) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned int i = 0; 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (strlen(mac) != ETH_ALEN*3-1) 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xtables_error(PARAMETER_PROBLEM, "Bad mac address \"%s\"", mac); 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (i = 0; i < ETH_ALEN; i++) { 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) long number; 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) char *end; 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) number = strtol(mac + i*3, &end, 16); 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (end == mac + i*3 + 2 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) && number >= 0 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) && number <= 255) 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) info->srcaddr[i] = number; 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xtables_error(PARAMETER_PROBLEM, 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Bad mac address `%s'", mac); 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)mac_parse(int c, char **argv, int invert, unsigned int *flags, 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const void *entry, struct xt_entry_match **match) 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct xt_mac_info *macinfo = (struct xt_mac_info *)(*match)->data; 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) switch (c) { 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case '1': 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xtables_check_inverse(optarg, &invert, &optind, 0, argv); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parse_mac(optarg, macinfo); 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (invert) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) macinfo->invert = 1; 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *flags = 1; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 1; 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void print_mac(const unsigned char macaddress[ETH_ALEN]) 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned int i; 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("%02X", macaddress[0]); 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (i = 1; i < ETH_ALEN; i++) 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf(":%02X", macaddress[i]); 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf(" "); 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void mac_check(unsigned int flags) 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!flags) 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xtables_error(PARAMETER_PROBLEM, 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "You must specify `--mac-source'"); 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)mac_print(const void *ip, const struct xt_entry_match *match, int numeric) 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const struct xt_mac_info *info = (void *)match->data; 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("MAC "); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (info->invert) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("! "); 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) print_mac(info->srcaddr); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void mac_save(const void *ip, const struct xt_entry_match *match) 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const struct xt_mac_info *info = (void *)match->data; 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (info->invert) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("! "); 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("--mac-source "); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) print_mac(info->srcaddr); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static struct xtables_match mac_match = { 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .family = NFPROTO_UNSPEC, 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .name = "mac", 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .version = XTABLES_VERSION, 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .size = XT_ALIGN(sizeof(struct xt_mac_info)), 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .userspacesize = XT_ALIGN(sizeof(struct xt_mac_info)), 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .help = mac_help, 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .parse = mac_parse, 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .final_check = mac_check, 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .print = mac_print, 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .save = mac_save, 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .extra_opts = mac_opts, 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void _init(void) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xtables_register_match(&mac_match); 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)