| #include <stdio.h> |
| #include <xtables.h> |
| #include <linux/netfilter/xt_physdev.h> |
| |
| enum { |
| O_PHYSDEV_IN = 0, |
| O_PHYSDEV_OUT, |
| O_PHYSDEV_IS_IN, |
| O_PHYSDEV_IS_OUT, |
| O_PHYSDEV_IS_BRIDGED, |
| }; |
| |
| static void physdev_help(void) |
| { |
| printf( |
| "physdev match options:\n" |
| " [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n" |
| " [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n" |
| " [!] --physdev-is-in arrived on a bridge device\n" |
| " [!] --physdev-is-out will leave on a bridge device\n" |
| " [!] --physdev-is-bridged it's a bridged packet\n"); |
| } |
| |
| #define s struct xt_physdev_info |
| static const struct xt_option_entry physdev_opts[] = { |
| {.name = "physdev-in", .id = O_PHYSDEV_IN, .type = XTTYPE_STRING, |
| .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physindev)}, |
| {.name = "physdev-out", .id = O_PHYSDEV_OUT, .type = XTTYPE_STRING, |
| .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physoutdev)}, |
| {.name = "physdev-is-in", .id = O_PHYSDEV_IS_IN, .type = XTTYPE_NONE, |
| .flags = XTOPT_INVERT}, |
| {.name = "physdev-is-out", .id = O_PHYSDEV_IS_OUT, |
| .type = XTTYPE_NONE, .flags = XTOPT_INVERT}, |
| {.name = "physdev-is-bridged", .id = O_PHYSDEV_IS_BRIDGED, |
| .type = XTTYPE_NONE, .flags = XTOPT_INVERT}, |
| XTOPT_TABLEEND, |
| }; |
| #undef s |
| |
| static void physdev_parse(struct xt_option_call *cb) |
| { |
| struct xt_physdev_info *info = cb->data; |
| |
| xtables_option_parse(cb); |
| switch (cb->entry->id) { |
| case O_PHYSDEV_IN: |
| xtables_parse_interface(cb->arg, info->physindev, |
| (unsigned char *)info->in_mask); |
| if (cb->invert) |
| info->invert |= XT_PHYSDEV_OP_IN; |
| info->bitmask |= XT_PHYSDEV_OP_IN; |
| break; |
| case O_PHYSDEV_OUT: |
| xtables_parse_interface(cb->arg, info->physoutdev, |
| (unsigned char *)info->out_mask); |
| if (cb->invert) |
| info->invert |= XT_PHYSDEV_OP_OUT; |
| info->bitmask |= XT_PHYSDEV_OP_OUT; |
| break; |
| case O_PHYSDEV_IS_IN: |
| info->bitmask |= XT_PHYSDEV_OP_ISIN; |
| if (cb->invert) |
| info->invert |= XT_PHYSDEV_OP_ISIN; |
| break; |
| case O_PHYSDEV_IS_OUT: |
| info->bitmask |= XT_PHYSDEV_OP_ISOUT; |
| if (cb->invert) |
| info->invert |= XT_PHYSDEV_OP_ISOUT; |
| break; |
| case O_PHYSDEV_IS_BRIDGED: |
| if (cb->invert) |
| info->invert |= XT_PHYSDEV_OP_BRIDGED; |
| info->bitmask |= XT_PHYSDEV_OP_BRIDGED; |
| break; |
| } |
| } |
| |
| static void physdev_check(struct xt_fcheck_call *cb) |
| { |
| if (cb->xflags == 0) |
| xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified"); |
| } |
| |
| static void |
| physdev_print(const void *ip, const struct xt_entry_match *match, int numeric) |
| { |
| const struct xt_physdev_info *info = (const void *)match->data; |
| |
| printf(" PHYSDEV match"); |
| if (info->bitmask & XT_PHYSDEV_OP_ISIN) |
| printf("%s --physdev-is-in", |
| info->invert & XT_PHYSDEV_OP_ISIN ? " !":""); |
| if (info->bitmask & XT_PHYSDEV_OP_IN) |
| printf("%s --physdev-in %s", |
| (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev); |
| |
| if (info->bitmask & XT_PHYSDEV_OP_ISOUT) |
| printf("%s --physdev-is-out", |
| info->invert & XT_PHYSDEV_OP_ISOUT ? " !":""); |
| if (info->bitmask & XT_PHYSDEV_OP_OUT) |
| printf("%s --physdev-out %s", |
| (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev); |
| if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) |
| printf("%s --physdev-is-bridged", |
| info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":""); |
| } |
| |
| static void physdev_save(const void *ip, const struct xt_entry_match *match) |
| { |
| const struct xt_physdev_info *info = (const void *)match->data; |
| |
| if (info->bitmask & XT_PHYSDEV_OP_ISIN) |
| printf("%s --physdev-is-in", |
| (info->invert & XT_PHYSDEV_OP_ISIN) ? " !" : ""); |
| if (info->bitmask & XT_PHYSDEV_OP_IN) |
| printf("%s --physdev-in %s", |
| (info->invert & XT_PHYSDEV_OP_IN) ? " !" : "", |
| info->physindev); |
| |
| if (info->bitmask & XT_PHYSDEV_OP_ISOUT) |
| printf("%s --physdev-is-out", |
| (info->invert & XT_PHYSDEV_OP_ISOUT) ? " !" : ""); |
| if (info->bitmask & XT_PHYSDEV_OP_OUT) |
| printf("%s --physdev-out %s", |
| (info->invert & XT_PHYSDEV_OP_OUT) ? " !" : "", |
| info->physoutdev); |
| if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) |
| printf("%s --physdev-is-bridged", |
| (info->invert & XT_PHYSDEV_OP_BRIDGED) ? " !" : ""); |
| } |
| |
| static struct xtables_match physdev_match = { |
| .family = NFPROTO_UNSPEC, |
| .name = "physdev", |
| .version = XTABLES_VERSION, |
| .size = XT_ALIGN(sizeof(struct xt_physdev_info)), |
| .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)), |
| .help = physdev_help, |
| .print = physdev_print, |
| .save = physdev_save, |
| .x6_parse = physdev_parse, |
| .x6_fcheck = physdev_check, |
| .x6_options = physdev_opts, |
| }; |
| |
| void _init(void) |
| { |
| xtables_register_match(&physdev_match); |
| } |