1 #include <stdio.h> 2 #include <xtables.h> 3 #include <linux/netfilter/xt_physdev.h> 4 5 enum { 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 13 static 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 25 static 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 40 static 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 78 static 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 84 static void 85 physdev_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 108 static 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 132 static 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 146 void _init(void) 147 { 148 xtables_register_match(&physdev_match); 149 } 150