libxt_physdev.c revision bbe83862a5e1baf15f7c923352d4afdf59bc70e2
1/* Shared library add-on to iptables to add bridge port matching support. */ 2#include <stdio.h> 3#include <string.h> 4#include <stdlib.h> 5#include <getopt.h> 6#include <ctype.h> 7#include <xtables.h> 8#include <linux/netfilter/xt_physdev.h> 9#if defined(__GLIBC__) && __GLIBC__ == 2 10#include <net/ethernet.h> 11#else 12#include <linux/if_ether.h> 13#endif 14 15static void physdev_help(void) 16{ 17 printf( 18"physdev match options:\n" 19" [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n" 20" [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n" 21" [!] --physdev-is-in arrived on a bridge device\n" 22" [!] --physdev-is-out will leave on a bridge device\n" 23" [!] --physdev-is-bridged it's a bridged packet\n"); 24} 25 26static const struct option physdev_opts[] = { 27 { "physdev-in", 1, NULL, '1' }, 28 { "physdev-out", 1, NULL, '2' }, 29 { "physdev-is-in", 0, NULL, '3' }, 30 { "physdev-is-out", 0, NULL, '4' }, 31 { "physdev-is-bridged", 0, NULL, '5' }, 32 { .name = NULL } 33}; 34 35static int 36physdev_parse(int c, char **argv, int invert, unsigned int *flags, 37 const void *entry, struct xt_entry_match **match) 38{ 39 struct xt_physdev_info *info = 40 (struct xt_physdev_info*)(*match)->data; 41 42 switch (c) { 43 case '1': 44 if (*flags & XT_PHYSDEV_OP_IN) 45 goto multiple_use; 46 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 47 xtables_parse_interface(optarg, info->physindev, 48 (unsigned char *)info->in_mask); 49 if (invert) 50 info->invert |= XT_PHYSDEV_OP_IN; 51 info->bitmask |= XT_PHYSDEV_OP_IN; 52 *flags |= XT_PHYSDEV_OP_IN; 53 break; 54 55 case '2': 56 if (*flags & XT_PHYSDEV_OP_OUT) 57 goto multiple_use; 58 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 59 xtables_parse_interface(optarg, info->physoutdev, 60 (unsigned char *)info->out_mask); 61 if (invert) 62 info->invert |= XT_PHYSDEV_OP_OUT; 63 info->bitmask |= XT_PHYSDEV_OP_OUT; 64 *flags |= XT_PHYSDEV_OP_OUT; 65 break; 66 67 case '3': 68 if (*flags & XT_PHYSDEV_OP_ISIN) 69 goto multiple_use; 70 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 71 info->bitmask |= XT_PHYSDEV_OP_ISIN; 72 if (invert) 73 info->invert |= XT_PHYSDEV_OP_ISIN; 74 *flags |= XT_PHYSDEV_OP_ISIN; 75 break; 76 77 case '4': 78 if (*flags & XT_PHYSDEV_OP_ISOUT) 79 goto multiple_use; 80 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 81 info->bitmask |= XT_PHYSDEV_OP_ISOUT; 82 if (invert) 83 info->invert |= XT_PHYSDEV_OP_ISOUT; 84 *flags |= XT_PHYSDEV_OP_ISOUT; 85 break; 86 87 case '5': 88 if (*flags & XT_PHYSDEV_OP_BRIDGED) 89 goto multiple_use; 90 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 91 if (invert) 92 info->invert |= XT_PHYSDEV_OP_BRIDGED; 93 *flags |= XT_PHYSDEV_OP_BRIDGED; 94 info->bitmask |= XT_PHYSDEV_OP_BRIDGED; 95 break; 96 97 default: 98 return 0; 99 } 100 101 return 1; 102multiple_use: 103 xtables_error(PARAMETER_PROBLEM, 104 "multiple use of the same physdev option is not allowed"); 105 106} 107 108static void physdev_check(unsigned int flags) 109{ 110 if (flags == 0) 111 xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified"); 112} 113 114static void 115physdev_print(const void *ip, const struct xt_entry_match *match, int numeric) 116{ 117 const struct xt_physdev_info *info = (const void *)match->data; 118 119 printf("PHYSDEV match"); 120 if (info->bitmask & XT_PHYSDEV_OP_ISIN) 121 printf("%s --physdev-is-in", 122 info->invert & XT_PHYSDEV_OP_ISIN ? " !":""); 123 if (info->bitmask & XT_PHYSDEV_OP_IN) 124 printf("%s --physdev-in %s", 125 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev); 126 127 if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 128 printf("%s --physdev-is-out", 129 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":""); 130 if (info->bitmask & XT_PHYSDEV_OP_OUT) 131 printf("%s --physdev-out %s", 132 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev); 133 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 134 printf("%s --physdev-is-bridged", 135 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":""); 136 printf(" "); 137} 138 139static void physdev_save(const void *ip, const struct xt_entry_match *match) 140{ 141 const struct xt_physdev_info *info = (const void *)match->data; 142 143 if (info->bitmask & XT_PHYSDEV_OP_ISIN) 144 printf("%s--physdev-is-in ", 145 (info->invert & XT_PHYSDEV_OP_ISIN) ? "! " : ""); 146 if (info->bitmask & XT_PHYSDEV_OP_IN) 147 printf("%s--physdev-in %s ", 148 (info->invert & XT_PHYSDEV_OP_IN) ? "! " : "", 149 info->physindev); 150 151 if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 152 printf("%s--physdev-is-out ", 153 (info->invert & XT_PHYSDEV_OP_ISOUT) ? "! " : ""); 154 if (info->bitmask & XT_PHYSDEV_OP_OUT) 155 printf("%s--physdev-out %s ", 156 (info->invert & XT_PHYSDEV_OP_OUT) ? "! " : "", 157 info->physoutdev); 158 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 159 printf("%s--physdev-is-bridged ", 160 (info->invert & XT_PHYSDEV_OP_BRIDGED) ? "! " : ""); 161} 162 163static struct xtables_match physdev_match = { 164 .family = NFPROTO_UNSPEC, 165 .name = "physdev", 166 .version = XTABLES_VERSION, 167 .size = XT_ALIGN(sizeof(struct xt_physdev_info)), 168 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)), 169 .help = physdev_help, 170 .parse = physdev_parse, 171 .final_check = physdev_check, 172 .print = physdev_print, 173 .save = physdev_save, 174 .extra_opts = physdev_opts, 175}; 176 177void _init(void) 178{ 179 xtables_register_match(&physdev_match); 180} 181