1 /* Shared library add-on to iptables to add MAC address support. */ 2 #include <stdio.h> 3 #include <netdb.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <getopt.h> 7 #if defined(__GLIBC__) && __GLIBC__ == 2 8 #include <net/ethernet.h> 9 #else 10 #include <linux/if_ether.h> 11 #endif 12 #include <ip6tables.h> 13 #include <linux/netfilter_ipv6/ip6t_mac.h> 14 15 /* Function which prints out usage message. */ 16 static void 17 help(void) 18 { 19 printf( 20 "MAC v%s options:\n" 21 " --mac-source [!] XX:XX:XX:XX:XX:XX\n" 22 " Match source MAC address\n" 23 "\n", IPTABLES_VERSION); 24 } 25 26 static struct option opts[] = { 27 { "mac-source", 1, 0, '1' }, 28 {0} 29 }; 30 31 static void 32 parse_mac(const char *mac, struct ip6t_mac_info *info) 33 { 34 unsigned int i = 0; 35 36 if (strlen(mac) != ETH_ALEN*3-1) 37 exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac); 38 39 for (i = 0; i < ETH_ALEN; i++) { 40 long number; 41 char *end; 42 43 number = strtol(mac + i*3, &end, 16); 44 45 if (end == mac + i*3 + 2 46 && number >= 0 47 && number <= 255) 48 info->srcaddr[i] = number; 49 else 50 exit_error(PARAMETER_PROBLEM, 51 "Bad mac address `%s'", mac); 52 } 53 } 54 55 /* Function which parses command options; returns true if it 56 ate an option */ 57 static int 58 parse(int c, char **argv, int invert, unsigned int *flags, 59 const struct ip6t_entry *entry, 60 unsigned int *nfcache, 61 struct ip6t_entry_match **match) 62 { 63 struct ip6t_mac_info *macinfo = (struct ip6t_mac_info *)(*match)->data; 64 65 switch (c) { 66 case '1': 67 check_inverse(optarg, &invert, &optind, 0); 68 parse_mac(argv[optind-1], macinfo); 69 if (invert) 70 macinfo->invert = 1; 71 *flags = 1; 72 break; 73 74 default: 75 return 0; 76 } 77 78 return 1; 79 } 80 81 static void print_mac(unsigned char macaddress[ETH_ALEN]) 82 { 83 unsigned int i; 84 85 printf("%02X", macaddress[0]); 86 for (i = 1; i < ETH_ALEN; i++) 87 printf(":%02X", macaddress[i]); 88 printf(" "); 89 } 90 91 /* Final check; must have specified --mac. */ 92 static void final_check(unsigned int flags) 93 { 94 if (!flags) 95 exit_error(PARAMETER_PROBLEM, 96 "You must specify `--mac-source'"); 97 } 98 99 /* Prints out the matchinfo. */ 100 static void 101 print(const struct ip6t_ip6 *ip, 102 const struct ip6t_entry_match *match, 103 int numeric) 104 { 105 printf("MAC "); 106 107 if (((struct ip6t_mac_info *)match->data)->invert) 108 printf("! "); 109 110 print_mac(((struct ip6t_mac_info *)match->data)->srcaddr); 111 } 112 113 /* Saves the union ip6t_matchinfo in parsable form to stdout. */ 114 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match) 115 { 116 if (((struct ip6t_mac_info *)match->data)->invert) 117 printf("! "); 118 119 printf("--mac-source "); 120 print_mac(((struct ip6t_mac_info *)match->data)->srcaddr); 121 } 122 123 static struct ip6tables_match mac = { 124 .name = "mac", 125 .version = IPTABLES_VERSION, 126 .size = IP6T_ALIGN(sizeof(struct ip6t_mac_info)), 127 .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_mac_info)), 128 .help = &help, 129 .parse = &parse, 130 .final_check = &final_check, 131 .print = &print, 132 .save = &save, 133 .extra_opts = opts, 134 }; 135 136 void _init(void) 137 { 138 register_match6(&mac); 139 } 140