embox

Форк
0
/
netfilter.c 
417 строк · 8.7 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @date 12.03.13
6
 * @author Ilia Vaprol
7
 */
8

9
#include <errno.h>
10
#include <mem/misc/pool.h>
11
#include <framework/mod/options.h>
12
#include <assert.h>
13
#include <net/netfilter.h>
14
#include <net/skbuff.h>
15
#include <net/l3/ipv4/ip.h>
16
#include <string.h>
17
#include <stddef.h>
18

19
#include <net/l4/udp.h>
20
#include <net/l4/tcp.h>
21

22
#define MODOPS_NETFILTER_AMOUNT_RULES  OPTION_GET(NUMBER, amount_rules)
23

24
/**
25
 * Storage of nf_rule structure
26
 */
27
POOL_DEF(nf_rule_pool, struct nf_rule, MODOPS_NETFILTER_AMOUNT_RULES);
28

29
/**
30
 * Default chains of rules
31
 */
32
DLIST_DEFINE(nf_input_rules);
33
DLIST_DEFINE(nf_forward_rules);
34
DLIST_DEFINE(nf_output_rules);
35

36
/**
37
 * Default policy for chains
38
 */
39
static enum nf_target nf_input_default_target = NF_TARGET_ACCEPT;
40
static enum nf_target nf_forward_default_target = NF_TARGET_ACCEPT;
41
static enum nf_target nf_output_default_target = NF_TARGET_ACCEPT;
42

43
static void free_rule(struct nf_rule *r) {
44
	assert(r != NULL);
45
	dlist_del_init(&r->lnk);
46
	pool_free(&nf_rule_pool, r);
47
}
48

49
int nf_chain_get_by_name(const char *chain_name) {
50
	if (chain_name == NULL) {
51
		return NF_CHAIN_UNKNOWN;
52
	}
53
	else if (0 == strcmp(chain_name, "INPUT")) {
54
		return NF_CHAIN_INPUT;
55
	}
56
	else if (0 == strcmp(chain_name, "FORWARD")) {
57
		return NF_CHAIN_FORWARD;
58
	}
59
	else if (0 == strcmp(chain_name, "OUTPUT")) {
60
		return NF_CHAIN_OUTPUT;
61
	}
62
	else {
63
		return NF_CHAIN_UNKNOWN;
64
	}
65
}
66

67
const char *nf_chain_to_str(int chain) {
68
	switch (chain) {
69
	default: return NULL;
70
	case NF_CHAIN_INPUT: return "INPUT";
71
	case NF_CHAIN_FORWARD: return "FORWARD";
72
	case NF_CHAIN_OUTPUT: return "OUTPUT";
73
	}
74
}
75

76
enum nf_target nf_target_get_by_name(const char *target_name) {
77
	if (target_name == NULL) {
78
		return NF_TARGET_UNKNOWN;
79
	}
80
	else if (0 == strcmp(target_name, "DROP")) {
81
		return NF_TARGET_DROP;
82
	}
83
	else if (0 == strcmp(target_name, "ACCEPT")) {
84
		return NF_TARGET_ACCEPT;
85
	}
86
	else {
87
		return NF_TARGET_UNKNOWN;
88
	}
89
}
90

91
const char *nf_target_to_str(enum nf_target target) {
92
	switch (target) {
93
	default: return NULL;
94
	case NF_TARGET_DROP: return "DROP";
95
	case NF_TARGET_ACCEPT: return "ACCEPT";
96
	}
97
}
98

99
enum nf_proto nf_proto_get_by_name(const char *proto_name) {
100
	if (proto_name == NULL) {
101
		return NF_PROTO_UNKNOWN;
102
	}
103
	else if (0 == strcmp(proto_name, "all")) {
104
		return NF_PROTO_ALL;
105
	}
106
	else if (0 == strcmp(proto_name, "icmp")) {
107
		return NF_PROTO_ICMP;
108
	}
109
	else if (0 == strcmp(proto_name, "tcp")) {
110
		return NF_PROTO_TCP;
111
	}
112
	else if (0 == strcmp(proto_name, "udp")) {
113
		return NF_PROTO_UDP;
114
	}
115
	else {
116
		return NF_PROTO_UNKNOWN;
117
	}
118
}
119

120
const char *nf_proto_to_str(enum nf_proto proto) {
121
	switch (proto) {
122
	default: return NULL;
123
	case NF_PROTO_ALL: return "all";
124
	case NF_PROTO_ICMP: return "icmp";
125
	case NF_PROTO_TCP: return "tcp";
126
	case NF_PROTO_UDP: return "udp";
127
	}
128
}
129

130
struct dlist_head *nf_get_chain(int chain) {
131
	switch (chain) {
132
	default: return NULL;
133
	case NF_CHAIN_INPUT: return &nf_input_rules;
134
	case NF_CHAIN_FORWARD: return &nf_forward_rules;
135
	case NF_CHAIN_OUTPUT: return &nf_output_rules;
136
	}
137
}
138

139
enum nf_target nf_get_chain_target(int chain) {
140
	switch (chain) {
141
	default: return NF_TARGET_UNKNOWN;
142
	case NF_CHAIN_INPUT: return nf_input_default_target;
143
	case NF_CHAIN_FORWARD: return nf_forward_default_target;
144
	case NF_CHAIN_OUTPUT: return nf_output_default_target;
145
	}
146
}
147

148
int nf_set_chain_target(int chain, enum nf_target target) {
149
	if (target == NF_TARGET_UNKNOWN) {
150
		return -EINVAL;
151
	}
152

153
	switch (chain) {
154
	default: return -EINVAL;
155
	case NF_CHAIN_INPUT:
156
		nf_input_default_target = target;
157
		break;
158
	case NF_CHAIN_FORWARD:
159
		nf_forward_default_target = target;
160
		break;
161
	case NF_CHAIN_OUTPUT:
162
		nf_output_default_target = target;
163
		break;
164
	}
165

166
	return 0;
167
}
168

169
struct nf_rule *nf_get_rule_by_num(int chain, size_t r_num) {
170
	struct dlist_head *rules;
171
	size_t i;
172
	struct nf_rule *r;
173

174
	rules = nf_get_chain(chain);
175
	if (rules == NULL) {
176
		return NULL;
177
	}
178

179
	i = 0;
180
	dlist_foreach_entry(r, rules, lnk) {
181
		if (i == r_num) {
182
			return r;
183
		}
184
		++i;
185
	}
186

187
	return NULL;
188
}
189

190
int nf_rule_init(struct nf_rule *r) {
191
	if (r == NULL) {
192
		return -EINVAL;
193
	}
194

195
	memset(r, 0, sizeof *r);
196
	dlist_head_init(&r->lnk);
197

198
	return 0;
199
}
200

201
int nf_rule_copy(struct nf_rule *r_dst,
202
		const struct nf_rule *r_src) {
203
	struct dlist_head dst_link;
204

205
	if ((r_dst == NULL) || (r_src == NULL)) {
206
		return -EINVAL;
207
	}
208

209
	memcpy(&dst_link, &r_dst->lnk, sizeof dst_link);
210
	memcpy(r_dst, r_src, sizeof *r_dst);
211
	memcpy(&r_dst->lnk, &dst_link, sizeof r_dst->lnk);
212

213
	return 0;
214
}
215

216
static int nf_chain_rule_prepare(int chain, const struct nf_rule *r,
217
		struct dlist_head **rules_p, struct nf_rule **new_r_p) {
218
	struct dlist_head *rules;
219
	struct nf_rule *new_r;
220

221
	rules = nf_get_chain(chain);
222
	if (rules == NULL) {
223
		return -EINVAL;
224
	}
225

226
	if (r == NULL) {
227
		return -EINVAL;
228
	}
229

230
	new_r = pool_alloc(&nf_rule_pool);
231
	if (new_r == NULL) {
232
		return -ENOMEM;
233
	}
234

235
	nf_rule_init(new_r);
236
	nf_rule_copy(new_r, r);
237

238
	*rules_p = rules;
239
	*new_r_p = new_r;
240

241
	return 0;
242
}
243

244

245
int nf_add_rule(int chain, const struct nf_rule *r) {
246
	struct dlist_head *rules;
247
	struct nf_rule *new_r;
248
	int res;
249

250
	res = nf_chain_rule_prepare(chain, r, &rules, &new_r);
251
	if (res != 0) {
252
		return res;
253
	}
254

255
	dlist_add_prev(&new_r->lnk, rules);
256

257
	return 0;
258
}
259

260
int nf_insert_rule(int chain, const struct nf_rule *r, size_t num) {
261
	struct dlist_head *rules;
262
	struct nf_rule *new_r, *old_r;
263
	int res;
264

265
	res = nf_chain_rule_prepare(chain, r, &rules, &new_r);
266
	if (res != 0) {
267
		return res;
268
	}
269

270
	old_r = nf_get_rule_by_num(chain, num);
271
	if (!old_r) {
272
		dlist_add_prev(&new_r->lnk, rules);
273
	} else {
274
		dlist_add_prev(&new_r->lnk, &old_r->lnk);
275
	}
276

277
	return 0;
278
}
279

280
int nf_set_rule(int chain, const struct nf_rule *r, size_t r_num) {
281
	struct nf_rule *new_r;
282

283
	if (r == NULL) {
284
		return -EINVAL;
285
	}
286

287
	new_r = nf_get_rule_by_num(chain, r_num);
288
	if (new_r == NULL) {
289
		return -ENOENT;
290
	}
291

292
	nf_rule_copy(new_r, r);
293

294
	return 0;
295
}
296

297
int nf_del_rule(int chain, size_t r_num) {
298
	struct nf_rule *r;
299

300
	r = nf_get_rule_by_num(chain, r_num);
301
	if (r == NULL) {
302
		return -ENOENT;
303
	}
304

305
	free_rule(r);
306

307
	return 0;
308
}
309

310
int nf_clear(int chain) {
311
	struct dlist_head *rules;
312
	struct nf_rule *r = NULL;
313

314
	rules = nf_get_chain(chain);
315
	if (rules == NULL) {
316
		return -EINVAL;
317
	}
318

319
	dlist_foreach_entry(r, rules, lnk) {
320
		free_rule(r);
321
	}
322

323
	return 0;
324
}
325

326
#define NF_TEST_NOT_FIELD(test_r, r, field)         \
327
	(!r->set_##field ? 1 : !test_r->set_##field ? 0 \
328
		: (assert(!test_r->not_##field),            \
329
			(0 == memcmp(&test_r->field, &r->field, \
330
					sizeof test_r->field))          \
331
				!= !!r->not_##field))
332

333
int nf_test_rule(int chain, const struct nf_rule *test_r) {
334
	struct dlist_head *rules;
335
	struct nf_rule *r;
336

337
	rules = nf_get_chain(chain);
338
	if (rules == NULL) {
339
		return -EINVAL;
340
	}
341

342
	if (test_r == NULL) {
343
		return -EINVAL;
344
	}
345

346
	dlist_foreach_entry(r, rules, lnk) {
347
		if ((r->target != NF_TARGET_UNKNOWN)
348
				&& NF_TEST_NOT_FIELD(test_r, r, hwaddr_src)
349
				&& NF_TEST_NOT_FIELD(test_r, r, hwaddr_dst)
350
				&& NF_TEST_NOT_FIELD(test_r, r, saddr)
351
				&& NF_TEST_NOT_FIELD(test_r, r, daddr)
352
				&& (((test_r->proto != NF_PROTO_ALL)
353
						&& (r->proto != NF_PROTO_ALL)
354
						&& NF_TEST_NOT_FIELD(test_r, r, proto))
355
					|| ((test_r->proto == NF_PROTO_ALL) && !test_r->not_proto
356
						&& (r->proto == NF_PROTO_ALL) && !r->not_proto)
357
					|| ((test_r->proto != NF_PROTO_ALL)
358
						&& ((r->proto == NF_PROTO_ALL) && !r->not_proto)))
359
				&& NF_TEST_NOT_FIELD(test_r, r, sport)
360
				&& NF_TEST_NOT_FIELD(test_r, r, dport)
361
				&& (!r->test_hnd ? 1 : r->test_hnd(test_r, r->test_hnd_data))) {
362

363
			return test_r->target != r->target;
364
		}
365
	}
366

367
	return test_r->target != nf_get_chain_target(chain);
368
}
369

370
int nf_test_skb(int chain, enum nf_target target,
371
		const struct sk_buff *test_skb) {
372
	struct nf_rule rule;
373

374
	if (test_skb == NULL) {
375
		return -EINVAL;
376
	}
377

378
	nf_rule_init(&rule);
379
	rule.target = target;
380
	NF_SET_NOT_FIELD_PTR(&rule, saddr, 0, &test_skb->nh.iph->saddr,
381
			sizeof test_skb->nh.iph->saddr);
382
	NF_SET_NOT_FIELD_PTR(&rule, daddr, 0, &test_skb->nh.iph->daddr,
383
			sizeof test_skb->nh.iph->daddr);
384
	switch (test_skb->nh.iph->proto) {
385
	case IPPROTO_ICMP:
386
		NF_SET_NOT_FIELD(&rule, proto, 0, NF_PROTO_ICMP);
387
		break;
388
	case IPPROTO_TCP:
389
		NF_SET_NOT_FIELD(&rule, proto, 0, NF_PROTO_TCP);
390
		NF_SET_NOT_FIELD(&rule, sport, 0, test_skb->h.th->source);
391
		NF_SET_NOT_FIELD(&rule, dport, 0, test_skb->h.th->dest);
392
		break;
393
	case IPPROTO_UDP:
394
		NF_SET_NOT_FIELD(&rule, proto, 0, NF_PROTO_UDP);
395
		NF_SET_NOT_FIELD(&rule, sport, 0, test_skb->h.uh->source);
396
		NF_SET_NOT_FIELD(&rule, dport, 0, test_skb->h.uh->dest);
397
		break;
398
	}
399

400
	return nf_test_rule(chain, &rule);
401
}
402

403
int nf_test_raw(int chain, enum nf_target target, const void *hwaddr_dst,
404
		const void *hwaddr_src, size_t hwaddr_len) {
405

406
	struct nf_rule rule;
407

408
	nf_rule_init(&rule);
409

410
	rule.target = target;
411
	NF_SET_NOT_FIELD_PTR(&rule, hwaddr_src, 0, hwaddr_src,
412
			hwaddr_len);
413
	NF_SET_NOT_FIELD_PTR(&rule, hwaddr_dst, 0, hwaddr_dst,
414
			hwaddr_len);
415

416
	return nf_test_rule(chain, &rule);
417
}
418

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.