xref: /aosp_15_r20/external/iptables/extensions/libxt_devgroup.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
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