19ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* Shared library add-on to iptables to add devgroup matching support. 29ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy * 39ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 49ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy */ 59ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <stdio.h> 69ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <string.h> 79ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <stdlib.h> 89ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <errno.h> 99ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <xtables.h> 109ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <linux/netfilter/xt_devgroup.h> 119ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 129ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_help(void) 139ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 149ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy printf( 159ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"devgroup match options:\n" 169ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"[!] --src-group value[/mask] Match device group of incoming device\n" 179ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"[!] --dst-group value[/mask] Match device group of outgoing device\n" 189ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy ); 199ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 209ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 219ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyenum { 225d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt O_SRC_GROUP = 0, 235d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt O_DST_GROUP, 249ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}; 259ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 265d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic const struct xt_option_entry devgroup_opts[] = { 275d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt {.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING, 285d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt .flags = XTOPT_INVERT}, 295d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt {.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING, 305d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt .flags = XTOPT_INVERT}, 315d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt XTOPT_TABLEEND, 329ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}; 339ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 349ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* array of devgroups from /etc/iproute2/group_map */ 355d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic struct xtables_lmap *devgroups; 369ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 375d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic void devgroup_init(struct xt_entry_match *match) 389ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 395d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt const char file[] = "/etc/iproute2/group_map"; 405d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt devgroups = xtables_lmap_init(file); 415d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt if (devgroups == NULL && errno != ENOENT) 425d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno)); 439ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 449ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 45c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardtstatic void devgroup_parse_groupspec(const char *arg, unsigned int *group, 46c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt unsigned int *mask) 47c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt{ 48c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt char *end; 49d18b451ec82bbaeaf385241ebdf926912a075adeJan Engelhardt bool ok; 50c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt 51d18b451ec82bbaeaf385241ebdf926912a075adeJan Engelhardt ok = xtables_strtoui(arg, &end, group, 0, UINT32_MAX); 52d18b451ec82bbaeaf385241ebdf926912a075adeJan Engelhardt if (ok && (*end == '/' || *end == '\0')) { 53c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt if (*end == '/') 54d18b451ec82bbaeaf385241ebdf926912a075adeJan Engelhardt ok = xtables_strtoui(end + 1, NULL, mask, 55d18b451ec82bbaeaf385241ebdf926912a075adeJan Engelhardt 0, UINT32_MAX); 56c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt else 57c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt *mask = ~0U; 58d18b451ec82bbaeaf385241ebdf926912a075adeJan Engelhardt if (!ok) 59c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt xtables_error(PARAMETER_PROBLEM, 60c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt "Bad group value \"%s\"", arg); 61c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt } else { 62c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt *group = xtables_lmap_name2id(devgroups, arg); 63c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt if (*group == -1) 64c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt xtables_error(PARAMETER_PROBLEM, 65c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt "Device group \"%s\" not found", arg); 66c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt *mask = ~0U; 67c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt } 68c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt} 69c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt 705d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic void devgroup_parse(struct xt_option_call *cb) 719ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 725d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt struct xt_devgroup_info *info = cb->data; 73c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt unsigned int id, mask; 749ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 755d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt xtables_option_parse(cb); 765d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt switch (cb->entry->id) { 775d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt case O_SRC_GROUP: 78c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt devgroup_parse_groupspec(cb->arg, &id, &mask); 79c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt info->src_group = id; 80c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt info->src_mask = mask; 8117f7937f79af4d260c60cb800e56fc0df0a48b37Lutz Jaenicke info->flags |= XT_DEVGROUP_MATCH_SRC; 825d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt if (cb->invert) 839ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy info->flags |= XT_DEVGROUP_INVERT_SRC; 849ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy break; 855d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt case O_DST_GROUP: 86c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt devgroup_parse_groupspec(cb->arg, &id, &mask); 87c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt info->dst_group = id; 88c0b7138f39882e2bf8f3d85d15e0ffbd868ed7baJan Engelhardt info->dst_mask = mask; 8917f7937f79af4d260c60cb800e56fc0df0a48b37Lutz Jaenicke info->flags |= XT_DEVGROUP_MATCH_DST; 905d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt if (cb->invert) 919ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy info->flags |= XT_DEVGROUP_INVERT_DST; 929ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy break; 939ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy } 949ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 959ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 969ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void 979ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyprint_devgroup(unsigned int id, unsigned int mask, int numeric) 989ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 999ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy const char *name = NULL; 1009ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1019ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy if (mask != 0xffffffff) 102c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt printf("0x%x/0x%x", id, mask); 1039ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy else { 1049ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy if (numeric == 0) 1055d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt name = xtables_lmap_id2name(devgroups, id); 1069ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy if (name) 107c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt printf("%s", name); 1089ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy else 109c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt printf("0x%x", id); 1109ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy } 1119ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 1129ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1139ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_show(const char *pfx, const struct xt_devgroup_info *info, 1149ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy int numeric) 1159ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 1169ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy if (info->flags & XT_DEVGROUP_MATCH_SRC) { 1179ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy if (info->flags & XT_DEVGROUP_INVERT_SRC) 118c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt printf(" !"); 119c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt printf(" %ssrc-group ", pfx); 1209ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy print_devgroup(info->src_group, info->src_mask, numeric); 1219ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy } 1229ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1239ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy if (info->flags & XT_DEVGROUP_MATCH_DST) { 1249ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy if (info->flags & XT_DEVGROUP_INVERT_DST) 125c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt printf(" !"); 126c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt printf(" %sdst-group ", pfx); 1279ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy print_devgroup(info->src_group, info->src_mask, numeric); 1289ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy } 1299ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 1309ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1319ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_print(const void *ip, const struct xt_entry_match *match, 1329ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy int numeric) 1339ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 1349ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy const struct xt_devgroup_info *info = (const void *)match->data; 1359ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1369ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy devgroup_show("", info, numeric); 1379ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 1389ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1399ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_save(const void *ip, const struct xt_entry_match *match) 1409ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 1419ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy const struct xt_devgroup_info *info = (const void *)match->data; 1429ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1439ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy devgroup_show("--", info, 0); 1449ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 1459ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1465d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic void devgroup_check(struct xt_fcheck_call *cb) 1479ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 1485d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt if (cb->xflags == 0) 1499ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy xtables_error(PARAMETER_PROBLEM, 1509ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy "devgroup match: You must specify either " 1519ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy "'--src-group' or '--dst-group'"); 1529ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 1539ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1549ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic struct xtables_match devgroup_mt_reg = { 1559ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .name = "devgroup", 1569ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .version = XTABLES_VERSION, 1579ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .family = NFPROTO_UNSPEC, 1589ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .size = XT_ALIGN(sizeof(struct xt_devgroup_info)), 1599ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .userspacesize = XT_ALIGN(sizeof(struct xt_devgroup_info)), 1605d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt .init = devgroup_init, 1619ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .help = devgroup_help, 1629ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .print = devgroup_print, 1639ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy .save = devgroup_save, 1645d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt .x6_parse = devgroup_parse, 1655d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt .x6_fcheck = devgroup_check, 1665d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt .x6_options = devgroup_opts, 1679ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}; 1689ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy 1699ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyvoid _init(void) 1709ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{ 1719ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy xtables_register_match(&devgroup_mt_reg); 1729ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy} 173