x_tables.c 30.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * x_tables core - Backend for {ip,ip6,arp}_tables
 *
 * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
 *
 * Based on existing ip_tables code which is
 *   Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
 *   Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#include <linux/kernel.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
I
Ingo Molnar 已提交
23
#include <linux/mutex.h>
A
Al Viro 已提交
24
#include <linux/mm.h>
25
#include <net/net_namespace.h>
26 27 28

#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp.h>
29 30 31
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_arp/arp_tables.h>
I
Ingo Molnar 已提交
32

33 34
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
35
MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
36 37 38

#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))

39 40 41
struct compat_delta {
	struct compat_delta *next;
	unsigned int offset;
42
	int delta;
43 44
};

45
struct xt_af {
I
Ingo Molnar 已提交
46
	struct mutex mutex;
47 48
	struct list_head match;
	struct list_head target;
49
#ifdef CONFIG_COMPAT
50
	struct mutex compat_mutex;
51 52
	struct compat_delta *compat_offsets;
#endif
53 54 55 56 57 58 59 60 61 62
};

static struct xt_af *xt;

#ifdef DEBUG_IP_FIREWALL_USER
#define duprintf(format, args...) printk(format , ## args)
#else
#define duprintf(format, args...)
#endif

63 64 65 66 67 68
static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
	[NFPROTO_UNSPEC] = "x",
	[NFPROTO_IPV4]   = "ip",
	[NFPROTO_ARP]    = "arp",
	[NFPROTO_BRIDGE] = "eb",
	[NFPROTO_IPV6]   = "ip6",
69 70
};

71 72
/* Registration hooks for targets. */
int
73
xt_register_target(struct xt_target *target)
74
{
75 76
	u_int8_t af = target->family;
	int ret;
77

I
Ingo Molnar 已提交
78
	ret = mutex_lock_interruptible(&xt[af].mutex);
79 80 81
	if (ret != 0)
		return ret;
	list_add(&target->list, &xt[af].target);
I
Ingo Molnar 已提交
82
	mutex_unlock(&xt[af].mutex);
83 84 85 86 87
	return ret;
}
EXPORT_SYMBOL(xt_register_target);

void
88
xt_unregister_target(struct xt_target *target)
89
{
90
	u_int8_t af = target->family;
91

I
Ingo Molnar 已提交
92
	mutex_lock(&xt[af].mutex);
P
Patrick McHardy 已提交
93
	list_del(&target->list);
I
Ingo Molnar 已提交
94
	mutex_unlock(&xt[af].mutex);
95 96 97
}
EXPORT_SYMBOL(xt_unregister_target);

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
int
xt_register_targets(struct xt_target *target, unsigned int n)
{
	unsigned int i;
	int err = 0;

	for (i = 0; i < n; i++) {
		err = xt_register_target(&target[i]);
		if (err)
			goto err;
	}
	return err;

err:
	if (i > 0)
		xt_unregister_targets(target, i);
	return err;
}
EXPORT_SYMBOL(xt_register_targets);

void
xt_unregister_targets(struct xt_target *target, unsigned int n)
{
	unsigned int i;

	for (i = 0; i < n; i++)
		xt_unregister_target(&target[i]);
}
EXPORT_SYMBOL(xt_unregister_targets);

128
int
129
xt_register_match(struct xt_match *match)
130
{
131 132
	u_int8_t af = match->family;
	int ret;
133

I
Ingo Molnar 已提交
134
	ret = mutex_lock_interruptible(&xt[af].mutex);
135 136 137 138
	if (ret != 0)
		return ret;

	list_add(&match->list, &xt[af].match);
I
Ingo Molnar 已提交
139
	mutex_unlock(&xt[af].mutex);
140 141 142 143 144 145

	return ret;
}
EXPORT_SYMBOL(xt_register_match);

void
146
xt_unregister_match(struct xt_match *match)
147
{
148
	u_int8_t af = match->family;
149

I
Ingo Molnar 已提交
150
	mutex_lock(&xt[af].mutex);
P
Patrick McHardy 已提交
151
	list_del(&match->list);
I
Ingo Molnar 已提交
152
	mutex_unlock(&xt[af].mutex);
153 154 155
}
EXPORT_SYMBOL(xt_unregister_match);

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
int
xt_register_matches(struct xt_match *match, unsigned int n)
{
	unsigned int i;
	int err = 0;

	for (i = 0; i < n; i++) {
		err = xt_register_match(&match[i]);
		if (err)
			goto err;
	}
	return err;

err:
	if (i > 0)
		xt_unregister_matches(match, i);
	return err;
}
EXPORT_SYMBOL(xt_register_matches);

void
xt_unregister_matches(struct xt_match *match, unsigned int n)
{
	unsigned int i;

	for (i = 0; i < n; i++)
		xt_unregister_match(&match[i]);
}
EXPORT_SYMBOL(xt_unregister_matches);

186 187 188 189 190 191 192 193

/*
 * These are weird, but module loading must not be done with mutex
 * held (since they will register), and we have to have a single
 * function to use try_then_request_module().
 */

/* Find match, grabs ref.  Returns ERR_PTR() on error. */
194
struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
195 196 197 198
{
	struct xt_match *m;
	int err = 0;

I
Ingo Molnar 已提交
199
	if (mutex_lock_interruptible(&xt[af].mutex) != 0)
200 201 202 203 204 205
		return ERR_PTR(-EINTR);

	list_for_each_entry(m, &xt[af].match, list) {
		if (strcmp(m->name, name) == 0) {
			if (m->revision == revision) {
				if (try_module_get(m->me)) {
I
Ingo Molnar 已提交
206
					mutex_unlock(&xt[af].mutex);
207 208 209 210 211 212
					return m;
				}
			} else
				err = -EPROTOTYPE; /* Found something. */
		}
	}
I
Ingo Molnar 已提交
213
	mutex_unlock(&xt[af].mutex);
214 215 216 217 218

	if (af != NFPROTO_UNSPEC)
		/* Try searching again in the family-independent list */
		return xt_find_match(NFPROTO_UNSPEC, name, revision);

219 220 221 222 223
	return ERR_PTR(err);
}
EXPORT_SYMBOL(xt_find_match);

/* Find target, grabs ref.  Returns ERR_PTR() on error. */
224
struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
225 226 227 228
{
	struct xt_target *t;
	int err = 0;

I
Ingo Molnar 已提交
229
	if (mutex_lock_interruptible(&xt[af].mutex) != 0)
230 231 232 233 234 235
		return ERR_PTR(-EINTR);

	list_for_each_entry(t, &xt[af].target, list) {
		if (strcmp(t->name, name) == 0) {
			if (t->revision == revision) {
				if (try_module_get(t->me)) {
I
Ingo Molnar 已提交
236
					mutex_unlock(&xt[af].mutex);
237 238 239 240 241 242
					return t;
				}
			} else
				err = -EPROTOTYPE; /* Found something. */
		}
	}
I
Ingo Molnar 已提交
243
	mutex_unlock(&xt[af].mutex);
244 245 246 247 248

	if (af != NFPROTO_UNSPEC)
		/* Try searching again in the family-independent list */
		return xt_find_target(NFPROTO_UNSPEC, name, revision);

249 250 251 252
	return ERR_PTR(err);
}
EXPORT_SYMBOL(xt_find_target);

253
struct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision)
254 255 256 257
{
	struct xt_target *target;

	target = try_then_request_module(xt_find_target(af, name, revision),
258
					 "%st_%s", xt_prefix[af], name);
259 260 261 262 263 264
	if (IS_ERR(target) || !target)
		return NULL;
	return target;
}
EXPORT_SYMBOL_GPL(xt_request_find_target);

265
static int match_revfn(u8 af, const char *name, u8 revision, int *bestp)
266
{
267
	const struct xt_match *m;
268 269 270 271 272 273 274 275 276 277
	int have_rev = 0;

	list_for_each_entry(m, &xt[af].match, list) {
		if (strcmp(m->name, name) == 0) {
			if (m->revision > *bestp)
				*bestp = m->revision;
			if (m->revision == revision)
				have_rev = 1;
		}
	}
278 279 280 281

	if (af != NFPROTO_UNSPEC && !have_rev)
		return match_revfn(NFPROTO_UNSPEC, name, revision, bestp);

282 283 284
	return have_rev;
}

285
static int target_revfn(u8 af, const char *name, u8 revision, int *bestp)
286
{
287
	const struct xt_target *t;
288 289 290 291 292 293 294 295 296 297
	int have_rev = 0;

	list_for_each_entry(t, &xt[af].target, list) {
		if (strcmp(t->name, name) == 0) {
			if (t->revision > *bestp)
				*bestp = t->revision;
			if (t->revision == revision)
				have_rev = 1;
		}
	}
298 299 300 301

	if (af != NFPROTO_UNSPEC && !have_rev)
		return target_revfn(NFPROTO_UNSPEC, name, revision, bestp);

302 303 304 305
	return have_rev;
}

/* Returns true or false (if no such extension at all) */
306
int xt_find_revision(u8 af, const char *name, u8 revision, int target,
307 308 309 310
		     int *err)
{
	int have_rev, best = -1;

I
Ingo Molnar 已提交
311
	if (mutex_lock_interruptible(&xt[af].mutex) != 0) {
312 313 314 315 316 317 318
		*err = -EINTR;
		return 1;
	}
	if (target == 1)
		have_rev = target_revfn(af, name, revision, &best);
	else
		have_rev = match_revfn(af, name, revision, &best);
I
Ingo Molnar 已提交
319
	mutex_unlock(&xt[af].mutex);
320 321 322 323 324 325 326 327 328 329 330 331 332 333

	/* Nothing at all?  Return 0 to try loading module. */
	if (best == -1) {
		*err = -ENOENT;
		return 0;
	}

	*err = best;
	if (!have_rev)
		*err = -EPROTONOSUPPORT;
	return 1;
}
EXPORT_SYMBOL_GPL(xt_find_revision);

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
static char *textify_hooks(char *buf, size_t size, unsigned int mask)
{
	static const char *const names[] = {
		"PREROUTING", "INPUT", "FORWARD",
		"OUTPUT", "POSTROUTING", "BROUTING",
	};
	unsigned int i;
	char *p = buf;
	bool np = false;
	int res;

	*p = '\0';
	for (i = 0; i < ARRAY_SIZE(names); ++i) {
		if (!(mask & (1 << i)))
			continue;
		res = snprintf(p, size, "%s%s", np ? "/" : "", names[i]);
		if (res > 0) {
			size -= res;
			p += res;
		}
		np = true;
	}

	return buf;
}

360
int xt_check_match(struct xt_mtchk_param *par,
361
		   unsigned int size, u_int8_t proto, bool inv_proto)
362
{
363 364
	if (XT_ALIGN(par->match->matchsize) != size &&
	    par->match->matchsize != -1) {
365 366 367 368
		/*
		 * ebt_among is exempt from centralized matchsize checking
		 * because it uses a dynamic-size data set.
		 */
369 370
		pr_err("%s_tables: %s.%u match: invalid size "
		       "%u (kernel) != (user) %u\n",
371
		       xt_prefix[par->family], par->match->name,
372
		       par->match->revision,
373
		       XT_ALIGN(par->match->matchsize), size);
374 375
		return -EINVAL;
	}
376 377
	if (par->match->table != NULL &&
	    strcmp(par->match->table, par->table) != 0) {
J
Joe Perches 已提交
378
		pr_err("%s_tables: %s match: only valid in %s table, not %s\n",
379
		       xt_prefix[par->family], par->match->name,
380
		       par->match->table, par->table);
381 382
		return -EINVAL;
	}
383
	if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
384 385
		char used[64], allow[64];

J
Joe Perches 已提交
386
		pr_err("%s_tables: %s match: used from hooks %s, but only "
387
		       "valid from %s\n",
388
		       xt_prefix[par->family], par->match->name,
389 390
		       textify_hooks(used, sizeof(used), par->hook_mask),
		       textify_hooks(allow, sizeof(allow), par->match->hooks));
391 392
		return -EINVAL;
	}
393
	if (par->match->proto && (par->match->proto != proto || inv_proto)) {
J
Joe Perches 已提交
394
		pr_err("%s_tables: %s match: only valid for protocol %u\n",
395 396
		       xt_prefix[par->family], par->match->name,
		       par->match->proto);
397 398
		return -EINVAL;
	}
399
	if (par->match->checkentry != NULL && !par->match->checkentry(par))
400
		return -EINVAL;
401 402 403 404
	return 0;
}
EXPORT_SYMBOL_GPL(xt_check_match);

405
#ifdef CONFIG_COMPAT
406
int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta)
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
{
	struct compat_delta *tmp;

	tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
	if (!tmp)
		return -ENOMEM;

	tmp->offset = offset;
	tmp->delta = delta;

	if (xt[af].compat_offsets) {
		tmp->next = xt[af].compat_offsets->next;
		xt[af].compat_offsets->next = tmp;
	} else {
		xt[af].compat_offsets = tmp;
		tmp->next = NULL;
	}
	return 0;
}
EXPORT_SYMBOL_GPL(xt_compat_add_offset);

428
void xt_compat_flush_offsets(u_int8_t af)
429 430 431 432 433 434 435 436 437 438 439 440 441
{
	struct compat_delta *tmp, *next;

	if (xt[af].compat_offsets) {
		for (tmp = xt[af].compat_offsets; tmp; tmp = next) {
			next = tmp->next;
			kfree(tmp);
		}
		xt[af].compat_offsets = NULL;
	}
}
EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);

442
int xt_compat_calc_jump(u_int8_t af, unsigned int offset)
443 444
{
	struct compat_delta *tmp;
445
	int delta;
446 447 448 449 450 451 452 453

	for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
		if (tmp->offset < offset)
			delta += tmp->delta;
	return delta;
}
EXPORT_SYMBOL_GPL(xt_compat_calc_jump);

454
int xt_compat_match_offset(const struct xt_match *match)
455
{
456 457 458 459 460
	u_int16_t csize = match->compatsize ? : match->matchsize;
	return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);
}
EXPORT_SYMBOL_GPL(xt_compat_match_offset);

461
int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
462
			      unsigned int *size)
463
{
464
	const struct xt_match *match = m->u.kernel.match;
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
	int pad, off = xt_compat_match_offset(match);
	u_int16_t msize = cm->u.user.match_size;

	m = *dstptr;
	memcpy(m, cm, sizeof(*cm));
	if (match->compat_from_user)
		match->compat_from_user(m->data, cm->data);
	else
		memcpy(m->data, cm->data, msize - sizeof(*cm));
	pad = XT_ALIGN(match->matchsize) - match->matchsize;
	if (pad > 0)
		memset(m->data + match->matchsize, 0, pad);

	msize += off;
	m->u.user.match_size = msize;

	*size += off;
	*dstptr += msize;
484
	return 0;
485 486 487
}
EXPORT_SYMBOL_GPL(xt_compat_match_from_user);

488 489
int xt_compat_match_to_user(const struct xt_entry_match *m,
			    void __user **dstptr, unsigned int *size)
490
{
491
	const struct xt_match *match = m->u.kernel.match;
492 493 494 495 496
	struct compat_xt_entry_match __user *cm = *dstptr;
	int off = xt_compat_match_offset(match);
	u_int16_t msize = m->u.user.match_size - off;

	if (copy_to_user(cm, m, sizeof(*cm)) ||
497 498 499
	    put_user(msize, &cm->u.user.match_size) ||
	    copy_to_user(cm->u.user.name, m->u.kernel.match->name,
			 strlen(m->u.kernel.match->name) + 1))
500
		return -EFAULT;
501 502 503 504 505 506 507

	if (match->compat_to_user) {
		if (match->compat_to_user((void __user *)cm->data, m->data))
			return -EFAULT;
	} else {
		if (copy_to_user(cm->data, m->data, msize - sizeof(*cm)))
			return -EFAULT;
508
	}
509 510 511 512

	*size -= off;
	*dstptr += msize;
	return 0;
513
}
514 515
EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
#endif /* CONFIG_COMPAT */
516

517
int xt_check_target(struct xt_tgchk_param *par,
518
		    unsigned int size, u_int8_t proto, bool inv_proto)
519
{
520
	if (XT_ALIGN(par->target->targetsize) != size) {
521 522
		pr_err("%s_tables: %s.%u target: invalid size "
		       "%u (kernel) != (user) %u\n",
523
		       xt_prefix[par->family], par->target->name,
524
		       par->target->revision,
525
		       XT_ALIGN(par->target->targetsize), size);
526 527
		return -EINVAL;
	}
528 529
	if (par->target->table != NULL &&
	    strcmp(par->target->table, par->table) != 0) {
J
Joe Perches 已提交
530
		pr_err("%s_tables: %s target: only valid in %s table, not %s\n",
531
		       xt_prefix[par->family], par->target->name,
532
		       par->target->table, par->table);
533 534
		return -EINVAL;
	}
535
	if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
536 537
		char used[64], allow[64];

J
Joe Perches 已提交
538
		pr_err("%s_tables: %s target: used from hooks %s, but only "
539
		       "usable from %s\n",
540
		       xt_prefix[par->family], par->target->name,
541 542
		       textify_hooks(used, sizeof(used), par->hook_mask),
		       textify_hooks(allow, sizeof(allow), par->target->hooks));
543 544
		return -EINVAL;
	}
545
	if (par->target->proto && (par->target->proto != proto || inv_proto)) {
J
Joe Perches 已提交
546
		pr_err("%s_tables: %s target: only valid for protocol %u\n",
547
		       xt_prefix[par->family], par->target->name,
548
		       par->target->proto);
549 550
		return -EINVAL;
	}
551
	if (par->target->checkentry != NULL && !par->target->checkentry(par))
552
		return -EINVAL;
553 554 555 556
	return 0;
}
EXPORT_SYMBOL_GPL(xt_check_target);

557
#ifdef CONFIG_COMPAT
558
int xt_compat_target_offset(const struct xt_target *target)
559
{
560 561 562 563 564 565
	u_int16_t csize = target->compatsize ? : target->targetsize;
	return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);
}
EXPORT_SYMBOL_GPL(xt_compat_target_offset);

void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
566
				unsigned int *size)
567
{
568
	const struct xt_target *target = t->u.kernel.target;
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
	int pad, off = xt_compat_target_offset(target);
	u_int16_t tsize = ct->u.user.target_size;

	t = *dstptr;
	memcpy(t, ct, sizeof(*ct));
	if (target->compat_from_user)
		target->compat_from_user(t->data, ct->data);
	else
		memcpy(t->data, ct->data, tsize - sizeof(*ct));
	pad = XT_ALIGN(target->targetsize) - target->targetsize;
	if (pad > 0)
		memset(t->data + target->targetsize, 0, pad);

	tsize += off;
	t->u.user.target_size = tsize;

	*size += off;
	*dstptr += tsize;
}
EXPORT_SYMBOL_GPL(xt_compat_target_from_user);

591 592
int xt_compat_target_to_user(const struct xt_entry_target *t,
			     void __user **dstptr, unsigned int *size)
593
{
594
	const struct xt_target *target = t->u.kernel.target;
595 596 597 598 599
	struct compat_xt_entry_target __user *ct = *dstptr;
	int off = xt_compat_target_offset(target);
	u_int16_t tsize = t->u.user.target_size - off;

	if (copy_to_user(ct, t, sizeof(*ct)) ||
600 601 602
	    put_user(tsize, &ct->u.user.target_size) ||
	    copy_to_user(ct->u.user.name, t->u.kernel.target->name,
			 strlen(t->u.kernel.target->name) + 1))
603
		return -EFAULT;
604 605 606 607 608 609 610

	if (target->compat_to_user) {
		if (target->compat_to_user((void __user *)ct->data, t->data))
			return -EFAULT;
	} else {
		if (copy_to_user(ct->data, t->data, tsize - sizeof(*ct)))
			return -EFAULT;
611
	}
612 613 614 615

	*size -= off;
	*dstptr += tsize;
	return 0;
616
}
617
EXPORT_SYMBOL_GPL(xt_compat_target_to_user);
618 619
#endif

620 621 622 623 624 625
struct xt_table_info *xt_alloc_table_info(unsigned int size)
{
	struct xt_table_info *newinfo;
	int cpu;

	/* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
626
	if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)
627 628
		return NULL;

629
	newinfo = kzalloc(XT_TABLE_INFO_SZ, GFP_KERNEL);
630 631 632 633 634
	if (!newinfo)
		return NULL;

	newinfo->size = size;

635
	for_each_possible_cpu(cpu) {
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
		if (size <= PAGE_SIZE)
			newinfo->entries[cpu] = kmalloc_node(size,
							GFP_KERNEL,
							cpu_to_node(cpu));
		else
			newinfo->entries[cpu] = vmalloc_node(size,
							cpu_to_node(cpu));

		if (newinfo->entries[cpu] == NULL) {
			xt_free_table_info(newinfo);
			return NULL;
		}
	}

	return newinfo;
}
EXPORT_SYMBOL(xt_alloc_table_info);

void xt_free_table_info(struct xt_table_info *info)
{
	int cpu;

658
	for_each_possible_cpu(cpu) {
659 660 661 662 663 664 665 666 667 668
		if (info->size <= PAGE_SIZE)
			kfree(info->entries[cpu]);
		else
			vfree(info->entries[cpu]);
	}
	kfree(info);
}
EXPORT_SYMBOL(xt_free_table_info);

/* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */
669 670
struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
				    const char *name)
671 672 673
{
	struct xt_table *t;

I
Ingo Molnar 已提交
674
	if (mutex_lock_interruptible(&xt[af].mutex) != 0)
675 676
		return ERR_PTR(-EINTR);

677
	list_for_each_entry(t, &net->xt.tables[af], list)
678 679
		if (strcmp(t->name, name) == 0 && try_module_get(t->me))
			return t;
I
Ingo Molnar 已提交
680
	mutex_unlock(&xt[af].mutex);
681 682 683 684 685 686
	return NULL;
}
EXPORT_SYMBOL_GPL(xt_find_table_lock);

void xt_table_unlock(struct xt_table *table)
{
I
Ingo Molnar 已提交
687
	mutex_unlock(&xt[table->af].mutex);
688 689 690
}
EXPORT_SYMBOL_GPL(xt_table_unlock);

691
#ifdef CONFIG_COMPAT
692
void xt_compat_lock(u_int8_t af)
693 694 695 696 697
{
	mutex_lock(&xt[af].compat_mutex);
}
EXPORT_SYMBOL_GPL(xt_compat_lock);

698
void xt_compat_unlock(u_int8_t af)
699 700 701 702 703
{
	mutex_unlock(&xt[af].compat_mutex);
}
EXPORT_SYMBOL_GPL(xt_compat_unlock);
#endif
704

705 706 707 708
DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks);
EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks);


709 710 711 712 713 714
struct xt_table_info *
xt_replace_table(struct xt_table *table,
	      unsigned int num_counters,
	      struct xt_table_info *newinfo,
	      int *error)
{
715
	struct xt_table_info *private;
716 717

	/* Do the substitution. */
718
	local_bh_disable();
719
	private = table->private;
720

721 722 723 724
	/* Check inside lock: is the old number correct? */
	if (num_counters != private->number) {
		duprintf("num_counters != table->private->number (%u/%u)\n",
			 num_counters, private->number);
725
		local_bh_enable();
726 727 728 729
		*error = -EAGAIN;
		return NULL;
	}

730 731 732 733 734 735 736 737 738 739 740 741
	table->private = newinfo;
	newinfo->initial_entries = private->initial_entries;

	/*
	 * Even though table entries have now been swapped, other CPU's
	 * may still be using the old entries. This is okay, because
	 * resynchronization happens because of the locking done
	 * during the get_counters() routine.
	 */
	local_bh_enable();

	return private;
742 743 744
}
EXPORT_SYMBOL_GPL(xt_replace_table);

745 746
struct xt_table *xt_register_table(struct net *net,
				   const struct xt_table *input_table,
747 748
				   struct xt_table_info *bootstrap,
				   struct xt_table_info *newinfo)
749 750 751
{
	int ret;
	struct xt_table_info *private;
752
	struct xt_table *t, *table;
753

754
	/* Don't add one object to multiple lists. */
755
	table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL);
756 757 758 759 760
	if (!table) {
		ret = -ENOMEM;
		goto out;
	}

I
Ingo Molnar 已提交
761
	ret = mutex_lock_interruptible(&xt[table->af].mutex);
762
	if (ret != 0)
763
		goto out_free;
764 765

	/* Don't autoload: we'd eat our tail... */
766
	list_for_each_entry(t, &net->xt.tables[table->af], list) {
P
Patrick McHardy 已提交
767 768 769 770
		if (strcmp(t->name, table->name) == 0) {
			ret = -EEXIST;
			goto unlock;
		}
771 772 773 774
	}

	/* Simplifies replace_table code. */
	table->private = bootstrap;
775

776 777 778 779 780 781 782 783 784
	if (!xt_replace_table(table, 0, newinfo, &ret))
		goto unlock;

	private = table->private;
	duprintf("table->private->number = %u\n", private->number);

	/* save number of initial entries */
	private->initial_entries = private->number;

785
	list_add(&table->list, &net->xt.tables[table->af]);
786 787
	mutex_unlock(&xt[table->af].mutex);
	return table;
788 789

 unlock:
I
Ingo Molnar 已提交
790
	mutex_unlock(&xt[table->af].mutex);
791 792
out_free:
	kfree(table);
793 794
out:
	return ERR_PTR(ret);
795 796 797 798 799 800 801
}
EXPORT_SYMBOL_GPL(xt_register_table);

void *xt_unregister_table(struct xt_table *table)
{
	struct xt_table_info *private;

I
Ingo Molnar 已提交
802
	mutex_lock(&xt[table->af].mutex);
803
	private = table->private;
P
Patrick McHardy 已提交
804
	list_del(&table->list);
I
Ingo Molnar 已提交
805
	mutex_unlock(&xt[table->af].mutex);
806
	kfree(table);
807 808 809 810 811 812

	return private;
}
EXPORT_SYMBOL_GPL(xt_unregister_table);

#ifdef CONFIG_PROC_FS
813 814
struct xt_names_priv {
	struct seq_net_private p;
815
	u_int8_t af;
816
};
817
static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
818
{
819
	struct xt_names_priv *priv = seq->private;
820
	struct net *net = seq_file_net(seq);
821
	u_int8_t af = priv->af;
822

823
	mutex_lock(&xt[af].mutex);
824
	return seq_list_start(&net->xt.tables[af], *pos);
825
}
826

827 828
static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
829
	struct xt_names_priv *priv = seq->private;
830
	struct net *net = seq_file_net(seq);
831
	u_int8_t af = priv->af;
832

833
	return seq_list_next(v, &net->xt.tables[af], pos);
834 835
}

836
static void xt_table_seq_stop(struct seq_file *seq, void *v)
837
{
838
	struct xt_names_priv *priv = seq->private;
839
	u_int8_t af = priv->af;
840

841 842
	mutex_unlock(&xt[af].mutex);
}
843

844 845 846
static int xt_table_seq_show(struct seq_file *seq, void *v)
{
	struct xt_table *table = list_entry(v, struct xt_table, list);
847

848 849 850 851 852
	if (strlen(table->name))
		return seq_printf(seq, "%s\n", table->name);
	else
		return 0;
}
853

854 855 856 857 858 859 860 861 862 863
static const struct seq_operations xt_table_seq_ops = {
	.start	= xt_table_seq_start,
	.next	= xt_table_seq_next,
	.stop	= xt_table_seq_stop,
	.show	= xt_table_seq_show,
};

static int xt_table_open(struct inode *inode, struct file *file)
{
	int ret;
864
	struct xt_names_priv *priv;
865

866 867
	ret = seq_open_net(inode, file, &xt_table_seq_ops,
			   sizeof(struct xt_names_priv));
868
	if (!ret) {
869 870
		priv = ((struct seq_file *)file->private_data)->private;
		priv->af = (unsigned long)PDE(inode)->data;
871 872
	}
	return ret;
873 874
}

875 876 877 878 879
static const struct file_operations xt_table_ops = {
	.owner	 = THIS_MODULE,
	.open	 = xt_table_open,
	.read	 = seq_read,
	.llseek	 = seq_lseek,
880
	.release = seq_release_net,
881 882
};

883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
/*
 * Traverse state for ip{,6}_{tables,matches} for helping crossing
 * the multi-AF mutexes.
 */
struct nf_mttg_trav {
	struct list_head *head, *curr;
	uint8_t class, nfproto;
};

enum {
	MTTG_TRAV_INIT,
	MTTG_TRAV_NFP_UNSPEC,
	MTTG_TRAV_NFP_SPEC,
	MTTG_TRAV_DONE,
};

static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos,
    bool is_target)
901
{
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
	static const uint8_t next_class[] = {
		[MTTG_TRAV_NFP_UNSPEC] = MTTG_TRAV_NFP_SPEC,
		[MTTG_TRAV_NFP_SPEC]   = MTTG_TRAV_DONE,
	};
	struct nf_mttg_trav *trav = seq->private;

	switch (trav->class) {
	case MTTG_TRAV_INIT:
		trav->class = MTTG_TRAV_NFP_UNSPEC;
		mutex_lock(&xt[NFPROTO_UNSPEC].mutex);
		trav->head = trav->curr = is_target ?
			&xt[NFPROTO_UNSPEC].target : &xt[NFPROTO_UNSPEC].match;
 		break;
	case MTTG_TRAV_NFP_UNSPEC:
		trav->curr = trav->curr->next;
		if (trav->curr != trav->head)
			break;
		mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
		mutex_lock(&xt[trav->nfproto].mutex);
		trav->head = trav->curr = is_target ?
			&xt[trav->nfproto].target : &xt[trav->nfproto].match;
		trav->class = next_class[trav->class];
		break;
	case MTTG_TRAV_NFP_SPEC:
		trav->curr = trav->curr->next;
		if (trav->curr != trav->head)
			break;
		/* fallthru, _stop will unlock */
	default:
		return NULL;
	}
933

934 935 936
	if (ppos != NULL)
		++*ppos;
	return trav;
937
}
938

939 940
static void *xt_mttg_seq_start(struct seq_file *seq, loff_t *pos,
    bool is_target)
941
{
942 943
	struct nf_mttg_trav *trav = seq->private;
	unsigned int j;
944

945 946 947 948 949
	trav->class = MTTG_TRAV_INIT;
	for (j = 0; j < *pos; ++j)
		if (xt_mttg_seq_next(seq, NULL, NULL, is_target) == NULL)
			return NULL;
	return trav;
950 951
}

952
static void xt_mttg_seq_stop(struct seq_file *seq, void *v)
953
{
954 955 956 957 958 959 960 961 962 963 964
	struct nf_mttg_trav *trav = seq->private;

	switch (trav->class) {
	case MTTG_TRAV_NFP_UNSPEC:
		mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
		break;
	case MTTG_TRAV_NFP_SPEC:
		mutex_unlock(&xt[trav->nfproto].mutex);
		break;
	}
}
965

966 967 968
static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
{
	return xt_mttg_seq_start(seq, pos, false);
969 970
}

971
static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos)
972
{
973 974
	return xt_mttg_seq_next(seq, v, ppos, false);
}
975

976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
static int xt_match_seq_show(struct seq_file *seq, void *v)
{
	const struct nf_mttg_trav *trav = seq->private;
	const struct xt_match *match;

	switch (trav->class) {
	case MTTG_TRAV_NFP_UNSPEC:
	case MTTG_TRAV_NFP_SPEC:
		if (trav->curr == trav->head)
			return 0;
		match = list_entry(trav->curr, struct xt_match, list);
		return (*match->name == '\0') ? 0 :
		       seq_printf(seq, "%s\n", match->name);
	}
	return 0;
991 992
}

993 994 995
static const struct seq_operations xt_match_seq_ops = {
	.start	= xt_match_seq_start,
	.next	= xt_match_seq_next,
996
	.stop	= xt_mttg_seq_stop,
997
	.show	= xt_match_seq_show,
998 999
};

1000
static int xt_match_open(struct inode *inode, struct file *file)
1001
{
1002 1003
	struct seq_file *seq;
	struct nf_mttg_trav *trav;
1004 1005
	int ret;

1006 1007 1008
	trav = kmalloc(sizeof(*trav), GFP_KERNEL);
	if (trav == NULL)
		return -ENOMEM;
1009

1010 1011 1012 1013
	ret = seq_open(file, &xt_match_seq_ops);
	if (ret < 0) {
		kfree(trav);
		return ret;
1014
	}
1015 1016 1017 1018 1019

	seq = file->private_data;
	seq->private = trav;
	trav->nfproto = (unsigned long)PDE(inode)->data;
	return 0;
1020 1021 1022 1023 1024 1025 1026
}

static const struct file_operations xt_match_ops = {
	.owner	 = THIS_MODULE,
	.open	 = xt_match_open,
	.read	 = seq_read,
	.llseek	 = seq_lseek,
1027
	.release = seq_release_private,
1028
};
1029

1030 1031
static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos)
{
1032
	return xt_mttg_seq_start(seq, pos, true);
1033 1034
}

1035
static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *ppos)
1036
{
1037
	return xt_mttg_seq_next(seq, v, ppos, true);
1038 1039 1040 1041
}

static int xt_target_seq_show(struct seq_file *seq, void *v)
{
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
	const struct nf_mttg_trav *trav = seq->private;
	const struct xt_target *target;

	switch (trav->class) {
	case MTTG_TRAV_NFP_UNSPEC:
	case MTTG_TRAV_NFP_SPEC:
		if (trav->curr == trav->head)
			return 0;
		target = list_entry(trav->curr, struct xt_target, list);
		return (*target->name == '\0') ? 0 :
		       seq_printf(seq, "%s\n", target->name);
	}
	return 0;
1055 1056 1057 1058 1059
}

static const struct seq_operations xt_target_seq_ops = {
	.start	= xt_target_seq_start,
	.next	= xt_target_seq_next,
1060
	.stop	= xt_mttg_seq_stop,
1061 1062 1063 1064 1065
	.show	= xt_target_seq_show,
};

static int xt_target_open(struct inode *inode, struct file *file)
{
1066 1067
	struct seq_file *seq;
	struct nf_mttg_trav *trav;
1068 1069
	int ret;

1070 1071 1072
	trav = kmalloc(sizeof(*trav), GFP_KERNEL);
	if (trav == NULL)
		return -ENOMEM;
1073

1074 1075 1076 1077
	ret = seq_open(file, &xt_target_seq_ops);
	if (ret < 0) {
		kfree(trav);
		return ret;
1078
	}
1079 1080 1081 1082 1083

	seq = file->private_data;
	seq->private = trav;
	trav->nfproto = (unsigned long)PDE(inode)->data;
	return 0;
1084 1085
}

1086
static const struct file_operations xt_target_ops = {
1087
	.owner	 = THIS_MODULE,
1088
	.open	 = xt_target_open,
1089 1090
	.read	 = seq_read,
	.llseek	 = seq_lseek,
1091
	.release = seq_release_private,
1092 1093 1094 1095 1096 1097 1098 1099
};

#define FORMAT_TABLES	"_tables_names"
#define	FORMAT_MATCHES	"_tables_matches"
#define FORMAT_TARGETS 	"_tables_targets"

#endif /* CONFIG_PROC_FS */

1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
/**
 * xt_hook_link - set up hooks for a new table
 * @table:	table with metadata needed to set up hooks
 * @fn:		Hook function
 *
 * This function will take care of creating and registering the necessary
 * Netfilter hooks for XT tables.
 */
struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
{
	unsigned int hook_mask = table->valid_hooks;
	uint8_t i, num_hooks = hweight32(hook_mask);
	uint8_t hooknum;
	struct nf_hook_ops *ops;
	int ret;

	ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
	if (ops == NULL)
		return ERR_PTR(-ENOMEM);

	for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0;
	     hook_mask >>= 1, ++hooknum) {
		if (!(hook_mask & 1))
			continue;
		ops[i].hook     = fn;
		ops[i].owner    = table->me;
		ops[i].pf       = table->af;
		ops[i].hooknum  = hooknum;
		ops[i].priority = table->priority;
		++i;
	}

	ret = nf_register_hooks(ops, num_hooks);
	if (ret < 0) {
		kfree(ops);
		return ERR_PTR(ret);
	}

	return ops;
}
EXPORT_SYMBOL_GPL(xt_hook_link);

/**
 * xt_hook_unlink - remove hooks for a table
 * @ops:	nf_hook_ops array as returned by nf_hook_link
 * @hook_mask:	the very same mask that was passed to nf_hook_link
 */
void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
{
	nf_unregister_hooks(ops, hweight32(table->valid_hooks));
	kfree(ops);
}
EXPORT_SYMBOL_GPL(xt_hook_unlink);

1154
int xt_proto_init(struct net *net, u_int8_t af)
1155 1156 1157 1158 1159 1160
{
#ifdef CONFIG_PROC_FS
	char buf[XT_FUNCTION_MAXNAMELEN];
	struct proc_dir_entry *proc;
#endif

1161
	if (af >= ARRAY_SIZE(xt_prefix))
1162 1163 1164 1165
		return -EINVAL;


#ifdef CONFIG_PROC_FS
1166
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1167
	strlcat(buf, FORMAT_TABLES, sizeof(buf));
1168 1169
	proc = proc_create_data(buf, 0440, net->proc_net, &xt_table_ops,
				(void *)(unsigned long)af);
1170 1171 1172
	if (!proc)
		goto out;

1173
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1174
	strlcat(buf, FORMAT_MATCHES, sizeof(buf));
1175 1176
	proc = proc_create_data(buf, 0440, net->proc_net, &xt_match_ops,
				(void *)(unsigned long)af);
1177 1178 1179
	if (!proc)
		goto out_remove_tables;

1180
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1181
	strlcat(buf, FORMAT_TARGETS, sizeof(buf));
1182 1183
	proc = proc_create_data(buf, 0440, net->proc_net, &xt_target_ops,
				(void *)(unsigned long)af);
1184 1185 1186 1187 1188 1189 1190 1191
	if (!proc)
		goto out_remove_matches;
#endif

	return 0;

#ifdef CONFIG_PROC_FS
out_remove_matches:
1192
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1193
	strlcat(buf, FORMAT_MATCHES, sizeof(buf));
1194
	proc_net_remove(net, buf);
1195 1196

out_remove_tables:
1197
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1198
	strlcat(buf, FORMAT_TABLES, sizeof(buf));
1199
	proc_net_remove(net, buf);
1200 1201 1202 1203 1204 1205
out:
	return -1;
#endif
}
EXPORT_SYMBOL_GPL(xt_proto_init);

1206
void xt_proto_fini(struct net *net, u_int8_t af)
1207 1208 1209 1210
{
#ifdef CONFIG_PROC_FS
	char buf[XT_FUNCTION_MAXNAMELEN];

1211
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1212
	strlcat(buf, FORMAT_TABLES, sizeof(buf));
1213
	proc_net_remove(net, buf);
1214

1215
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1216
	strlcat(buf, FORMAT_TARGETS, sizeof(buf));
1217
	proc_net_remove(net, buf);
1218

1219
	strlcpy(buf, xt_prefix[af], sizeof(buf));
1220
	strlcat(buf, FORMAT_MATCHES, sizeof(buf));
1221
	proc_net_remove(net, buf);
1222 1223 1224 1225
#endif /*CONFIG_PROC_FS*/
}
EXPORT_SYMBOL_GPL(xt_proto_fini);

1226 1227 1228 1229
static int __net_init xt_net_init(struct net *net)
{
	int i;

1230
	for (i = 0; i < NFPROTO_NUMPROTO; i++)
1231 1232 1233 1234 1235 1236 1237
		INIT_LIST_HEAD(&net->xt.tables[i]);
	return 0;
}

static struct pernet_operations xt_net_ops = {
	.init = xt_net_init,
};
1238 1239 1240

static int __init xt_init(void)
{
1241 1242 1243 1244 1245 1246 1247 1248
	unsigned int i;
	int rv;

	for_each_possible_cpu(i) {
		struct xt_info_lock *lock = &per_cpu(xt_info_locks, i);
		spin_lock_init(&lock->lock);
		lock->readers = 0;
	}
1249

1250
	xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL);
1251 1252 1253
	if (!xt)
		return -ENOMEM;

1254
	for (i = 0; i < NFPROTO_NUMPROTO; i++) {
I
Ingo Molnar 已提交
1255
		mutex_init(&xt[i].mutex);
1256 1257
#ifdef CONFIG_COMPAT
		mutex_init(&xt[i].compat_mutex);
1258
		xt[i].compat_offsets = NULL;
1259
#endif
1260 1261 1262
		INIT_LIST_HEAD(&xt[i].target);
		INIT_LIST_HEAD(&xt[i].match);
	}
1263 1264 1265 1266
	rv = register_pernet_subsys(&xt_net_ops);
	if (rv < 0)
		kfree(xt);
	return rv;
1267 1268 1269 1270
}

static void __exit xt_fini(void)
{
1271
	unregister_pernet_subsys(&xt_net_ops);
1272 1273 1274 1275 1276 1277
	kfree(xt);
}

module_init(xt_init);
module_exit(xt_fini);