diff options
author | Harald Welte <laforge@netfilter.org> | 2006-01-12 13:30:04 -0800 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-01-12 14:06:43 -0800 |
commit | 2e4e6a17af35be359cc8f1c924f8f198fbd478cc (patch) | |
tree | cb4b5438dcf9ff9d57518a26124308bcbfffd214 /net | |
parent | 880b005f294454d989783d0984dc554dfe3c8214 (diff) | |
download | kernel_samsung_crespo-2e4e6a17af35be359cc8f1c924f8f198fbd478cc.zip kernel_samsung_crespo-2e4e6a17af35be359cc8f1c924f8f198fbd478cc.tar.gz kernel_samsung_crespo-2e4e6a17af35be359cc8f1c924f8f198fbd478cc.tar.bz2 |
[NETFILTER] x_tables: Abstraction layer for {ip,ip6,arp}_tables
This monster-patch tries to do the best job for unifying the data
structures and backend interfaces for the three evil clones ip_tables,
ip6_tables and arp_tables. In an ideal world we would never have
allowed this kind of copy+paste programming... but well, our world
isn't (yet?) ideal.
o introduce a new x_tables module
o {ip,arp,ip6}_tables depend on this x_tables module
o registration functions for tables, matches and targets are only
wrappers around x_tables provided functions
o all matches/targets that are used from ip_tables and ip6_tables
are now implemented as xt_FOOBAR.c files and provide module aliases
to ipt_FOOBAR and ip6t_FOOBAR
o header files for xt_matches are in include/linux/netfilter/,
include/linux/netfilter_{ipv4,ipv6} contains compatibility wrappers
around the xt_FOOBAR.h headers
Based on this patchset we're going to further unify the code,
gradually getting rid of all the layer 3 specific assumptions.
Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
98 files changed, 2646 insertions, 3446 deletions
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 9f6e019..a29c123 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -15,6 +15,7 @@ #include <linux/netfilter.h> #include <linux/module.h> #include <linux/ip.h> +#include <linux/in.h> #include <linux/if_arp.h> #include <linux/spinlock.h> diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index a9893ec..db78303 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -182,6 +182,7 @@ config IP_NF_QUEUE config IP_NF_IPTABLES tristate "IP tables support (required for filtering/masq/NAT)" + depends on NETFILTER_XTABLES help iptables is a general, extensible packet identification framework. The packet filtering and full NAT (masquerading, port forwarding, @@ -191,16 +192,6 @@ config IP_NF_IPTABLES To compile it as a module, choose M here. If unsure, say N. # The matches. -config IP_NF_MATCH_LIMIT - tristate "limit match support" - depends on IP_NF_IPTABLES - help - limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target ("LOG - target support", below) and to avoid some Denial of Service attacks. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_IPRANGE tristate "IP range match support" depends on IP_NF_IPTABLES @@ -210,37 +201,6 @@ config IP_NF_MATCH_IPRANGE To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_MAC - tristate "MAC address match support" - depends on IP_NF_IPTABLES - help - MAC matching allows you to match packets based on the source - Ethernet address of the packet. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_PKTTYPE - tristate "Packet type match support" - depends on IP_NF_IPTABLES - help - Packet type matching allows you to match a packet by - its "class", eg. BROADCAST, MULTICAST, ... - - Typical usage: - iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_MARK - tristate "netfilter MARK match support" - depends on IP_NF_IPTABLES - help - Netfilter mark matching allows you to match packets based on the - `nfmark' value in the packet. This can be set by the MARK target - (see below). - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_MULTIPORT tristate "Multiple port match support" depends on IP_NF_IPTABLES @@ -301,15 +261,6 @@ config IP_NF_MATCH_AH_ESP To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_LENGTH - tristate "LENGTH match support" - depends on IP_NF_IPTABLES - help - This option allows you to match the length of a packet against a - specific value or range of values. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_TTL tristate "TTL match support" depends on IP_NF_IPTABLES @@ -319,50 +270,6 @@ config IP_NF_MATCH_TTL To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_TCPMSS - tristate "tcpmss match support" - depends on IP_NF_IPTABLES - help - This option adds a `tcpmss' match, which allows you to examine the - MSS value of TCP SYN packets, which control the maximum packet size - for that connection. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_HELPER - tristate "Helper match support" - depends on IP_NF_IPTABLES - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - Helper matching allows you to match packets in dynamic connections - tracked by a conntrack-helper, ie. ip_conntrack_ftp - - To compile it as a module, choose M here. If unsure, say Y. - -config IP_NF_MATCH_STATE - tristate "Connection state match support" - depends on IP_NF_IPTABLES - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - Connection state matching allows you to match packets based on their - relationship to a tracked connection (ie. previous packets). This - is a powerful tool for packet classification. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_CONNTRACK - tristate "Connection tracking match support" - depends on IP_NF_IPTABLES - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - This is a general conntrack match module, a superset of the state match. - - It allows matching on additional conntrack information, which is - useful in complex configurations, such as NAT gateways with multiple - internet links or tunnels. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_OWNER tristate "Owner match support" depends on IP_NF_IPTABLES @@ -372,15 +279,6 @@ config IP_NF_MATCH_OWNER To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_PHYSDEV - tristate "Physdev match support" - depends on IP_NF_IPTABLES && BRIDGE_NETFILTER - help - Physdev packet matching matches against the physical bridge ports - the IP packet arrived on or will leave by. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_ADDRTYPE tristate 'address type match support' depends on IP_NF_IPTABLES @@ -391,75 +289,6 @@ config IP_NF_MATCH_ADDRTYPE If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. If unsure, say `N'. -config IP_NF_MATCH_REALM - tristate 'realm match support' - depends on IP_NF_IPTABLES - select NET_CLS_ROUTE - help - This option adds a `realm' match, which allows you to use the realm - key from the routing subsystem inside iptables. - - This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option - in tc world. - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. - -config IP_NF_MATCH_SCTP - tristate 'SCTP protocol match support' - depends on IP_NF_IPTABLES - help - With this option enabled, you will be able to use the iptables - `sctp' match in order to match on SCTP source/destination ports - and SCTP chunk types. - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. - -config IP_NF_MATCH_DCCP - tristate 'DCCP protocol match support' - depends on IP_NF_IPTABLES - help - With this option enabled, you will be able to use the iptables - `dccp' match in order to match on DCCP source/destination ports - and DCCP flags. - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. - -config IP_NF_MATCH_COMMENT - tristate 'comment match support' - depends on IP_NF_IPTABLES - help - This option adds a `comment' dummy-match, which allows you to put - comments in your iptables ruleset. - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. - -config IP_NF_MATCH_CONNMARK - tristate 'Connection mark match support' - depends on IP_NF_IPTABLES - depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) - help - This option adds a `connmark' match, which allows you to match the - connection mark value previously set for the session by `CONNMARK'. - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. The module will be called - ipt_connmark.o. If unsure, say `N'. - -config IP_NF_MATCH_CONNBYTES - tristate 'Connection byte/packet counter match support' - depends on IP_NF_IPTABLES - depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4) - help - This option adds a `connbytes' match, which allows you to match the - number of bytes and/or packets for each direction within a connection. - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. - config IP_NF_MATCH_HASHLIMIT tristate 'hashlimit match support' depends on IP_NF_IPTABLES @@ -474,19 +303,6 @@ config IP_NF_MATCH_HASHLIMIT destination IP' or `500pps from any given source IP' with a single IPtables rule. -config IP_NF_MATCH_STRING - tristate 'string match support' - depends on IP_NF_IPTABLES - select TEXTSEARCH - select TEXTSEARCH_KMP - select TEXTSEARCH_BM - select TEXTSEARCH_FSM - help - This option adds a `string' match, which allows you to look for - pattern matchings in packets. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_POLICY tristate "IPsec policy match support" depends on IP_NF_IPTABLES && XFRM @@ -572,17 +388,6 @@ config IP_NF_TARGET_TCPMSS To compile it as a module, choose M here. If unsure, say N. -config IP_NF_TARGET_NFQUEUE - tristate "NFQUEUE Target Support" - depends on IP_NF_IPTABLES - help - This Target replaced the old obsolete QUEUE target. - - As opposed to QUEUE, it supports 65535 different queues, - not just one. - - To compile it as a module, choose M here. If unsure, say N. - # NAT + specific targets config IP_NF_NAT tristate "Full NAT" @@ -735,31 +540,6 @@ config IP_NF_TARGET_DSCP To compile it as a module, choose M here. If unsure, say N. -config IP_NF_TARGET_MARK - tristate "MARK target support" - depends on IP_NF_MANGLE - help - This option adds a `MARK' target, which allows you to create rules - in the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet prior to routing. This can change - the routing method (see `Use netfilter MARK value as routing - key') and can also be used by other subsystems to change their - behavior. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_TARGET_CLASSIFY - tristate "CLASSIFY target support" - depends on IP_NF_MANGLE - help - This option adds a `CLASSIFY' target, which enables the user to set - the priority of a packet. Some qdiscs can use this value for - classification, among these are: - - atm, cbq, dsmark, pfifo_fast, htb, prio - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_TARGET_TTL tristate 'TTL target support' depends on IP_NF_MANGLE @@ -774,19 +554,6 @@ config IP_NF_TARGET_TTL To compile it as a module, choose M here. If unsure, say N. -config IP_NF_TARGET_CONNMARK - tristate 'CONNMARK target support' - depends on IP_NF_MANGLE - depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) - help - This option adds a `CONNMARK' target, which allows one to manipulate - the connection mark value. Similar to the MARK target, but - affects the connection mark value rather than the packet mark value. - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. The module will be called - ipt_CONNMARK.o. If unsure, say `N'. - config IP_NF_TARGET_CLUSTERIP tristate "CLUSTERIP target support (EXPERIMENTAL)" depends on IP_NF_MANGLE && EXPERIMENTAL @@ -810,23 +577,10 @@ config IP_NF_RAW If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. If unsure, say `N'. -config IP_NF_TARGET_NOTRACK - tristate 'NOTRACK target support' - depends on IP_NF_RAW - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - The NOTRACK target allows a select rule to specify - which packets *not* to enter the conntrack/NAT - subsystem with all the consequences (no ICMP error tracking, - no protocol helpers for the selected packets). - - If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. - - # ARP tables config IP_NF_ARPTABLES tristate "ARP tables support" + depends on NETFILTER_XTABLES help arptables is a general, extensible packet identification framework. The ARP packet filtering and mangling (manipulation)subsystems diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 549b01a..bcefe64 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -47,14 +47,8 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o -obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o -obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o -obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o -obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o -obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o -obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o @@ -62,40 +56,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o -obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o -obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o -obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o -obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o -obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o -obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o -obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o -obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o -obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o -obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o # targets obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o -obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o -obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o -obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o -obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o -obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o # generic ARP tables obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index b6d5284..afe3d8f 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -24,6 +24,7 @@ #include <asm/uaccess.h> #include <asm/semaphore.h> +#include <linux/netfilter/x_tables.h> #include <linux/netfilter_arp/arp_tables.h> MODULE_LICENSE("GPL"); @@ -55,28 +56,9 @@ do { \ #else #define ARP_NF_ASSERT(x) #endif -#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) -static DECLARE_MUTEX(arpt_mutex); - -#define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) -#define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) #include <linux/netfilter_ipv4/listhelp.h> -struct arpt_table_info { - unsigned int size; - unsigned int number; - unsigned int initial_entries; - unsigned int hook_entry[NF_ARP_NUMHOOKS]; - unsigned int underflow[NF_ARP_NUMHOOKS]; - void *entries[NR_CPUS]; -}; - -static LIST_HEAD(arpt_target); -static LIST_HEAD(arpt_tables); -#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) -#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) - static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, char *hdr_addr, int len) { @@ -223,9 +205,9 @@ static inline int arp_checkentry(const struct arpt_arp *arp) } static unsigned int arpt_error(struct sk_buff **pskb, - unsigned int hooknum, const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const void *targinfo, void *userinfo) { @@ -254,6 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, struct arpt_entry *e, *back; const char *indev, *outdev; void *table_base; + struct xt_table_info *private = table->private; /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + @@ -265,9 +248,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb, outdev = out ? out->name : nulldevname; read_lock_bh(&table->lock); - table_base = (void *)table->private->entries[smp_processor_id()]; - e = get_entry(table_base, table->private->hook_entry[hook]); - back = get_entry(table_base, table->private->underflow[hook]); + table_base = (void *)private->entries[smp_processor_id()]; + e = get_entry(table_base, private->hook_entry[hook]); + back = get_entry(table_base, private->underflow[hook]); arp = (*pskb)->nh.arph; do { @@ -315,8 +298,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb, * abs. verdicts */ verdict = t->u.kernel.target->target(pskb, - hook, in, out, + hook, t->data, userdata); @@ -341,106 +324,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb, return verdict; } -/* - * 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 table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ -static inline struct arpt_table *find_table_lock(const char *name) -{ - struct arpt_table *t; - - if (down_interruptible(&arpt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &arpt_tables, list) - if (strcmp(t->name, name) == 0 && try_module_get(t->me)) - return t; - up(&arpt_mutex); - return NULL; -} - - -/* Find target, grabs ref. Returns ERR_PTR() on error. */ -static inline struct arpt_target *find_target(const char *name, u8 revision) -{ - struct arpt_target *t; - int err = 0; - - if (down_interruptible(&arpt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &arpt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision == revision) { - if (try_module_get(t->me)) { - up(&arpt_mutex); - return t; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&arpt_mutex); - return ERR_PTR(err); -} - -struct arpt_target *arpt_find_target(const char *name, u8 revision) -{ - struct arpt_target *target; - - target = try_then_request_module(find_target(name, revision), - "arpt_%s", name); - if (IS_ERR(target) || !target) - return NULL; - return target; -} - -static int target_revfn(const char *name, u8 revision, int *bestp) -{ - struct arpt_target *t; - int have_rev = 0; - - list_for_each_entry(t, &arpt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision > *bestp) - *bestp = t->revision; - if (t->revision == revision) - have_rev =1; - } - } - return have_rev; -} - -/* Returns true or false (if no such extension at all) */ -static inline int find_revision(const char *name, u8 revision, - int (*revfn)(const char *, u8, int *), - int *err) -{ - int have_rev, best = -1; - - if (down_interruptible(&arpt_mutex) != 0) { - *err = -EINTR; - return 1; - } - have_rev = revfn(name, revision, &best); - up(&arpt_mutex); - - /* 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; -} - - /* All zeroes == unconditional rule. */ static inline int unconditional(const struct arpt_arp *arp) { @@ -456,7 +339,7 @@ static inline int unconditional(const struct arpt_arp *arp) /* Figures out from what hook each rule can be called: returns 0 if * there are loops. Puts hook bitmask in comefrom. */ -static int mark_source_chains(struct arpt_table_info *newinfo, +static int mark_source_chains(struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -587,8 +470,8 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i } t = arpt_get_target(e); - target = try_then_request_module(find_target(t->u.user.name, - t->u.user.revision), + target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, + t->u.user.revision), "arpt_%s", t->u.user.name); if (IS_ERR(target) || !target) { duprintf("check_entry: `%s' not found\n", t->u.user.name); @@ -622,7 +505,7 @@ out: } static inline int check_entry_size_and_hooks(struct arpt_entry *e, - struct arpt_table_info *newinfo, + struct xt_table_info *newinfo, unsigned char *base, unsigned char *limit, const unsigned int *hook_entries, @@ -656,7 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, < 0 (not ARPT_RETURN). --RR */ /* Clear counters and comefrom */ - e->counters = ((struct arpt_counters) { 0, 0 }); + e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; (*i)++; @@ -683,7 +566,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) */ static int translate_table(const char *name, unsigned int valid_hooks, - struct arpt_table_info *newinfo, + struct xt_table_info *newinfo, void *entry0, unsigned int size, unsigned int number, @@ -764,34 +647,9 @@ static int translate_table(const char *name, return ret; } -static struct arpt_table_info *replace_table(struct arpt_table *table, - unsigned int num_counters, - struct arpt_table_info *newinfo, - int *error) -{ - struct arpt_table_info *oldinfo; - - /* Do the substitution. */ - write_lock_bh(&table->lock); - /* Check inside lock: is the old number correct? */ - if (num_counters != table->private->number) { - duprintf("num_counters != table->private->number (%u/%u)\n", - num_counters, table->private->number); - write_unlock_bh(&table->lock); - *error = -EAGAIN; - return NULL; - } - oldinfo = table->private; - table->private = newinfo; - newinfo->initial_entries = oldinfo->initial_entries; - write_unlock_bh(&table->lock); - - return oldinfo; -} - /* Gets counters. */ static inline int add_entry_to_counter(const struct arpt_entry *e, - struct arpt_counters total[], + struct xt_counters total[], unsigned int *i) { ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -801,7 +659,7 @@ static inline int add_entry_to_counter(const struct arpt_entry *e, } static inline int set_entry_to_counter(const struct arpt_entry *e, - struct arpt_counters total[], + struct xt_counters total[], unsigned int *i) { SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -810,8 +668,8 @@ static inline int set_entry_to_counter(const struct arpt_entry *e, return 0; } -static void get_counters(const struct arpt_table_info *t, - struct arpt_counters counters[]) +static void get_counters(const struct xt_table_info *t, + struct xt_counters counters[]) { unsigned int cpu; unsigned int i; @@ -849,7 +707,8 @@ static int copy_entries_to_user(unsigned int total_size, { unsigned int off, num, countersize; struct arpt_entry *e; - struct arpt_counters *counters; + struct xt_counters *counters; + struct xt_table_info *private = table->private; int ret = 0; void *loc_cpu_entry; @@ -857,18 +716,18 @@ static int copy_entries_to_user(unsigned int total_size, * (other than comefrom, which userspace doesn't care * about). */ - countersize = sizeof(struct arpt_counters) * table->private->number; - counters = vmalloc(countersize); + countersize = sizeof(struct xt_counters) * private->number; + counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) return -ENOMEM; /* First, sum counters... */ write_lock_bh(&table->lock); - get_counters(table->private, counters); + get_counters(private, counters); write_unlock_bh(&table->lock); - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; /* ... then copy entire thing ... */ if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { ret = -EFAULT; @@ -911,75 +770,34 @@ static int get_entries(const struct arpt_get_entries *entries, int ret; struct arpt_table *t; - t = find_table_lock(entries->name); + t = xt_find_table_lock(NF_ARP, entries->name); if (t || !IS_ERR(t)) { + struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", - t->private->number); - if (entries->size == t->private->size) - ret = copy_entries_to_user(t->private->size, + private->number); + if (entries->size == private->size) + ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", - t->private->size, - entries->size); + private->size, entries->size); ret = -EINVAL; } module_put(t->me); - up(&arpt_mutex); + xt_table_unlock(t); } else ret = t ? PTR_ERR(t) : -ENOENT; return ret; } -static void free_table_info(struct arpt_table_info *info) -{ - int cpu; - for_each_cpu(cpu) { - if (info->size <= PAGE_SIZE) - kfree(info->entries[cpu]); - else - vfree(info->entries[cpu]); - } - kfree(info); -} - -static struct arpt_table_info *alloc_table_info(unsigned int size) -{ - struct arpt_table_info *newinfo; - int cpu; - - newinfo = kzalloc(sizeof(struct arpt_table_info), GFP_KERNEL); - if (!newinfo) - return NULL; - - newinfo->size = size; - - for_each_cpu(cpu) { - 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) { - free_table_info(newinfo); - return NULL; - } - } - - return newinfo; -} - static int do_replace(void __user *user, unsigned int len) { int ret; struct arpt_replace tmp; struct arpt_table *t; - struct arpt_table_info *newinfo, *oldinfo; - struct arpt_counters *counters; + struct xt_table_info *newinfo, *oldinfo; + struct xt_counters *counters; void *loc_cpu_entry, *loc_cpu_old_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) @@ -989,11 +807,7 @@ static int do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; - /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ - if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) - return -ENOMEM; - - newinfo = alloc_table_info(tmp.size); + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; @@ -1005,7 +819,7 @@ static int do_replace(void __user *user, unsigned int len) goto free_newinfo; } - counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters)); + counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); if (!counters) { ret = -ENOMEM; goto free_newinfo; @@ -1019,7 +833,7 @@ static int do_replace(void __user *user, unsigned int len) duprintf("arp_tables: Translated table\n"); - t = try_then_request_module(find_table_lock(tmp.name), + t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name), "arptable_%s", tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1034,7 +848,7 @@ static int do_replace(void __user *user, unsigned int len) goto put_module; } - oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); + oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) goto put_module; @@ -1054,23 +868,23 @@ static int do_replace(void __user *user, unsigned int len) loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); - free_table_info(oldinfo); + xt_free_table_info(oldinfo); if (copy_to_user(tmp.counters, counters, - sizeof(struct arpt_counters) * tmp.num_counters) != 0) + sizeof(struct xt_counters) * tmp.num_counters) != 0) ret = -EFAULT; vfree(counters); - up(&arpt_mutex); + xt_table_unlock(t); return ret; put_module: module_put(t->me); - up(&arpt_mutex); + xt_table_unlock(t); free_newinfo_counters_untrans: ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); free_newinfo_counters: vfree(counters); free_newinfo: - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } @@ -1078,7 +892,7 @@ static int do_replace(void __user *user, unsigned int len) * and everything is OK. */ static inline int add_counter_to_entry(struct arpt_entry *e, - const struct arpt_counters addme[], + const struct xt_counters addme[], unsigned int *i) { @@ -1091,15 +905,16 @@ static inline int add_counter_to_entry(struct arpt_entry *e, static int do_add_counters(void __user *user, unsigned int len) { unsigned int i; - struct arpt_counters_info tmp, *paddc; + struct xt_counters_info tmp, *paddc; struct arpt_table *t; + struct xt_table_info *private; int ret = 0; void *loc_cpu_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters)) + if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) return -EINVAL; paddc = vmalloc(len); @@ -1111,29 +926,30 @@ static int do_add_counters(void __user *user, unsigned int len) goto free; } - t = find_table_lock(tmp.name); + t = xt_find_table_lock(NF_ARP, tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; } write_lock_bh(&t->lock); - if (t->private->number != paddc->num_counters) { + private = t->private; + if (private->number != paddc->num_counters) { ret = -EINVAL; goto unlock_up_free; } i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = t->private->entries[smp_processor_id()]; + loc_cpu_entry = private->entries[smp_processor_id()]; ARPT_ENTRY_ITERATE(loc_cpu_entry, - t->private->size, + private->size, add_counter_to_entry, paddc->counters, &i); unlock_up_free: write_unlock_bh(&t->lock); - up(&arpt_mutex); + xt_table_unlock(t); module_put(t->me); free: vfree(paddc); @@ -1190,25 +1006,26 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len } name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; - t = try_then_request_module(find_table_lock(name), + t = try_then_request_module(xt_find_table_lock(NF_ARP, name), "arptable_%s", name); if (t && !IS_ERR(t)) { struct arpt_getinfo info; + struct xt_table_info *private = t->private; info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, t->private->hook_entry, + memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); - memcpy(info.underflow, t->private->underflow, + memcpy(info.underflow, private->underflow, sizeof(info.underflow)); - info.num_entries = t->private->number; - info.size = t->private->size; + info.num_entries = private->number; + info.size = private->size; strcpy(info.name, name); if (copy_to_user(user, &info, *len) != 0) ret = -EFAULT; else ret = 0; - up(&arpt_mutex); + xt_table_unlock(t); module_put(t->me); } else ret = t ? PTR_ERR(t) : -ENOENT; @@ -1233,7 +1050,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len } case ARPT_SO_GET_REVISION_TARGET: { - struct arpt_get_revision rev; + struct xt_get_revision rev; if (*len != sizeof(rev)) { ret = -EINVAL; @@ -1244,8 +1061,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len break; } - try_then_request_module(find_revision(rev.name, rev.revision, - target_revfn, &ret), + try_then_request_module(xt_find_revision(NF_ARP, rev.name, + rev.revision, 1, &ret), "arpt_%s", rev.name); break; } @@ -1258,38 +1075,16 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len return ret; } -/* Registration hooks for targets. */ -int arpt_register_target(struct arpt_target *target) -{ - int ret; - - ret = down_interruptible(&arpt_mutex); - if (ret != 0) - return ret; - - list_add(&target->list, &arpt_target); - up(&arpt_mutex); - - return ret; -} - -void arpt_unregister_target(struct arpt_target *target) -{ - down(&arpt_mutex); - LIST_DELETE(&arpt_target, target); - up(&arpt_mutex); -} - int arpt_register_table(struct arpt_table *table, const struct arpt_replace *repl) { int ret; - struct arpt_table_info *newinfo; - static struct arpt_table_info bootstrap + struct xt_table_info *newinfo; + static struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; - newinfo = alloc_table_info(repl->size); + newinfo = xt_alloc_table_info(repl->size); if (!newinfo) { ret = -ENOMEM; return ret; @@ -1304,60 +1099,33 @@ int arpt_register_table(struct arpt_table *table, repl->num_entries, repl->hook_entry, repl->underflow); + duprintf("arpt_register_table: translate table gives %d\n", ret); if (ret != 0) { - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } - ret = down_interruptible(&arpt_mutex); - if (ret != 0) { - free_table_info(newinfo); + if (xt_register_table(table, &bootstrap, newinfo) != 0) { + xt_free_table_info(newinfo); return ret; } - /* Don't autoload: we'd eat our tail... */ - if (list_named_find(&arpt_tables, table->name)) { - ret = -EEXIST; - goto free_unlock; - } - - /* Simplifies replace_table code. */ - table->private = &bootstrap; - if (!replace_table(table, 0, newinfo, &ret)) - goto free_unlock; - - duprintf("table->private->number = %u\n", - table->private->number); - - /* save number of initial entries */ - table->private->initial_entries = table->private->number; - - rwlock_init(&table->lock); - list_prepend(&arpt_tables, table); - - unlock: - up(&arpt_mutex); - return ret; - - free_unlock: - free_table_info(newinfo); - goto unlock; + return 0; } void arpt_unregister_table(struct arpt_table *table) { + struct xt_table_info *private; void *loc_cpu_entry; - down(&arpt_mutex); - LIST_DELETE(&arpt_tables, table); - up(&arpt_mutex); + private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; - ARPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); - free_table_info(table->private); + xt_free_table_info(private); } /* The built-in targets: standard (NULL) and error. */ @@ -1380,52 +1148,15 @@ static struct nf_sockopt_ops arpt_sockopts = { .get = do_arpt_get_ctl, }; -#ifdef CONFIG_PROC_FS -static inline int print_name(const struct arpt_table *t, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if ((*count)++ >= start_offset) { - unsigned int namelen; - - namelen = sprintf(buffer + *pos, "%s\n", t->name); - if (*pos + namelen > length) { - /* Stop iterating */ - return 1; - } - *pos += namelen; - } - return 0; -} - -static int arpt_get_tables(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&arpt_mutex) != 0) - return 0; - - LIST_FIND(&arpt_tables, print_name, struct arpt_table *, - offset, buffer, length, &pos, &count); - - up(&arpt_mutex); - - /* `start' hack - see fs/proc/generic.c line ~105 */ - *start=(char *)((unsigned long)count-offset); - return pos; -} -#endif /*CONFIG_PROC_FS*/ - static int __init init(void) { int ret; + xt_proto_init(NF_ARP); + /* Noone else will be downing sem now, so we won't sleep */ - down(&arpt_mutex); - list_append(&arpt_target, &arpt_standard_target); - list_append(&arpt_target, &arpt_error_target); - up(&arpt_mutex); + xt_register_target(NF_ARP, &arpt_standard_target); + xt_register_target(NF_ARP, &arpt_error_target); /* Register setsockopt */ ret = nf_register_sockopt(&arpt_sockopts); @@ -1434,19 +1165,6 @@ static int __init init(void) return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - - proc = proc_net_create("arp_tables_names", 0, arpt_get_tables); - if (!proc) { - nf_unregister_sockopt(&arpt_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } -#endif - printk("arp_tables: (C) 2002 David S. Miller\n"); return 0; } @@ -1454,16 +1172,12 @@ static int __init init(void) static void __exit fini(void) { nf_unregister_sockopt(&arpt_sockopts); -#ifdef CONFIG_PROC_FS - proc_net_remove("arp_tables_names"); -#endif + xt_proto_fini(NF_ARP); } EXPORT_SYMBOL(arpt_register_table); EXPORT_SYMBOL(arpt_unregister_table); EXPORT_SYMBOL(arpt_do_table); -EXPORT_SYMBOL(arpt_register_target); -EXPORT_SYMBOL(arpt_unregister_target); module_init(init); module_exit(fini); diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index 3e592ec..c97650a 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c @@ -8,8 +8,9 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); MODULE_DESCRIPTION("arptables arp payload mangle target"); static unsigned int -target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, - const struct net_device *out, const void *targinfo, void *userinfo) +target(struct sk_buff **pskb, const struct net_device *in, + const struct net_device *out, unsigned int hooknum, const void *targinfo, + void *userinfo) { const struct arpt_mangle *mangle = targinfo; struct arphdr *arp; @@ -64,7 +65,7 @@ target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, } static int -checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo, +checkentry(const char *tablename, const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct arpt_mangle *mangle = targinfo; diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 0d759f5..f6ab45f 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -145,6 +145,7 @@ static struct arpt_table packet_filter = { .lock = RW_LOCK_UNLOCKED, .private = NULL, .me = THIS_MODULE, + .af = NF_ARP, }; /* The work comes in here from netfilter.c */ diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 9dec129..833fcb4 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -944,7 +944,7 @@ module_exit(fini); /* Some modules need us, but don't depend directly on any symbol. They should call this. */ -void need_ip_conntrack(void) +void need_conntrack(void) { } @@ -962,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple); EXPORT_SYMBOL(invert_tuplepr); EXPORT_SYMBOL(ip_conntrack_alter_reply); EXPORT_SYMBOL(ip_conntrack_destroyed); -EXPORT_SYMBOL(need_ip_conntrack); +EXPORT_SYMBOL(need_conntrack); EXPORT_SYMBOL(ip_conntrack_helper_register); EXPORT_SYMBOL(ip_conntrack_helper_unregister); EXPORT_SYMBOL(ip_ct_iterate_cleanup); diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index cb66b8b..1de8628 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c @@ -95,6 +95,7 @@ static struct ipt_table nat_table = { .valid_hooks = NAT_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET, }; /* Source NAT */ @@ -168,7 +169,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, } static int ipt_snat_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) @@ -201,7 +202,7 @@ static int ipt_snat_checkentry(const char *tablename, } static int ipt_dnat_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 8b8a1f0..ad438fb 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -364,7 +364,7 @@ static int init_or_cleanup(int init) { int ret = 0; - need_ip_conntrack(); + need_conntrack(); if (!init) goto cleanup; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 877bc96..2371b20 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -2,7 +2,7 @@ * Packet matching code. * * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling - * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> + * 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 @@ -11,6 +11,8 @@ * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> * - increase module usage count as soon as we have rules inside * a table + * 08 Oct 2005 Harald Welte <lafore@netfilter.org> + * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables" */ #include <linux/config.h> #include <linux/cache.h> @@ -20,8 +22,6 @@ #include <linux/vmalloc.h> #include <linux/netdevice.h> #include <linux/module.h> -#include <linux/tcp.h> -#include <linux/udp.h> #include <linux/icmp.h> #include <net/ip.h> #include <asm/uaccess.h> @@ -30,6 +30,7 @@ #include <linux/err.h> #include <linux/cpumask.h> +#include <linux/netfilter/x_tables.h> #include <linux/netfilter_ipv4/ip_tables.h> MODULE_LICENSE("GPL"); @@ -62,14 +63,6 @@ do { \ #else #define IP_NF_ASSERT(x) #endif -#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) - -static DECLARE_MUTEX(ipt_mutex); - -/* Must have mutex */ -#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) -#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) -#include <linux/netfilter_ipv4/listhelp.h> #if 0 /* All the better to debug you with... */ @@ -86,36 +79,6 @@ static DECLARE_MUTEX(ipt_mutex); Hence the start of any table is given by get_table() below. */ -/* The table itself */ -struct ipt_table_info -{ - /* Size per table */ - unsigned int size; - /* Number of entries: FIXME. --RR */ - unsigned int number; - /* Initial number of entries. Needed for module usage count */ - unsigned int initial_entries; - - /* Entry points and underflows */ - unsigned int hook_entry[NF_IP_NUMHOOKS]; - unsigned int underflow[NF_IP_NUMHOOKS]; - - /* ipt_entry tables: one per CPU */ - void *entries[NR_CPUS]; -}; - -static LIST_HEAD(ipt_target); -static LIST_HEAD(ipt_match); -static LIST_HEAD(ipt_tables); -#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) -#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) - -#if 0 -#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) -#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) -#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) -#endif - /* Returns whether matches rule or not. */ static inline int ip_packet_match(const struct iphdr *ip, @@ -234,7 +197,8 @@ int do_match(struct ipt_entry_match *m, int *hotdrop) { /* Stop iteration if it doesn't match */ - if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop)) + if (!m->u.kernel.match->match(skb, in, out, m->data, offset, + skb->nh.iph->ihl*4, hotdrop)) return 1; else return 0; @@ -265,6 +229,7 @@ ipt_do_table(struct sk_buff **pskb, const char *indev, *outdev; void *table_base; struct ipt_entry *e, *back; + struct xt_table_info *private = table->private; /* Initialization */ ip = (*pskb)->nh.iph; @@ -281,24 +246,11 @@ ipt_do_table(struct sk_buff **pskb, read_lock_bh(&table->lock); IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - table_base = (void *)table->private->entries[smp_processor_id()]; - e = get_entry(table_base, table->private->hook_entry[hook]); - -#ifdef CONFIG_NETFILTER_DEBUG - /* Check noone else using our table */ - if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac - && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) { - printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", - smp_processor_id(), - table->name, - &((struct ipt_entry *)table_base)->comefrom, - ((struct ipt_entry *)table_base)->comefrom); - } - ((struct ipt_entry *)table_base)->comefrom = 0x57acc001; -#endif + table_base = (void *)private->entries[smp_processor_id()]; + e = get_entry(table_base, private->hook_entry[hook]); /* For return from builtin chain */ - back = get_entry(table_base, table->private->underflow[hook]); + back = get_entry(table_base, private->underflow[hook]); do { IP_NF_ASSERT(e); @@ -384,9 +336,6 @@ ipt_do_table(struct sk_buff **pskb, } } while (!hotdrop); -#ifdef CONFIG_NETFILTER_DEBUG - ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac; -#endif read_unlock_bh(&table->lock); #ifdef DEBUG_ALLOW_ALL @@ -398,145 +347,6 @@ ipt_do_table(struct sk_buff **pskb, #endif } -/* - * 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 table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ -static inline struct ipt_table *find_table_lock(const char *name) -{ - struct ipt_table *t; - - if (down_interruptible(&ipt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ipt_tables, list) - if (strcmp(t->name, name) == 0 && try_module_get(t->me)) - return t; - up(&ipt_mutex); - return NULL; -} - -/* Find match, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ipt_match *find_match(const char *name, u8 revision) -{ - struct ipt_match *m; - int err = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(m, &ipt_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision == revision) { - if (try_module_get(m->me)) { - up(&ipt_mutex); - return m; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ipt_mutex); - return ERR_PTR(err); -} - -/* Find target, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ipt_target *find_target(const char *name, u8 revision) -{ - struct ipt_target *t; - int err = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ipt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision == revision) { - if (try_module_get(t->me)) { - up(&ipt_mutex); - return t; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ipt_mutex); - return ERR_PTR(err); -} - -struct ipt_target *ipt_find_target(const char *name, u8 revision) -{ - struct ipt_target *target; - - target = try_then_request_module(find_target(name, revision), - "ipt_%s", name); - if (IS_ERR(target) || !target) - return NULL; - return target; -} - -static int match_revfn(const char *name, u8 revision, int *bestp) -{ - struct ipt_match *m; - int have_rev = 0; - - list_for_each_entry(m, &ipt_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision > *bestp) - *bestp = m->revision; - if (m->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -static int target_revfn(const char *name, u8 revision, int *bestp) -{ - struct ipt_target *t; - int have_rev = 0; - - list_for_each_entry(t, &ipt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision > *bestp) - *bestp = t->revision; - if (t->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -/* Returns true or false (if no such extension at all) */ -static inline int find_revision(const char *name, u8 revision, - int (*revfn)(const char *, u8, int *), - int *err) -{ - int have_rev, best = -1; - - if (down_interruptible(&ipt_mutex) != 0) { - *err = -EINTR; - return 1; - } - have_rev = revfn(name, revision, &best); - up(&ipt_mutex); - - /* 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; -} - - /* All zeroes == unconditional rule. */ static inline int unconditional(const struct ipt_ip *ip) @@ -553,7 +363,7 @@ unconditional(const struct ipt_ip *ip) /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int -mark_source_chains(struct ipt_table_info *newinfo, +mark_source_chains(struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -699,7 +509,7 @@ check_match(struct ipt_entry_match *m, { struct ipt_match *match; - match = try_then_request_module(find_match(m->u.user.name, + match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, m->u.user.revision), "ipt_%s", m->u.user.name); if (IS_ERR(match) || !match) { @@ -744,7 +554,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, goto cleanup_matches; t = ipt_get_target(e); - target = try_then_request_module(find_target(t->u.user.name, + target = try_then_request_module(xt_find_target(AF_INET, + t->u.user.name, t->u.user.revision), "ipt_%s", t->u.user.name); if (IS_ERR(target) || !target) { @@ -781,7 +592,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, static inline int check_entry_size_and_hooks(struct ipt_entry *e, - struct ipt_table_info *newinfo, + struct xt_table_info *newinfo, unsigned char *base, unsigned char *limit, const unsigned int *hook_entries, @@ -815,7 +626,7 @@ check_entry_size_and_hooks(struct ipt_entry *e, < 0 (not IPT_RETURN). --RR */ /* Clear counters and comefrom */ - e->counters = ((struct ipt_counters) { 0, 0 }); + e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; (*i)++; @@ -845,7 +656,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) static int translate_table(const char *name, unsigned int valid_hooks, - struct ipt_table_info *newinfo, + struct xt_table_info *newinfo, void *entry0, unsigned int size, unsigned int number, @@ -922,48 +733,10 @@ translate_table(const char *name, return ret; } -static struct ipt_table_info * -replace_table(struct ipt_table *table, - unsigned int num_counters, - struct ipt_table_info *newinfo, - int *error) -{ - struct ipt_table_info *oldinfo; - -#ifdef CONFIG_NETFILTER_DEBUG - { - int cpu; - - for_each_cpu(cpu) { - struct ipt_entry *table_base = newinfo->entries[cpu]; - if (table_base) - table_base->comefrom = 0xdead57ac; - } - } -#endif - - /* Do the substitution. */ - write_lock_bh(&table->lock); - /* Check inside lock: is the old number correct? */ - if (num_counters != table->private->number) { - duprintf("num_counters != table->private->number (%u/%u)\n", - num_counters, table->private->number); - write_unlock_bh(&table->lock); - *error = -EAGAIN; - return NULL; - } - oldinfo = table->private; - table->private = newinfo; - newinfo->initial_entries = oldinfo->initial_entries; - write_unlock_bh(&table->lock); - - return oldinfo; -} - /* Gets counters. */ static inline int add_entry_to_counter(const struct ipt_entry *e, - struct ipt_counters total[], + struct xt_counters total[], unsigned int *i) { ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -984,8 +757,8 @@ set_entry_to_counter(const struct ipt_entry *e, } static void -get_counters(const struct ipt_table_info *t, - struct ipt_counters counters[]) +get_counters(const struct xt_table_info *t, + struct xt_counters counters[]) { unsigned int cpu; unsigned int i; @@ -1024,14 +797,15 @@ copy_entries_to_user(unsigned int total_size, { unsigned int off, num, countersize; struct ipt_entry *e; - struct ipt_counters *counters; + struct xt_counters *counters; + struct xt_table_info *private = table->private; int ret = 0; void *loc_cpu_entry; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care about). */ - countersize = sizeof(struct ipt_counters) * table->private->number; + countersize = sizeof(struct xt_counters) * private->number; counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) @@ -1039,14 +813,14 @@ copy_entries_to_user(unsigned int total_size, /* First, sum counters... */ write_lock_bh(&table->lock); - get_counters(table->private, counters); + get_counters(private, counters); write_unlock_bh(&table->lock); /* choose the copy that is on our node/cpu, ... * This choice is lazy (because current thread is * allowed to migrate to another cpu) */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; /* ... then copy entire thing ... */ if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { ret = -EFAULT; @@ -1108,74 +882,36 @@ get_entries(const struct ipt_get_entries *entries, int ret; struct ipt_table *t; - t = find_table_lock(entries->name); + t = xt_find_table_lock(AF_INET, entries->name); if (t && !IS_ERR(t)) { + struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", - t->private->number); - if (entries->size == t->private->size) - ret = copy_entries_to_user(t->private->size, + private->number); + if (entries->size == private->size) + ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", - t->private->size, + private->size, entries->size); ret = -EINVAL; } module_put(t->me); - up(&ipt_mutex); + xt_table_unlock(t); } else ret = t ? PTR_ERR(t) : -ENOENT; return ret; } -static void free_table_info(struct ipt_table_info *info) -{ - int cpu; - for_each_cpu(cpu) { - if (info->size <= PAGE_SIZE) - kfree(info->entries[cpu]); - else - vfree(info->entries[cpu]); - } - kfree(info); -} - -static struct ipt_table_info *alloc_table_info(unsigned int size) -{ - struct ipt_table_info *newinfo; - int cpu; - - newinfo = kzalloc(sizeof(struct ipt_table_info), GFP_KERNEL); - if (!newinfo) - return NULL; - - newinfo->size = size; - - for_each_cpu(cpu) { - 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] == 0) { - free_table_info(newinfo); - return NULL; - } - } - - return newinfo; -} - static int do_replace(void __user *user, unsigned int len) { int ret; struct ipt_replace tmp; struct ipt_table *t; - struct ipt_table_info *newinfo, *oldinfo; - struct ipt_counters *counters; + struct xt_table_info *newinfo, *oldinfo; + struct xt_counters *counters; void *loc_cpu_entry, *loc_cpu_old_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) @@ -1185,11 +921,7 @@ do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; - /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ - if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) - return -ENOMEM; - - newinfo = alloc_table_info(tmp.size); + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; @@ -1201,7 +933,7 @@ do_replace(void __user *user, unsigned int len) goto free_newinfo; } - counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters)); + counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); if (!counters) { ret = -ENOMEM; goto free_newinfo; @@ -1215,7 +947,7 @@ do_replace(void __user *user, unsigned int len) duprintf("ip_tables: Translated table\n"); - t = try_then_request_module(find_table_lock(tmp.name), + t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name), "iptable_%s", tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1230,7 +962,7 @@ do_replace(void __user *user, unsigned int len) goto put_module; } - oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); + oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) goto put_module; @@ -1249,23 +981,23 @@ do_replace(void __user *user, unsigned int len) /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); - free_table_info(oldinfo); + xt_free_table_info(oldinfo); if (copy_to_user(tmp.counters, counters, - sizeof(struct ipt_counters) * tmp.num_counters) != 0) + sizeof(struct xt_counters) * tmp.num_counters) != 0) ret = -EFAULT; vfree(counters); - up(&ipt_mutex); + xt_table_unlock(t); return ret; put_module: module_put(t->me); - up(&ipt_mutex); + xt_table_unlock(t); free_newinfo_counters_untrans: IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); free_newinfo_counters: vfree(counters); free_newinfo: - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } @@ -1273,7 +1005,7 @@ do_replace(void __user *user, unsigned int len) * and everything is OK. */ static inline int add_counter_to_entry(struct ipt_entry *e, - const struct ipt_counters addme[], + const struct xt_counters addme[], unsigned int *i) { #if 0 @@ -1295,15 +1027,16 @@ static int do_add_counters(void __user *user, unsigned int len) { unsigned int i; - struct ipt_counters_info tmp, *paddc; + struct xt_counters_info tmp, *paddc; struct ipt_table *t; + struct xt_table_info *private; int ret = 0; void *loc_cpu_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters)) + if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) return -EINVAL; paddc = vmalloc_node(len, numa_node_id()); @@ -1315,29 +1048,30 @@ do_add_counters(void __user *user, unsigned int len) goto free; } - t = find_table_lock(tmp.name); + t = xt_find_table_lock(AF_INET, tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; } write_lock_bh(&t->lock); - if (t->private->number != paddc->num_counters) { + private = t->private; + if (private->number != paddc->num_counters) { ret = -EINVAL; goto unlock_up_free; } i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = t->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_entry, - t->private->size, + private->size, add_counter_to_entry, paddc->counters, &i); unlock_up_free: write_unlock_bh(&t->lock); - up(&ipt_mutex); + xt_table_unlock(t); module_put(t->me); free: vfree(paddc); @@ -1396,25 +1130,26 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } name[IPT_TABLE_MAXNAMELEN-1] = '\0'; - t = try_then_request_module(find_table_lock(name), + t = try_then_request_module(xt_find_table_lock(AF_INET, name), "iptable_%s", name); if (t && !IS_ERR(t)) { struct ipt_getinfo info; + struct xt_table_info *private = t->private; info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, t->private->hook_entry, + memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); - memcpy(info.underflow, t->private->underflow, + memcpy(info.underflow, private->underflow, sizeof(info.underflow)); - info.num_entries = t->private->number; - info.size = t->private->size; + info.num_entries = private->number; + info.size = private->size; memcpy(info.name, name, sizeof(info.name)); if (copy_to_user(user, &info, *len) != 0) ret = -EFAULT; else ret = 0; - up(&ipt_mutex); + xt_table_unlock(t); module_put(t->me); } else ret = t ? PTR_ERR(t) : -ENOENT; @@ -1441,7 +1176,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case IPT_SO_GET_REVISION_MATCH: case IPT_SO_GET_REVISION_TARGET: { struct ipt_get_revision rev; - int (*revfn)(const char *, u8, int *); + int target; if (*len != sizeof(rev)) { ret = -EINVAL; @@ -1453,12 +1188,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } if (cmd == IPT_SO_GET_REVISION_TARGET) - revfn = target_revfn; + target = 1; else - revfn = match_revfn; + target = 0; - try_then_request_module(find_revision(rev.name, rev.revision, - revfn, &ret), + try_then_request_module(xt_find_revision(AF_INET, rev.name, + rev.revision, + target, &ret), "ipt_%s", rev.name); break; } @@ -1471,60 +1207,15 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return ret; } -/* Registration hooks for targets. */ -int -ipt_register_target(struct ipt_target *target) +int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) { int ret; - - ret = down_interruptible(&ipt_mutex); - if (ret != 0) - return ret; - list_add(&target->list, &ipt_target); - up(&ipt_mutex); - return ret; -} - -void -ipt_unregister_target(struct ipt_target *target) -{ - down(&ipt_mutex); - LIST_DELETE(&ipt_target, target); - up(&ipt_mutex); -} - -int -ipt_register_match(struct ipt_match *match) -{ - int ret; - - ret = down_interruptible(&ipt_mutex); - if (ret != 0) - return ret; - - list_add(&match->list, &ipt_match); - up(&ipt_mutex); - - return ret; -} - -void -ipt_unregister_match(struct ipt_match *match) -{ - down(&ipt_mutex); - LIST_DELETE(&ipt_match, match); - up(&ipt_mutex); -} - -int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) -{ - int ret; - struct ipt_table_info *newinfo; - static struct ipt_table_info bootstrap + struct xt_table_info *newinfo; + static struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; - newinfo = alloc_table_info(repl->size); + newinfo = xt_alloc_table_info(repl->size); if (!newinfo) return -ENOMEM; @@ -1540,246 +1231,29 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) repl->hook_entry, repl->underflow); if (ret != 0) { - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } - ret = down_interruptible(&ipt_mutex); - if (ret != 0) { - free_table_info(newinfo); + if (xt_register_table(table, &bootstrap, newinfo) != 0) { + xt_free_table_info(newinfo); return ret; } - /* Don't autoload: we'd eat our tail... */ - if (list_named_find(&ipt_tables, table->name)) { - ret = -EEXIST; - goto free_unlock; - } - - /* Simplifies replace_table code. */ - table->private = &bootstrap; - if (!replace_table(table, 0, newinfo, &ret)) - goto free_unlock; - - duprintf("table->private->number = %u\n", - table->private->number); - - /* save number of initial entries */ - table->private->initial_entries = table->private->number; - - rwlock_init(&table->lock); - list_prepend(&ipt_tables, table); - - unlock: - up(&ipt_mutex); - return ret; - - free_unlock: - free_table_info(newinfo); - goto unlock; + return 0; } void ipt_unregister_table(struct ipt_table *table) { + struct xt_table_info *private; void *loc_cpu_entry; - down(&ipt_mutex); - LIST_DELETE(&ipt_tables, table); - up(&ipt_mutex); + private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; - IPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, - cleanup_entry, NULL); - free_table_info(table->private); -} - -/* Returns 1 if the port is matched by the range, 0 otherwise */ -static inline int -port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) -{ - int ret; - - ret = (port >= min && port <= max) ^ invert; - return ret; -} - -static int -tcp_find_option(u_int8_t option, - const struct sk_buff *skb, - unsigned int optlen, - int invert, - int *hotdrop) -{ - /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ - u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; - unsigned int i; - - duprintf("tcp_match: finding option\n"); - - if (!optlen) - return invert; - - /* If we don't have the whole header, drop packet. */ - op = skb_header_pointer(skb, - skb->nh.iph->ihl*4 + sizeof(struct tcphdr), - optlen, _opt); - if (op == NULL) { - *hotdrop = 1; - return 0; - } - - for (i = 0; i < optlen; ) { - if (op[i] == option) return !invert; - if (op[i] < 2) i++; - else i += op[i+1]?:1; - } - - return invert; -} - -static int -tcp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - struct tcphdr _tcph, *th; - const struct ipt_tcp *tcpinfo = matchinfo; - - if (offset) { - /* To quote Alan: - - Don't allow a fragment of TCP 8 bytes in. Nobody normal - causes this. Its a cracker trying to break in by doing a - flag overwrite to pass the direction checks. - */ - if (offset == 1) { - duprintf("Dropping evil TCP offset=1 frag.\n"); - *hotdrop = 1; - } - /* Must not be a fragment. */ - return 0; - } - -#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) - - th = skb_header_pointer(skb, skb->nh.iph->ihl*4, - sizeof(_tcph), &_tcph); - if (th == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil TCP offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], - ntohs(th->source), - !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT))) - return 0; - if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], - ntohs(th->dest), - !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT))) - return 0; - if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) - == tcpinfo->flg_cmp, - IPT_TCP_INV_FLAGS)) - return 0; - if (tcpinfo->option) { - if (th->doff * 4 < sizeof(_tcph)) { - *hotdrop = 1; - return 0; - } - if (!tcp_find_option(tcpinfo->option, skb, - th->doff*4 - sizeof(_tcph), - tcpinfo->invflags & IPT_TCP_INV_OPTION, - hotdrop)) - return 0; - } - return 1; -} - -/* Called when user tries to insert an entry of this type. */ -static int -tcp_checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ipt_tcp *tcpinfo = matchinfo; - - /* Must specify proto == TCP, and no unknown invflags */ - return ip->proto == IPPROTO_TCP - && !(ip->invflags & IPT_INV_PROTO) - && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp)) - && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK); -} - -static int -udp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - struct udphdr _udph, *uh; - const struct ipt_udp *udpinfo = matchinfo; - - /* Must not be a fragment. */ - if (offset) - return 0; - - uh = skb_header_pointer(skb, skb->nh.iph->ihl*4, - sizeof(_udph), &_udph); - if (uh == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil UDP tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return port_match(udpinfo->spts[0], udpinfo->spts[1], - ntohs(uh->source), - !!(udpinfo->invflags & IPT_UDP_INV_SRCPT)) - && port_match(udpinfo->dpts[0], udpinfo->dpts[1], - ntohs(uh->dest), - !!(udpinfo->invflags & IPT_UDP_INV_DSTPT)); -} - -/* Called when user tries to insert an entry of this type. */ -static int -udp_checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) -{ - const struct ipt_udp *udpinfo = matchinfo; - - /* Must specify proto == UDP, and no unknown invflags */ - if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) { - duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, - IPPROTO_UDP); - return 0; - } - if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) { - duprintf("ipt_udp: matchsize %u != %u\n", - matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp))); - return 0; - } - if (udpinfo->invflags & ~IPT_UDP_INV_MASK) { - duprintf("ipt_udp: unknown flags %X\n", - udpinfo->invflags); - return 0; - } - - return 1; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + xt_free_table_info(private); } /* Returns 1 if the type and code is matched by the range, 0 otherwise */ @@ -1798,6 +1272,7 @@ icmp_match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct icmphdr _icmph, *ic; @@ -1807,8 +1282,7 @@ icmp_match(const struct sk_buff *skb, if (offset) return 0; - ic = skb_header_pointer(skb, skb->nh.iph->ihl*4, - sizeof(_icmph), &_icmph); + ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); if (ic == NULL) { /* We've been asked to examine this packet, and we * can't. Hence, no choice but to drop. @@ -1828,11 +1302,12 @@ icmp_match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int icmp_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *info, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { + const struct ipt_ip *ip = info; const struct ipt_icmp *icmpinfo = matchinfo; /* Must specify proto == ICMP, and no unknown invflags */ @@ -1862,123 +1337,22 @@ static struct nf_sockopt_ops ipt_sockopts = { .get = do_ipt_get_ctl, }; -static struct ipt_match tcp_matchstruct = { - .name = "tcp", - .match = &tcp_match, - .checkentry = &tcp_checkentry, -}; - -static struct ipt_match udp_matchstruct = { - .name = "udp", - .match = &udp_match, - .checkentry = &udp_checkentry, -}; - static struct ipt_match icmp_matchstruct = { .name = "icmp", .match = &icmp_match, .checkentry = &icmp_checkentry, }; -#ifdef CONFIG_PROC_FS -static inline int print_name(const char *i, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if ((*count)++ >= start_offset) { - unsigned int namelen; - - namelen = sprintf(buffer + *pos, "%s\n", - i + sizeof(struct list_head)); - if (*pos + namelen > length) { - /* Stop iterating */ - return 1; - } - *pos += namelen; - } - return 0; -} - -static inline int print_target(const struct ipt_target *t, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if (t == &ipt_standard_target || t == &ipt_error_target) - return 0; - return print_name((char *)t, start_offset, buffer, length, pos, count); -} - -static int ipt_get_tables(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return 0; - - LIST_FIND(&ipt_tables, print_name, void *, - offset, buffer, length, &pos, &count); - - up(&ipt_mutex); - - /* `start' hack - see fs/proc/generic.c line ~105 */ - *start=(char *)((unsigned long)count-offset); - return pos; -} - -static int ipt_get_targets(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return 0; - - LIST_FIND(&ipt_target, print_target, struct ipt_target *, - offset, buffer, length, &pos, &count); - - up(&ipt_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static int ipt_get_matches(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return 0; - - LIST_FIND(&ipt_match, print_name, void *, - offset, buffer, length, &pos, &count); - - up(&ipt_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = -{ { "ip_tables_names", ipt_get_tables }, - { "ip_tables_targets", ipt_get_targets }, - { "ip_tables_matches", ipt_get_matches }, - { NULL, NULL} }; -#endif /*CONFIG_PROC_FS*/ - static int __init init(void) { int ret; + xt_proto_init(AF_INET); + /* Noone else will be downing sem now, so we won't sleep */ - down(&ipt_mutex); - list_append(&ipt_target, &ipt_standard_target); - list_append(&ipt_target, &ipt_error_target); - list_append(&ipt_match, &tcp_matchstruct); - list_append(&ipt_match, &udp_matchstruct); - list_append(&ipt_match, &icmp_matchstruct); - up(&ipt_mutex); + xt_register_target(AF_INET, &ipt_standard_target); + xt_register_target(AF_INET, &ipt_error_target); + xt_register_match(AF_INET, &icmp_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ipt_sockopts); @@ -1987,49 +1361,23 @@ static int __init init(void) return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - int i; - - for (i = 0; ipt_proc_entry[i].name; i++) { - proc = proc_net_create(ipt_proc_entry[i].name, 0, - ipt_proc_entry[i].get_info); - if (!proc) { - while (--i >= 0) - proc_net_remove(ipt_proc_entry[i].name); - nf_unregister_sockopt(&ipt_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } - } -#endif - - printk("ip_tables: (C) 2000-2002 Netfilter core team\n"); + printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; } static void __exit fini(void) { nf_unregister_sockopt(&ipt_sockopts); -#ifdef CONFIG_PROC_FS - { - int i; - for (i = 0; ipt_proc_entry[i].name; i++) - proc_net_remove(ipt_proc_entry[i].name); - } -#endif + + xt_unregister_match(AF_INET, &icmp_matchstruct); + xt_unregister_target(AF_INET, &ipt_error_target); + xt_unregister_target(AF_INET, &ipt_standard_target); + + xt_proto_fini(AF_INET); } EXPORT_SYMBOL(ipt_register_table); EXPORT_SYMBOL(ipt_unregister_table); -EXPORT_SYMBOL(ipt_register_match); -EXPORT_SYMBOL(ipt_unregister_match); EXPORT_SYMBOL(ipt_do_table); -EXPORT_SYMBOL(ipt_register_target); -EXPORT_SYMBOL(ipt_unregister_target); -EXPORT_SYMBOL(ipt_find_target); - module_init(init); module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 45c52d8..d9bc971 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -379,12 +379,13 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { struct ipt_clusterip_tgt_info *cipinfo = targinfo; + const struct ipt_entry *e = e_void; struct clusterip_config *config; diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c index 6e31957..898cdf7 100644 --- a/net/ipv4/netfilter/ipt_DSCP.c +++ b/net/ipv4/netfilter/ipt_DSCP.c @@ -57,7 +57,7 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index a131969..7064454 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c @@ -113,12 +113,13 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; + const struct ipt_entry *e = e_void; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 30be0f1..6606ddb 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -431,7 +431,7 @@ ipt_log_target(struct sk_buff **pskb, } static int ipt_log_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 2786051..12c56d3 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -40,7 +40,7 @@ static DEFINE_RWLOCK(masq_lock); /* FIXME: Multiple targets. --RR */ static int masquerade_check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index e6e7b60..b074467 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c @@ -31,7 +31,7 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); static int check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c deleted file mode 100644 index 3cedc9b..0000000 --- a/net/ipv4/netfilter/ipt_NFQUEUE.c +++ /dev/null @@ -1,70 +0,0 @@ -/* iptables module for using new netfilter netlink queue - * - * (C) 2005 by Harald Welte <laforge@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/module.h> -#include <linux/skbuff.h> - -#include <linux/netfilter.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_NFQUEUE.h> - -MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); -MODULE_DESCRIPTION("iptables NFQUEUE target"); -MODULE_LICENSE("GPL"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_NFQ_info *tinfo = targinfo; - - return NF_QUEUE_NR(tinfo->queuenum); -} - -static int -checkentry(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_NFQ_info))) { - printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", - targinfosize, - IPT_ALIGN(sizeof(struct ipt_NFQ_info))); - return 0; - } - - return 1; -} - -static struct ipt_target ipt_NFQ_reg = { - .name = "NFQUEUE", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_target(&ipt_NFQ_reg); -} - -static void __exit fini(void) -{ - ipt_unregister_target(&ipt_NFQ_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 5245bfd..140be51 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c @@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables REDIRECT target module"); /* FIXME: Take multiple ranges --RR */ static int redirect_check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 6693526..3eb47aa 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -282,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb, } static int check(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_reject_info *rejinfo = targinfo; + const struct ipt_entry *e = e_void; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 7a0536d..a22de59 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c @@ -49,7 +49,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip"); static int same_check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c index 8db70d6..c122841 100644 --- a/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/net/ipv4/netfilter/ipt_TCPMSS.c @@ -210,12 +210,13 @@ static inline int find_syn_match(const struct ipt_entry_match *m) /* Must specify -p tcp --syn/--tcp-flags SYN */ static int ipt_tcpmss_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_tcpmss_info *tcpmssinfo = targinfo; + const struct ipt_entry *e = e_void; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index deadb36..3a44a56 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c @@ -52,7 +52,7 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index b9ae6a9..b769eb2 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c @@ -66,7 +66,7 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, } static int ipt_ttl_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 38641cd..641dbc4 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -330,7 +330,7 @@ static void ipt_logfn(unsigned int pf, } static int ipt_ulog_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hookmask) diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index e19c2a5..d6b83a9 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c @@ -29,7 +29,7 @@ static inline int match_type(u_int32_t addr, u_int16_t mask) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_addrtype_info *info = matchinfo; const struct iphdr *iph = skb->nh.iph; @@ -43,7 +43,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return ret; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c index a0fea84..144adfe 100644 --- a/net/ipv4/netfilter/ipt_ah.c +++ b/net/ipv4/netfilter/ipt_ah.c @@ -41,6 +41,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ip_auth_hdr _ahdr, *ah; @@ -50,7 +51,7 @@ match(const struct sk_buff *skb, if (offset) return 0; - ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + ah = skb_header_pointer(skb, protoff, sizeof(_ahdr), &_ahdr); if (ah == NULL) { /* We've been asked to examine this packet, and we @@ -69,12 +70,13 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip_void, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) { const struct ipt_ah *ahinfo = matchinfo; + const struct ipt_ip *ip = ip_void; /* Must specify proto == AH, and no unknown invflags */ if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c index 5df52a6..92063b4 100644 --- a/net/ipv4/netfilter/ipt_dscp.c +++ b/net/ipv4/netfilter/ipt_dscp.c @@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_dscp_info *info = matchinfo; const struct iphdr *iph = skb->nh.iph; @@ -31,7 +31,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index b6f7181..e68b0c7 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c @@ -67,7 +67,7 @@ static inline int match_tcp(const struct sk_buff *skb, static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_ecn_info *info = matchinfo; @@ -85,11 +85,12 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return 1; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip_void, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { const struct ipt_ecn_info *info = matchinfo; + const struct ipt_ip *ip = ip_void; if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) return 0; diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c index e1d0dd3..9de191a 100644 --- a/net/ipv4/netfilter/ipt_esp.c +++ b/net/ipv4/netfilter/ipt_esp.c @@ -42,6 +42,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ip_esp_hdr _esp, *eh; @@ -51,7 +52,7 @@ match(const struct sk_buff *skb, if (offset) return 0; - eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp); if (eh == NULL) { /* We've been asked to examine this packet, and we @@ -70,12 +71,13 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip_void, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) { const struct ipt_esp *espinfo = matchinfo; + const struct ipt_ip *ip = ip_void; /* Must specify proto == ESP, and no unknown invflags */ if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index 2dd1ccc..4fe48c1 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c @@ -429,6 +429,7 @@ hashlimit_match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ipt_hashlimit_info *r = @@ -504,7 +505,7 @@ hashlimit_match(const struct sk_buff *skb, static int hashlimit_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c index b835b7b..13fb16f 100644 --- a/net/ipv4/netfilter/ipt_iprange.c +++ b/net/ipv4/netfilter/ipt_iprange.c @@ -28,7 +28,7 @@ match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_iprange_info *info = matchinfo; const struct iphdr *iph = skb->nh.iph; @@ -63,7 +63,7 @@ match(const struct sk_buff *skb, } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_length.c b/net/ipv4/netfilter/ipt_length.c deleted file mode 100644 index 4eabcfb..0000000 --- a/net/ipv4/netfilter/ipt_length.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Kernel module to match packet length. */ -/* (C) 1999-2001 James Morris <jmorros@intercode.com.au> - * - * 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/module.h> -#include <linux/skbuff.h> - -#include <linux/netfilter_ipv4/ipt_length.h> -#include <linux/netfilter_ipv4/ip_tables.h> - -MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); -MODULE_DESCRIPTION("IP tables packet length matching module"); -MODULE_LICENSE("GPL"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - const struct ipt_length_info *info = matchinfo; - u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); - - return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; -} - -static int -checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_length_info))) - return 0; - - return 1; -} - -static struct ipt_match length_match = { - .name = "length", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_match(&length_match); -} - -static void __exit fini(void) -{ - ipt_unregister_match(&length_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c index 99e8188..2d52326 100644 --- a/net/ipv4/netfilter/ipt_multiport.c +++ b/net/ipv4/netfilter/ipt_multiport.c @@ -97,6 +97,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { u16 _ports[2], *pptr; @@ -105,7 +106,7 @@ match(const struct sk_buff *skb, if (offset) return 0; - pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); if (pptr == NULL) { /* We've been asked to examine this packet, and we @@ -128,6 +129,7 @@ match_v1(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { u16 _ports[2], *pptr; @@ -136,7 +138,7 @@ match_v1(const struct sk_buff *skb, if (offset) return 0; - pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); if (pptr == NULL) { /* We've been asked to examine this packet, and we @@ -154,7 +156,7 @@ match_v1(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) @@ -164,7 +166,7 @@ checkentry(const char *tablename, static int checkentry_v1(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 0cee286..4843d0c 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c @@ -27,6 +27,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { const struct ipt_owner_info *info = matchinfo; @@ -51,7 +52,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_physdev.c b/net/ipv4/netfilter/ipt_physdev.c deleted file mode 100644 index 03f5548..0000000 --- a/net/ipv4/netfilter/ipt_physdev.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Kernel module to match the bridge port in and - * out device for IP packets coming into contact with a bridge. */ - -/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be> - * - * 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/module.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ipt_physdev.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_bridge.h> -#define MATCH 1 -#define NOMATCH 0 - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); -MODULE_DESCRIPTION("iptables bridge physical device match module"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - int i; - static const char nulldevname[IFNAMSIZ]; - const struct ipt_physdev_info *info = matchinfo; - unsigned int ret; - const char *indev, *outdev; - struct nf_bridge_info *nf_bridge; - - /* Not a bridged IP packet or no info available yet: - * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if - * the destination device will be a bridge. */ - if (!(nf_bridge = skb->nf_bridge)) { - /* Return MATCH if the invert flags of the used options are on */ - if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && - !(info->invert & IPT_PHYSDEV_OP_BRIDGED)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) && - !(info->invert & IPT_PHYSDEV_OP_ISIN)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) && - !(info->invert & IPT_PHYSDEV_OP_ISOUT)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_IN) && - !(info->invert & IPT_PHYSDEV_OP_IN)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_OUT) && - !(info->invert & IPT_PHYSDEV_OP_OUT)) - return NOMATCH; - return MATCH; - } - - /* This only makes sense in the FORWARD and POSTROUTING chains */ - if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && - (!!(nf_bridge->mask & BRNF_BRIDGED) ^ - !(info->invert & IPT_PHYSDEV_OP_BRIDGED))) - return NOMATCH; - - if ((info->bitmask & IPT_PHYSDEV_OP_ISIN && - (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) || - (info->bitmask & IPT_PHYSDEV_OP_ISOUT && - (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT)))) - return NOMATCH; - - if (!(info->bitmask & IPT_PHYSDEV_OP_IN)) - goto match_outdev; - indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; - for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { - ret |= (((const unsigned int *)indev)[i] - ^ ((const unsigned int *)info->physindev)[i]) - & ((const unsigned int *)info->in_mask)[i]; - } - - if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN)) - return NOMATCH; - -match_outdev: - if (!(info->bitmask & IPT_PHYSDEV_OP_OUT)) - return MATCH; - outdev = nf_bridge->physoutdev ? - nf_bridge->physoutdev->name : nulldevname; - for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { - ret |= (((const unsigned int *)outdev)[i] - ^ ((const unsigned int *)info->physoutdev)[i]) - & ((const unsigned int *)info->out_mask)[i]; - } - - return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT); -} - -static int -checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ipt_physdev_info *info = matchinfo; - - if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info))) - return 0; - if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) || - info->bitmask & ~IPT_PHYSDEV_OP_MASK) - return 0; - return 1; -} - -static struct ipt_match physdev_match = { - .name = "physdev", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_match(&physdev_match); -} - -static void __exit fini(void) -{ - ipt_unregister_match(&physdev_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 5ddccb1..44611d6 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -104,6 +104,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop); /* Function to hash a given address into the hash table of table_size size */ @@ -317,7 +318,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned skb->nh.iph->daddr = 0; /* Clear ttl since we have no way of knowing it */ skb->nh.iph->ttl = 0; - match(skb,NULL,NULL,info,0,NULL); + match(skb,NULL,NULL,info,0,0,NULL); kfree(skb->nh.iph); out_free_skb: @@ -357,6 +358,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { int pkt_count, hits_found, ans; @@ -654,7 +656,7 @@ match(const struct sk_buff *skb, */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c index 086a1bb..9ab765e 100644 --- a/net/ipv4/netfilter/ipt_tos.c +++ b/net/ipv4/netfilter/ipt_tos.c @@ -23,6 +23,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { const struct ipt_tos_info *info = matchinfo; @@ -32,7 +33,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c index 219aa9d..82da53f 100644 --- a/net/ipv4/netfilter/ipt_ttl.c +++ b/net/ipv4/netfilter/ipt_ttl.c @@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_ttl_info *info = matchinfo; @@ -47,7 +47,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return 0; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 260a4f0..212a307 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -78,7 +78,8 @@ static struct ipt_table packet_filter = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .me = THIS_MODULE + .me = THIS_MODULE, + .af = AF_INET, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 160eb11..3212a5c 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -109,6 +109,7 @@ static struct ipt_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 47449ba..fdb9e9c 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -83,7 +83,8 @@ static struct ipt_table packet_raw = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .me = THIS_MODULE + .me = THIS_MODULE, + .af = AF_INET, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0c56c52..167619f 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -575,7 +575,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - need_nf_conntrack(); + need_conntrack(); return init_or_cleanup(1); } @@ -587,9 +587,4 @@ static void __exit fini(void) module_init(init); module_exit(fini); -void need_ip_conntrack(void) -{ -} - -EXPORT_SYMBOL(need_ip_conntrack); EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 105dd69..2d6f8ec 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -41,6 +41,7 @@ config IP6_NF_QUEUE config IP6_NF_IPTABLES tristate "IP6 tables support (required for filtering/masq/NAT)" + depends on NETFILTER_XTABLES help ip6tables is a general, extensible packet identification framework. Currently only the packet filtering and packet mangling subsystem @@ -50,25 +51,6 @@ config IP6_NF_IPTABLES To compile it as a module, choose M here. If unsure, say N. # The simple matches. -config IP6_NF_MATCH_LIMIT - tristate "limit match support" - depends on IP6_NF_IPTABLES - help - limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target ("LOG - target support", below) and to avoid some Denial of Service attacks. - - To compile it as a module, choose M here. If unsure, say N. - -config IP6_NF_MATCH_MAC - tristate "MAC address match support" - depends on IP6_NF_IPTABLES - help - mac matching allows you to match packets based on the source - Ethernet address of the packet. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_RT tristate "Routing header match support" depends on IP6_NF_IPTABLES @@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_MARK - tristate "netfilter MARK match support" - depends on IP6_NF_IPTABLES - help - Netfilter mark matching allows you to match packets based on the - `nfmark' value in the packet. This can be set by the MARK target - (see below). - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_IPV6HEADER tristate "IPv6 Extension Headers Match" depends on IP6_NF_IPTABLES @@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_LENGTH - tristate "Packet Length match support" - depends on IP6_NF_IPTABLES - help - This option allows you to match the length of a packet against a - specific value or range of values. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_EUI64 tristate "EUI64 address check" depends on IP6_NF_IPTABLES @@ -170,15 +133,6 @@ config IP6_NF_MATCH_EUI64 To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_PHYSDEV - tristate "Physdev match support" - depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER - help - Physdev packet matching matches against the physical bridge ports - the IP packet arrived on or will leave by. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_POLICY tristate "IPsec policy match support" depends on IP6_NF_IPTABLES && XFRM @@ -219,17 +173,6 @@ config IP6_NF_TARGET_REJECT To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_TARGET_NFQUEUE - tristate "NFQUEUE Target Support" - depends on IP6_NF_IPTABLES - help - This Target replaced the old obsolete QUEUE target. - - As opposed to QUEUE, it supports 65535 different queues, - not just one. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MANGLE tristate "Packet mangling" depends on IP6_NF_IPTABLES @@ -240,19 +183,6 @@ config IP6_NF_MANGLE To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_TARGET_MARK - tristate "MARK target support" - depends on IP6_NF_MANGLE - help - This option adds a `MARK' target, which allows you to create rules - in the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet packet prior to routing. This can change - the routing method (see `Use netfilter MARK value as routing - key') and can also be used by other subsystems to change their - behavior. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_TARGET_HL tristate 'HL (hoplimit) target support' depends on IP6_NF_MANGLE diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index c0c809b..663b474 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -4,10 +4,7 @@ # Link order matters here. obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o -obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o -obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o -obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o @@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o -obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o -obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o -obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1390370..847068f 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -13,6 +13,9 @@ * a table * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> * - new extension header parser code + * 15 Oct 2005 Harald Welte <laforge@netfilter.org> + * - Unification of {ip,ip6}_tables into x_tables + * - Removed tcp and udp code, since it's not ipv6 specific */ #include <linux/capability.h> @@ -23,8 +26,6 @@ #include <linux/vmalloc.h> #include <linux/netdevice.h> #include <linux/module.h> -#include <linux/tcp.h> -#include <linux/udp.h> #include <linux/icmpv6.h> #include <net/ipv6.h> #include <asm/uaccess.h> @@ -33,6 +34,7 @@ #include <linux/cpumask.h> #include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/netfilter/x_tables.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); @@ -67,13 +69,8 @@ do { \ #else #define IP_NF_ASSERT(x) #endif -#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) -static DECLARE_MUTEX(ip6t_mutex); -/* Must have mutex */ -#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) -#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) #include <linux/netfilter_ipv4/listhelp.h> #if 0 @@ -91,30 +88,6 @@ static DECLARE_MUTEX(ip6t_mutex); Hence the start of any table is given by get_table() below. */ -/* The table itself */ -struct ip6t_table_info -{ - /* Size per table */ - unsigned int size; - /* Number of entries: FIXME. --RR */ - unsigned int number; - /* Initial number of entries. Needed for module usage count */ - unsigned int initial_entries; - - /* Entry points and underflows */ - unsigned int hook_entry[NF_IP6_NUMHOOKS]; - unsigned int underflow[NF_IP6_NUMHOOKS]; - - /* ip6t_entry tables: one per CPU */ - void *entries[NR_CPUS]; -}; - -static LIST_HEAD(ip6t_target); -static LIST_HEAD(ip6t_match); -static LIST_HEAD(ip6t_tables); -#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) -#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) - #if 0 #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) @@ -297,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct ip6t_table *table, + struct xt_table *table, void *userdata) { static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); @@ -309,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb, const char *indev, *outdev; void *table_base; struct ip6t_entry *e, *back; + struct xt_table_info *private; /* Initialization */ indev = in ? in->name : nulldevname; @@ -321,9 +295,10 @@ ip6t_do_table(struct sk_buff **pskb, * match it. */ read_lock_bh(&table->lock); + private = table->private; IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - table_base = (void *)table->private->entries[smp_processor_id()]; - e = get_entry(table_base, table->private->hook_entry[hook]); + table_base = (void *)private->entries[smp_processor_id()]; + e = get_entry(table_base, private->hook_entry[hook]); #ifdef CONFIG_NETFILTER_DEBUG /* Check noone else using our table */ @@ -339,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb, #endif /* For return from builtin chain */ - back = get_entry(table_base, table->private->underflow[hook]); + back = get_entry(table_base, private->underflow[hook]); do { IP_NF_ASSERT(e); @@ -439,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb, #endif } -/* - * 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 table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ -static inline struct ip6t_table *find_table_lock(const char *name) -{ - struct ip6t_table *t; - - if (down_interruptible(&ip6t_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ip6t_tables, list) - if (strcmp(t->name, name) == 0 && try_module_get(t->me)) - return t; - up(&ip6t_mutex); - return NULL; -} - -/* Find match, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ip6t_match *find_match(const char *name, u8 revision) -{ - struct ip6t_match *m; - int err = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(m, &ip6t_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision == revision) { - if (try_module_get(m->me)) { - up(&ip6t_mutex); - return m; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ip6t_mutex); - return ERR_PTR(err); -} - -/* Find target, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ip6t_target *find_target(const char *name, u8 revision) -{ - struct ip6t_target *t; - int err = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ip6t_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision == revision) { - if (try_module_get(t->me)) { - up(&ip6t_mutex); - return t; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ip6t_mutex); - return ERR_PTR(err); -} - -struct ip6t_target *ip6t_find_target(const char *name, u8 revision) -{ - struct ip6t_target *target; - - target = try_then_request_module(find_target(name, revision), - "ip6t_%s", name); - if (IS_ERR(target) || !target) - return NULL; - return target; -} - -static int match_revfn(const char *name, u8 revision, int *bestp) -{ - struct ip6t_match *m; - int have_rev = 0; - - list_for_each_entry(m, &ip6t_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision > *bestp) - *bestp = m->revision; - if (m->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -static int target_revfn(const char *name, u8 revision, int *bestp) -{ - struct ip6t_target *t; - int have_rev = 0; - - list_for_each_entry(t, &ip6t_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision > *bestp) - *bestp = t->revision; - if (t->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -/* Returns true or fals (if no such extension at all) */ -static inline int find_revision(const char *name, u8 revision, - int (*revfn)(const char *, u8, int *), - int *err) -{ - int have_rev, best = -1; - - if (down_interruptible(&ip6t_mutex) != 0) { - *err = -EINTR; - return 1; - } - have_rev = revfn(name, revision, &best); - up(&ip6t_mutex); - - /* 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; -} - - /* All zeroes == unconditional rule. */ static inline int unconditional(const struct ip6t_ip6 *ipv6) @@ -594,7 +430,7 @@ unconditional(const struct ip6t_ip6 *ipv6) /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int -mark_source_chains(struct ip6t_table_info *newinfo, +mark_source_chains(struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -740,11 +576,11 @@ check_match(struct ip6t_entry_match *m, { struct ip6t_match *match; - match = try_then_request_module(find_match(m->u.user.name, - m->u.user.revision), + match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, + m->u.user.revision), "ip6t_%s", m->u.user.name); if (IS_ERR(match) || !match) { - duprintf("check_match: `%s' not found\n", m->u.user.name); + duprintf("check_match: `%s' not found\n", m->u.user.name); return match ? PTR_ERR(match) : -ENOENT; } m->u.kernel.match = match; @@ -785,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, goto cleanup_matches; t = ip6t_get_target(e); - target = try_then_request_module(find_target(t->u.user.name, - t->u.user.revision), + target = try_then_request_module(xt_find_target(AF_INET6, + t->u.user.name, + t->u.user.revision), "ip6t_%s", t->u.user.name); if (IS_ERR(target) || !target) { duprintf("check_entry: `%s' not found\n", t->u.user.name); @@ -822,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, static inline int check_entry_size_and_hooks(struct ip6t_entry *e, - struct ip6t_table_info *newinfo, + struct xt_table_info *newinfo, unsigned char *base, unsigned char *limit, const unsigned int *hook_entries, @@ -856,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, < 0 (not IP6T_RETURN). --RR */ /* Clear counters and comefrom */ - e->counters = ((struct ip6t_counters) { 0, 0 }); + e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; (*i)++; @@ -886,7 +723,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) static int translate_table(const char *name, unsigned int valid_hooks, - struct ip6t_table_info *newinfo, + struct xt_table_info *newinfo, void *entry0, unsigned int size, unsigned int number, @@ -963,48 +800,10 @@ translate_table(const char *name, return ret; } -static struct ip6t_table_info * -replace_table(struct ip6t_table *table, - unsigned int num_counters, - struct ip6t_table_info *newinfo, - int *error) -{ - struct ip6t_table_info *oldinfo; - -#ifdef CONFIG_NETFILTER_DEBUG - { - int cpu; - - for_each_cpu(cpu) { - struct ip6t_entry *table_base = newinfo->entries[cpu]; - if (table_base) - table_base->comefrom = 0xdead57ac; - } - } -#endif - - /* Do the substitution. */ - write_lock_bh(&table->lock); - /* Check inside lock: is the old number correct? */ - if (num_counters != table->private->number) { - duprintf("num_counters != table->private->number (%u/%u)\n", - num_counters, table->private->number); - write_unlock_bh(&table->lock); - *error = -EAGAIN; - return NULL; - } - oldinfo = table->private; - table->private = newinfo; - newinfo->initial_entries = oldinfo->initial_entries; - write_unlock_bh(&table->lock); - - return oldinfo; -} - /* Gets counters. */ static inline int add_entry_to_counter(const struct ip6t_entry *e, - struct ip6t_counters total[], + struct xt_counters total[], unsigned int *i) { ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -1025,8 +824,8 @@ set_entry_to_counter(const struct ip6t_entry *e, } static void -get_counters(const struct ip6t_table_info *t, - struct ip6t_counters counters[]) +get_counters(const struct xt_table_info *t, + struct xt_counters counters[]) { unsigned int cpu; unsigned int i; @@ -1060,19 +859,20 @@ get_counters(const struct ip6t_table_info *t, static int copy_entries_to_user(unsigned int total_size, - struct ip6t_table *table, + struct xt_table *table, void __user *userptr) { unsigned int off, num, countersize; struct ip6t_entry *e; - struct ip6t_counters *counters; + struct xt_counters *counters; + struct xt_table_info *private = table->private; int ret = 0; void *loc_cpu_entry; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care about). */ - countersize = sizeof(struct ip6t_counters) * table->private->number; + countersize = sizeof(struct xt_counters) * private->number; counters = vmalloc(countersize); if (counters == NULL) @@ -1080,11 +880,11 @@ copy_entries_to_user(unsigned int total_size, /* First, sum counters... */ write_lock_bh(&table->lock); - get_counters(table->private, counters); + get_counters(private, counters); write_unlock_bh(&table->lock); /* choose the copy that is on ourc node/cpu */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { ret = -EFAULT; goto free_counters; @@ -1143,87 +943,42 @@ get_entries(const struct ip6t_get_entries *entries, struct ip6t_get_entries __user *uptr) { int ret; - struct ip6t_table *t; + struct xt_table *t; - t = find_table_lock(entries->name); + t = xt_find_table_lock(AF_INET6, entries->name); if (t && !IS_ERR(t)) { - duprintf("t->private->number = %u\n", - t->private->number); - if (entries->size == t->private->size) - ret = copy_entries_to_user(t->private->size, + struct xt_table_info *private = t->private; + duprintf("t->private->number = %u\n", private->number); + if (entries->size == private->size) + ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", - t->private->size, - entries->size); + private->size, entries->size); ret = -EINVAL; } module_put(t->me); - up(&ip6t_mutex); + xt_table_unlock(t); } else ret = t ? PTR_ERR(t) : -ENOENT; return ret; } -static void free_table_info(struct ip6t_table_info *info) -{ - int cpu; - for_each_cpu(cpu) { - if (info->size <= PAGE_SIZE) - kfree(info->entries[cpu]); - else - vfree(info->entries[cpu]); - } - kfree(info); -} - -static struct ip6t_table_info *alloc_table_info(unsigned int size) -{ - struct ip6t_table_info *newinfo; - int cpu; - - newinfo = kzalloc(sizeof(struct ip6t_table_info), GFP_KERNEL); - if (!newinfo) - return NULL; - - newinfo->size = size; - - for_each_cpu(cpu) { - 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) { - free_table_info(newinfo); - return NULL; - } - } - - return newinfo; -} - static int do_replace(void __user *user, unsigned int len) { int ret; struct ip6t_replace tmp; - struct ip6t_table *t; - struct ip6t_table_info *newinfo, *oldinfo; - struct ip6t_counters *counters; + struct xt_table *t; + struct xt_table_info *newinfo, *oldinfo; + struct xt_counters *counters; void *loc_cpu_entry, *loc_cpu_old_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ - if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) - return -ENOMEM; - - newinfo = alloc_table_info(tmp.size); + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; @@ -1235,7 +990,7 @@ do_replace(void __user *user, unsigned int len) goto free_newinfo; } - counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); + counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); if (!counters) { ret = -ENOMEM; goto free_newinfo; @@ -1249,7 +1004,7 @@ do_replace(void __user *user, unsigned int len) duprintf("ip_tables: Translated table\n"); - t = try_then_request_module(find_table_lock(tmp.name), + t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name), "ip6table_%s", tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1264,7 +1019,7 @@ do_replace(void __user *user, unsigned int len) goto put_module; } - oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); + oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) goto put_module; @@ -1283,23 +1038,23 @@ do_replace(void __user *user, unsigned int len) /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); - free_table_info(oldinfo); + xt_free_table_info(oldinfo); if (copy_to_user(tmp.counters, counters, - sizeof(struct ip6t_counters) * tmp.num_counters) != 0) + sizeof(struct xt_counters) * tmp.num_counters) != 0) ret = -EFAULT; vfree(counters); - up(&ip6t_mutex); + xt_table_unlock(t); return ret; put_module: module_put(t->me); - up(&ip6t_mutex); + xt_table_unlock(t); free_newinfo_counters_untrans: IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); free_newinfo_counters: vfree(counters); free_newinfo: - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } @@ -1307,7 +1062,7 @@ do_replace(void __user *user, unsigned int len) * and everything is OK. */ static inline int add_counter_to_entry(struct ip6t_entry *e, - const struct ip6t_counters addme[], + const struct xt_counters addme[], unsigned int *i) { #if 0 @@ -1329,15 +1084,16 @@ static int do_add_counters(void __user *user, unsigned int len) { unsigned int i; - struct ip6t_counters_info tmp, *paddc; - struct ip6t_table *t; + struct xt_counters_info tmp, *paddc; + struct xt_table_info *private; + struct xt_table *t; int ret = 0; void *loc_cpu_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) + if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) return -EINVAL; paddc = vmalloc(len); @@ -1349,29 +1105,30 @@ do_add_counters(void __user *user, unsigned int len) goto free; } - t = find_table_lock(tmp.name); + t = xt_find_table_lock(AF_INET6, tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; } write_lock_bh(&t->lock); - if (t->private->number != paddc->num_counters) { + private = t->private; + if (private->number != paddc->num_counters) { ret = -EINVAL; goto unlock_up_free; } i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = t->private->entries[smp_processor_id()]; + loc_cpu_entry = private->entries[smp_processor_id()]; IP6T_ENTRY_ITERATE(loc_cpu_entry, - t->private->size, + private->size, add_counter_to_entry, paddc->counters, &i); unlock_up_free: write_unlock_bh(&t->lock); - up(&ip6t_mutex); + xt_table_unlock(t); module_put(t->me); free: vfree(paddc); @@ -1415,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) switch (cmd) { case IP6T_SO_GET_INFO: { char name[IP6T_TABLE_MAXNAMELEN]; - struct ip6t_table *t; + struct xt_table *t; if (*len != sizeof(struct ip6t_getinfo)) { duprintf("length %u != %u\n", *len, @@ -1430,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; - t = try_then_request_module(find_table_lock(name), + t = try_then_request_module(xt_find_table_lock(AF_INET6, name), "ip6table_%s", name); if (t && !IS_ERR(t)) { struct ip6t_getinfo info; + struct xt_table_info *private = t->private; info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, t->private->hook_entry, + memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); - memcpy(info.underflow, t->private->underflow, + memcpy(info.underflow, private->underflow, sizeof(info.underflow)); - info.num_entries = t->private->number; - info.size = t->private->size; + info.num_entries = private->number; + info.size = private->size; memcpy(info.name, name, sizeof(info.name)); if (copy_to_user(user, &info, *len) != 0) ret = -EFAULT; else ret = 0; - up(&ip6t_mutex); + xt_table_unlock(t); module_put(t->me); } else ret = t ? PTR_ERR(t) : -ENOENT; @@ -1475,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case IP6T_SO_GET_REVISION_MATCH: case IP6T_SO_GET_REVISION_TARGET: { struct ip6t_get_revision rev; - int (*revfn)(const char *, u8, int *); + int target; if (*len != sizeof(rev)) { ret = -EINVAL; @@ -1487,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } if (cmd == IP6T_SO_GET_REVISION_TARGET) - revfn = target_revfn; + target = 1; else - revfn = match_revfn; + target = 0; - try_then_request_module(find_revision(rev.name, rev.revision, - revfn, &ret), + try_then_request_module(xt_find_revision(AF_INET6, rev.name, + rev.revision, + target, &ret), "ip6t_%s", rev.name); break; } @@ -1505,61 +1264,16 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return ret; } -/* Registration hooks for targets. */ -int -ip6t_register_target(struct ip6t_target *target) -{ - int ret; - - ret = down_interruptible(&ip6t_mutex); - if (ret != 0) - return ret; - list_add(&target->list, &ip6t_target); - up(&ip6t_mutex); - return ret; -} - -void -ip6t_unregister_target(struct ip6t_target *target) -{ - down(&ip6t_mutex); - LIST_DELETE(&ip6t_target, target); - up(&ip6t_mutex); -} - -int -ip6t_register_match(struct ip6t_match *match) -{ - int ret; - - ret = down_interruptible(&ip6t_mutex); - if (ret != 0) - return ret; - - list_add(&match->list, &ip6t_match); - up(&ip6t_mutex); - - return ret; -} - -void -ip6t_unregister_match(struct ip6t_match *match) -{ - down(&ip6t_mutex); - LIST_DELETE(&ip6t_match, match); - up(&ip6t_mutex); -} - -int ip6t_register_table(struct ip6t_table *table, +int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) { int ret; - struct ip6t_table_info *newinfo; - static struct ip6t_table_info bootstrap + struct xt_table_info *newinfo; + static struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; - newinfo = alloc_table_info(repl->size); + newinfo = xt_alloc_table_info(repl->size); if (!newinfo) return -ENOMEM; @@ -1573,244 +1287,29 @@ int ip6t_register_table(struct ip6t_table *table, repl->hook_entry, repl->underflow); if (ret != 0) { - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } - ret = down_interruptible(&ip6t_mutex); - if (ret != 0) { - free_table_info(newinfo); + if (xt_register_table(table, &bootstrap, newinfo) != 0) { + xt_free_table_info(newinfo); return ret; } - /* Don't autoload: we'd eat our tail... */ - if (list_named_find(&ip6t_tables, table->name)) { - ret = -EEXIST; - goto free_unlock; - } - - /* Simplifies replace_table code. */ - table->private = &bootstrap; - if (!replace_table(table, 0, newinfo, &ret)) - goto free_unlock; - - duprintf("table->private->number = %u\n", - table->private->number); - - /* save number of initial entries */ - table->private->initial_entries = table->private->number; - - rwlock_init(&table->lock); - list_prepend(&ip6t_tables, table); - - unlock: - up(&ip6t_mutex); - return ret; - - free_unlock: - free_table_info(newinfo); - goto unlock; + return 0; } -void ip6t_unregister_table(struct ip6t_table *table) +void ip6t_unregister_table(struct xt_table *table) { + struct xt_table_info *private; void *loc_cpu_entry; - down(&ip6t_mutex); - LIST_DELETE(&ip6t_tables, table); - up(&ip6t_mutex); + private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; - IP6T_ENTRY_ITERATE(loc_cpu_entry, table->private->size, - cleanup_entry, NULL); - free_table_info(table->private); -} - -/* Returns 1 if the port is matched by the range, 0 otherwise */ -static inline int -port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) -{ - int ret; - - ret = (port >= min && port <= max) ^ invert; - return ret; -} - -static int -tcp_find_option(u_int8_t option, - const struct sk_buff *skb, - unsigned int tcpoff, - unsigned int optlen, - int invert, - int *hotdrop) -{ - /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ - u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; - unsigned int i; - - duprintf("tcp_match: finding option\n"); - if (!optlen) - return invert; - /* If we don't have the whole header, drop packet. */ - op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen, - _opt); - if (op == NULL) { - *hotdrop = 1; - return 0; - } - - for (i = 0; i < optlen; ) { - if (op[i] == option) return !invert; - if (op[i] < 2) i++; - else i += op[i+1]?:1; - } - - return invert; -} - -static int -tcp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct tcphdr _tcph, *th; - const struct ip6t_tcp *tcpinfo = matchinfo; - - if (offset) { - /* To quote Alan: - - Don't allow a fragment of TCP 8 bytes in. Nobody normal - causes this. Its a cracker trying to break in by doing a - flag overwrite to pass the direction checks. - */ - if (offset == 1) { - duprintf("Dropping evil TCP offset=1 frag.\n"); - *hotdrop = 1; - } - /* Must not be a fragment. */ - return 0; - } - -#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) - - th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); - if (th == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil TCP offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], - ntohs(th->source), - !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))) - return 0; - if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], - ntohs(th->dest), - !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))) - return 0; - if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) - == tcpinfo->flg_cmp, - IP6T_TCP_INV_FLAGS)) - return 0; - if (tcpinfo->option) { - if (th->doff * 4 < sizeof(_tcph)) { - *hotdrop = 1; - return 0; - } - if (!tcp_find_option(tcpinfo->option, skb, protoff, - th->doff*4 - sizeof(*th), - tcpinfo->invflags & IP6T_TCP_INV_OPTION, - hotdrop)) - return 0; - } - return 1; -} - -/* Called when user tries to insert an entry of this type. */ -static int -tcp_checkentry(const char *tablename, - const struct ip6t_ip6 *ipv6, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ip6t_tcp *tcpinfo = matchinfo; - - /* Must specify proto == TCP, and no unknown invflags */ - return ipv6->proto == IPPROTO_TCP - && !(ipv6->invflags & IP6T_INV_PROTO) - && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp)) - && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK); -} - -static int -udp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct udphdr _udph, *uh; - const struct ip6t_udp *udpinfo = matchinfo; - - /* Must not be a fragment. */ - if (offset) - return 0; - - uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); - if (uh == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil UDP tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return port_match(udpinfo->spts[0], udpinfo->spts[1], - ntohs(uh->source), - !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT)) - && port_match(udpinfo->dpts[0], udpinfo->dpts[1], - ntohs(uh->dest), - !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT)); -} - -/* Called when user tries to insert an entry of this type. */ -static int -udp_checkentry(const char *tablename, - const struct ip6t_ip6 *ipv6, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) -{ - const struct ip6t_udp *udpinfo = matchinfo; - - /* Must specify proto == UDP, and no unknown invflags */ - if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) { - duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, - IPPROTO_UDP); - return 0; - } - if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) { - duprintf("ip6t_udp: matchsize %u != %u\n", - matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp))); - return 0; - } - if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) { - duprintf("ip6t_udp: unknown flags %X\n", - udpinfo->invflags); - return 0; - } - - return 1; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + xt_free_table_info(private); } /* Returns 1 if the type and code is matched by the range, 0 otherwise */ @@ -1858,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int icmp6_checkentry(const char *tablename, - const struct ip6t_ip6 *ipv6, + const void *entry, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { + const struct ip6t_ip6 *ipv6 = entry; const struct ip6t_icmp *icmpinfo = matchinfo; /* Must specify proto == ICMP, and no unknown invflags */ @@ -1892,164 +1392,42 @@ static struct nf_sockopt_ops ip6t_sockopts = { .get = do_ip6t_get_ctl, }; -static struct ip6t_match tcp_matchstruct = { - .name = "tcp", - .match = &tcp_match, - .checkentry = &tcp_checkentry, -}; - -static struct ip6t_match udp_matchstruct = { - .name = "udp", - .match = &udp_match, - .checkentry = &udp_checkentry, -}; - static struct ip6t_match icmp6_matchstruct = { .name = "icmp6", .match = &icmp6_match, .checkentry = &icmp6_checkentry, }; -#ifdef CONFIG_PROC_FS -static inline int print_name(const char *i, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if ((*count)++ >= start_offset) { - unsigned int namelen; - - namelen = sprintf(buffer + *pos, "%s\n", - i + sizeof(struct list_head)); - if (*pos + namelen > length) { - /* Stop iterating */ - return 1; - } - *pos += namelen; - } - return 0; -} - -static inline int print_target(const struct ip6t_target *t, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if (t == &ip6t_standard_target || t == &ip6t_error_target) - return 0; - return print_name((char *)t, start_offset, buffer, length, pos, count); -} - -static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return 0; - - LIST_FIND(&ip6t_tables, print_name, char *, - offset, buffer, length, &pos, &count); - - up(&ip6t_mutex); - - /* `start' hack - see fs/proc/generic.c line ~105 */ - *start=(char *)((unsigned long)count-offset); - return pos; -} - -static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return 0; - - LIST_FIND(&ip6t_target, print_target, struct ip6t_target *, - offset, buffer, length, &pos, &count); - - up(&ip6t_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return 0; - - LIST_FIND(&ip6t_match, print_name, char *, - offset, buffer, length, &pos, &count); - - up(&ip6t_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] = -{ { "ip6_tables_names", ip6t_get_tables }, - { "ip6_tables_targets", ip6t_get_targets }, - { "ip6_tables_matches", ip6t_get_matches }, - { NULL, NULL} }; -#endif /*CONFIG_PROC_FS*/ - static int __init init(void) { int ret; + xt_proto_init(AF_INET6); + /* Noone else will be downing sem now, so we won't sleep */ - down(&ip6t_mutex); - list_append(&ip6t_target, &ip6t_standard_target); - list_append(&ip6t_target, &ip6t_error_target); - list_append(&ip6t_match, &tcp_matchstruct); - list_append(&ip6t_match, &udp_matchstruct); - list_append(&ip6t_match, &icmp6_matchstruct); - up(&ip6t_mutex); + xt_register_target(AF_INET6, &ip6t_standard_target); + xt_register_target(AF_INET6, &ip6t_error_target); + xt_register_match(AF_INET6, &icmp6_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ip6t_sockopts); if (ret < 0) { duprintf("Unable to register sockopts.\n"); + xt_proto_fini(AF_INET6); return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - int i; - - for (i = 0; ip6t_proc_entry[i].name; i++) { - proc = proc_net_create(ip6t_proc_entry[i].name, 0, - ip6t_proc_entry[i].get_info); - if (!proc) { - while (--i >= 0) - proc_net_remove(ip6t_proc_entry[i].name); - nf_unregister_sockopt(&ip6t_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } - } -#endif - - printk("ip6_tables: (C) 2000-2002 Netfilter core team\n"); + printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; } static void __exit fini(void) { nf_unregister_sockopt(&ip6t_sockopts); -#ifdef CONFIG_PROC_FS - { - int i; - for (i = 0; ip6t_proc_entry[i].name; i++) - proc_net_remove(ip6t_proc_entry[i].name); - } -#endif + xt_unregister_match(AF_INET6, &icmp6_matchstruct); + xt_unregister_target(AF_INET6, &ip6t_error_target); + xt_unregister_target(AF_INET6, &ip6t_standard_target); + xt_proto_fini(AF_INET6); } /* @@ -2128,10 +1506,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, EXPORT_SYMBOL(ip6t_register_table); EXPORT_SYMBOL(ip6t_unregister_table); EXPORT_SYMBOL(ip6t_do_table); -EXPORT_SYMBOL(ip6t_register_match); -EXPORT_SYMBOL(ip6t_unregister_match); -EXPORT_SYMBOL(ip6t_register_target); -EXPORT_SYMBOL(ip6t_unregister_target); EXPORT_SYMBOL(ip6t_ext_hdr); EXPORT_SYMBOL(ipv6_find_hdr); EXPORT_SYMBOL(ip6_masked_addrcmp); diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index 8f5549b..306200c 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c @@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, } static int ip6t_hl_checkentry(const char *tablename, - const struct ip6t_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index ae4653b..fc19d8a 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -444,7 +444,7 @@ ip6t_log_target(struct sk_buff **pskb, static int ip6t_log_checkentry(const char *tablename, - const struct ip6t_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c deleted file mode 100644 index eab8fb8..0000000 --- a/net/ipv6/netfilter/ip6t_MARK.c +++ /dev/null @@ -1,81 +0,0 @@ -/* This is a module which is used for setting the NFMARK field of an skb. */ - -/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca> - * - * 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/module.h> -#include <linux/skbuff.h> -#include <linux/ip.h> -#include <net/checksum.h> - -#include <linux/netfilter_ipv6/ip6_tables.h> -#include <linux/netfilter_ipv6/ip6t_MARK.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ip6t_mark_target_info *markinfo = targinfo; - - if((*pskb)->nfmark != markinfo->mark) - (*pskb)->nfmark = markinfo->mark; - - return IP6T_CONTINUE; -} - -static int -checkentry(const char *tablename, - const struct ip6t_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) { - printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", - targinfosize, - IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))); - return 0; - } - - if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); - return 0; - } - - return 1; -} - -static struct ip6t_target ip6t_mark_reg = { - .name = "MARK", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE -}; - -static int __init init(void) -{ - printk(KERN_DEBUG "registering ipv6 mark target\n"); - if (ip6t_register_target(&ip6t_mark_reg)) - return -EINVAL; - - return 0; -} - -static void __exit fini(void) -{ - ip6t_unregister_target(&ip6t_mark_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c deleted file mode 100644 index c6e3730..0000000 --- a/net/ipv6/netfilter/ip6t_NFQUEUE.c +++ /dev/null @@ -1,70 +0,0 @@ -/* ip6tables module for using new netfilter netlink queue - * - * (C) 2005 by Harald Welte <laforge@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/module.h> -#include <linux/skbuff.h> - -#include <linux/netfilter.h> -#include <linux/netfilter_ipv6/ip6_tables.h> -#include <linux/netfilter_ipv4/ipt_NFQUEUE.h> - -MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); -MODULE_DESCRIPTION("ip6tables NFQUEUE target"); -MODULE_LICENSE("GPL"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_NFQ_info *tinfo = targinfo; - - return NF_QUEUE_NR(tinfo->queuenum); -} - -static int -checkentry(const char *tablename, - const struct ip6t_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) { - printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", - targinfosize, - IP6T_ALIGN(sizeof(struct ipt_NFQ_info))); - return 0; - } - - return 1; -} - -static struct ip6t_target ipt_NFQ_reg = { - .name = "NFQUEUE", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_target(&ipt_NFQ_reg); -} - -static void __exit fini(void) -{ - ip6t_unregister_target(&ipt_NFQ_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index b03e87a..c745717 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb, } static int check(const char *tablename, - const struct ip6t_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ip6t_reject_info *rejinfo = targinfo; + const struct ip6t_entry *e = entry; if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index f5c1a7f..219a303 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -98,7 +98,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *entry, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 48cf5f9..80fe826 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c @@ -178,7 +178,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *info, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e1828f6..724285d 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c @@ -76,7 +76,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 616c2cb..ddf5f57 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c @@ -62,7 +62,7 @@ match(const struct sk_buff *skb, static int ip6t_eui64_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index d1549b2..a9964b9 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -115,7 +115,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index e3bc8e2..ed8ded1 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -178,7 +178,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *entry, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c index 0beaff5..c5d9079 100644 --- a/net/ipv6/netfilter/ip6t_hl.c +++ b/net/ipv6/netfilter/ip6t_hl.c @@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return 0; } -static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, +static int checkentry(const char *tablename, const void *entry, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 32e67f0..fda1cea 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c @@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb, static int ipv6header_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c deleted file mode 100644 index e0537d3..0000000 --- a/net/ipv6/netfilter/ip6t_length.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Length Match - IPv6 Port */ - -/* (C) 1999-2001 James Morris <jmorros@intercode.com.au> - * - * 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/module.h> -#include <linux/skbuff.h> -#include <linux/netfilter_ipv6/ip6t_length.h> -#include <linux/netfilter_ipv6/ip6_tables.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); -MODULE_DESCRIPTION("IPv6 packet length match"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ip6t_length_info *info = matchinfo; - u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); - - return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; -} - -static int -checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info))) - return 0; - - return 1; -} - -static struct ip6t_match length_match = { - .name = "length", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_match(&length_match); -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&length_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c deleted file mode 100644 index fb782f6..0000000 --- a/net/ipv6/netfilter/ip6t_limit.c +++ /dev/null @@ -1,147 +0,0 @@ -/* Kernel module to control the rate - * - * 2 September 1999: Changed from the target RATE to the match - * `limit', removed logging. Did I mention that - * Alexey is a fucking genius? - * Rusty Russell (rusty@rustcorp.com.au). */ - -/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr> - * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr> - * - * 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/module.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> - -#include <linux/netfilter_ipv6/ip6_tables.h> -#include <linux/netfilter_ipv6/ip6t_limit.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); -MODULE_DESCRIPTION("rate limiting within ip6tables"); - -/* The algorithm used is the Simple Token Bucket Filter (TBF) - * see net/sched/sch_tbf.c in the linux source tree - */ - -static DEFINE_SPINLOCK(limit_lock); - -/* Rusty: This is my (non-mathematically-inclined) understanding of - this algorithm. The `average rate' in jiffies becomes your initial - amount of credit `credit' and the most credit you can ever have - `credit_cap'. The `peak rate' becomes the cost of passing the - test, `cost'. - - `prev' tracks the last packet hit: you gain one credit per jiffy. - If you get credit balance more than this, the extra credit is - discarded. Every time the match passes, you lose `cost' credits; - if you don't have that many, the test fails. - - See Alexey's formal explanation in net/sched/sch_tbf.c. - - To avoid underflow, we multiply by 128 (ie. you get 128 credits per - jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds - at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes - per second at 100HZ. */ - -#define CREDITS_PER_JIFFY 128 - -static int -ip6t_limit_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master; - unsigned long now = jiffies; - - spin_lock_bh(&limit_lock); - r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY; - if (r->credit > r->credit_cap) - r->credit = r->credit_cap; - - if (r->credit >= r->cost) { - /* We're not limited. */ - r->credit -= r->cost; - spin_unlock_bh(&limit_lock); - return 1; - } - - spin_unlock_bh(&limit_lock); - return 0; -} - -/* Precision saver. */ -static u_int32_t -user2credits(u_int32_t user) -{ - /* If multiplying would overflow... */ - if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) - /* Divide first. */ - return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; - - return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE; -} - -static int -ip6t_limit_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - struct ip6t_rateinfo *r = matchinfo; - - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo))) - return 0; - - /* Check for overflow. */ - if (r->burst == 0 - || user2credits(r->avg * r->burst) < user2credits(r->avg)) { - printk("Call rusty: overflow in ip6t_limit: %u/%u\n", - r->avg, r->burst); - return 0; - } - - /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies * - 128. */ - r->prev = jiffies; - r->credit = user2credits(r->avg * r->burst); /* Credits full. */ - r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ - r->cost = user2credits(r->avg); - - /* For SMP, we only want to use one set of counters. */ - r->master = r; - - return 1; -} - -static struct ip6t_match ip6t_limit_reg = { - .name = "limit", - .match = ip6t_limit_match, - .checkentry = ip6t_limit_checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - if (ip6t_register_match(&ip6t_limit_reg)) - return -EINVAL; - return 0; -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&ip6t_limit_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c deleted file mode 100644 index c848152..0000000 --- a/net/ipv6/netfilter/ip6t_mac.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Kernel module to match MAC address parameters. */ - -/* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 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/module.h> -#include <linux/skbuff.h> -#include <linux/if_ether.h> -#include <linux/etherdevice.h> - -#include <linux/netfilter_ipv6/ip6t_mac.h> -#include <linux/netfilter_ipv6/ip6_tables.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MAC address matching module for IPv6"); -MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ip6t_mac_info *info = matchinfo; - - /* Is mac pointer valid? */ - return (skb->mac.raw >= skb->head - && (skb->mac.raw + ETH_HLEN) <= skb->data - /* If so, compare... */ - && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr)) - ^ info->invert)); -} - -static int -ip6t_mac_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (hook_mask - & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) - | (1 << NF_IP6_FORWARD))) { - printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or" - " FORWARD\n"); - return 0; - } - - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info))) - return 0; - - return 1; -} - -static struct ip6t_match mac_match = { - .name = "mac", - .match = &match, - .checkentry = &ip6t_mac_checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_match(&mac_match); -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&mac_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c deleted file mode 100644 index affc3de..0000000 --- a/net/ipv6/netfilter/ip6t_mark.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Kernel module to match NFMARK values. */ - -/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca> - * - * 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/module.h> -#include <linux/skbuff.h> - -#include <linux/netfilter_ipv6/ip6t_mark.h> -#include <linux/netfilter_ipv6/ip6_tables.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); -MODULE_DESCRIPTION("ip6tables mark match"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ip6t_mark_info *info = matchinfo; - - return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; -} - -static int -checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info))) - return 0; - - return 1; -} - -static struct ip6t_match mark_match = { - .name = "mark", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_match(&mark_match); -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&mark_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c index 6e32461..49f7829 100644 --- a/net/ipv6/netfilter/ip6t_multiport.c +++ b/net/ipv6/netfilter/ip6t_multiport.c @@ -84,11 +84,12 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *info, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { + const struct ip6t_ip6 *ip = info; const struct ip6t_multiport *multiinfo = matchinfo; if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 4de4cda..5409b37 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -53,7 +53,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index c1e770e..8465b43 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -183,7 +183,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *entry, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 4c00286..ce4a968 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET6, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 85c1e6e..30a4627 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET6, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index c2982ef..db28ba3 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -106,11 +106,12 @@ static struct } }; -static struct ip6t_table packet_raw = { +static struct xt_table packet_raw = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .me = THIS_MODULE + .me = THIS_MODULE, + .af = AF_INET6, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e57d6fc..92ad53d 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -584,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); static int __init init(void) { - need_nf_conntrack(); + need_conntrack(); return init_or_cleanup(1); } @@ -595,9 +595,3 @@ static void __exit fini(void) module_init(init); module_exit(fini); - -void need_ip6_conntrack(void) -{ -} - -EXPORT_SYMBOL(need_ip6_conntrack); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index f3e5ffb..84ef9a1 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb struct nf_ct_frag6_queue { - struct nf_ct_frag6_queue *next; - struct list_head lru_list; /* lru list member */ + struct hlist_node list; + struct list_head lru_list; /* lru list member */ __u32 id; /* fragment id */ struct in6_addr saddr; @@ -90,14 +90,13 @@ struct nf_ct_frag6_queue #define FIRST_IN 2 #define LAST_IN 1 __u16 nhoffset; - struct nf_ct_frag6_queue **pprev; }; /* Hash table. */ #define FRAG6Q_HASHSZ 64 -static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; +static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ]; static DEFINE_RWLOCK(nf_ct_frag6_lock); static u32 nf_ct_frag6_hash_rnd; static LIST_HEAD(nf_ct_frag6_lru_list); @@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0; static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) { - if (fq->next) - fq->next->pprev = fq->pprev; - *fq->pprev = fq->next; + hlist_del(&fq->list); list_del(&fq->lru_list); nf_ct_frag6_nqueues--; } @@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy) get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); for (i = 0; i < FRAG6Q_HASHSZ; i++) { struct nf_ct_frag6_queue *q; + struct hlist_node *p, *n; - q = nf_ct_frag6_hash[i]; - while (q) { - struct nf_ct_frag6_queue *next = q->next; + hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) { unsigned int hval = ip6qhashfn(q->id, &q->saddr, &q->daddr); - if (hval != i) { - /* Unlink. */ - if (q->next) - q->next->pprev = q->pprev; - *q->pprev = q->next; - + hlist_del(&q->list); /* Relink to new hash chain. */ - if ((q->next = nf_ct_frag6_hash[hval]) != NULL) - q->next->pprev = &q->next; - nf_ct_frag6_hash[hval] = q; - q->pprev = &nf_ct_frag6_hash[hval]; + hlist_add_head(&q->list, + &nf_ct_frag6_hash[hval]); } - - q = next; } } write_unlock(&nf_ct_frag6_lock); @@ -314,15 +301,17 @@ out: /* Creation primitives. */ - static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, struct nf_ct_frag6_queue *fq_in) { struct nf_ct_frag6_queue *fq; +#ifdef CONFIG_SMP + struct hlist_node *n; +#endif write_lock(&nf_ct_frag6_lock); #ifdef CONFIG_SMP - for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { + hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { if (fq->id == fq_in->id && !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { @@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, atomic_inc(&fq->refcnt); atomic_inc(&fq->refcnt); - if ((fq->next = nf_ct_frag6_hash[hash]) != NULL) - fq->next->pprev = &fq->next; - nf_ct_frag6_hash[hash] = fq; - fq->pprev = &nf_ct_frag6_hash[hash]; + hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]); INIT_LIST_HEAD(&fq->lru_list); list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); nf_ct_frag6_nqueues++; @@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue * fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) { struct nf_ct_frag6_queue *fq; + struct hlist_node *n; unsigned int hash = ip6qhashfn(id, src, dst); read_lock(&nf_ct_frag6_lock); - for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { + hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { if (fq->id == id && !ipv6_addr_cmp(src, &fq->saddr) && !ipv6_addr_cmp(dst, &fq->daddr)) { diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 7d55f9c..99c0a0f 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -103,3 +103,261 @@ config NF_CT_NETLINK This option enables support for a netlink-based userspace interface endmenu + +config NETFILTER_XTABLES + tristate "Netfilter Xtables support (required for ip_tables)" + help + This is required if you intend to use any of ip_tables, + ip6_tables or arp_tables. + +# alphabetically ordered list of targets + +config NETFILTER_XT_TARGET_CLASSIFY + tristate '"CLASSIFY" target support' + depends on NETFILTER_XTABLES + help + This option adds a `CLASSIFY' target, which enables the user to set + the priority of a packet. Some qdiscs can use this value for + classification, among these are: + + atm, cbq, dsmark, pfifo_fast, htb, prio + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_TARGET_CONNMARK + tristate '"CONNMARK" target support' + depends on NETFILTER_XTABLES + depends on IP_NF_MANGLE || IP6_NF_MANGLE + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) + help + This option adds a `CONNMARK' target, which allows one to manipulate + the connection mark value. Similar to the MARK target, but + affects the connection mark value rather than the packet mark value. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. The module will be called + ipt_CONNMARK.o. If unsure, say `N'. + +config NETFILTER_XT_TARGET_MARK + tristate '"MARK" target support' + depends on NETFILTER_XTABLES + help + This option adds a `MARK' target, which allows you to create rules + in the `mangle' table which alter the netfilter mark (nfmark) field + associated with the packet prior to routing. This can change + the routing method (see `Use netfilter MARK value as routing + key') and can also be used by other subsystems to change their + behavior. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_TARGET_NFQUEUE + tristate '"NFQUEUE" target Support' + depends on NETFILTER_XTABLES + help + This Target replaced the old obsolete QUEUE target. + + As opposed to QUEUE, it supports 65535 different queues, + not just one. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_TARGET_NOTRACK + tristate '"NOTRACK" target support' + depends on NETFILTER_XTABLES + depends on IP_NF_RAW || IP6_NF_RAW + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + The NOTRACK target allows a select rule to specify + which packets *not* to enter the conntrack/NAT + subsystem with all the consequences (no ICMP error tracking, + no protocol helpers for the selected packets). + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. If unsure, say `N'. + +config NETFILTER_XT_MATCH_COMMENT + tristate '"comment" match support' + depends on NETFILTER_XTABLES + help + This option adds a `comment' dummy-match, which allows you to put + comments in your iptables ruleset. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. If unsure, say `N'. + +config NETFILTER_XT_MATCH_CONNBYTES + tristate '"connbytes" per-connection counter match support' + depends on NETFILTER_XTABLES + depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT + help + This option adds a `connbytes' match, which allows you to match the + number of bytes and/or packets for each direction within a connection. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. If unsure, say `N'. + +config NETFILTER_XT_MATCH_CONNMARK + tristate '"connmark" connection mark match support' + depends on NETFILTER_XTABLES + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK + help + This option adds a `connmark' match, which allows you to match the + connection mark value previously set for the session by `CONNMARK'. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. The module will be called + ipt_connmark.o. If unsure, say `N'. + +config NETFILTER_XT_MATCH_CONNTRACK + tristate '"conntrack" connection tracking match support' + depends on NETFILTER_XTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + This is a general conntrack match module, a superset of the state match. + + It allows matching on additional conntrack information, which is + useful in complex configurations, such as NAT gateways with multiple + internet links or tunnels. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_DCCP + tristate '"DCCP" protocol match support' + depends on NETFILTER_XTABLES + help + With this option enabled, you will be able to use the iptables + `dccp' match in order to match on DCCP source/destination ports + and DCCP flags. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. If unsure, say `N'. + +config NETFILTER_XT_MATCH_HELPER + tristate '"helper" match support' + depends on NETFILTER_XTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + Helper matching allows you to match packets in dynamic connections + tracked by a conntrack-helper, ie. ip_conntrack_ftp + + To compile it as a module, choose M here. If unsure, say Y. + +config NETFILTER_XT_MATCH_LENGTH + tristate '"length" match support' + depends on NETFILTER_XTABLES + help + This option allows you to match the length of a packet against a + specific value or range of values. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_LIMIT + tristate '"limit" match support' + depends on NETFILTER_XTABLES + help + limit matching allows you to control the rate at which a rule can be + matched: mainly useful in combination with the LOG target ("LOG + target support", below) and to avoid some Denial of Service attacks. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_MAC + tristate '"mac" address match support' + depends on NETFILTER_XTABLES + help + MAC matching allows you to match packets based on the source + Ethernet address of the packet. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_MARK + tristate '"mark" match support' + depends on NETFILTER_XTABLES + help + Netfilter mark matching allows you to match packets based on the + `nfmark' value in the packet. This can be set by the MARK target + (see below). + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_PHYSDEV + tristate '"physdev" match support' + depends on NETFILTER_XTABLES && BRIDGE_NETFILTER + help + Physdev packet matching matches against the physical bridge ports + the IP packet arrived on or will leave by. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_PKTTYPE + tristate '"pkttype" packet type match support' + depends on NETFILTER_XTABLES + help + Packet type matching allows you to match a packet by + its "class", eg. BROADCAST, MULTICAST, ... + + Typical usage: + iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_REALM + tristate '"realm" match support' + depends on NETFILTER_XTABLES + select NET_CLS_ROUTE + help + This option adds a `realm' match, which allows you to use the realm + key from the routing subsystem inside iptables. + + This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option + in tc world. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. If unsure, say `N'. + +config NETFILTER_XT_MATCH_SCTP + tristate '"sctp" protocol match support' + depends on NETFILTER_XTABLES + help + With this option enabled, you will be able to use the + `sctp' match in order to match on SCTP source/destination ports + and SCTP chunk types. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. If unsure, say `N'. + +config NETFILTER_XT_MATCH_STATE + tristate '"state" match support' + depends on NETFILTER_XTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + Connection state matching allows you to match packets based on their + relationship to a tracked connection (ie. previous packets). This + is a powerful tool for packet classification. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_STRING + tristate '"string" match support' + depends on NETFILTER_XTABLES + select TEXTSEARCH + select TEXTSEARCH_KMP + select TEXTSEARCH_BM + select TEXTSEARCH_FSM + help + This option adds a `string' match, which allows you to look for + pattern matchings in packets. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_TCPMSS + tristate '"tcpmss" match support' + depends on NETFILTER_XTABLES + help + This option adds a `tcpmss' match, which allows you to examine the + MSS value of TCP SYN packets, which control the maximum packet size + for that connection. + + To compile it as a module, choose M here. If unsure, say N. + diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index cb21831..746172e 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -1,4 +1,5 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o +nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o obj-$(CONFIG_NETFILTER) = netfilter.o @@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o -nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o - +# connection tracking obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o -obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o # SCTP protocol connection tracking obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o # netlink interface for nf_conntrack obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o + +# connection tracking helpers +obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o + +# generic X tables +obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o + +# targets +obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o +obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o +obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o + +# matches +obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o +obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o +obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o +obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o +obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o +obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o +obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o +obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o +obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o +obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o +obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o +obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o +obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o +obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o +obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 3531d14..617599a 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -821,7 +821,7 @@ module_exit(fini); /* Some modules need us, but don't depend directly on any symbol. They should call this. */ -void need_nf_conntrack(void) +void need_conntrack(void) { } @@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister); EXPORT_SYMBOL(nf_ct_invert_tuplepr); EXPORT_SYMBOL(nf_conntrack_alter_reply); EXPORT_SYMBOL(nf_conntrack_destroyed); -EXPORT_SYMBOL(need_nf_conntrack); +EXPORT_SYMBOL(need_conntrack); EXPORT_SYMBOL(nf_conntrack_helper_register); EXPORT_SYMBOL(nf_conntrack_helper_unregister); EXPORT_SYMBOL(nf_ct_iterate_cleanup); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c new file mode 100644 index 0000000..d7817af --- /dev/null +++ b/net/netfilter/x_tables.c @@ -0,0 +1,624 @@ +/* + * 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/config.h> +#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> + +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter_arp.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); +MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module"); + +#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) + +struct xt_af { + struct semaphore mutex; + struct list_head match; + struct list_head target; + struct list_head tables; +}; + +static struct xt_af *xt; + +#ifdef DEBUG_IP_FIREWALL_USER +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + +enum { + TABLE, + TARGET, + MATCH, +}; + +/* Registration hooks for targets. */ +int +xt_register_target(int af, struct xt_target *target) +{ + int ret; + + ret = down_interruptible(&xt[af].mutex); + if (ret != 0) + return ret; + list_add(&target->list, &xt[af].target); + up(&xt[af].mutex); + return ret; +} +EXPORT_SYMBOL(xt_register_target); + +void +xt_unregister_target(int af, struct xt_target *target) +{ + down(&xt[af].mutex); + LIST_DELETE(&xt[af].target, target); + up(&xt[af].mutex); +} +EXPORT_SYMBOL(xt_unregister_target); + +int +xt_register_match(int af, struct xt_match *match) +{ + int ret; + + ret = down_interruptible(&xt[af].mutex); + if (ret != 0) + return ret; + + list_add(&match->list, &xt[af].match); + up(&xt[af].mutex); + + return ret; +} +EXPORT_SYMBOL(xt_register_match); + +void +xt_unregister_match(int af, struct xt_match *match) +{ + down(&xt[af].mutex); + LIST_DELETE(&xt[af].match, match); + up(&xt[af].mutex); +} +EXPORT_SYMBOL(xt_unregister_match); + + +/* + * 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. */ +struct xt_match *xt_find_match(int af, const char *name, u8 revision) +{ + struct xt_match *m; + int err = 0; + + if (down_interruptible(&xt[af].mutex) != 0) + 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)) { + up(&xt[af].mutex); + return m; + } + } else + err = -EPROTOTYPE; /* Found something. */ + } + } + up(&xt[af].mutex); + return ERR_PTR(err); +} +EXPORT_SYMBOL(xt_find_match); + +/* Find target, grabs ref. Returns ERR_PTR() on error. */ +struct xt_target *xt_find_target(int af, const char *name, u8 revision) +{ + struct xt_target *t; + int err = 0; + + if (down_interruptible(&xt[af].mutex) != 0) + 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)) { + up(&xt[af].mutex); + return t; + } + } else + err = -EPROTOTYPE; /* Found something. */ + } + } + up(&xt[af].mutex); + return ERR_PTR(err); +} +EXPORT_SYMBOL(xt_find_target); + +static const char *xt_prefix[NPROTO] = { + [AF_INET] = "ipt_%s", + [AF_INET6] = "ip6t_%s", + [NF_ARP] = "arpt_%s", +}; + +struct xt_target *xt_request_find_target(int af, const char *name, u8 revision) +{ + struct xt_target *target; + + target = try_then_request_module(xt_find_target(af, name, revision), + xt_prefix[af], name); + if (IS_ERR(target) || !target) + return NULL; + return target; +} +EXPORT_SYMBOL_GPL(xt_request_find_target); + +static int match_revfn(int af, const char *name, u8 revision, int *bestp) +{ + struct xt_match *m; + 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; + } + } + return have_rev; +} + +static int target_revfn(int af, const char *name, u8 revision, int *bestp) +{ + struct xt_target *t; + 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; + } + } + return have_rev; +} + +/* Returns true or false (if no such extension at all) */ +int xt_find_revision(int af, const char *name, u8 revision, int target, + int *err) +{ + int have_rev, best = -1; + + if (down_interruptible(&xt[af].mutex) != 0) { + *err = -EINTR; + return 1; + } + if (target == 1) + have_rev = target_revfn(af, name, revision, &best); + else + have_rev = match_revfn(af, name, revision, &best); + up(&xt[af].mutex); + + /* 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); + +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 */ + if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages) + return NULL; + + newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL); + if (!newinfo) + return NULL; + + newinfo->size = size; + + for_each_cpu(cpu) { + 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; + + for_each_cpu(cpu) { + 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. */ +struct xt_table *xt_find_table_lock(int af, const char *name) +{ + struct xt_table *t; + + if (down_interruptible(&xt[af].mutex) != 0) + return ERR_PTR(-EINTR); + + list_for_each_entry(t, &xt[af].tables, list) + if (strcmp(t->name, name) == 0 && try_module_get(t->me)) + return t; + up(&xt[af].mutex); + return NULL; +} +EXPORT_SYMBOL_GPL(xt_find_table_lock); + +void xt_table_unlock(struct xt_table *table) +{ + up(&xt[table->af].mutex); +} +EXPORT_SYMBOL_GPL(xt_table_unlock); + + +struct xt_table_info * +xt_replace_table(struct xt_table *table, + unsigned int num_counters, + struct xt_table_info *newinfo, + int *error) +{ + struct xt_table_info *oldinfo, *private; + + /* Do the substitution. */ + write_lock_bh(&table->lock); + private = table->private; + /* 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); + write_unlock_bh(&table->lock); + *error = -EAGAIN; + return NULL; + } + oldinfo = private; + table->private = newinfo; + newinfo->initial_entries = oldinfo->initial_entries; + write_unlock_bh(&table->lock); + + return oldinfo; +} +EXPORT_SYMBOL_GPL(xt_replace_table); + +int xt_register_table(struct xt_table *table, + struct xt_table_info *bootstrap, + struct xt_table_info *newinfo) +{ + int ret; + struct xt_table_info *private; + + ret = down_interruptible(&xt[table->af].mutex); + if (ret != 0) + return ret; + + /* Don't autoload: we'd eat our tail... */ + if (list_named_find(&xt[table->af].tables, table->name)) { + ret = -EEXIST; + goto unlock; + } + + /* Simplifies replace_table code. */ + table->private = bootstrap; + 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; + + rwlock_init(&table->lock); + list_prepend(&xt[table->af].tables, table); + + ret = 0; + unlock: + up(&xt[table->af].mutex); + return ret; +} +EXPORT_SYMBOL_GPL(xt_register_table); + +void *xt_unregister_table(struct xt_table *table) +{ + struct xt_table_info *private; + + down(&xt[table->af].mutex); + private = table->private; + LIST_DELETE(&xt[table->af].tables, table); + up(&xt[table->af].mutex); + + return private; +} +EXPORT_SYMBOL_GPL(xt_unregister_table); + +#ifdef CONFIG_PROC_FS +static char *xt_proto_prefix[NPROTO] = { + [AF_INET] = "ip", + [AF_INET6] = "ip6", + [NF_ARP] = "arp", +}; + +static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos) +{ + struct list_head *head = list->next; + + if (!head || list_empty(list)) + return NULL; + + while (pos && (head = head->next)) { + if (head == list) + return NULL; + pos--; + } + return pos ? NULL : head; +} + +static struct list_head *type2list(u_int16_t af, u_int16_t type) +{ + struct list_head *list; + + switch (type) { + case TARGET: + list = &xt[af].target; + break; + case MATCH: + list = &xt[af].match; + break; + case TABLE: + list = &xt[af].tables; + break; + default: + list = NULL; + break; + } + + return list; +} + +static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private; + u_int16_t af = (unsigned long)pde->data & 0xffff; + u_int16_t type = (unsigned long)pde->data >> 16; + struct list_head *list; + + if (af >= NPROTO) + return NULL; + + list = type2list(af, type); + if (!list) + return NULL; + + if (down_interruptible(&xt[af].mutex) != 0) + return NULL; + + return xt_get_idx(list, seq, *pos); +} + +static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct proc_dir_entry *pde = seq->private; + u_int16_t af = (unsigned long)pde->data & 0xffff; + u_int16_t type = (unsigned long)pde->data >> 16; + struct list_head *list; + + if (af >= NPROTO) + return NULL; + + list = type2list(af, type); + if (!list) + return NULL; + + (*pos)++; + return xt_get_idx(list, seq, *pos); +} + +static void xt_tgt_seq_stop(struct seq_file *seq, void *v) +{ + struct proc_dir_entry *pde = seq->private; + u_int16_t af = (unsigned long)pde->data & 0xffff; + + up(&xt[af].mutex); +} + +static int xt_name_seq_show(struct seq_file *seq, void *v) +{ + char *name = (char *)v + sizeof(struct list_head); + + if (strlen(name)) + return seq_printf(seq, "%s\n", name); + else + return 0; +} + +static struct seq_operations xt_tgt_seq_ops = { + .start = xt_tgt_seq_start, + .next = xt_tgt_seq_next, + .stop = xt_tgt_seq_stop, + .show = xt_name_seq_show, +}; + +static int xt_tgt_open(struct inode *inode, struct file *file) +{ + int ret; + + ret = seq_open(file, &xt_tgt_seq_ops); + if (!ret) { + struct seq_file *seq = file->private_data; + struct proc_dir_entry *pde = PDE(inode); + + seq->private = pde; + } + + return ret; +} + +static struct file_operations xt_file_ops = { + .owner = THIS_MODULE, + .open = xt_tgt_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +#define FORMAT_TABLES "_tables_names" +#define FORMAT_MATCHES "_tables_matches" +#define FORMAT_TARGETS "_tables_targets" + +#endif /* CONFIG_PROC_FS */ + +int xt_proto_init(int af) +{ +#ifdef CONFIG_PROC_FS + char buf[XT_FUNCTION_MAXNAMELEN]; + struct proc_dir_entry *proc; +#endif + + if (af >= NPROTO) + return -EINVAL; + + +#ifdef CONFIG_PROC_FS + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TABLES, sizeof(buf)); + proc = proc_net_fops_create(buf, 0440, &xt_file_ops); + if (!proc) + goto out; + proc->data = (void *) ((unsigned long) af | (TABLE << 16)); + + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + proc = proc_net_fops_create(buf, 0440, &xt_file_ops); + if (!proc) + goto out_remove_tables; + proc->data = (void *) ((unsigned long) af | (MATCH << 16)); + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TARGETS, sizeof(buf)); + proc = proc_net_fops_create(buf, 0440, &xt_file_ops); + if (!proc) + goto out_remove_matches; + proc->data = (void *) ((unsigned long) af | (TARGET << 16)); +#endif + + return 0; + +#ifdef CONFIG_PROC_FS +out_remove_matches: + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + proc_net_remove(buf); + +out_remove_tables: + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TABLES, sizeof(buf)); + proc_net_remove(buf); +out: + return -1; +#endif +} +EXPORT_SYMBOL_GPL(xt_proto_init); + +void xt_proto_fini(int af) +{ +#ifdef CONFIG_PROC_FS + char buf[XT_FUNCTION_MAXNAMELEN]; + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TABLES, sizeof(buf)); + proc_net_remove(buf); + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TARGETS, sizeof(buf)); + proc_net_remove(buf); + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + proc_net_remove(buf); +#endif /*CONFIG_PROC_FS*/ +} +EXPORT_SYMBOL_GPL(xt_proto_fini); + + +static int __init xt_init(void) +{ + int i; + + xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL); + if (!xt) + return -ENOMEM; + + for (i = 0; i < NPROTO; i++) { + init_MUTEX(&xt[i].mutex); + INIT_LIST_HEAD(&xt[i].target); + INIT_LIST_HEAD(&xt[i].match); + INIT_LIST_HEAD(&xt[i].tables); + } + return 0; +} + +static void __exit xt_fini(void) +{ + kfree(xt); +} + +module_init(xt_init); +module_exit(xt_fini); + diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index dab78d8..78ee266 100644 --- a/net/ipv4/netfilter/ipt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c @@ -15,12 +15,13 @@ #include <linux/ip.h> #include <net/checksum.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_CLASSIFY.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_CLASSIFY.h> MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("iptables qdisc classification target module"); +MODULE_ALIAS("ipt_CLASSIFY"); static unsigned int target(struct sk_buff **pskb, @@ -30,25 +31,25 @@ target(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_classify_target_info *clinfo = targinfo; + const struct xt_classify_target_info *clinfo = targinfo; - if((*pskb)->priority != clinfo->priority) + if ((*pskb)->priority != clinfo->priority) (*pskb)->priority = clinfo->priority; - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){ + if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){ printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_classify_target_info))); + XT_ALIGN(sizeof(struct xt_classify_target_info))); return 0; } @@ -69,21 +70,39 @@ checkentry(const char *tablename, return 1; } -static struct ipt_target ipt_classify_reg = { +static struct xt_target classify_reg = { + .name = "CLASSIFY", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; +static struct xt_target classify6_reg = { .name = "CLASSIFY", .target = target, .checkentry = checkentry, .me = THIS_MODULE, }; + static int __init init(void) { - return ipt_register_target(&ipt_classify_reg); + int ret; + + ret = xt_register_target(AF_INET, &classify_reg); + if (ret) + return ret; + + ret = xt_register_target(AF_INET6, &classify6_reg); + if (ret) + xt_unregister_target(AF_INET, &classify_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_target(&ipt_classify_reg); + xt_unregister_target(AF_INET, &classify_reg); + xt_unregister_target(AF_INET6, &classify6_reg); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index 8acac5a..22506e3 100644 --- a/net/ipv4/netfilter/ipt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c @@ -26,9 +26,10 @@ MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); MODULE_DESCRIPTION("IP tables CONNMARK matching module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_CONNMARK"); -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_CONNMARK.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_CONNMARK.h> #include <net/netfilter/nf_conntrack_compat.h> static unsigned int @@ -39,7 +40,7 @@ target(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_connmark_target_info *markinfo = targinfo; + const struct xt_connmark_target_info *markinfo = targinfo; u_int32_t diff; u_int32_t nfmark; u_int32_t newmark; @@ -48,17 +49,17 @@ target(struct sk_buff **pskb, if (ctmark) { switch(markinfo->mode) { - case IPT_CONNMARK_SET: + case XT_CONNMARK_SET: newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; if (newmark != *ctmark) *ctmark = newmark; break; - case IPT_CONNMARK_SAVE: + case XT_CONNMARK_SAVE: newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); if (*ctmark != newmark) *ctmark = newmark; break; - case IPT_CONNMARK_RESTORE: + case XT_CONNMARK_RESTORE: nfmark = (*pskb)->nfmark; diff = (*ctmark ^ nfmark) & markinfo->mask; if (diff != 0) @@ -67,25 +68,25 @@ target(struct sk_buff **pskb, } } - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - struct ipt_connmark_target_info *matchinfo = targinfo; - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { + struct xt_connmark_target_info *matchinfo = targinfo; + if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) { printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); + XT_ALIGN(sizeof(struct xt_connmark_target_info))); return 0; } - if (matchinfo->mode == IPT_CONNMARK_RESTORE) { + if (matchinfo->mode == XT_CONNMARK_RESTORE) { if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; @@ -100,7 +101,13 @@ checkentry(const char *tablename, return 1; } -static struct ipt_target ipt_connmark_reg = { +static struct xt_target connmark_reg = { + .name = "CONNMARK", + .target = &target, + .checkentry = &checkentry, + .me = THIS_MODULE +}; +static struct xt_target connmark6_reg = { .name = "CONNMARK", .target = &target, .checkentry = &checkentry, @@ -109,13 +116,25 @@ static struct ipt_target ipt_connmark_reg = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_target(&ipt_connmark_reg); + int ret; + + need_conntrack(); + + ret = xt_register_target(AF_INET, &connmark_reg); + if (ret) + return ret; + + ret = xt_register_target(AF_INET6, &connmark6_reg); + if (ret) + xt_unregister_target(AF_INET, &connmark_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_target(&ipt_connmark_reg); + xt_unregister_target(AF_INET, &connmark_reg); + xt_unregister_target(AF_INET6, &connmark6_reg); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/netfilter/xt_MARK.c index 52b4f2c..0c11ee9 100644 --- a/net/ipv4/netfilter/ipt_MARK.c +++ b/net/netfilter/xt_MARK.c @@ -12,12 +12,14 @@ #include <linux/ip.h> #include <net/checksum.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_MARK.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_MARK.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); -MODULE_DESCRIPTION("iptables MARK modification module"); +MODULE_DESCRIPTION("ip[6]tables MARK modification module"); +MODULE_ALIAS("ipt_MARK"); +MODULE_ALIAS("ip6t_MARK"); static unsigned int target_v0(struct sk_buff **pskb, @@ -27,12 +29,12 @@ target_v0(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_mark_target_info *markinfo = targinfo; + const struct xt_mark_target_info *markinfo = targinfo; if((*pskb)->nfmark != markinfo->mark) (*pskb)->nfmark = markinfo->mark; - return IPT_CONTINUE; + return XT_CONTINUE; } static unsigned int @@ -43,19 +45,19 @@ target_v1(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_mark_target_info_v1 *markinfo = targinfo; + const struct xt_mark_target_info_v1 *markinfo = targinfo; int mark = 0; switch (markinfo->mode) { - case IPT_MARK_SET: + case XT_MARK_SET: mark = markinfo->mark; break; - case IPT_MARK_AND: + case XT_MARK_AND: mark = (*pskb)->nfmark & markinfo->mark; break; - case IPT_MARK_OR: + case XT_MARK_OR: mark = (*pskb)->nfmark | markinfo->mark; break; } @@ -63,23 +65,23 @@ target_v1(struct sk_buff **pskb, if((*pskb)->nfmark != mark) (*pskb)->nfmark = mark; - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry_v0(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - struct ipt_mark_target_info *markinfo = targinfo; + struct xt_mark_target_info *markinfo = targinfo; - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { + if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) { printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_mark_target_info))); + XT_ALIGN(sizeof(struct xt_mark_target_info))); return 0; } @@ -98,17 +100,17 @@ checkentry_v0(const char *tablename, static int checkentry_v1(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - struct ipt_mark_target_info_v1 *markinfo = targinfo; + struct xt_mark_target_info_v1 *markinfo = targinfo; - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){ + if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){ printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))); + XT_ALIGN(sizeof(struct xt_mark_target_info_v1))); return 0; } @@ -117,9 +119,9 @@ checkentry_v1(const char *tablename, return 0; } - if (markinfo->mode != IPT_MARK_SET - && markinfo->mode != IPT_MARK_AND - && markinfo->mode != IPT_MARK_OR) { + if (markinfo->mode != XT_MARK_SET + && markinfo->mode != XT_MARK_AND + && markinfo->mode != XT_MARK_OR) { printk(KERN_WARNING "MARK: unknown mode %u\n", markinfo->mode); return 0; @@ -133,7 +135,7 @@ checkentry_v1(const char *tablename, return 1; } -static struct ipt_target ipt_mark_reg_v0 = { +static struct xt_target ipt_mark_reg_v0 = { .name = "MARK", .target = target_v0, .checkentry = checkentry_v0, @@ -141,7 +143,7 @@ static struct ipt_target ipt_mark_reg_v0 = { .revision = 0, }; -static struct ipt_target ipt_mark_reg_v1 = { +static struct xt_target ipt_mark_reg_v1 = { .name = "MARK", .target = target_v1, .checkentry = checkentry_v1, @@ -149,23 +151,40 @@ static struct ipt_target ipt_mark_reg_v1 = { .revision = 1, }; +static struct xt_target ip6t_mark_reg_v0 = { + .name = "MARK", + .target = target_v0, + .checkentry = checkentry_v0, + .me = THIS_MODULE, + .revision = 0, +}; + static int __init init(void) { int err; - err = ipt_register_target(&ipt_mark_reg_v0); - if (!err) { - err = ipt_register_target(&ipt_mark_reg_v1); - if (err) - ipt_unregister_target(&ipt_mark_reg_v0); + err = xt_register_target(AF_INET, &ipt_mark_reg_v0); + if (err) + return err; + + err = xt_register_target(AF_INET, &ipt_mark_reg_v1); + if (err) + xt_unregister_target(AF_INET, &ipt_mark_reg_v0); + + err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0); + if (err) { + xt_unregister_target(AF_INET, &ipt_mark_reg_v0); + xt_unregister_target(AF_INET, &ipt_mark_reg_v1); } + return err; } static void __exit fini(void) { - ipt_unregister_target(&ipt_mark_reg_v0); - ipt_unregister_target(&ipt_mark_reg_v1); + xt_unregister_target(AF_INET, &ipt_mark_reg_v0); + xt_unregister_target(AF_INET, &ipt_mark_reg_v1); + xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0); } module_init(init); diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c new file mode 100644 index 0000000..8b76b6f --- /dev/null +++ b/net/netfilter/xt_NFQUEUE.c @@ -0,0 +1,107 @@ +/* iptables module for using new netfilter netlink queue + * + * (C) 2005 by Harald Welte <laforge@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/module.h> +#include <linux/skbuff.h> + +#include <linux/netfilter.h> +#include <linux/netfilter_arp.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_NFQUEUE.h> + +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); +MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_NFQUEUE"); +MODULE_ALIAS("ip6t_NFQUEUE"); +MODULE_ALIAS("arpt_NFQUEUE"); + +static unsigned int +target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userinfo) +{ + const struct xt_NFQ_info *tinfo = targinfo; + + return NF_QUEUE_NR(tinfo->queuenum); +} + +static int +checkentry(const char *tablename, + const void *entry, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) { + printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", + targinfosize, + XT_ALIGN(sizeof(struct xt_NFQ_info))); + return 0; + } + + return 1; +} + +static struct xt_target ipt_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static struct xt_target ip6t_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static struct xt_target arpt_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int ret; + ret = xt_register_target(AF_INET, &ipt_NFQ_reg); + if (ret) + return ret; + ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg); + if (ret) + goto out_ip; + ret = xt_register_target(NF_ARP, &arpt_NFQ_reg); + if (ret) + goto out_ip6; + + return ret; +out_ip6: + xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); +out_ip: + xt_unregister_target(AF_INET, &ipt_NFQ_reg); + + return ret; +} + +static void __exit fini(void) +{ + xt_unregister_target(NF_ARP, &arpt_NFQ_reg); + xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); + xt_unregister_target(AF_INET, &ipt_NFQ_reg); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index e3c69d0..24d477a 100644 --- a/net/ipv4/netfilter/ipt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c @@ -4,9 +4,12 @@ #include <linux/module.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter/x_tables.h> #include <net/netfilter/nf_conntrack_compat.h> +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_NOTRACK"); + static unsigned int target(struct sk_buff **pskb, const struct net_device *in, @@ -17,7 +20,7 @@ target(struct sk_buff **pskb, { /* Previously seen (loopback)? Ignore. */ if ((*pskb)->nfct != NULL) - return IPT_CONTINUE; + return XT_CONTINUE; /* Attach fake conntrack entry. If there is a real ct entry correspondig to this packet, @@ -27,12 +30,12 @@ target(struct sk_buff **pskb, (*pskb)->nfctinfo = IP_CT_NEW; nf_conntrack_get((*pskb)->nfct); - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) @@ -51,26 +54,39 @@ checkentry(const char *tablename, return 1; } -static struct ipt_target ipt_notrack_reg = { +static struct xt_target notrack_reg = { .name = "NOTRACK", .target = target, .checkentry = checkentry, - .me = THIS_MODULE + .me = THIS_MODULE, +}; +static struct xt_target notrack6_reg = { + .name = "NOTRACK", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, }; static int __init init(void) { - if (ipt_register_target(&ipt_notrack_reg)) - return -EINVAL; + int ret; + + ret = xt_register_target(AF_INET, ¬rack_reg); + if (ret) + return ret; - return 0; + ret = xt_register_target(AF_INET6, ¬rack6_reg); + if (ret) + xt_unregister_target(AF_INET, ¬rack_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_target(&ipt_notrack_reg); + xt_unregister_target(AF_INET6, ¬rack6_reg); + xt_unregister_target(AF_INET, ¬rack_reg); } module_init(init); module_exit(fini); -MODULE_LICENSE("GPL"); diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/netfilter/xt_comment.c index 6b76a1e..4ba6fd6 100644 --- a/net/ipv4/netfilter/ipt_comment.c +++ b/net/netfilter/xt_comment.c @@ -6,12 +6,14 @@ #include <linux/module.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_comment.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_comment.h> MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); MODULE_DESCRIPTION("iptables comment match module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_comment"); +MODULE_ALIAS("ip6t_comment"); static int match(const struct sk_buff *skb, @@ -19,6 +21,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protooff, int *hotdrop) { /* We always match */ @@ -27,18 +30,25 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { /* Check the size */ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info))) return 0; return 1; } -static struct ipt_match comment_match = { +static struct xt_match comment_match = { + .name = "comment", + .match = match, + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static struct xt_match comment6_match = { .name = "comment", .match = match, .checkentry = checkentry, @@ -47,12 +57,23 @@ static struct ipt_match comment_match = { static int __init init(void) { - return ipt_register_match(&comment_match); + int ret; + + ret = xt_register_match(AF_INET, &comment_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &comment6_match); + if (ret) + xt_unregister_match(AF_INET, &comment_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&comment_match); + xt_unregister_match(AF_INET, &comment_match); + xt_unregister_match(AF_INET6, &comment6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/netfilter/xt_connbytes.c index d68a048..150d2a4 100644 --- a/net/ipv4/netfilter/ipt_connbytes.c +++ b/net/netfilter/xt_connbytes.c @@ -6,13 +6,15 @@ * - add functionality to match number of packets * - add functionality to match average packet size * - add support to match directions seperately + * 2005-10-16 Harald Welte <laforge@netfilter.org> + * - Port to x_tables * */ #include <linux/module.h> #include <linux/skbuff.h> #include <net/netfilter/nf_conntrack_compat.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_connbytes.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_connbytes.h> #include <asm/div64.h> #include <asm/bitops.h> @@ -20,6 +22,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); +MODULE_ALIAS("ipt_connbytes"); /* 64bit divisor, dividend and result. dynamic precision */ static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) @@ -43,9 +46,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_connbytes_info *sinfo = matchinfo; + const struct xt_connbytes_info *sinfo = matchinfo; u_int64_t what = 0; /* initialize to make gcc happy */ const struct ip_conntrack_counter *counters; @@ -53,45 +57,45 @@ match(const struct sk_buff *skb, return 0; /* no match */ switch (sinfo->what) { - case IPT_CONNBYTES_PKTS: + case XT_CONNBYTES_PKTS: switch (sinfo->direction) { - case IPT_CONNBYTES_DIR_ORIGINAL: + case XT_CONNBYTES_DIR_ORIGINAL: what = counters[IP_CT_DIR_ORIGINAL].packets; break; - case IPT_CONNBYTES_DIR_REPLY: + case XT_CONNBYTES_DIR_REPLY: what = counters[IP_CT_DIR_REPLY].packets; break; - case IPT_CONNBYTES_DIR_BOTH: + case XT_CONNBYTES_DIR_BOTH: what = counters[IP_CT_DIR_ORIGINAL].packets; what += counters[IP_CT_DIR_REPLY].packets; break; } break; - case IPT_CONNBYTES_BYTES: + case XT_CONNBYTES_BYTES: switch (sinfo->direction) { - case IPT_CONNBYTES_DIR_ORIGINAL: + case XT_CONNBYTES_DIR_ORIGINAL: what = counters[IP_CT_DIR_ORIGINAL].bytes; break; - case IPT_CONNBYTES_DIR_REPLY: + case XT_CONNBYTES_DIR_REPLY: what = counters[IP_CT_DIR_REPLY].bytes; break; - case IPT_CONNBYTES_DIR_BOTH: + case XT_CONNBYTES_DIR_BOTH: what = counters[IP_CT_DIR_ORIGINAL].bytes; what += counters[IP_CT_DIR_REPLY].bytes; break; } break; - case IPT_CONNBYTES_AVGPKT: + case XT_CONNBYTES_AVGPKT: switch (sinfo->direction) { - case IPT_CONNBYTES_DIR_ORIGINAL: + case XT_CONNBYTES_DIR_ORIGINAL: what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, counters[IP_CT_DIR_ORIGINAL].packets); break; - case IPT_CONNBYTES_DIR_REPLY: + case XT_CONNBYTES_DIR_REPLY: what = div64_64(counters[IP_CT_DIR_REPLY].bytes, counters[IP_CT_DIR_REPLY].packets); break; - case IPT_CONNBYTES_DIR_BOTH: + case XT_CONNBYTES_DIR_BOTH: { u_int64_t bytes; u_int64_t pkts; @@ -117,30 +121,36 @@ match(const struct sk_buff *skb, } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ipt_connbytes_info *sinfo = matchinfo; + const struct xt_connbytes_info *sinfo = matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info))) return 0; - if (sinfo->what != IPT_CONNBYTES_PKTS && - sinfo->what != IPT_CONNBYTES_BYTES && - sinfo->what != IPT_CONNBYTES_AVGPKT) + if (sinfo->what != XT_CONNBYTES_PKTS && + sinfo->what != XT_CONNBYTES_BYTES && + sinfo->what != XT_CONNBYTES_AVGPKT) return 0; - if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL && - sinfo->direction != IPT_CONNBYTES_DIR_REPLY && - sinfo->direction != IPT_CONNBYTES_DIR_BOTH) + if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && + sinfo->direction != XT_CONNBYTES_DIR_REPLY && + sinfo->direction != XT_CONNBYTES_DIR_BOTH) return 0; return 1; } -static struct ipt_match state_match = { +static struct xt_match connbytes_match = { + .name = "connbytes", + .match = &match, + .checkentry = &check, + .me = THIS_MODULE +}; +static struct xt_match connbytes6_match = { .name = "connbytes", .match = &match, .checkentry = &check, @@ -149,12 +159,21 @@ static struct ipt_match state_match = { static int __init init(void) { - return ipt_register_match(&state_match); + int ret; + ret = xt_register_match(AF_INET, &connbytes_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &connbytes6_match); + if (ret) + xt_unregister_match(AF_INET, &connbytes_match); + return ret; } static void __exit fini(void) { - ipt_unregister_match(&state_match); + xt_unregister_match(AF_INET, &connbytes_match); + xt_unregister_match(AF_INET6, &connbytes6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/netfilter/xt_connmark.c index 5306ef2..d06e925 100644 --- a/net/ipv4/netfilter/ipt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -25,9 +25,10 @@ MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); MODULE_DESCRIPTION("IP tables connmark match module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_connmark"); -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_connmark.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_connmark.h> #include <net/netfilter/nf_conntrack_compat.h> static int @@ -36,9 +37,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_connmark_info *info = matchinfo; + const struct xt_connmark_info *info = matchinfo; u_int32_t ctinfo; const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); if (!ctmark) @@ -49,14 +51,14 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_connmark_info *cm = - (struct ipt_connmark_info *)matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info))) + struct xt_connmark_info *cm = + (struct xt_connmark_info *)matchinfo; + if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info))) return 0; if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { @@ -67,21 +69,40 @@ checkentry(const char *tablename, return 1; } -static struct ipt_match connmark_match = { +static struct xt_match connmark_match = { + .name = "connmark", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE +}; +static struct xt_match connmark6_match = { .name = "connmark", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE }; + static int __init init(void) { - return ipt_register_match(&connmark_match); + int ret; + + need_conntrack(); + + ret = xt_register_match(AF_INET, &connmark_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &connmark6_match); + if (ret) + xt_unregister_match(AF_INET, &connmark_match); + return ret; } static void __exit fini(void) { - ipt_unregister_match(&connmark_match); + xt_unregister_match(AF_INET6, &connmark6_match); + xt_unregister_match(AF_INET, &connmark_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/netfilter/xt_conntrack.c index c8d1870..ffdebc9 100644 --- a/net/ipv4/netfilter/ipt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -18,12 +18,13 @@ #include <net/netfilter/nf_conntrack.h> #endif -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_conntrack.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_conntrack.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); MODULE_DESCRIPTION("iptables connection tracking match module"); +MODULE_ALIAS("ipt_conntrack"); #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) @@ -33,9 +34,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_conntrack_info *sinfo = matchinfo; + const struct xt_conntrack_info *sinfo = matchinfo; struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; unsigned int statebit; @@ -45,58 +47,58 @@ match(const struct sk_buff *skb, #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) if (ct == &ip_conntrack_untracked) - statebit = IPT_CONNTRACK_STATE_UNTRACKED; + statebit = XT_CONNTRACK_STATE_UNTRACKED; else if (ct) - statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); + statebit = XT_CONNTRACK_STATE_BIT(ctinfo); else - statebit = IPT_CONNTRACK_STATE_INVALID; + statebit = XT_CONNTRACK_STATE_INVALID; - if(sinfo->flags & IPT_CONNTRACK_STATE) { + if(sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) - statebit |= IPT_CONNTRACK_STATE_SNAT; + statebit |= XT_CONNTRACK_STATE_SNAT; if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) - statebit |= IPT_CONNTRACK_STATE_DNAT; + statebit |= XT_CONNTRACK_STATE_DNAT; } - if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) + if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_PROTO) { - if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) + if(sinfo->flags & XT_CONNTRACK_PROTO) { + if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) + if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) + if(sinfo->flags & XT_CONNTRACK_ORIGDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) + if(sinfo->flags & XT_CONNTRACK_REPLSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) + if(sinfo->flags & XT_CONNTRACK_REPLDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_STATUS) { - if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) + if(sinfo->flags & XT_CONNTRACK_STATUS) { + if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { + if(sinfo->flags & XT_CONNTRACK_EXPIRES) { unsigned long expires; if(!ct) @@ -104,7 +106,7 @@ match(const struct sk_buff *skb, expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; - if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) + if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) return 0; } @@ -118,9 +120,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_conntrack_info *sinfo = matchinfo; + const struct xt_conntrack_info *sinfo = matchinfo; struct nf_conn *ct; enum ip_conntrack_info ctinfo; unsigned int statebit; @@ -130,58 +133,58 @@ match(const struct sk_buff *skb, #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) if (ct == &nf_conntrack_untracked) - statebit = IPT_CONNTRACK_STATE_UNTRACKED; + statebit = XT_CONNTRACK_STATE_UNTRACKED; else if (ct) - statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); + statebit = XT_CONNTRACK_STATE_BIT(ctinfo); else - statebit = IPT_CONNTRACK_STATE_INVALID; + statebit = XT_CONNTRACK_STATE_INVALID; - if(sinfo->flags & IPT_CONNTRACK_STATE) { + if(sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) - statebit |= IPT_CONNTRACK_STATE_SNAT; + statebit |= XT_CONNTRACK_STATE_SNAT; if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) - statebit |= IPT_CONNTRACK_STATE_DNAT; + statebit |= XT_CONNTRACK_STATE_DNAT; } - if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) + if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_PROTO) { - if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) + if(sinfo->flags & XT_CONNTRACK_PROTO) { + if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) + if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) + if(sinfo->flags & XT_CONNTRACK_ORIGDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) + if(sinfo->flags & XT_CONNTRACK_REPLSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) + if(sinfo->flags & XT_CONNTRACK_REPLDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_STATUS) { - if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) + if(sinfo->flags & XT_CONNTRACK_STATUS) { + if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { + if(sinfo->flags & XT_CONNTRACK_EXPIRES) { unsigned long expires; if(!ct) @@ -189,7 +192,7 @@ match(const struct sk_buff *skb, expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; - if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) + if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) return 0; } @@ -199,18 +202,18 @@ match(const struct sk_buff *skb, #endif /* CONFIG_NF_IP_CONNTRACK */ static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info))) return 0; return 1; } -static struct ipt_match conntrack_match = { +static struct xt_match conntrack_match = { .name = "conntrack", .match = &match, .checkentry = &check, @@ -219,13 +222,16 @@ static struct ipt_match conntrack_match = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_match(&conntrack_match); + int ret; + need_conntrack(); + ret = xt_register_match(AF_INET, &conntrack_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&conntrack_match); + xt_unregister_match(AF_INET, &conntrack_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/netfilter/xt_dccp.c index ad3278b..779f42f 100644 --- a/net/ipv4/netfilter/ipt_dccp.c +++ b/net/netfilter/xt_dccp.c @@ -14,8 +14,16 @@ #include <net/ip.h> #include <linux/dccp.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_dccp.h> + #include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_dccp.h> +#include <linux/netfilter_ipv6/ip6_tables.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); +MODULE_DESCRIPTION("Match for DCCP protocol packets"); +MODULE_ALIAS("ipt_dccp"); #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ || (!!((invflag) & (option)) ^ (cond))) @@ -26,6 +34,7 @@ static DEFINE_SPINLOCK(dccp_buflock); static inline int dccp_find_option(u_int8_t option, const struct sk_buff *skb, + unsigned int protoff, const struct dccp_hdr *dh, int *hotdrop) { @@ -44,9 +53,7 @@ dccp_find_option(u_int8_t option, return 0; spin_lock_bh(&dccp_buflock); - op = skb_header_pointer(skb, - skb->nh.iph->ihl*4 + optoff, - optlen, dccp_optbuf); + op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf); if (op == NULL) { /* If we don't have the whole header, drop packet. */ spin_unlock_bh(&dccp_buflock); @@ -78,10 +85,10 @@ match_types(const struct dccp_hdr *dh, u_int16_t typemask) } static inline int -match_option(u_int8_t option, const struct sk_buff *skb, +match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff, const struct dccp_hdr *dh, int *hotdrop) { - return dccp_find_option(option, skb, dh, hotdrop); + return dccp_find_option(option, skb, protoff, dh, hotdrop); } static int @@ -90,16 +97,17 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_dccp_info *info = - (const struct ipt_dccp_info *)matchinfo; + const struct xt_dccp_info *info = + (const struct xt_dccp_info *)matchinfo; struct dccp_hdr _dh, *dh; if (offset) return 0; - dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh); + dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh); if (dh == NULL) { *hotdrop = 1; return 0; @@ -107,42 +115,73 @@ match(const struct sk_buff *skb, return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) && (ntohs(dh->dccph_sport) <= info->spts[1])), - IPT_DCCP_SRC_PORTS, info->flags, info->invflags) + XT_DCCP_SRC_PORTS, info->flags, info->invflags) && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) && (ntohs(dh->dccph_dport) <= info->dpts[1])), - IPT_DCCP_DEST_PORTS, info->flags, info->invflags) + XT_DCCP_DEST_PORTS, info->flags, info->invflags) && DCCHECK(match_types(dh, info->typemask), - IPT_DCCP_TYPE, info->flags, info->invflags) - && DCCHECK(match_option(info->option, skb, dh, hotdrop), - IPT_DCCP_OPTION, info->flags, info->invflags); + XT_DCCP_TYPE, info->flags, info->invflags) + && DCCHECK(match_option(info->option, skb, protoff, dh, + hotdrop), + XT_DCCP_OPTION, info->flags, info->invflags); } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ipt_dccp_info *info; + const struct ipt_ip *ip = inf; + const struct xt_dccp_info *info; - info = (const struct ipt_dccp_info *)matchinfo; + info = (const struct xt_dccp_info *)matchinfo; return ip->proto == IPPROTO_DCCP - && !(ip->invflags & IPT_INV_PROTO) - && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info)) - && !(info->flags & ~IPT_DCCP_VALID_FLAGS) - && !(info->invflags & ~IPT_DCCP_VALID_FLAGS) + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) + && !(info->flags & ~XT_DCCP_VALID_FLAGS) + && !(info->invflags & ~XT_DCCP_VALID_FLAGS) && !(info->invflags & ~info->flags); } -static struct ipt_match dccp_match = +static int +checkentry6(const char *tablename, + const void *inf, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ip = inf; + const struct xt_dccp_info *info; + + info = (const struct xt_dccp_info *)matchinfo; + + return ip->proto == IPPROTO_DCCP + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) + && !(info->flags & ~XT_DCCP_VALID_FLAGS) + && !(info->invflags & ~XT_DCCP_VALID_FLAGS) + && !(info->invflags & ~info->flags); +} + + +static struct xt_match dccp_match = { .name = "dccp", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE, }; +static struct xt_match dccp6_match = +{ + .name = "dccp", + .match = &match, + .checkentry = &checkentry6, + .me = THIS_MODULE, +}; + static int __init init(void) { @@ -154,23 +193,29 @@ static int __init init(void) dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); if (!dccp_optbuf) return -ENOMEM; - ret = ipt_register_match(&dccp_match); + ret = xt_register_match(AF_INET, &dccp_match); if (ret) - kfree(dccp_optbuf); + goto out_kfree; + ret = xt_register_match(AF_INET6, &dccp6_match); + if (ret) + goto out_unreg; + + return ret; + +out_unreg: + xt_unregister_match(AF_INET, &dccp_match); +out_kfree: + kfree(dccp_optbuf); return ret; } static void __exit fini(void) { - ipt_unregister_match(&dccp_match); + xt_unregister_match(AF_INET6, &dccp6_match); + xt_unregister_match(AF_INET, &dccp_match); kfree(dccp_optbuf); } module_init(init); module_exit(fini); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); -MODULE_DESCRIPTION("Match for DCCP protocol packets"); - diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/netfilter/xt_helper.c index aef649e..38b6715 100644 --- a/net/ipv4/netfilter/ipt_helper.c +++ b/net/netfilter/xt_helper.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/netfilter.h> -#include <linux/interrupt.h> #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) #include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h> @@ -23,12 +22,14 @@ #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_helper.h> #endif -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_helper.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_helper.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); MODULE_DESCRIPTION("iptables helper match module"); +MODULE_ALIAS("ipt_helper"); +MODULE_ALIAS("ip6t_helper"); #if 0 #define DEBUGP printk @@ -43,27 +44,28 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_helper_info *info = matchinfo; + const struct xt_helper_info *info = matchinfo; struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; int ret = info->invert; ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); if (!ct) { - DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); + DEBUGP("xt_helper: Eek! invalid conntrack?\n"); return ret; } if (!ct->master) { - DEBUGP("ipt_helper: conntrack %p has no master\n", ct); + DEBUGP("xt_helper: conntrack %p has no master\n", ct); return ret; } read_lock_bh(&ip_conntrack_lock); if (!ct->master->helper) { - DEBUGP("ipt_helper: master ct %p has no helper\n", + DEBUGP("xt_helper: master ct %p has no helper\n", exp->expectant); goto out_unlock; } @@ -89,27 +91,28 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_helper_info *info = matchinfo; + const struct xt_helper_info *info = matchinfo; struct nf_conn *ct; enum ip_conntrack_info ctinfo; int ret = info->invert; ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); if (!ct) { - DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); + DEBUGP("xt_helper: Eek! invalid conntrack?\n"); return ret; } if (!ct->master) { - DEBUGP("ipt_helper: conntrack %p has no master\n", ct); + DEBUGP("xt_helper: conntrack %p has no master\n", ct); return ret; } read_lock_bh(&nf_conntrack_lock); if (!ct->master->helper) { - DEBUGP("ipt_helper: master ct %p has no helper\n", + DEBUGP("xt_helper: master ct %p has no helper\n", exp->expectant); goto out_unlock; } @@ -129,23 +132,29 @@ out_unlock: #endif static int check(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_helper_info *info = matchinfo; + struct xt_helper_info *info = matchinfo; info->name[29] = '\0'; /* verify size */ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info))) return 0; return 1; } -static struct ipt_match helper_match = { +static struct xt_match helper_match = { + .name = "helper", + .match = &match, + .checkentry = &check, + .me = THIS_MODULE, +}; +static struct xt_match helper6_match = { .name = "helper", .match = &match, .checkentry = &check, @@ -154,13 +163,24 @@ static struct ipt_match helper_match = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_match(&helper_match); + int ret; + need_conntrack(); + + ret = xt_register_match(AF_INET, &helper_match); + if (ret < 0) + return ret; + + ret = xt_register_match(AF_INET6, &helper6_match); + if (ret < 0) + xt_unregister_match(AF_INET, &helper_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&helper_match); + xt_unregister_match(AF_INET, &helper_match); + xt_unregister_match(AF_INET6, &helper6_match); } module_init(init); diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c new file mode 100644 index 0000000..ab6c710 --- /dev/null +++ b/net/netfilter/xt_length.c @@ -0,0 +1,98 @@ +/* Kernel module to match packet length. */ +/* (C) 1999-2001 James Morris <jmorros@intercode.com.au> + * + * 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/module.h> +#include <linux/skbuff.h> +#include <net/ip.h> + +#include <linux/netfilter/xt_length.h> +#include <linux/netfilter/x_tables.h> + +MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); +MODULE_DESCRIPTION("IP tables packet length matching module"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_length"); +MODULE_ALIAS("ip6t_length"); + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + const struct xt_length_info *info = matchinfo; + u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); + + return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; +} + +static int +match6(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + const struct xt_length_info *info = matchinfo; + u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); + + return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; +} + +static int +checkentry(const char *tablename, + const void *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != XT_ALIGN(sizeof(struct xt_length_info))) + return 0; + + return 1; +} + +static struct xt_match length_match = { + .name = "length", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; +static struct xt_match length6_match = { + .name = "length", + .match = &match6, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int ret; + ret = xt_register_match(AF_INET, &length_match); + if (ret) + return ret; + ret = xt_register_match(AF_INET6, &length6_match); + if (ret) + xt_unregister_match(AF_INET, &length_match); + + return ret; +} + +static void __exit fini(void) +{ + xt_unregister_match(AF_INET, &length_match); + xt_unregister_match(AF_INET6, &length6_match); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/netfilter/xt_limit.c index 0c24dcc..15e4050 100644 --- a/net/ipv4/netfilter/ipt_limit.c +++ b/net/netfilter/xt_limit.c @@ -18,12 +18,14 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_limit.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_limit.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); MODULE_DESCRIPTION("iptables rate limit match"); +MODULE_ALIAS("ipt_limit"); +MODULE_ALIAS("ip6t_limit"); /* The algorithm used is the Simple Token Bucket Filter (TBF) * see net/sched/sch_tbf.c in the linux source tree @@ -68,9 +70,10 @@ ipt_limit_match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master; + struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master; unsigned long now = jiffies; spin_lock_bh(&limit_lock); @@ -96,32 +99,32 @@ user2credits(u_int32_t user) /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) /* Divide first. */ - return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; + return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; - return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE; + return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; } static int ipt_limit_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_rateinfo *r = matchinfo; + struct xt_rateinfo *r = matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo))) + if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo))) return 0; /* Check for overflow. */ if (r->burst == 0 || user2credits(r->avg * r->burst) < user2credits(r->avg)) { - printk("Overflow in ipt_limit, try lower: %u/%u\n", + printk("Overflow in xt_limit, try lower: %u/%u\n", r->avg, r->burst); return 0; } - /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies * + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * 128. */ r->prev = jiffies; r->credit = user2credits(r->avg * r->burst); /* Credits full. */ @@ -134,7 +137,13 @@ ipt_limit_checkentry(const char *tablename, return 1; } -static struct ipt_match ipt_limit_reg = { +static struct xt_match ipt_limit_reg = { + .name = "limit", + .match = ipt_limit_match, + .checkentry = ipt_limit_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match limit6_reg = { .name = "limit", .match = ipt_limit_match, .checkentry = ipt_limit_checkentry, @@ -143,14 +152,23 @@ static struct ipt_match ipt_limit_reg = { static int __init init(void) { - if (ipt_register_match(&ipt_limit_reg)) - return -EINVAL; - return 0; + int ret; + + ret = xt_register_match(AF_INET, &ipt_limit_reg); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &limit6_reg); + if (ret) + xt_unregister_match(AF_INET, &ipt_limit_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&ipt_limit_reg); + xt_unregister_match(AF_INET, &ipt_limit_reg); + xt_unregister_match(AF_INET6, &limit6_reg); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/netfilter/xt_mac.c index 1b9bb45..0461dcb 100644 --- a/net/ipv4/netfilter/ipt_mac.c +++ b/net/netfilter/xt_mac.c @@ -13,12 +13,15 @@ #include <linux/if_ether.h> #include <linux/etherdevice.h> -#include <linux/netfilter_ipv4/ipt_mac.h> -#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4.h> +#include <linux/netfilter/xt_mac.h> +#include <linux/netfilter/x_tables.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); MODULE_DESCRIPTION("iptables mac matching module"); +MODULE_ALIAS("ipt_mac"); +MODULE_ALIAS("ip6t_mac"); static int match(const struct sk_buff *skb, @@ -26,9 +29,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_mac_info *info = matchinfo; + const struct xt_mac_info *info = matchinfo; /* Is mac pointer valid? */ return (skb->mac.raw >= skb->head @@ -40,7 +44,7 @@ match(const struct sk_buff *skb, static int ipt_mac_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) @@ -49,17 +53,23 @@ ipt_mac_checkentry(const char *tablename, if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD))) { - printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); + printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); return 0; } - if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info))) return 0; return 1; } -static struct ipt_match mac_match = { +static struct xt_match mac_match = { + .name = "mac", + .match = &match, + .checkentry = &ipt_mac_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match mac6_match = { .name = "mac", .match = &match, .checkentry = &ipt_mac_checkentry, @@ -68,12 +78,22 @@ static struct ipt_match mac_match = { static int __init init(void) { - return ipt_register_match(&mac_match); + int ret; + ret = xt_register_match(AF_INET, &mac_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &mac6_match); + if (ret) + xt_unregister_match(AF_INET, &mac_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&mac_match); + xt_unregister_match(AF_INET, &mac_match); + xt_unregister_match(AF_INET6, &mac6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/netfilter/xt_mark.c index 00bef6c..2a0ac62 100644 --- a/net/ipv4/netfilter/ipt_mark.c +++ b/net/netfilter/xt_mark.c @@ -10,12 +10,14 @@ #include <linux/module.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ipt_mark.h> -#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter/xt_mark.h> +#include <linux/netfilter/x_tables.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); MODULE_DESCRIPTION("iptables mark matching module"); +MODULE_ALIAS("ipt_mark"); +MODULE_ALIAS("ip6t_mark"); static int match(const struct sk_buff *skb, @@ -23,23 +25,24 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_mark_info *info = matchinfo; + const struct xt_mark_info *info = matchinfo; return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *entry, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo; + struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info))) return 0; if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { @@ -50,7 +53,14 @@ checkentry(const char *tablename, return 1; } -static struct ipt_match mark_match = { +static struct xt_match mark_match = { + .name = "mark", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match mark6_match = { .name = "mark", .match = &match, .checkentry = &checkentry, @@ -59,12 +69,22 @@ static struct ipt_match mark_match = { static int __init init(void) { - return ipt_register_match(&mark_match); + int ret; + ret = xt_register_match(AF_INET, &mark_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &mark6_match); + if (ret) + xt_unregister_match(AF_INET, &mark_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&mark_match); + xt_unregister_match(AF_INET, &mark_match); + xt_unregister_match(AF_INET6, &mark6_match); } module_init(init); diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/netfilter/xt_physdev.c index 71515c8..19bb57c 100644 --- a/net/ipv6/netfilter/ip6t_physdev.c +++ b/net/netfilter/xt_physdev.c @@ -10,8 +10,8 @@ #include <linux/module.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv6/ip6t_physdev.h> -#include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/netfilter/xt_physdev.h> +#include <linux/netfilter/x_tables.h> #include <linux/netfilter_bridge.h> #define MATCH 1 #define NOMATCH 0 @@ -19,6 +19,8 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); MODULE_DESCRIPTION("iptables bridge physical device match module"); +MODULE_ALIAS("ipt_physdev"); +MODULE_ALIAS("ip6t_physdev"); static int match(const struct sk_buff *skb, @@ -31,7 +33,7 @@ match(const struct sk_buff *skb, { int i; static const char nulldevname[IFNAMSIZ]; - const struct ip6t_physdev_info *info = matchinfo; + const struct xt_physdev_info *info = matchinfo; unsigned int ret; const char *indev, *outdev; struct nf_bridge_info *nf_bridge; @@ -41,37 +43,37 @@ match(const struct sk_buff *skb, * the destination device will be a bridge. */ if (!(nf_bridge = skb->nf_bridge)) { /* Return MATCH if the invert flags of the used options are on */ - if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && - !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)) + if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && + !(info->invert & XT_PHYSDEV_OP_BRIDGED)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) && - !(info->invert & IP6T_PHYSDEV_OP_ISIN)) + if ((info->bitmask & XT_PHYSDEV_OP_ISIN) && + !(info->invert & XT_PHYSDEV_OP_ISIN)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) && - !(info->invert & IP6T_PHYSDEV_OP_ISOUT)) + if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) && + !(info->invert & XT_PHYSDEV_OP_ISOUT)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_IN) && - !(info->invert & IP6T_PHYSDEV_OP_IN)) + if ((info->bitmask & XT_PHYSDEV_OP_IN) && + !(info->invert & XT_PHYSDEV_OP_IN)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) && - !(info->invert & IP6T_PHYSDEV_OP_OUT)) + if ((info->bitmask & XT_PHYSDEV_OP_OUT) && + !(info->invert & XT_PHYSDEV_OP_OUT)) return NOMATCH; return MATCH; } /* This only makes sense in the FORWARD and POSTROUTING chains */ - if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && + if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && (!!(nf_bridge->mask & BRNF_BRIDGED) ^ - !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))) + !(info->invert & XT_PHYSDEV_OP_BRIDGED))) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN && - (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) || - (info->bitmask & IP6T_PHYSDEV_OP_ISOUT && - (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT)))) + if ((info->bitmask & XT_PHYSDEV_OP_ISIN && + (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) || + (info->bitmask & XT_PHYSDEV_OP_ISOUT && + (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT)))) return NOMATCH; - if (!(info->bitmask & IP6T_PHYSDEV_OP_IN)) + if (!(info->bitmask & XT_PHYSDEV_OP_IN)) goto match_outdev; indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { @@ -80,11 +82,11 @@ match(const struct sk_buff *skb, & ((const unsigned int *)info->in_mask)[i]; } - if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN)) + if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN)) return NOMATCH; match_outdev: - if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT)) + if (!(info->bitmask & XT_PHYSDEV_OP_OUT)) return MATCH; outdev = nf_bridge->physoutdev ? nf_bridge->physoutdev->name : nulldevname; @@ -94,27 +96,34 @@ match_outdev: & ((const unsigned int *)info->out_mask)[i]; } - return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT); + return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT); } static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ip6t_physdev_info *info = matchinfo; + const struct xt_physdev_info *info = matchinfo; - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info))) return 0; - if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) || - info->bitmask & ~IP6T_PHYSDEV_OP_MASK) + if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || + info->bitmask & ~XT_PHYSDEV_OP_MASK) return 0; return 1; } -static struct ip6t_match physdev_match = { +static struct xt_match physdev_match = { + .name = "physdev", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match physdev6_match = { .name = "physdev", .match = &match, .checkentry = &checkentry, @@ -123,12 +132,23 @@ static struct ip6t_match physdev_match = { static int __init init(void) { - return ip6t_register_match(&physdev_match); + int ret; + + ret = xt_register_match(AF_INET, &physdev_match); + if (ret < 0) + return ret; + + ret = xt_register_match(AF_INET6, &physdev6_match); + if (ret < 0) + xt_unregister_match(AF_INET, &physdev_match); + + return ret; } static void __exit fini(void) { - ip6t_unregister_match(&physdev_match); + xt_unregister_match(AF_INET, &physdev_match); + xt_unregister_match(AF_INET6, &physdev6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_pkttype.c b/net/netfilter/xt_pkttype.c index 8ddb1dc..ab1b263 100644 --- a/net/ipv4/netfilter/ipt_pkttype.c +++ b/net/netfilter/xt_pkttype.c @@ -10,60 +10,72 @@ #include <linux/if_ether.h> #include <linux/if_packet.h> -#include <linux/netfilter_ipv4/ipt_pkttype.h> -#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter/xt_pkttype.h> +#include <linux/netfilter/x_tables.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); +MODULE_ALIAS("ipt_pkttype"); +MODULE_ALIAS("ip6t_pkttype"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_pkttype_info *info = matchinfo; + const struct xt_pkttype_info *info = matchinfo; - return (skb->pkt_type == info->pkttype) ^ info->invert; + return (skb->pkt_type == info->pkttype) ^ info->invert; } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { -/* - if (hook_mask - & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) - | (1 << NF_IP_FORWARD))) { - printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); - return 0; - } -*/ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info))) return 0; return 1; } -static struct ipt_match pkttype_match = { +static struct xt_match pkttype_match = { .name = "pkttype", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE, }; +static struct xt_match pkttype6_match = { + .name = "pkttype", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + static int __init init(void) { - return ipt_register_match(&pkttype_match); + int ret; + ret = xt_register_match(AF_INET, &pkttype_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &pkttype6_match); + if (ret) + xt_unregister_match(AF_INET, &pkttype_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&pkttype_match); + xt_unregister_match(AF_INET, &pkttype_match); + xt_unregister_match(AF_INET6, &pkttype6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/netfilter/xt_realm.c index 54a6897..2b7e178 100644 --- a/net/ipv4/netfilter/ipt_realm.c +++ b/net/netfilter/xt_realm.c @@ -14,12 +14,14 @@ #include <linux/netdevice.h> #include <net/route.h> -#include <linux/netfilter_ipv4/ipt_realm.h> -#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4.h> +#include <linux/netfilter/xt_realm.h> +#include <linux/netfilter/x_tables.h> MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("iptables realm match"); +MODULE_DESCRIPTION("X_tables realm match"); +MODULE_ALIAS("ipt_realm"); static int match(const struct sk_buff *skb, @@ -27,16 +29,17 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_realm_info *info = matchinfo; + const struct xt_realm_info *info = matchinfo; struct dst_entry *dst = skb->dst; return (info->id == (dst->tclassid & info->mask)) ^ info->invert; } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) @@ -44,18 +47,18 @@ static int check(const char *tablename, if (hook_mask & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { - printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " + printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, " "LOCAL_IN or FORWARD.\n"); return 0; } - if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { - printk("ipt_realm: invalid matchsize.\n"); + if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) { + printk("xt_realm: invalid matchsize.\n"); return 0; } return 1; } -static struct ipt_match realm_match = { +static struct xt_match realm_match = { .name = "realm", .match = match, .checkentry = check, @@ -64,12 +67,12 @@ static struct ipt_match realm_match = { static int __init init(void) { - return ipt_register_match(&realm_match); + return xt_register_match(AF_INET, &realm_match); } static void __exit fini(void) { - ipt_unregister_match(&realm_match); + xt_unregister_match(AF_INET, &realm_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/netfilter/xt_sctp.c index fe2b327..10fbfc5 100644 --- a/net/ipv4/netfilter/ipt_sctp.c +++ b/net/netfilter/xt_sctp.c @@ -1,10 +1,18 @@ #include <linux/module.h> #include <linux/skbuff.h> #include <net/ip.h> +#include <net/ipv6.h> #include <linux/sctp.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_sctp.h> #include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_sctp.h> +#include <linux/netfilter_ipv6/ip6_tables.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kiran Kumar Immidi"); +MODULE_DESCRIPTION("Match for SCTP protocol packets"); +MODULE_ALIAS("ipt_sctp"); #ifdef DEBUG_SCTP #define duprintf(format, args...) printk(format , ## args) @@ -16,7 +24,7 @@ || (!!((invflag) & (option)) ^ (cond))) static int -match_flags(const struct ipt_sctp_flag_info *flag_info, +match_flags(const struct xt_sctp_flag_info *flag_info, const int flag_count, u_int8_t chunktype, u_int8_t chunkflags) @@ -32,15 +40,15 @@ match_flags(const struct ipt_sctp_flag_info *flag_info, return 1; } -static int +static inline int match_packet(const struct sk_buff *skb, + unsigned int offset, const u_int32_t *chunkmap, int chunk_match_type, - const struct ipt_sctp_flag_info *flag_info, + const struct xt_sctp_flag_info *flag_info, const int flag_count, int *hotdrop) { - int offset; u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; sctp_chunkhdr_t _sch, *sch; @@ -52,7 +60,6 @@ match_packet(const struct sk_buff *skb, SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); } - offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t); do { sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); if (sch == NULL) { @@ -118,19 +125,20 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_sctp_info *info; + const struct xt_sctp_info *info; sctp_sctphdr_t _sh, *sh; - info = (const struct ipt_sctp_info *)matchinfo; + info = (const struct xt_sctp_info *)matchinfo; if (offset) { duprintf("Dropping non-first fragment.. FIXME\n"); return 0; } - sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh); + sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh); if (sh == NULL) { duprintf("Dropping evil TCP offset=0 tinygram.\n"); *hotdrop = 1; @@ -140,64 +148,103 @@ match(const struct sk_buff *skb, return SCCHECK(((ntohs(sh->source) >= info->spts[0]) && (ntohs(sh->source) <= info->spts[1])), - IPT_SCTP_SRC_PORTS, info->flags, info->invflags) + XT_SCTP_SRC_PORTS, info->flags, info->invflags) && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) && (ntohs(sh->dest) <= info->dpts[1])), - IPT_SCTP_DEST_PORTS, info->flags, info->invflags) - && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type, + XT_SCTP_DEST_PORTS, info->flags, info->invflags) + && SCCHECK(match_packet(skb, protoff, + info->chunkmap, info->chunk_match_type, info->flag_info, info->flag_count, hotdrop), - IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags); + XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct xt_sctp_info *info; + const struct ipt_ip *ip = inf; + + info = (const struct xt_sctp_info *)matchinfo; + + return ip->proto == IPPROTO_SCTP + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) + && !(info->flags & ~XT_SCTP_VALID_FLAGS) + && !(info->invflags & ~XT_SCTP_VALID_FLAGS) + && !(info->invflags & ~info->flags) + && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || + (info->chunk_match_type & + (SCTP_CHUNK_MATCH_ALL + | SCTP_CHUNK_MATCH_ANY + | SCTP_CHUNK_MATCH_ONLY))); +} + +static int +checkentry6(const char *tablename, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ipt_sctp_info *info; + const struct xt_sctp_info *info; + const struct ip6t_ip6 *ip = inf; - info = (const struct ipt_sctp_info *)matchinfo; + info = (const struct xt_sctp_info *)matchinfo; return ip->proto == IPPROTO_SCTP - && !(ip->invflags & IPT_INV_PROTO) - && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info)) - && !(info->flags & ~IPT_SCTP_VALID_FLAGS) - && !(info->invflags & ~IPT_SCTP_VALID_FLAGS) + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) + && !(info->flags & ~XT_SCTP_VALID_FLAGS) + && !(info->invflags & ~XT_SCTP_VALID_FLAGS) && !(info->invflags & ~info->flags) - && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || + && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || (info->chunk_match_type & (SCTP_CHUNK_MATCH_ALL | SCTP_CHUNK_MATCH_ANY | SCTP_CHUNK_MATCH_ONLY))); } -static struct ipt_match sctp_match = + +static struct xt_match sctp_match = { - .list = { NULL, NULL}, .name = "sctp", .match = &match, .checkentry = &checkentry, - .destroy = NULL, + .me = THIS_MODULE +}; +static struct xt_match sctp6_match = +{ + .name = "sctp", + .match = &match, + .checkentry = &checkentry6, .me = THIS_MODULE }; + static int __init init(void) { - return ipt_register_match(&sctp_match); + int ret; + ret = xt_register_match(AF_INET, &sctp_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &sctp6_match); + if (ret) + xt_unregister_match(AF_INET, &sctp_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&sctp_match); + xt_unregister_match(AF_INET6, &sctp6_match); + xt_unregister_match(AF_INET, &sctp_match); } module_init(init); module_exit(fini); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kiran Kumar Immidi"); -MODULE_DESCRIPTION("Match for SCTP protocol packets"); - diff --git a/net/ipv4/netfilter/ipt_state.c b/net/netfilter/xt_state.c index 4d7f16b..39ce808 100644 --- a/net/ipv4/netfilter/ipt_state.c +++ b/net/netfilter/xt_state.c @@ -1,7 +1,7 @@ /* Kernel module to match connection tracking information. */ /* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> + * (C) 2002-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 @@ -11,12 +11,14 @@ #include <linux/module.h> #include <linux/skbuff.h> #include <net/netfilter/nf_conntrack_compat.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_state.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_state.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); -MODULE_DESCRIPTION("iptables connection tracking state match module"); +MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module"); +MODULE_ALIAS("ipt_state"); +MODULE_ALIAS("ip6t_state"); static int match(const struct sk_buff *skb, @@ -24,35 +26,43 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_state_info *sinfo = matchinfo; + const struct xt_state_info *sinfo = matchinfo; enum ip_conntrack_info ctinfo; unsigned int statebit; if (nf_ct_is_untracked(skb)) - statebit = IPT_STATE_UNTRACKED; + statebit = XT_STATE_UNTRACKED; else if (!nf_ct_get_ctinfo(skb, &ctinfo)) - statebit = IPT_STATE_INVALID; + statebit = XT_STATE_INVALID; else - statebit = IPT_STATE_BIT(ctinfo); + statebit = XT_STATE_BIT(ctinfo); return (sinfo->statemask & statebit); } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_state_info))) return 0; return 1; } -static struct ipt_match state_match = { +static struct xt_match state_match = { + .name = "state", + .match = &match, + .checkentry = &check, + .me = THIS_MODULE, +}; + +static struct xt_match state6_match = { .name = "state", .match = &match, .checkentry = &check, @@ -61,13 +71,25 @@ static struct ipt_match state_match = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_match(&state_match); + int ret; + + need_conntrack(); + + ret = xt_register_match(AF_INET, &state_match); + if (ret < 0) + return ret; + + ret = xt_register_match(AF_INET6, &state6_match); + if (ret < 0) + xt_unregister_match(AF_INET,&state_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&state_match); + xt_unregister_match(AF_INET, &state_match); + xt_unregister_match(AF_INET6, &state6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_string.c b/net/netfilter/xt_string.c index b5def20..7c7d5c8 100644 --- a/net/ipv4/netfilter/ipt_string.c +++ b/net/netfilter/xt_string.c @@ -11,23 +11,26 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_string.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_string.h> #include <linux/textsearch.h> MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); MODULE_DESCRIPTION("IP tables string match module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_string"); +MODULE_ALIAS("ip6t_string"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ts_state state; - struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo; + struct xt_string_info *conf = (struct xt_string_info *) matchinfo; memset(&state, 0, sizeof(struct ts_state)); @@ -36,18 +39,18 @@ static int match(const struct sk_buff *skb, != UINT_MAX) && !conf->invert; } -#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m) +#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_string_info *conf = matchinfo; + struct xt_string_info *conf = matchinfo; struct ts_config *ts_conf; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_string_info))) return 0; /* Damn, can't handle this case properly with iptables... */ @@ -69,7 +72,14 @@ static void destroy(void *matchinfo, unsigned int matchsize) textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); } -static struct ipt_match string_match = { +static struct xt_match string_match = { + .name = "string", + .match = match, + .checkentry = checkentry, + .destroy = destroy, + .me = THIS_MODULE +}; +static struct xt_match string6_match = { .name = "string", .match = match, .checkentry = checkentry, @@ -79,12 +89,22 @@ static struct ipt_match string_match = { static int __init init(void) { - return ipt_register_match(&string_match); + int ret; + + ret = xt_register_match(AF_INET, &string_match); + if (ret) + return ret; + ret = xt_register_match(AF_INET6, &string6_match); + if (ret) + xt_unregister_match(AF_INET, &string_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&string_match); + xt_unregister_match(AF_INET, &string_match); + xt_unregister_match(AF_INET6, &string6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/netfilter/xt_tcpmss.c index 4dc9b16..acf7f53 100644 --- a/net/ipv4/netfilter/ipt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c @@ -1,6 +1,7 @@ /* Kernel module to match TCP MSS values. */ /* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> + * Portions (C) 2005 by Harald Welte <laforge@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 @@ -11,19 +12,24 @@ #include <linux/skbuff.h> #include <net/tcp.h> -#include <linux/netfilter_ipv4/ipt_tcpmss.h> +#include <linux/netfilter/xt_tcpmss.h> +#include <linux/netfilter/x_tables.h> + #include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv6/ip6_tables.h> #define TH_SYN 0x02 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); MODULE_DESCRIPTION("iptables TCP MSS match module"); +MODULE_ALIAS("ipt_tcpmss"); /* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ static inline int mssoption_match(u_int16_t min, u_int16_t max, const struct sk_buff *skb, + unsigned int protoff, int invert, int *hotdrop) { @@ -33,8 +39,7 @@ mssoption_match(u_int16_t min, u_int16_t max, unsigned int i, optlen; /* If we don't have the whole header, drop packet. */ - th = skb_header_pointer(skb, skb->nh.iph->ihl * 4, - sizeof(_tcph), &_tcph); + th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); if (th == NULL) goto dropit; @@ -47,8 +52,7 @@ mssoption_match(u_int16_t min, u_int16_t max, goto out; /* Truncated options. */ - op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th), - optlen, _opt); + op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt); if (op == NULL) goto dropit; @@ -79,22 +83,24 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_tcpmss_match_info *info = matchinfo; + const struct xt_tcpmss_match_info *info = matchinfo; - return mssoption_match(info->mss_min, info->mss_max, skb, + return mssoption_match(info->mss_min, info->mss_max, skb, protoff, info->invert, hotdrop); } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ipinfo, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info))) + const struct ipt_ip *ip = ipinfo; + if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) return 0; /* Must specify -p tcp */ @@ -106,21 +112,60 @@ checkentry(const char *tablename, return 1; } -static struct ipt_match tcpmss_match = { +static int +checkentry6(const char *tablename, + const void *ipinfo, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ip = ipinfo; + + if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) + return 0; + + /* Must specify -p tcp */ + if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) { + printk("tcpmss: Only works on TCP packets\n"); + return 0; + } + + return 1; +} + +static struct xt_match tcpmss_match = { .name = "tcpmss", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE, }; +static struct xt_match tcpmss6_match = { + .name = "tcpmss", + .match = &match, + .checkentry = &checkentry6, + .me = THIS_MODULE, +}; + + static int __init init(void) { - return ipt_register_match(&tcpmss_match); + int ret; + ret = xt_register_match(AF_INET, &tcpmss_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &tcpmss6_match); + if (ret) + xt_unregister_match(AF_INET, &tcpmss_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&tcpmss_match); + xt_unregister_match(AF_INET6, &tcpmss6_match); + xt_unregister_match(AF_INET, &tcpmss_match); } module_init(init); diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c new file mode 100644 index 0000000..33f86fd --- /dev/null +++ b/net/netfilter/xt_tcpudp.c @@ -0,0 +1,333 @@ +#include <linux/types.h> +#include <linux/module.h> +#include <net/ip.h> +#include <net/ipv6.h> +#include <net/tcp.h> +#include <net/udp.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_tcpudp.h> +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv6/ip6_tables.h> + +MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("xt_tcp"); +MODULE_ALIAS("xt_udp"); +MODULE_ALIAS("ipt_udp"); +MODULE_ALIAS("ipt_tcp"); +MODULE_ALIAS("ip6t_udp"); +MODULE_ALIAS("ip6t_tcp"); + +#ifdef DEBUG_IP_FIREWALL_USER +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + + +/* Returns 1 if the port is matched by the range, 0 otherwise */ +static inline int +port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) +{ + int ret; + + ret = (port >= min && port <= max) ^ invert; + return ret; +} + +static int +tcp_find_option(u_int8_t option, + const struct sk_buff *skb, + unsigned int protoff, + unsigned int optlen, + int invert, + int *hotdrop) +{ + /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ + u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; + unsigned int i; + + duprintf("tcp_match: finding option\n"); + + if (!optlen) + return invert; + + /* If we don't have the whole header, drop packet. */ + op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr), + optlen, _opt); + if (op == NULL) { + *hotdrop = 1; + return 0; + } + + for (i = 0; i < optlen; ) { + if (op[i] == option) return !invert; + if (op[i] < 2) i++; + else i += op[i+1]?:1; + } + + return invert; +} + +static int +tcp_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + struct tcphdr _tcph, *th; + const struct xt_tcp *tcpinfo = matchinfo; + + if (offset) { + /* To quote Alan: + + Don't allow a fragment of TCP 8 bytes in. Nobody normal + causes this. Its a cracker trying to break in by doing a + flag overwrite to pass the direction checks. + */ + if (offset == 1) { + duprintf("Dropping evil TCP offset=1 frag.\n"); + *hotdrop = 1; + } + /* Must not be a fragment. */ + return 0; + } + +#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) + + th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); + if (th == NULL) { + /* We've been asked to examine this packet, and we + can't. Hence, no choice but to drop. */ + duprintf("Dropping evil TCP offset=0 tinygram.\n"); + *hotdrop = 1; + return 0; + } + + if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], + ntohs(th->source), + !!(tcpinfo->invflags & XT_TCP_INV_SRCPT))) + return 0; + if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], + ntohs(th->dest), + !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) + return 0; + if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) + == tcpinfo->flg_cmp, + XT_TCP_INV_FLAGS)) + return 0; + if (tcpinfo->option) { + if (th->doff * 4 < sizeof(_tcph)) { + *hotdrop = 1; + return 0; + } + if (!tcp_find_option(tcpinfo->option, skb, protoff, + th->doff*4 - sizeof(_tcph), + tcpinfo->invflags & XT_TCP_INV_OPTION, + hotdrop)) + return 0; + } + return 1; +} + +/* Called when user tries to insert an entry of this type. */ +static int +tcp_checkentry(const char *tablename, + const void *info, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ipt_ip *ip = info; + const struct xt_tcp *tcpinfo = matchinfo; + + /* Must specify proto == TCP, and no unknown invflags */ + return ip->proto == IPPROTO_TCP + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) + && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); +} + +/* Called when user tries to insert an entry of this type. */ +static int +tcp6_checkentry(const char *tablename, + const void *entry, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ipv6 = entry; + const struct xt_tcp *tcpinfo = matchinfo; + + /* Must specify proto == TCP, and no unknown invflags */ + return ipv6->proto == IPPROTO_TCP + && !(ipv6->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) + && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); +} + + +static int +udp_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + struct udphdr _udph, *uh; + const struct xt_udp *udpinfo = matchinfo; + + /* Must not be a fragment. */ + if (offset) + return 0; + + uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); + if (uh == NULL) { + /* We've been asked to examine this packet, and we + can't. Hence, no choice but to drop. */ + duprintf("Dropping evil UDP tinygram.\n"); + *hotdrop = 1; + return 0; + } + + return port_match(udpinfo->spts[0], udpinfo->spts[1], + ntohs(uh->source), + !!(udpinfo->invflags & XT_UDP_INV_SRCPT)) + && port_match(udpinfo->dpts[0], udpinfo->dpts[1], + ntohs(uh->dest), + !!(udpinfo->invflags & XT_UDP_INV_DSTPT)); +} + +/* Called when user tries to insert an entry of this type. */ +static int +udp_checkentry(const char *tablename, + const void *info, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) +{ + const struct ipt_ip *ip = info; + const struct xt_udp *udpinfo = matchinfo; + + /* Must specify proto == UDP, and no unknown invflags */ + if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) { + duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, + IPPROTO_UDP); + return 0; + } + if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { + duprintf("ipt_udp: matchsize %u != %u\n", + matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); + return 0; + } + if (udpinfo->invflags & ~XT_UDP_INV_MASK) { + duprintf("ipt_udp: unknown flags %X\n", + udpinfo->invflags); + return 0; + } + + return 1; +} + +/* Called when user tries to insert an entry of this type. */ +static int +udp6_checkentry(const char *tablename, + const void *entry, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ipv6 = entry; + const struct xt_udp *udpinfo = matchinfo; + + /* Must specify proto == UDP, and no unknown invflags */ + if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) { + duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, + IPPROTO_UDP); + return 0; + } + if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { + duprintf("ip6t_udp: matchsize %u != %u\n", + matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); + return 0; + } + if (udpinfo->invflags & ~XT_UDP_INV_MASK) { + duprintf("ip6t_udp: unknown flags %X\n", + udpinfo->invflags); + return 0; + } + + return 1; +} + +static struct xt_match tcp_matchstruct = { + .name = "tcp", + .match = &tcp_match, + .checkentry = &tcp_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match tcp6_matchstruct = { + .name = "tcp", + .match = &tcp_match, + .checkentry = &tcp6_checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match udp_matchstruct = { + .name = "udp", + .match = &udp_match, + .checkentry = &udp_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match udp6_matchstruct = { + .name = "udp", + .match = &udp_match, + .checkentry = &udp6_checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int ret; + ret = xt_register_match(AF_INET, &tcp_matchstruct); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &tcp6_matchstruct); + if (ret) + goto out_unreg_tcp; + + ret = xt_register_match(AF_INET, &udp_matchstruct); + if (ret) + goto out_unreg_tcp6; + + ret = xt_register_match(AF_INET6, &udp6_matchstruct); + if (ret) + goto out_unreg_udp; + + return ret; + +out_unreg_udp: + xt_unregister_match(AF_INET, &tcp_matchstruct); +out_unreg_tcp6: + xt_unregister_match(AF_INET6, &tcp6_matchstruct); +out_unreg_tcp: + xt_unregister_match(AF_INET, &tcp_matchstruct); + return ret; +} + +static void __exit fini(void) +{ + xt_unregister_match(AF_INET6, &udp6_matchstruct); + xt_unregister_match(AF_INET, &udp_matchstruct); + xt_unregister_match(AF_INET6, &tcp6_matchstruct); + xt_unregister_match(AF_INET, &tcp_matchstruct); +} + +module_init(init); +module_exit(fini); diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index b500193..39a22a3 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -62,7 +62,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) struct ipt_target *target; int ret = 0; - target = ipt_find_target(t->u.user.name, t->u.user.revision); + target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision); if (!target) return -ENOENT; |