x_tables.c revision 37f9f7334b86ffc3b8a1921842ae33cb9aa22ee3
12e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/*
22e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * x_tables core - Backend for {ip,ip6,arp}_tables
32e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *
42e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
52e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *
62e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * Based on existing ip_tables code which is
72e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *   Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
82e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *   Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
92e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *
102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * This program is free software; you can redistribute it and/or modify
112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * it under the terms of the GNU General Public License version 2 as
122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * published by the Free Software Foundation.
132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *
142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte */
152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/config.h>
172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/kernel.h>
182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/socket.h>
192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/net.h>
202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/proc_fs.h>
212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/seq_file.h>
222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/string.h>
232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/vmalloc.h>
242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/netfilter/x_tables.h>
262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/netfilter_arp.h>
272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_LICENSE("GPL");
292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_af {
352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct semaphore mutex;
362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct list_head match;
372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct list_head target;
382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct list_head tables;
392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte};
402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic struct xt_af *xt;
422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef DEBUG_IP_FIREWALL_USER
442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define duprintf(format, args...) printk(format , ## args)
452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#else
462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define duprintf(format, args...)
472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif
482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteenum {
502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	TABLE,
512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	TARGET,
522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	MATCH,
532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte};
542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardystatic const char *xt_prefix[NPROTO] = {
5637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	[AF_INET] 	= "ip",
5737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	[AF_INET6] 	= "ip6",
5837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	[NF_ARP]	= "arp",
5937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy};
6037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy
612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Registration hooks for targets. */
622e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteint
632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltext_register_target(int af, struct xt_target *target)
642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int ret;
662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	ret = down_interruptible(&xt[af].mutex);
682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (ret != 0)
692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return ret;
702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_add(&target->list, &xt[af].target);
712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return ret;
732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_register_target);
752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid
772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltext_unregister_target(int af, struct xt_target *target)
782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	down(&xt[af].mutex);
802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	LIST_DELETE(&xt[af].target, target);
812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_unregister_target);
842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteint
862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltext_register_match(int af, struct xt_match *match)
872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int ret;
892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	ret = down_interruptible(&xt[af].mutex);
912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (ret != 0)
922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return ret;
932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_add(&match->list, &xt[af].match);
952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return ret;
982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
992e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_register_match);
1002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid
1022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltext_unregister_match(int af, struct xt_match *match)
1032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
1042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	down(&xt[af].mutex);
1052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	LIST_DELETE(&xt[af].match, match);
1062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
1072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
1082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_unregister_match);
1092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/*
1122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * These are weird, but module loading must not be done with mutex
1132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * held (since they will register), and we have to have a single
1142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * function to use try_then_request_module().
1152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte */
1162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Find match, grabs ref.  Returns ERR_PTR() on error. */
1182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_match *xt_find_match(int af, const char *name, u8 revision)
1192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
1202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_match *m;
1212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int err = 0;
1222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (down_interruptible(&xt[af].mutex) != 0)
1242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return ERR_PTR(-EINTR);
1252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_for_each_entry(m, &xt[af].match, list) {
1272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (strcmp(m->name, name) == 0) {
1282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			if (m->revision == revision) {
1292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				if (try_module_get(m->me)) {
1302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte					up(&xt[af].mutex);
1312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte					return m;
1322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				}
1332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			} else
1342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				err = -EPROTOTYPE; /* Found something. */
1352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		}
1362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
1372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
1382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return ERR_PTR(err);
1392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
1402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_find_match);
1412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Find target, grabs ref.  Returns ERR_PTR() on error. */
1432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_target *xt_find_target(int af, const char *name, u8 revision)
1442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
1452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_target *t;
1462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int err = 0;
1472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (down_interruptible(&xt[af].mutex) != 0)
1492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return ERR_PTR(-EINTR);
1502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_for_each_entry(t, &xt[af].target, list) {
1522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (strcmp(t->name, name) == 0) {
1532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			if (t->revision == revision) {
1542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				if (try_module_get(t->me)) {
1552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte					up(&xt[af].mutex);
1562e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte					return t;
1572e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				}
1582e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			} else
1592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				err = -EPROTOTYPE; /* Found something. */
1602e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		}
1612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
1622e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
1632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return ERR_PTR(err);
1642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
1652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_find_target);
1662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
1682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
1692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_target *target;
1702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	target = try_then_request_module(xt_find_target(af, name, revision),
17237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy					 "%st_%s", xt_prefix[af], name);
1732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (IS_ERR(target) || !target)
1742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
1752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return target;
1762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
1772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_request_find_target);
1782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic int match_revfn(int af, const char *name, u8 revision, int *bestp)
1802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
1812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_match *m;
1822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int have_rev = 0;
1832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_for_each_entry(m, &xt[af].match, list) {
1852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (strcmp(m->name, name) == 0) {
1862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			if (m->revision > *bestp)
1872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				*bestp = m->revision;
1882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			if (m->revision == revision)
1892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				have_rev = 1;
1902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		}
1912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
1922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return have_rev;
1932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
1942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
1952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic int target_revfn(int af, const char *name, u8 revision, int *bestp)
1962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
1972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_target *t;
1982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int have_rev = 0;
1992e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
2002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_for_each_entry(t, &xt[af].target, list) {
2012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (strcmp(t->name, name) == 0) {
2022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			if (t->revision > *bestp)
2032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				*bestp = t->revision;
2042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			if (t->revision == revision)
2052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte				have_rev = 1;
2062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		}
2072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
2082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return have_rev;
2092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
2102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
2112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Returns true or false (if no such extension at all) */
2122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteint xt_find_revision(int af, const char *name, u8 revision, int target,
2132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		     int *err)
2142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
2152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int have_rev, best = -1;
2162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
2172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (down_interruptible(&xt[af].mutex) != 0) {
2182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		*err = -EINTR;
2192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return 1;
2202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
2212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (target == 1)
2222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		have_rev = target_revfn(af, name, revision, &best);
2232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	else
2242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		have_rev = match_revfn(af, name, revision, &best);
2252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
2262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
2272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	/* Nothing at all?  Return 0 to try loading module. */
2282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (best == -1) {
2292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		*err = -ENOENT;
2302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return 0;
2312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
2322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
2332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	*err = best;
2342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!have_rev)
2352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		*err = -EPROTONOSUPPORT;
2362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return 1;
2372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
2382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_find_revision);
2392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
24037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardyint xt_check_match(const struct xt_match *match, unsigned short family,
24137f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy                   unsigned int size, const char *table, unsigned int hook_mask,
24237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		   unsigned short proto, int inv_proto)
24337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy{
24437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (XT_ALIGN(match->matchsize) != size) {
24537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s match: invalid size %Zu != %u\n",
24637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], match->name,
24737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       XT_ALIGN(match->matchsize), size);
24837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
24937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
25037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (match->table && strcmp(match->table, table)) {
25137f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s match: only valid in %s table, not %s\n",
25237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], match->name, match->table, table);
25337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
25437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
25537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (match->hooks && (hook_mask & ~match->hooks) != 0) {
25637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s match: bad hook_mask %u\n",
25737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], match->name, hook_mask);
25837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
25937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
26037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (match->proto && (match->proto != proto || inv_proto)) {
26137f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s match: only valid for protocol %u\n",
26237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], match->name, match->proto);
26337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
26437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
26537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	return 0;
26637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy}
26737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardyEXPORT_SYMBOL_GPL(xt_check_match);
26837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy
26937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardyint xt_check_target(const struct xt_target *target, unsigned short family,
27037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		    unsigned int size, const char *table, unsigned int hook_mask,
27137f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		    unsigned short proto, int inv_proto)
27237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy{
27337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (XT_ALIGN(target->targetsize) != size) {
27437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s target: invalid size %Zu != %u\n",
27537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], target->name,
27637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       XT_ALIGN(target->targetsize), size);
27737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
27837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
27937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (target->table && strcmp(target->table, table)) {
28037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s target: only valid in %s table, not %s\n",
28137f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], target->name, target->table, table);
28237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
28337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
28437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (target->hooks && (hook_mask & ~target->hooks) != 0) {
28537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s target: bad hook_mask %u\n",
28637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], target->name, hook_mask);
28737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
28837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
28937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	if (target->proto && (target->proto != proto || inv_proto)) {
29037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		printk("%s_tables: %s target: only valid for protocol %u\n",
29137f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		       xt_prefix[family], target->name, target->proto);
29237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy		return -EINVAL;
29337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	}
29437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy	return 0;
29537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy}
29637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardyEXPORT_SYMBOL_GPL(xt_check_target);
29737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy
2982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_table_info *xt_alloc_table_info(unsigned int size)
2992e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
3002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_table_info *newinfo;
3012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int cpu;
3022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	/* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
3042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
3052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
3062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL);
3082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!newinfo)
3092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
3102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	newinfo->size = size;
3122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	for_each_cpu(cpu) {
3142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (size <= PAGE_SIZE)
3152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			newinfo->entries[cpu] = kmalloc_node(size,
3162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte							GFP_KERNEL,
3172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte							cpu_to_node(cpu));
3182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		else
3192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			newinfo->entries[cpu] = vmalloc_node(size,
3202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte							cpu_to_node(cpu));
3212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (newinfo->entries[cpu] == NULL) {
3232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			xt_free_table_info(newinfo);
3242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			return NULL;
3252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		}
3262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
3272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return newinfo;
3292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
3302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_alloc_table_info);
3312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid xt_free_table_info(struct xt_table_info *info)
3332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
3342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int cpu;
3352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	for_each_cpu(cpu) {
3372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (info->size <= PAGE_SIZE)
3382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			kfree(info->entries[cpu]);
3392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		else
3402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			vfree(info->entries[cpu]);
3412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
3422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	kfree(info);
3432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
3442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_free_table_info);
3452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */
3472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_table *xt_find_table_lock(int af, const char *name)
3482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
3492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_table *t;
3502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (down_interruptible(&xt[af].mutex) != 0)
3522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return ERR_PTR(-EINTR);
3532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_for_each_entry(t, &xt[af].tables, list)
3552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (strcmp(t->name, name) == 0 && try_module_get(t->me))
3562e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			return t;
3572e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
3582e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return NULL;
3592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
3602e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_find_table_lock);
3612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3622e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid xt_table_unlock(struct xt_table *table)
3632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
3642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[table->af].mutex);
3652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
3662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_table_unlock);
3672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_table_info *
3702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltext_replace_table(struct xt_table *table,
3712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	      unsigned int num_counters,
3722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	      struct xt_table_info *newinfo,
3732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	      int *error)
3742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
3752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_table_info *oldinfo, *private;
3762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	/* Do the substitution. */
3782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	write_lock_bh(&table->lock);
3792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	private = table->private;
3802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	/* Check inside lock: is the old number correct? */
3812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (num_counters != private->number) {
3822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		duprintf("num_counters != table->private->number (%u/%u)\n",
3832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			 num_counters, private->number);
3842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		write_unlock_bh(&table->lock);
3852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		*error = -EAGAIN;
3862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
3872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
3882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	oldinfo = private;
3892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	table->private = newinfo;
3902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	newinfo->initial_entries = oldinfo->initial_entries;
3912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	write_unlock_bh(&table->lock);
3922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return oldinfo;
3942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
3952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_replace_table);
3962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
3972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteint xt_register_table(struct xt_table *table,
3982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		      struct xt_table_info *bootstrap,
3992e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		      struct xt_table_info *newinfo)
4002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
4012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int ret;
4022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_table_info *private;
4032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	ret = down_interruptible(&xt[table->af].mutex);
4052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (ret != 0)
4062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return ret;
4072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	/* Don't autoload: we'd eat our tail... */
4092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (list_named_find(&xt[table->af].tables, table->name)) {
4102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		ret = -EEXIST;
4112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		goto unlock;
4122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
4132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	/* Simplifies replace_table code. */
4152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	table->private = bootstrap;
4162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!xt_replace_table(table, 0, newinfo, &ret))
4172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		goto unlock;
4182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	private = table->private;
4202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	duprintf("table->private->number = %u\n", private->number);
4212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	/* save number of initial entries */
4232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	private->initial_entries = private->number;
4242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	rwlock_init(&table->lock);
4262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list_prepend(&xt[table->af].tables, table);
4272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	ret = 0;
4292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte unlock:
4302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[table->af].mutex);
4312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return ret;
4322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
4332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_register_table);
4342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid *xt_unregister_table(struct xt_table *table)
4362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
4372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct xt_table_info *private;
4382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	down(&xt[table->af].mutex);
4402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	private = table->private;
4412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	LIST_DELETE(&xt[table->af].tables, table);
4422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[table->af].mutex);
4432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return private;
4452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
4462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_unregister_table);
4472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS
4492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic char *xt_proto_prefix[NPROTO] = {
4502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	[AF_INET]	= "ip",
4512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	[AF_INET6]	= "ip6",
4522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	[NF_ARP]	= "arp",
4532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte};
4542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos)
4562e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
4572e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct list_head *head = list->next;
4582e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!head || list_empty(list))
4602e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
4612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4622e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	while (pos && (head = head->next)) {
4632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		if (head == list)
4642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte			return NULL;
4652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		pos--;
4662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
4672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return pos ? NULL : head;
4682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
4692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic struct list_head *type2list(u_int16_t af, u_int16_t type)
4712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
4722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct list_head *list;
4732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	switch (type) {
4752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	case TARGET:
4762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		list = &xt[af].target;
4772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		break;
4782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	case MATCH:
4792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		list = &xt[af].match;
4802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		break;
4812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	case TABLE:
4822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		list = &xt[af].tables;
4832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		break;
4842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	default:
4852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		list = NULL;
4862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		break;
4872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
4882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return list;
4902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
4912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
4932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
4942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
4952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	u_int16_t af = (unsigned long)pde->data & 0xffff;
4962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	u_int16_t type = (unsigned long)pde->data >> 16;
4972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct list_head *list;
4982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
4992e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (af >= NPROTO)
5002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
5012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list = type2list(af, type);
5032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!list)
5042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
5052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (down_interruptible(&xt[af].mutex) != 0)
5072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
5082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return xt_get_idx(list, seq, *pos);
5102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
5112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
5132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
5142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct proc_dir_entry *pde = seq->private;
5152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	u_int16_t af = (unsigned long)pde->data & 0xffff;
5162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	u_int16_t type = (unsigned long)pde->data >> 16;
5172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct list_head *list;
5182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (af >= NPROTO)
5202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
5212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	list = type2list(af, type);
5232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!list)
5242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return NULL;
5252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	(*pos)++;
5272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return xt_get_idx(list, seq, *pos);
5282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
5292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic void xt_tgt_seq_stop(struct seq_file *seq, void *v)
5312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
5322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct proc_dir_entry *pde = seq->private;
5332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	u_int16_t af = (unsigned long)pde->data & 0xffff;
5342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	up(&xt[af].mutex);
5362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
5372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic int xt_name_seq_show(struct seq_file *seq, void *v)
5392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
5402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	char *name = (char *)v + sizeof(struct list_head);
5412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (strlen(name))
5432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return seq_printf(seq, "%s\n", name);
5442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	else
5452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return 0;
5462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
5472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic struct seq_operations xt_tgt_seq_ops = {
5492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.start	= xt_tgt_seq_start,
5502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.next	= xt_tgt_seq_next,
5512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.stop	= xt_tgt_seq_stop,
5522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.show	= xt_name_seq_show,
5532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte};
5542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic int xt_tgt_open(struct inode *inode, struct file *file)
5562e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
5572e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int ret;
5582e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	ret = seq_open(file, &xt_tgt_seq_ops);
5602e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!ret) {
5612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		struct seq_file *seq = file->private_data;
5622e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		struct proc_dir_entry *pde = PDE(inode);
5632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		seq->private = pde;
5652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
5662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return ret;
5682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
5692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic struct file_operations xt_file_ops = {
5712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.owner	 = THIS_MODULE,
5722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.open	 = xt_tgt_open,
5732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.read	 = seq_read,
5742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.llseek	 = seq_lseek,
5752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.release = seq_release,
5762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte};
5772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define FORMAT_TABLES	"_tables_names"
5792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define	FORMAT_MATCHES	"_tables_matches"
5802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define FORMAT_TARGETS 	"_tables_targets"
5812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif /* CONFIG_PROC_FS */
5832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteint xt_proto_init(int af)
5852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
5862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS
5872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	char buf[XT_FUNCTION_MAXNAMELEN];
5882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	struct proc_dir_entry *proc;
5892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif
5902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (af >= NPROTO)
5922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return -EINVAL;
5932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
5952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS
5962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
5972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_TABLES, sizeof(buf));
5982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
5992e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!proc)
6002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		goto out;
6012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc->data = (void *) ((unsigned long) af | (TABLE << 16));
6022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
6052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_MATCHES, sizeof(buf));
6062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
6072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!proc)
6082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		goto out_remove_tables;
6092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc->data = (void *) ((unsigned long) af | (MATCH << 16));
6102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
6122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_TARGETS, sizeof(buf));
6132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
6142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!proc)
6152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		goto out_remove_matches;
6162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc->data = (void *) ((unsigned long) af | (TARGET << 16));
6172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif
6182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return 0;
6202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS
6222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteout_remove_matches:
6232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
6242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_MATCHES, sizeof(buf));
6252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc_net_remove(buf);
6262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteout_remove_tables:
6282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
6292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_TABLES, sizeof(buf));
6302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc_net_remove(buf);
6312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteout:
6322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return -1;
6332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif
6342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
6352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_proto_init);
6362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid xt_proto_fini(int af)
6382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
6392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS
6402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	char buf[XT_FUNCTION_MAXNAMELEN];
6412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
6432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_TABLES, sizeof(buf));
6442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc_net_remove(buf);
6452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
6472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_TARGETS, sizeof(buf));
6482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc_net_remove(buf);
6492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
6512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	strlcat(buf, FORMAT_MATCHES, sizeof(buf));
6522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	proc_net_remove(buf);
6532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif /*CONFIG_PROC_FS*/
6542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
6552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_proto_fini);
6562e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6572e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6582e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic int __init xt_init(void)
6592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
6602e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	int i;
6612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6622e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
6632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	if (!xt)
6642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		return -ENOMEM;
6652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	for (i = 0; i < NPROTO; i++) {
6672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		init_MUTEX(&xt[i].mutex);
6682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		INIT_LIST_HEAD(&xt[i].target);
6692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		INIT_LIST_HEAD(&xt[i].match);
6702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte		INIT_LIST_HEAD(&xt[i].tables);
6712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	}
6722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	return 0;
6732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
6742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic void __exit xt_fini(void)
6762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{
6772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	kfree(xt);
6782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}
6792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
6802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltemodule_init(xt_init);
6812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltemodule_exit(xt_fini);
6822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte
683