1 /* Shared library add-on to iptables to add devgroup matching support. 2 * 3 * Copyright (c) 2011 Patrick McHardy <kaber (at) 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 12 static 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 21 enum { 22 O_SRC_GROUP = 0, 23 O_DST_GROUP, 24 }; 25 26 static 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 */ 35 static struct xtables_lmap *devgroups; 36 37 static 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 45 static 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 70 static 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 96 static void 97 print_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 113 static 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 131 static 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 139 static 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 146 static 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 154 static 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 169 void _init(void) 170 { 171 xtables_register_match(&devgroup_mt_reg); 172 } 173