1#include <stdio.h> 2#include <xtables.h> 3#include <linux/netfilter/xt_physdev.h> 4 5enum { 6 O_PHYSDEV_IN = 0, 7 O_PHYSDEV_OUT, 8 O_PHYSDEV_IS_IN, 9 O_PHYSDEV_IS_OUT, 10 O_PHYSDEV_IS_BRIDGED, 11}; 12 13static void physdev_help(void) 14{ 15 printf( 16"physdev match options:\n" 17" [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n" 18" [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n" 19" [!] --physdev-is-in arrived on a bridge device\n" 20" [!] --physdev-is-out will leave on a bridge device\n" 21" [!] --physdev-is-bridged it's a bridged packet\n"); 22} 23 24#define s struct xt_physdev_info 25static const struct xt_option_entry physdev_opts[] = { 26 {.name = "physdev-in", .id = O_PHYSDEV_IN, .type = XTTYPE_STRING, 27 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physindev)}, 28 {.name = "physdev-out", .id = O_PHYSDEV_OUT, .type = XTTYPE_STRING, 29 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physoutdev)}, 30 {.name = "physdev-is-in", .id = O_PHYSDEV_IS_IN, .type = XTTYPE_NONE, 31 .flags = XTOPT_INVERT}, 32 {.name = "physdev-is-out", .id = O_PHYSDEV_IS_OUT, 33 .type = XTTYPE_NONE, .flags = XTOPT_INVERT}, 34 {.name = "physdev-is-bridged", .id = O_PHYSDEV_IS_BRIDGED, 35 .type = XTTYPE_NONE, .flags = XTOPT_INVERT}, 36 XTOPT_TABLEEND, 37}; 38#undef s 39 40static void physdev_parse(struct xt_option_call *cb) 41{ 42 struct xt_physdev_info *info = cb->data; 43 44 xtables_option_parse(cb); 45 switch (cb->entry->id) { 46 case O_PHYSDEV_IN: 47 xtables_parse_interface(cb->arg, info->physindev, 48 (unsigned char *)info->in_mask); 49 if (cb->invert) 50 info->invert |= XT_PHYSDEV_OP_IN; 51 info->bitmask |= XT_PHYSDEV_OP_IN; 52 break; 53 case O_PHYSDEV_OUT: 54 xtables_parse_interface(cb->arg, info->physoutdev, 55 (unsigned char *)info->out_mask); 56 if (cb->invert) 57 info->invert |= XT_PHYSDEV_OP_OUT; 58 info->bitmask |= XT_PHYSDEV_OP_OUT; 59 break; 60 case O_PHYSDEV_IS_IN: 61 info->bitmask |= XT_PHYSDEV_OP_ISIN; 62 if (cb->invert) 63 info->invert |= XT_PHYSDEV_OP_ISIN; 64 break; 65 case O_PHYSDEV_IS_OUT: 66 info->bitmask |= XT_PHYSDEV_OP_ISOUT; 67 if (cb->invert) 68 info->invert |= XT_PHYSDEV_OP_ISOUT; 69 break; 70 case O_PHYSDEV_IS_BRIDGED: 71 if (cb->invert) 72 info->invert |= XT_PHYSDEV_OP_BRIDGED; 73 info->bitmask |= XT_PHYSDEV_OP_BRIDGED; 74 break; 75 } 76} 77 78static void physdev_check(struct xt_fcheck_call *cb) 79{ 80 if (cb->xflags == 0) 81 xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified"); 82} 83 84static void 85physdev_print(const void *ip, const struct xt_entry_match *match, int numeric) 86{ 87 const struct xt_physdev_info *info = (const void *)match->data; 88 89 printf(" PHYSDEV match"); 90 if (info->bitmask & XT_PHYSDEV_OP_ISIN) 91 printf("%s --physdev-is-in", 92 info->invert & XT_PHYSDEV_OP_ISIN ? " !":""); 93 if (info->bitmask & XT_PHYSDEV_OP_IN) 94 printf("%s --physdev-in %s", 95 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev); 96 97 if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 98 printf("%s --physdev-is-out", 99 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":""); 100 if (info->bitmask & XT_PHYSDEV_OP_OUT) 101 printf("%s --physdev-out %s", 102 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev); 103 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 104 printf("%s --physdev-is-bridged", 105 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":""); 106} 107 108static void physdev_save(const void *ip, const struct xt_entry_match *match) 109{ 110 const struct xt_physdev_info *info = (const void *)match->data; 111 112 if (info->bitmask & XT_PHYSDEV_OP_ISIN) 113 printf("%s --physdev-is-in", 114 (info->invert & XT_PHYSDEV_OP_ISIN) ? " !" : ""); 115 if (info->bitmask & XT_PHYSDEV_OP_IN) 116 printf("%s --physdev-in %s", 117 (info->invert & XT_PHYSDEV_OP_IN) ? " !" : "", 118 info->physindev); 119 120 if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 121 printf("%s --physdev-is-out", 122 (info->invert & XT_PHYSDEV_OP_ISOUT) ? " !" : ""); 123 if (info->bitmask & XT_PHYSDEV_OP_OUT) 124 printf("%s --physdev-out %s", 125 (info->invert & XT_PHYSDEV_OP_OUT) ? " !" : "", 126 info->physoutdev); 127 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 128 printf("%s --physdev-is-bridged", 129 (info->invert & XT_PHYSDEV_OP_BRIDGED) ? " !" : ""); 130} 131 132static struct xtables_match physdev_match = { 133 .family = NFPROTO_UNSPEC, 134 .name = "physdev", 135 .version = XTABLES_VERSION, 136 .size = XT_ALIGN(sizeof(struct xt_physdev_info)), 137 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)), 138 .help = physdev_help, 139 .print = physdev_print, 140 .save = physdev_save, 141 .x6_parse = physdev_parse, 142 .x6_fcheck = physdev_check, 143 .x6_options = physdev_opts, 144}; 145 146void _init(void) 147{ 148 xtables_register_match(&physdev_match); 149} 150