• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
devgroup_help(void)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 static const char f_devgroups[] = "/etc/iproute2/group";
35 /* array of devgroups from f_devgroups[] */
36 static struct xtables_lmap *devgroups;
37 
devgroup_parse(struct xt_option_call * cb)38 static void devgroup_parse(struct xt_option_call *cb)
39 {
40 	struct xt_devgroup_info *info = cb->data;
41 	unsigned int group, mask;
42 
43 	xtables_option_parse(cb);
44 	xtables_parse_val_mask(cb, &group, &mask, devgroups);
45 
46 	switch (cb->entry->id) {
47 	case O_SRC_GROUP:
48 		info->src_group = group;
49 		info->src_mask  = mask;
50 		info->flags |= XT_DEVGROUP_MATCH_SRC;
51 		if (cb->invert)
52 			info->flags |= XT_DEVGROUP_INVERT_SRC;
53 		break;
54 	case O_DST_GROUP:
55 		info->dst_group = group;
56 		info->dst_mask  = mask;
57 		info->flags |= XT_DEVGROUP_MATCH_DST;
58 		if (cb->invert)
59 			info->flags |= XT_DEVGROUP_INVERT_DST;
60 		break;
61 	}
62 }
63 
devgroup_show(const char * pfx,const struct xt_devgroup_info * info,int numeric)64 static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
65 			  int numeric)
66 {
67 	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
68 		if (info->flags & XT_DEVGROUP_INVERT_SRC)
69 			printf(" !");
70 		printf(" %ssrc-group", pfx);
71 		xtables_print_val_mask(info->src_group, info->src_mask,
72 				       numeric ? NULL : devgroups);
73 	}
74 
75 	if (info->flags & XT_DEVGROUP_MATCH_DST) {
76 		if (info->flags & XT_DEVGROUP_INVERT_DST)
77 			printf(" !");
78 		printf(" %sdst-group", pfx);
79 		xtables_print_val_mask(info->dst_group, info->dst_mask,
80 				       numeric ? NULL : devgroups);
81 	}
82 }
83 
devgroup_print(const void * ip,const struct xt_entry_match * match,int numeric)84 static void devgroup_print(const void *ip, const struct xt_entry_match *match,
85                         int numeric)
86 {
87 	const struct xt_devgroup_info *info = (const void *)match->data;
88 
89 	devgroup_show("", info, numeric);
90 }
91 
devgroup_save(const void * ip,const struct xt_entry_match * match)92 static void devgroup_save(const void *ip, const struct xt_entry_match *match)
93 {
94 	const struct xt_devgroup_info *info = (const void *)match->data;
95 
96 	devgroup_show("--", info, 0);
97 }
98 
devgroup_check(struct xt_fcheck_call * cb)99 static void devgroup_check(struct xt_fcheck_call *cb)
100 {
101 	if (cb->xflags == 0)
102 		xtables_error(PARAMETER_PROBLEM,
103 			      "devgroup match: You must specify either "
104 			      "'--src-group' or '--dst-group'");
105 }
106 
107 static void
print_devgroup_xlate(unsigned int id,uint32_t op,unsigned int mask,struct xt_xlate * xl,int numeric)108 print_devgroup_xlate(unsigned int id, uint32_t op,  unsigned int mask,
109 		     struct xt_xlate *xl, int numeric)
110 {
111 	const char *name = NULL;
112 
113 	if (mask != 0xffffffff)
114 		xt_xlate_add(xl, "and 0x%x %s 0x%x", mask,
115 			   op == XT_OP_EQ ? "==" : "!=", id);
116 	else {
117 		if (numeric == 0)
118 			name = xtables_lmap_id2name(devgroups, id);
119 
120 		xt_xlate_add(xl, "%s", op == XT_OP_EQ ? "" : "!= ");
121 		if (name)
122 			xt_xlate_add(xl, "%s", name);
123 		else
124 			xt_xlate_add(xl, "0x%x", id);
125 	}
126 }
127 
devgroup_show_xlate(const struct xt_devgroup_info * info,struct xt_xlate * xl,int numeric)128 static void devgroup_show_xlate(const struct xt_devgroup_info *info,
129 				struct xt_xlate *xl, int numeric)
130 {
131 	enum xt_op op = XT_OP_EQ;
132 	char *space = "";
133 
134 	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
135 		if (info->flags & XT_DEVGROUP_INVERT_SRC)
136 			op = XT_OP_NEQ;
137 		xt_xlate_add(xl, "iifgroup ");
138 		print_devgroup_xlate(info->src_group, op,
139 				     info->src_mask, xl, numeric);
140 		space = " ";
141 	}
142 
143 	if (info->flags & XT_DEVGROUP_MATCH_DST) {
144 		if (info->flags & XT_DEVGROUP_INVERT_DST)
145 			op = XT_OP_NEQ;
146 		xt_xlate_add(xl, "%soifgroup ", space);
147 		print_devgroup_xlate(info->dst_group, op,
148 				     info->dst_mask, xl, numeric);
149 	}
150 }
151 
devgroup_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)152 static int devgroup_xlate(struct xt_xlate *xl,
153 			  const struct xt_xlate_mt_params *params)
154 {
155 	const struct xt_devgroup_info *info = (const void *)params->match->data;
156 
157 	devgroup_show_xlate(info, xl, 0);
158 
159 	return 1;
160 }
161 
162 static 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 	.help		= devgroup_help,
169 	.print		= devgroup_print,
170 	.save		= devgroup_save,
171 	.x6_parse	= devgroup_parse,
172 	.x6_fcheck	= devgroup_check,
173 	.x6_options	= devgroup_opts,
174 	.xlate		= devgroup_xlate,
175 };
176 
_init(void)177 void _init(void)
178 {
179 	devgroups = xtables_lmap_init(f_devgroups);
180 	if (devgroups == NULL && errno != ENOENT)
181 		fprintf(stderr, "Warning: %s: %s\n", f_devgroups,
182 			strerror(errno));
183 
184 	xtables_register_match(&devgroup_mt_reg);
185 }
186