1/* Shared library add-on to iptables to add devgroup matching support. 2 * 3 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 4 */ 5#include <stdio.h> 6#include <string.h> 7#include <stdlib.h> 8#include <errno.h> 9#include <xtables.h> 10#include <linux/netfilter/xt_devgroup.h> 11 12static void devgroup_help(void) 13{ 14 printf( 15"devgroup match options:\n" 16"[!] --src-group value[/mask] Match device group of incoming device\n" 17"[!] --dst-group value[/mask] Match device group of outgoing device\n" 18 ); 19} 20 21enum { 22 O_SRC_GROUP = 0, 23 O_DST_GROUP, 24}; 25 26static const struct xt_option_entry devgroup_opts[] = { 27 {.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING, 28 .flags = XTOPT_INVERT}, 29 {.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING, 30 .flags = XTOPT_INVERT}, 31 XTOPT_TABLEEND, 32}; 33 34/* array of devgroups from /etc/iproute2/group_map */ 35static struct xtables_lmap *devgroups; 36 37static void devgroup_init(struct xt_entry_match *match) 38{ 39 const char file[] = "/etc/iproute2/group_map"; 40 devgroups = xtables_lmap_init(file); 41 if (devgroups == NULL && errno != ENOENT) 42 fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno)); 43} 44 45static void devgroup_parse(struct xt_option_call *cb) 46{ 47 struct xt_devgroup_info *info = cb->data; 48 unsigned int id; 49 char *end; 50 51 xtables_option_parse(cb); 52 switch (cb->entry->id) { 53 case O_SRC_GROUP: 54 info->src_group = strtoul(cb->arg, &end, 0); 55 if (end != cb->arg && (*end == '/' || *end == '\0')) { 56 if (*end == '/') 57 info->src_mask = strtoul(end+1, &end, 0); 58 else 59 info->src_mask = 0xffffffff; 60 if (*end != '\0' || end == cb->arg) 61 xtables_error(PARAMETER_PROBLEM, 62 "Bad src-group value `%s'", 63 cb->arg); 64 } else { 65 id = xtables_lmap_name2id(devgroups, cb->arg); 66 if (id == -1) 67 xtables_error(PARAMETER_PROBLEM, 68 "Device group `%s' not found", 69 cb->arg); 70 info->src_group = id; 71 info->src_mask = 0xffffffff; 72 } 73 info->flags |= XT_DEVGROUP_MATCH_SRC; 74 if (cb->invert) 75 info->flags |= XT_DEVGROUP_INVERT_SRC; 76 break; 77 case O_DST_GROUP: 78 info->dst_group = strtoul(cb->arg, &end, 0); 79 if (end != cb->arg && (*end == '/' || *end == '\0')) { 80 if (*end == '/') 81 info->dst_mask = strtoul(end+1, &end, 0); 82 else 83 info->dst_mask = 0xffffffff; 84 if (*end != '\0' || end == cb->arg) 85 xtables_error(PARAMETER_PROBLEM, 86 "Bad dst-group value `%s'", 87 cb->arg); 88 } else { 89 id = xtables_lmap_name2id(devgroups, cb->arg); 90 if (id == -1) 91 xtables_error(PARAMETER_PROBLEM, 92 "Device group `%s' not found", 93 cb->arg); 94 info->dst_group = id; 95 info->dst_mask = 0xffffffff; 96 } 97 info->flags |= XT_DEVGROUP_MATCH_DST; 98 if (cb->invert) 99 info->flags |= XT_DEVGROUP_INVERT_DST; 100 break; 101 } 102} 103 104static void 105print_devgroup(unsigned int id, unsigned int mask, int numeric) 106{ 107 const char *name = NULL; 108 109 if (mask != 0xffffffff) 110 printf("0x%x/0x%x", id, mask); 111 else { 112 if (numeric == 0) 113 name = xtables_lmap_id2name(devgroups, id); 114 if (name) 115 printf("%s", name); 116 else 117 printf("0x%x", id); 118 } 119} 120 121static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info, 122 int numeric) 123{ 124 if (info->flags & XT_DEVGROUP_MATCH_SRC) { 125 if (info->flags & XT_DEVGROUP_INVERT_SRC) 126 printf(" !"); 127 printf(" %ssrc-group ", pfx); 128 print_devgroup(info->src_group, info->src_mask, numeric); 129 } 130 131 if (info->flags & XT_DEVGROUP_MATCH_DST) { 132 if (info->flags & XT_DEVGROUP_INVERT_DST) 133 printf(" !"); 134 printf(" %sdst-group ", pfx); 135 print_devgroup(info->src_group, info->src_mask, numeric); 136 } 137} 138 139static void devgroup_print(const void *ip, const struct xt_entry_match *match, 140 int numeric) 141{ 142 const struct xt_devgroup_info *info = (const void *)match->data; 143 144 devgroup_show("", info, numeric); 145} 146 147static void devgroup_save(const void *ip, const struct xt_entry_match *match) 148{ 149 const struct xt_devgroup_info *info = (const void *)match->data; 150 151 devgroup_show("--", info, 0); 152} 153 154static void devgroup_check(struct xt_fcheck_call *cb) 155{ 156 if (cb->xflags == 0) 157 xtables_error(PARAMETER_PROBLEM, 158 "devgroup match: You must specify either " 159 "'--src-group' or '--dst-group'"); 160} 161 162static struct xtables_match devgroup_mt_reg = { 163 .name = "devgroup", 164 .version = XTABLES_VERSION, 165 .family = NFPROTO_UNSPEC, 166 .size = XT_ALIGN(sizeof(struct xt_devgroup_info)), 167 .userspacesize = XT_ALIGN(sizeof(struct xt_devgroup_info)), 168 .init = devgroup_init, 169 .help = devgroup_help, 170 .print = devgroup_print, 171 .save = devgroup_save, 172 .x6_parse = devgroup_parse, 173 .x6_fcheck = devgroup_check, 174 .x6_options = devgroup_opts, 175}; 176 177void _init(void) 178{ 179 xtables_register_match(&devgroup_mt_reg); 180} 181