libxt_physdev.c revision 69f564e3890976461de0016cd81171ff8bfa8353
11254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer/* Shared library add-on to iptables to add bridge port matching support. */ 21254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <stdio.h> 31254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <string.h> 41254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <stdlib.h> 51254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <getopt.h> 61254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <ctype.h> 7fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI#include <xtables.h> 8fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI#include <linux/netfilter/xt_physdev.h> 91254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#if defined(__GLIBC__) && __GLIBC__ == 2 101254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <net/ethernet.h> 111254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#else 121254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <linux/if_ether.h> 131254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#endif 141254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 15181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_help(void) 161254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 171254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer printf( 188b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"physdev match options:\n" 19967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt" [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n" 20967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt" [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n" 2130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer" [!] --physdev-is-in arrived on a bridge device\n" 2230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer" [!] --physdev-is-out will leave on a bridge device\n" 238b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt" [!] --physdev-is-bridged it's a bridged packet\n"); 241254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 251254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 26181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic const struct option physdev_opts[] = { 27500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-in", 1, NULL, '1' }, 28500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-out", 1, NULL, '2' }, 29500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-is-in", 0, NULL, '3' }, 30500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-is-out", 0, NULL, '4' }, 31500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-is-bridged", 0, NULL, '5' }, 329ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 331254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}; 341254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 351254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymerstatic int 36181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtphysdev_parse(int c, char **argv, int invert, unsigned int *flags, 37181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt const void *entry, struct xt_entry_match **match) 381254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 39fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI struct xt_physdev_info *info = 40fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (struct xt_physdev_info*)(*match)->data; 411254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 421254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer switch (c) { 431254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer case '1': 44fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_IN) 4530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 460f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt xtables_check_inverse(optarg, &invert, &optind, 0); 47aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt xtables_parse_interface(argv[optind-1], info->physindev, 48efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte (unsigned char *)info->in_mask); 491254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer if (invert) 50fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_IN; 51fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_IN; 52fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_IN; 531254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer break; 541254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 551254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer case '2': 56fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_OUT) 5730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 580f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt xtables_check_inverse(optarg, &invert, &optind, 0); 59aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt xtables_parse_interface(argv[optind-1], info->physoutdev, 60efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte (unsigned char *)info->out_mask); 611254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer if (invert) 62fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_OUT; 63fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_OUT; 64fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_OUT; 6530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer break; 6630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 6730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer case '3': 68fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_ISIN) 6930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 700f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt xtables_check_inverse(optarg, &invert, &optind, 0); 71fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_ISIN; 7230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (invert) 73fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_ISIN; 74fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_ISIN; 7530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer break; 7630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 7730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer case '4': 78fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_ISOUT) 7930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 800f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt xtables_check_inverse(optarg, &invert, &optind, 0); 81fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_ISOUT; 8230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (invert) 83fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_ISOUT; 84fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_ISOUT; 8530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer break; 8630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 8730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer case '5': 88fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_BRIDGED) 8930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 900f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt xtables_check_inverse(optarg, &invert, &optind, 0); 9130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (invert) 92fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_BRIDGED; 93fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_BRIDGED; 94fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_BRIDGED; 951254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer break; 961254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 971254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer default: 981254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer return 0; 991254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer } 1001254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1011254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer return 1; 10230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymermultiple_use: 1031829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 10430596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer "multiple use of the same physdev option is not allowed"); 1051254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1061254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1071254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 108181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_check(unsigned int flags) 1091254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 11030596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (flags == 0) 1111829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified"); 1121254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1131254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1141254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymerstatic void 115181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtphysdev_print(const void *ip, const struct xt_entry_match *match, int numeric) 1161254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 11769f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt const struct xt_physdev_info *info = (const void *)match->data; 1181254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1191254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer printf("PHYSDEV match"); 120fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISIN) 12130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-is-in", 122fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert & XT_PHYSDEV_OP_ISIN ? " !":""); 123fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_IN) 12430596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-in %s", 125fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev); 12630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 127fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 12830596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-is-out", 129fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert & XT_PHYSDEV_OP_ISOUT ? " !":""); 130fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_OUT) 13130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-out %s", 132fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev); 133fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 13430596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-is-bridged", 135fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":""); 1361254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer printf(" "); 1371254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1381254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 139181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_save(const void *ip, const struct xt_entry_match *match) 1401254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 14169f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt const struct xt_physdev_info *info = (const void *)match->data; 1421254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 143fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISIN) 144d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-is-in ", 145d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_ISIN) ? "! " : ""); 146fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_IN) 147d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-in %s ", 148d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_IN) ? "! " : "", 149d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt info->physindev); 15030596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 151fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 152d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-is-out ", 153d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_ISOUT) ? "! " : ""); 154fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_OUT) 155d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-out %s ", 156d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_OUT) ? "! " : "", 157d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt info->physoutdev); 158fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 159d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-is-bridged ", 160d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_BRIDGED) ? "! " : ""); 1611254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1621254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 163181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match physdev_match = { 16403d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt .family = NFPROTO_IPV4, 1658caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira .name = "physdev", 1668b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 167fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_physdev_info)), 168fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)), 169181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = physdev_help, 170181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .parse = physdev_parse, 171181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .final_check = physdev_check, 172181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = physdev_print, 173181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = physdev_save, 174181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .extra_opts = physdev_opts, 175fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI}; 176fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI 177181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match physdev_match6 = { 17803d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt .family = NFPROTO_IPV6, 179fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .name = "physdev", 1808b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 181fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_physdev_info)), 182fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)), 183181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = physdev_help, 184181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .parse = physdev_parse, 185181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .final_check = physdev_check, 186181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = physdev_print, 187181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = physdev_save, 188181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .extra_opts = physdev_opts, 1891254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}; 1901254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1911254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymervoid _init(void) 1921254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 193181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&physdev_match); 194181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&physdev_match6); 1951254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 196