[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>
This commit is contained in:
Harald Welte
2006-01-12 13:30:04 -08:00
committed by David S. Miller
parent 880b005f29
commit 2e4e6a17af
154 changed files with 3614 additions and 4148 deletions

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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)

View File

@@ -364,7 +364,7 @@ static int init_or_cleanup(int init)
{
int ret = 0;
need_ip_conntrack();
need_conntrack();
if (!init) goto cleanup;

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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)

View File

@@ -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",

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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",

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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)) {

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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)) {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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);

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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);

View File

@@ -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<EFBFBD>me de Vivie <devivie@info.enserb.u-bordeaux.fr>
* (C) 1999 Herv<72> 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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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);

View File

@@ -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)) {

View File

@@ -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.

View File

@@ -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

View File

@@ -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);

624
net/netfilter/x_tables.c Normal file
View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

107
net/netfilter/xt_NFQUEUE.c Normal file
View File

@@ -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);

View File

@@ -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;
return 0;
ret = xt_register_target(AF_INET, &notrack_reg);
if (ret)
return ret;
ret = xt_register_target(AF_INET6, &notrack6_reg);
if (ret)
xt_unregister_target(AF_INET, &notrack_reg);
return ret;
}
static void __exit fini(void)
{
ipt_unregister_target(&ipt_notrack_reg);
xt_unregister_target(AF_INET6, &notrack6_reg);
xt_unregister_target(AF_INET, &notrack_reg);
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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");

View File

@@ -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);

98
net/netfilter/xt_length.c Normal file
View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 ipt_sctp_info *info;
const struct xt_sctp_info *info;
const struct ipt_ip *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 int
checkentry6(const char *tablename,
const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_sctp_info *info;
const struct ip6t_ip6 *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 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");

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

333
net/netfilter/xt_tcpudp.c Normal file
View File

@@ -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);

View File

@@ -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;