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