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_groupspec(const char *arg, unsigned int *group, 46 unsigned int *mask) 47{ 48 char *end; 49 bool ok; 50 51 ok = xtables_strtoui(arg, &end, group, 0, UINT32_MAX); 52 if (ok && (*end == '/' || *end == '\0')) { 53 if (*end == '/') 54 ok = xtables_strtoui(end + 1, NULL, mask, 55 0, UINT32_MAX); 56 else 57 *mask = ~0U; 58 if (!ok) 59 xtables_error(PARAMETER_PROBLEM, 60 "Bad group value \"%s\"", arg); 61 } else { 62 *group = xtables_lmap_name2id(devgroups, arg); 63 if (*group == -1) 64 xtables_error(PARAMETER_PROBLEM, 65 "Device group \"%s\" not found", arg); 66 *mask = ~0U; 67 } 68} 69 70static void devgroup_parse(struct xt_option_call *cb) 71{ 72 struct xt_devgroup_info *info = cb->data; 73 unsigned int id, mask; 74 75 xtables_option_parse(cb); 76 switch (cb->entry->id) { 77 case O_SRC_GROUP: 78 devgroup_parse_groupspec(cb->arg, &id, &mask); 79 info->src_group = id; 80 info->src_mask = mask; 81 info->flags |= XT_DEVGROUP_MATCH_SRC; 82 if (cb->invert) 83 info->flags |= XT_DEVGROUP_INVERT_SRC; 84 break; 85 case O_DST_GROUP: 86 devgroup_parse_groupspec(cb->arg, &id, &mask); 87 info->dst_group = id; 88 info->dst_mask = mask; 89 info->flags |= XT_DEVGROUP_MATCH_DST; 90 if (cb->invert) 91 info->flags |= XT_DEVGROUP_INVERT_DST; 92 break; 93 } 94} 95 96static void 97print_devgroup(unsigned int id, unsigned int mask, int numeric) 98{ 99 const char *name = NULL; 100 101 if (mask != 0xffffffff) 102 printf("0x%x/0x%x", id, mask); 103 else { 104 if (numeric == 0) 105 name = xtables_lmap_id2name(devgroups, id); 106 if (name) 107 printf("%s", name); 108 else 109 printf("0x%x", id); 110 } 111} 112 113static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info, 114 int numeric) 115{ 116 if (info->flags & XT_DEVGROUP_MATCH_SRC) { 117 if (info->flags & XT_DEVGROUP_INVERT_SRC) 118 printf(" !"); 119 printf(" %ssrc-group ", pfx); 120 print_devgroup(info->src_group, info->src_mask, numeric); 121 } 122 123 if (info->flags & XT_DEVGROUP_MATCH_DST) { 124 if (info->flags & XT_DEVGROUP_INVERT_DST) 125 printf(" !"); 126 printf(" %sdst-group ", pfx); 127 print_devgroup(info->src_group, info->src_mask, numeric); 128 } 129} 130 131static void devgroup_print(const void *ip, const struct xt_entry_match *match, 132 int numeric) 133{ 134 const struct xt_devgroup_info *info = (const void *)match->data; 135 136 devgroup_show("", info, numeric); 137} 138 139static void devgroup_save(const void *ip, const struct xt_entry_match *match) 140{ 141 const struct xt_devgroup_info *info = (const void *)match->data; 142 143 devgroup_show("--", info, 0); 144} 145 146static void devgroup_check(struct xt_fcheck_call *cb) 147{ 148 if (cb->xflags == 0) 149 xtables_error(PARAMETER_PROBLEM, 150 "devgroup match: You must specify either " 151 "'--src-group' or '--dst-group'"); 152} 153 154static struct xtables_match devgroup_mt_reg = { 155 .name = "devgroup", 156 .version = XTABLES_VERSION, 157 .family = NFPROTO_UNSPEC, 158 .size = XT_ALIGN(sizeof(struct xt_devgroup_info)), 159 .userspacesize = XT_ALIGN(sizeof(struct xt_devgroup_info)), 160 .init = devgroup_init, 161 .help = devgroup_help, 162 .print = devgroup_print, 163 .save = devgroup_save, 164 .x6_parse = devgroup_parse, 165 .x6_fcheck = devgroup_check, 166 .x6_options = devgroup_opts, 167}; 168 169void _init(void) 170{ 171 xtables_register_match(&devgroup_mt_reg); 172} 173