[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:
committed by
David S. Miller
parent
880b005f29
commit
2e4e6a17af
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* This is a module which is used for setting the skb->priority field
|
||||
* of an skb for qdisc classification.
|
||||
*/
|
||||
|
||||
/* (C) 2001-2002 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* 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_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
|
||||
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("iptables qdisc classification target module");
|
||||
|
||||
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_classify_target_info *clinfo = targinfo;
|
||||
|
||||
if((*pskb)->priority != clinfo->priority)
|
||||
(*pskb)->priority = clinfo->priority;
|
||||
|
||||
return IPT_CONTINUE;
|
||||
}
|
||||
|
||||
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_classify_target_info))){
|
||||
printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n",
|
||||
targinfosize,
|
||||
IPT_ALIGN(sizeof(struct ipt_classify_target_info)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hook_mask & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
|
||||
(1 << NF_IP_POST_ROUTING))) {
|
||||
printk(KERN_ERR "CLASSIFY: only valid in LOCAL_OUT, FORWARD "
|
||||
"and POST_ROUTING.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(tablename, "mangle") != 0) {
|
||||
printk(KERN_ERR "CLASSIFY: can only be called from "
|
||||
"\"mangle\" table, not \"%s\".\n",
|
||||
tablename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_target ipt_classify_reg = {
|
||||
.name = "CLASSIFY",
|
||||
.target = target,
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_target(&ipt_classify_reg);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_target(&ipt_classify_reg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/* This kernel module is used to modify the connection mark values, or
|
||||
* to optionally restore the skb nfmark from the connection mark
|
||||
*
|
||||
* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
|
||||
* by Henrik Nordstrom <hno@marasystems.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/checksum.h>
|
||||
|
||||
MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
|
||||
MODULE_DESCRIPTION("IP tables CONNMARK matching module");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
|
||||
#include <net/netfilter/nf_conntrack_compat.h>
|
||||
|
||||
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_connmark_target_info *markinfo = targinfo;
|
||||
u_int32_t diff;
|
||||
u_int32_t nfmark;
|
||||
u_int32_t newmark;
|
||||
u_int32_t ctinfo;
|
||||
u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
|
||||
|
||||
if (ctmark) {
|
||||
switch(markinfo->mode) {
|
||||
case IPT_CONNMARK_SET:
|
||||
newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
|
||||
if (newmark != *ctmark)
|
||||
*ctmark = newmark;
|
||||
break;
|
||||
case IPT_CONNMARK_SAVE:
|
||||
newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
|
||||
if (*ctmark != newmark)
|
||||
*ctmark = newmark;
|
||||
break;
|
||||
case IPT_CONNMARK_RESTORE:
|
||||
nfmark = (*pskb)->nfmark;
|
||||
diff = (*ctmark ^ nfmark) & markinfo->mask;
|
||||
if (diff != 0)
|
||||
(*pskb)->nfmark = nfmark ^ diff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IPT_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const char *tablename,
|
||||
const struct ipt_entry *e,
|
||||
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))) {
|
||||
printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
|
||||
targinfosize,
|
||||
IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (matchinfo->mode == IPT_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;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
|
||||
printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_target ipt_connmark_reg = {
|
||||
.name = "CONNMARK",
|
||||
.target = &target,
|
||||
.checkentry = &checkentry,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
need_ip_conntrack();
|
||||
return ipt_register_target(&ipt_connmark_reg);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_target(&ipt_connmark_reg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,172 +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_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_MARK.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
|
||||
MODULE_DESCRIPTION("iptables MARK modification module");
|
||||
|
||||
static unsigned int
|
||||
target_v0(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_mark_target_info *markinfo = targinfo;
|
||||
|
||||
if((*pskb)->nfmark != markinfo->mark)
|
||||
(*pskb)->nfmark = markinfo->mark;
|
||||
|
||||
return IPT_CONTINUE;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
target_v1(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_mark_target_info_v1 *markinfo = targinfo;
|
||||
int mark = 0;
|
||||
|
||||
switch (markinfo->mode) {
|
||||
case IPT_MARK_SET:
|
||||
mark = markinfo->mark;
|
||||
break;
|
||||
|
||||
case IPT_MARK_AND:
|
||||
mark = (*pskb)->nfmark & markinfo->mark;
|
||||
break;
|
||||
|
||||
case IPT_MARK_OR:
|
||||
mark = (*pskb)->nfmark | markinfo->mark;
|
||||
break;
|
||||
}
|
||||
|
||||
if((*pskb)->nfmark != mark)
|
||||
(*pskb)->nfmark = mark;
|
||||
|
||||
return IPT_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
checkentry_v0(const char *tablename,
|
||||
const struct ipt_entry *e,
|
||||
void *targinfo,
|
||||
unsigned int targinfosize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
struct ipt_mark_target_info *markinfo = targinfo;
|
||||
|
||||
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) {
|
||||
printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
|
||||
targinfosize,
|
||||
IPT_ALIGN(sizeof(struct ipt_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;
|
||||
}
|
||||
|
||||
if (markinfo->mark > 0xffffffff) {
|
||||
printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry_v1(const char *tablename,
|
||||
const struct ipt_entry *e,
|
||||
void *targinfo,
|
||||
unsigned int targinfosize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
struct ipt_mark_target_info_v1 *markinfo = targinfo;
|
||||
|
||||
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){
|
||||
printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
|
||||
targinfosize,
|
||||
IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(tablename, "mangle") != 0) {
|
||||
printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (markinfo->mode != IPT_MARK_SET
|
||||
&& markinfo->mode != IPT_MARK_AND
|
||||
&& markinfo->mode != IPT_MARK_OR) {
|
||||
printk(KERN_WARNING "MARK: unknown mode %u\n",
|
||||
markinfo->mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (markinfo->mark > 0xffffffff) {
|
||||
printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_target ipt_mark_reg_v0 = {
|
||||
.name = "MARK",
|
||||
.target = target_v0,
|
||||
.checkentry = checkentry_v0,
|
||||
.me = THIS_MODULE,
|
||||
.revision = 0,
|
||||
};
|
||||
|
||||
static struct ipt_target ipt_mark_reg_v1 = {
|
||||
.name = "MARK",
|
||||
.target = target_v1,
|
||||
.checkentry = checkentry_v1,
|
||||
.me = THIS_MODULE,
|
||||
.revision = 1,
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_target(&ipt_mark_reg_v0);
|
||||
ipt_unregister_target(&ipt_mark_reg_v1);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
@@ -1,76 +0,0 @@
|
||||
/* This is a module which is used for setting up fake conntracks
|
||||
* on packets so that they are not seen by the conntrack/NAT code.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <net/netfilter/nf_conntrack_compat.h>
|
||||
|
||||
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)
|
||||
{
|
||||
/* Previously seen (loopback)? Ignore. */
|
||||
if ((*pskb)->nfct != NULL)
|
||||
return IPT_CONTINUE;
|
||||
|
||||
/* Attach fake conntrack entry.
|
||||
If there is a real ct entry correspondig to this packet,
|
||||
it'll hang aroun till timing out. We don't deal with it
|
||||
for performance reasons. JK */
|
||||
nf_ct_untrack(*pskb);
|
||||
(*pskb)->nfctinfo = IP_CT_NEW;
|
||||
nf_conntrack_get((*pskb)->nfct);
|
||||
|
||||
return IPT_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const char *tablename,
|
||||
const struct ipt_entry *e,
|
||||
void *targinfo,
|
||||
unsigned int targinfosize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
if (targinfosize != 0) {
|
||||
printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
|
||||
targinfosize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(tablename, "raw") != 0) {
|
||||
printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_target ipt_notrack_reg = {
|
||||
.name = "NOTRACK",
|
||||
.target = target,
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
if (ipt_register_target(&ipt_notrack_reg))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_target(&ipt_notrack_reg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Implements a dummy match to allow attaching comments to rules
|
||||
*
|
||||
* 2003-05-13 Brad Fisher (brad@info-link.net)
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_comment.h>
|
||||
|
||||
MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
|
||||
MODULE_DESCRIPTION("iptables comment match 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)
|
||||
{
|
||||
/* We always match */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
/* Check the size */
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match comment_match = {
|
||||
.name = "comment",
|
||||
.match = match,
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&comment_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&comment_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,161 +0,0 @@
|
||||
/* Kernel module to match connection tracking byte counter.
|
||||
* GPL (C) 2002 Martin Devera (devik@cdi.cz).
|
||||
*
|
||||
* 2004-07-20 Harald Welte <laforge@netfilter.org>
|
||||
* - reimplemented to use per-connection accounting counters
|
||||
* - add functionality to match number of packets
|
||||
* - add functionality to match average packet size
|
||||
* - add support to match directions seperately
|
||||
*
|
||||
*/
|
||||
#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 <asm/div64.h>
|
||||
#include <asm/bitops.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
|
||||
MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
|
||||
|
||||
/* 64bit divisor, dividend and result. dynamic precision */
|
||||
static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor)
|
||||
{
|
||||
u_int32_t d = divisor;
|
||||
|
||||
if (divisor > 0xffffffffULL) {
|
||||
unsigned int shift = fls(divisor >> 32);
|
||||
|
||||
d = divisor >> shift;
|
||||
dividend >>= shift;
|
||||
}
|
||||
|
||||
do_div(dividend, d);
|
||||
return dividend;
|
||||
}
|
||||
|
||||
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_connbytes_info *sinfo = matchinfo;
|
||||
u_int64_t what = 0; /* initialize to make gcc happy */
|
||||
const struct ip_conntrack_counter *counters;
|
||||
|
||||
if (!(counters = nf_ct_get_counters(skb)))
|
||||
return 0; /* no match */
|
||||
|
||||
switch (sinfo->what) {
|
||||
case IPT_CONNBYTES_PKTS:
|
||||
switch (sinfo->direction) {
|
||||
case IPT_CONNBYTES_DIR_ORIGINAL:
|
||||
what = counters[IP_CT_DIR_ORIGINAL].packets;
|
||||
break;
|
||||
case IPT_CONNBYTES_DIR_REPLY:
|
||||
what = counters[IP_CT_DIR_REPLY].packets;
|
||||
break;
|
||||
case IPT_CONNBYTES_DIR_BOTH:
|
||||
what = counters[IP_CT_DIR_ORIGINAL].packets;
|
||||
what += counters[IP_CT_DIR_REPLY].packets;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IPT_CONNBYTES_BYTES:
|
||||
switch (sinfo->direction) {
|
||||
case IPT_CONNBYTES_DIR_ORIGINAL:
|
||||
what = counters[IP_CT_DIR_ORIGINAL].bytes;
|
||||
break;
|
||||
case IPT_CONNBYTES_DIR_REPLY:
|
||||
what = counters[IP_CT_DIR_REPLY].bytes;
|
||||
break;
|
||||
case IPT_CONNBYTES_DIR_BOTH:
|
||||
what = counters[IP_CT_DIR_ORIGINAL].bytes;
|
||||
what += counters[IP_CT_DIR_REPLY].bytes;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IPT_CONNBYTES_AVGPKT:
|
||||
switch (sinfo->direction) {
|
||||
case IPT_CONNBYTES_DIR_ORIGINAL:
|
||||
what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
|
||||
counters[IP_CT_DIR_ORIGINAL].packets);
|
||||
break;
|
||||
case IPT_CONNBYTES_DIR_REPLY:
|
||||
what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
|
||||
counters[IP_CT_DIR_REPLY].packets);
|
||||
break;
|
||||
case IPT_CONNBYTES_DIR_BOTH:
|
||||
{
|
||||
u_int64_t bytes;
|
||||
u_int64_t pkts;
|
||||
bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
|
||||
counters[IP_CT_DIR_REPLY].bytes;
|
||||
pkts = counters[IP_CT_DIR_ORIGINAL].packets+
|
||||
counters[IP_CT_DIR_REPLY].packets;
|
||||
|
||||
/* FIXME_THEORETICAL: what to do if sum
|
||||
* overflows ? */
|
||||
|
||||
what = div64_64(bytes, pkts);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (sinfo->count.to)
|
||||
return (what <= sinfo->count.to && what >= sinfo->count.from);
|
||||
else
|
||||
return (what >= sinfo->count.from);
|
||||
}
|
||||
|
||||
static int check(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
const struct ipt_connbytes_info *sinfo = matchinfo;
|
||||
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info)))
|
||||
return 0;
|
||||
|
||||
if (sinfo->what != IPT_CONNBYTES_PKTS &&
|
||||
sinfo->what != IPT_CONNBYTES_BYTES &&
|
||||
sinfo->what != IPT_CONNBYTES_AVGPKT)
|
||||
return 0;
|
||||
|
||||
if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL &&
|
||||
sinfo->direction != IPT_CONNBYTES_DIR_REPLY &&
|
||||
sinfo->direction != IPT_CONNBYTES_DIR_BOTH)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match state_match = {
|
||||
.name = "connbytes",
|
||||
.match = &match,
|
||||
.checkentry = &check,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&state_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&state_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,88 +0,0 @@
|
||||
/* This kernel module matches connection mark values set by the
|
||||
* CONNMARK target
|
||||
*
|
||||
* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
|
||||
* by Henrik Nordstrom <hno@marasystems.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
|
||||
MODULE_DESCRIPTION("IP tables connmark match module");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_connmark.h>
|
||||
#include <net/netfilter/nf_conntrack_compat.h>
|
||||
|
||||
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_connmark_info *info = matchinfo;
|
||||
u_int32_t ctinfo;
|
||||
const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo);
|
||||
if (!ctmark)
|
||||
return 0;
|
||||
|
||||
return (((*ctmark) & info->mask) == info->mark) ^ info->invert;
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const char *tablename,
|
||||
const struct ipt_ip *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)))
|
||||
return 0;
|
||||
|
||||
if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
|
||||
printk(KERN_WARNING "connmark: only support 32bit mark\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match connmark_match = {
|
||||
.name = "connmark",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&connmark_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&connmark_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,232 +0,0 @@
|
||||
/* Kernel module to match connection tracking information.
|
||||
* Superset of Rusty's minimalistic state match.
|
||||
*
|
||||
* (C) 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>
|
||||
|
||||
#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_tuple.h>
|
||||
#else
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#endif
|
||||
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_conntrack.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
|
||||
MODULE_DESCRIPTION("iptables connection tracking match module");
|
||||
|
||||
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_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)
|
||||
{
|
||||
const struct ipt_conntrack_info *sinfo = matchinfo;
|
||||
struct ip_conntrack *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
unsigned int statebit;
|
||||
|
||||
ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
|
||||
|
||||
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
|
||||
|
||||
if (ct == &ip_conntrack_untracked)
|
||||
statebit = IPT_CONNTRACK_STATE_UNTRACKED;
|
||||
else if (ct)
|
||||
statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
|
||||
else
|
||||
statebit = IPT_CONNTRACK_STATE_INVALID;
|
||||
|
||||
if(sinfo->flags & IPT_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;
|
||||
|
||||
if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip !=
|
||||
ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)
|
||||
statebit |= IPT_CONNTRACK_STATE_DNAT;
|
||||
}
|
||||
|
||||
if (FWINV((statebit & sinfo->statemask) == 0, IPT_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))
|
||||
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))
|
||||
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))
|
||||
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))
|
||||
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))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sinfo->flags & IPT_CONNTRACK_STATUS) {
|
||||
if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
|
||||
unsigned long expires;
|
||||
|
||||
if(!ct)
|
||||
return 0;
|
||||
|
||||
expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
|
||||
|
||||
if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* CONFIG_IP_NF_CONNTRACK */
|
||||
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_conntrack_info *sinfo = matchinfo;
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
unsigned int statebit;
|
||||
|
||||
ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
|
||||
|
||||
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
|
||||
|
||||
if (ct == &nf_conntrack_untracked)
|
||||
statebit = IPT_CONNTRACK_STATE_UNTRACKED;
|
||||
else if (ct)
|
||||
statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
|
||||
else
|
||||
statebit = IPT_CONNTRACK_STATE_INVALID;
|
||||
|
||||
if(sinfo->flags & IPT_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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (FWINV((statebit & sinfo->statemask) == 0, IPT_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))
|
||||
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))
|
||||
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))
|
||||
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))
|
||||
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))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sinfo->flags & IPT_CONNTRACK_STATUS) {
|
||||
if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
|
||||
unsigned long expires;
|
||||
|
||||
if(!ct)
|
||||
return 0;
|
||||
|
||||
expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
|
||||
|
||||
if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NF_IP_CONNTRACK */
|
||||
|
||||
static int check(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match conntrack_match = {
|
||||
.name = "conntrack",
|
||||
.match = &match,
|
||||
.checkentry = &check,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
need_ip_conntrack();
|
||||
return ipt_register_match(&conntrack_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&conntrack_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* iptables module for DCCP protocol header matching
|
||||
*
|
||||
* (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/spinlock.h>
|
||||
#include <net/ip.h>
|
||||
#include <linux/dccp.h>
|
||||
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_dccp.h>
|
||||
|
||||
#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
|
||||
|| (!!((invflag) & (option)) ^ (cond)))
|
||||
|
||||
static unsigned char *dccp_optbuf;
|
||||
static DEFINE_SPINLOCK(dccp_buflock);
|
||||
|
||||
static inline int
|
||||
dccp_find_option(u_int8_t option,
|
||||
const struct sk_buff *skb,
|
||||
const struct dccp_hdr *dh,
|
||||
int *hotdrop)
|
||||
{
|
||||
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
|
||||
unsigned char *op;
|
||||
unsigned int optoff = __dccp_hdr_len(dh);
|
||||
unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh);
|
||||
unsigned int i;
|
||||
|
||||
if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) {
|
||||
*hotdrop = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!optlen)
|
||||
return 0;
|
||||
|
||||
spin_lock_bh(&dccp_buflock);
|
||||
op = skb_header_pointer(skb,
|
||||
skb->nh.iph->ihl*4 + optoff,
|
||||
optlen, dccp_optbuf);
|
||||
if (op == NULL) {
|
||||
/* If we don't have the whole header, drop packet. */
|
||||
spin_unlock_bh(&dccp_buflock);
|
||||
*hotdrop = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < optlen; ) {
|
||||
if (op[i] == option) {
|
||||
spin_unlock_bh(&dccp_buflock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (op[i] < 2)
|
||||
i++;
|
||||
else
|
||||
i += op[i+1]?:1;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&dccp_buflock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
match_types(const struct dccp_hdr *dh, u_int16_t typemask)
|
||||
{
|
||||
return (typemask & (1 << dh->dccph_type));
|
||||
}
|
||||
|
||||
static inline int
|
||||
match_option(u_int8_t option, const struct sk_buff *skb,
|
||||
const struct dccp_hdr *dh, int *hotdrop)
|
||||
{
|
||||
return dccp_find_option(option, skb, dh, hotdrop);
|
||||
}
|
||||
|
||||
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_dccp_info *info =
|
||||
(const struct ipt_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);
|
||||
if (dh == NULL) {
|
||||
*hotdrop = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
|
||||
&& (ntohs(dh->dccph_sport) <= info->spts[1])),
|
||||
IPT_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)
|
||||
&& 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);
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
const struct ipt_dccp_info *info;
|
||||
|
||||
info = (const struct ipt_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)
|
||||
&& !(info->invflags & ~info->flags);
|
||||
}
|
||||
|
||||
static struct ipt_match dccp_match =
|
||||
{
|
||||
.name = "dccp",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* doff is 8 bits, so the maximum option size is (4*256). Don't put
|
||||
* this in BSS since DaveM is worried about locked TLB's for kernel
|
||||
* BSS. */
|
||||
dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
|
||||
if (!dccp_optbuf)
|
||||
return -ENOMEM;
|
||||
ret = ipt_register_match(&dccp_match);
|
||||
if (ret)
|
||||
kfree(dccp_optbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&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");
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
/* iptables module to match on related connections */
|
||||
/*
|
||||
* (C) 2001 Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 19 Mar 2002 Harald Welte <laforge@gnumonks.org>:
|
||||
* - Port to newnat infrastructure
|
||||
*/
|
||||
|
||||
#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>
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
|
||||
#else
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#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>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
|
||||
MODULE_DESCRIPTION("iptables helper match module");
|
||||
|
||||
#if 0
|
||||
#define DEBUGP printk
|
||||
#else
|
||||
#define DEBUGP(format, args...)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_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)
|
||||
{
|
||||
const struct ipt_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");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!ct->master) {
|
||||
DEBUGP("ipt_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",
|
||||
exp->expectant);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
DEBUGP("master's name = %s , info->name = %s\n",
|
||||
ct->master->helper->name, info->name);
|
||||
|
||||
if (info->name[0] == '\0')
|
||||
ret ^= 1;
|
||||
else
|
||||
ret ^= !strncmp(ct->master->helper->name, info->name,
|
||||
strlen(ct->master->helper->name));
|
||||
out_unlock:
|
||||
read_unlock_bh(&ip_conntrack_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* CONFIG_IP_NF_CONNTRACK */
|
||||
|
||||
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_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");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!ct->master) {
|
||||
DEBUGP("ipt_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",
|
||||
exp->expectant);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
DEBUGP("master's name = %s , info->name = %s\n",
|
||||
ct->master->helper->name, info->name);
|
||||
|
||||
if (info->name[0] == '\0')
|
||||
ret ^= 1;
|
||||
else
|
||||
ret ^= !strncmp(ct->master->helper->name, info->name,
|
||||
strlen(ct->master->helper->name));
|
||||
out_unlock:
|
||||
read_unlock_bh(&nf_conntrack_lock);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int check(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
struct ipt_helper_info *info = matchinfo;
|
||||
|
||||
info->name[29] = '\0';
|
||||
|
||||
/* verify size */
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match helper_match = {
|
||||
.name = "helper",
|
||||
.match = &match,
|
||||
.checkentry = &check,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
need_ip_conntrack();
|
||||
return ipt_register_match(&helper_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&helper_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
@@ -1,157 +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_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_limit.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
|
||||
MODULE_DESCRIPTION("iptables rate limit match");
|
||||
|
||||
/* 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 get the maxmum range, we multiply by this factor (ie. you get N
|
||||
credits per jiffy). We want to allow a rate as low as 1 per day
|
||||
(slowest userspace tool allows), which means
|
||||
CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32. ie. */
|
||||
#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
|
||||
|
||||
/* Repeated shift and or gives us all 1s, final shift and add 1 gives
|
||||
* us the power of 2 below the theoretical max, so GCC simply does a
|
||||
* shift. */
|
||||
#define _POW2_BELOW2(x) ((x)|((x)>>1))
|
||||
#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
|
||||
#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
|
||||
#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
|
||||
#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
|
||||
#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
|
||||
|
||||
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
|
||||
|
||||
static int
|
||||
ipt_limit_match(const struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
const void *matchinfo,
|
||||
int offset,
|
||||
int *hotdrop)
|
||||
{
|
||||
struct ipt_rateinfo *r = ((struct ipt_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 / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
|
||||
|
||||
return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE;
|
||||
}
|
||||
|
||||
static int
|
||||
ipt_limit_checkentry(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
struct ipt_rateinfo *r = matchinfo;
|
||||
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_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",
|
||||
r->avg, r->burst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* User avg in seconds * IPT_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 ipt_match ipt_limit_reg = {
|
||||
.name = "limit",
|
||||
.match = ipt_limit_match,
|
||||
.checkentry = ipt_limit_checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
if (ipt_register_match(&ipt_limit_reg))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&ipt_limit_reg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,80 +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_ipv4/ipt_mac.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
MODULE_DESCRIPTION("iptables mac matching 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)
|
||||
{
|
||||
const struct ipt_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
|
||||
ipt_mac_checkentry(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
/* FORWARD isn't always valid, but it's nice to be able to do --RR */
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match mac_match = {
|
||||
.name = "mac",
|
||||
.match = &match,
|
||||
.checkentry = &ipt_mac_checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&mac_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&mac_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,71 +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_ipv4/ipt_mark.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
|
||||
MODULE_DESCRIPTION("iptables mark matching 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)
|
||||
{
|
||||
const struct ipt_mark_info *info = matchinfo;
|
||||
|
||||
return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo;
|
||||
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info)))
|
||||
return 0;
|
||||
|
||||
if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
|
||||
printk(KERN_WARNING "mark: only supports 32bit mark\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match mark_match = {
|
||||
.name = "mark",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&mark_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&mark_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
@@ -1,70 +0,0 @@
|
||||
/* (C) 1999-2001 Michal Ludvig <michal@logix.cz>
|
||||
*
|
||||
* 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/if_packet.h>
|
||||
|
||||
#include <linux/netfilter_ipv4/ipt_pkttype.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
|
||||
MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
|
||||
|
||||
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_pkttype_info *info = matchinfo;
|
||||
|
||||
return (skb->pkt_type == info->pkttype) ^ info->invert;
|
||||
}
|
||||
|
||||
static int checkentry(const char *tablename,
|
||||
const struct ipt_ip *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)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match pkttype_match = {
|
||||
.name = "pkttype",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&pkttype_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&pkttype_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,76 +0,0 @@
|
||||
/* IP tables module for matching the routing realm
|
||||
*
|
||||
* $Id: ipt_realm.c,v 1.3 2004/03/05 13:25:40 laforge Exp $
|
||||
*
|
||||
* (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
|
||||
*
|
||||
* 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/netdevice.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <linux/netfilter_ipv4/ipt_realm.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("iptables realm match");
|
||||
|
||||
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_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,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
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, "
|
||||
"LOCAL_IN or FORWARD.\n");
|
||||
return 0;
|
||||
}
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) {
|
||||
printk("ipt_realm: invalid matchsize.\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match realm_match = {
|
||||
.name = "realm",
|
||||
.match = match,
|
||||
.checkentry = check,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&realm_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&realm_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -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)
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/ip.h>
|
||||
#include <linux/sctp.h>
|
||||
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_sctp.h>
|
||||
|
||||
#ifdef DEBUG_SCTP
|
||||
#define duprintf(format, args...) printk(format , ## args)
|
||||
#else
|
||||
#define duprintf(format, args...)
|
||||
#endif
|
||||
|
||||
#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
|
||||
|| (!!((invflag) & (option)) ^ (cond)))
|
||||
|
||||
static int
|
||||
match_flags(const struct ipt_sctp_flag_info *flag_info,
|
||||
const int flag_count,
|
||||
u_int8_t chunktype,
|
||||
u_int8_t chunkflags)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < flag_count; i++) {
|
||||
if (flag_info[i].chunktype == chunktype) {
|
||||
return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
match_packet(const struct sk_buff *skb,
|
||||
const u_int32_t *chunkmap,
|
||||
int chunk_match_type,
|
||||
const struct ipt_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;
|
||||
|
||||
#ifdef DEBUG_SCTP
|
||||
int i = 0;
|
||||
#endif
|
||||
|
||||
if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
|
||||
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) {
|
||||
duprintf("Dropping invalid SCTP packet.\n");
|
||||
*hotdrop = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
|
||||
++i, offset, sch->type, htons(sch->length), sch->flags);
|
||||
|
||||
offset += (htons(sch->length) + 3) & ~3;
|
||||
|
||||
duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
|
||||
|
||||
if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) {
|
||||
switch (chunk_match_type) {
|
||||
case SCTP_CHUNK_MATCH_ANY:
|
||||
if (match_flags(flag_info, flag_count,
|
||||
sch->type, sch->flags)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_CHUNK_MATCH_ALL:
|
||||
if (match_flags(flag_info, flag_count,
|
||||
sch->type, sch->flags)) {
|
||||
SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_CHUNK_MATCH_ONLY:
|
||||
if (!match_flags(flag_info, flag_count,
|
||||
sch->type, sch->flags)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (chunk_match_type) {
|
||||
case SCTP_CHUNK_MATCH_ONLY:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} while (offset < skb->len);
|
||||
|
||||
switch (chunk_match_type) {
|
||||
case SCTP_CHUNK_MATCH_ALL:
|
||||
return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
|
||||
case SCTP_CHUNK_MATCH_ANY:
|
||||
return 0;
|
||||
case SCTP_CHUNK_MATCH_ONLY:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This will never be reached, but required to stop compiler whine */
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_sctp_info *info;
|
||||
sctp_sctphdr_t _sh, *sh;
|
||||
|
||||
info = (const struct ipt_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);
|
||||
if (sh == NULL) {
|
||||
duprintf("Dropping evil TCP offset=0 tinygram.\n");
|
||||
*hotdrop = 1;
|
||||
return 0;
|
||||
}
|
||||
duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
|
||||
|
||||
return SCCHECK(((ntohs(sh->source) >= info->spts[0])
|
||||
&& (ntohs(sh->source) <= info->spts[1])),
|
||||
IPT_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,
|
||||
info->flag_info, info->flag_count,
|
||||
hotdrop),
|
||||
IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
const struct ipt_sctp_info *info;
|
||||
|
||||
info = (const struct ipt_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)
|
||||
&& !(info->invflags & ~info->flags)
|
||||
&& ((!(info->flags & IPT_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 =
|
||||
{
|
||||
.list = { NULL, NULL},
|
||||
.name = "sctp",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.destroy = NULL,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&sctp_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&sctp_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Kiran Kumar Immidi");
|
||||
MODULE_DESCRIPTION("Match for SCTP protocol packets");
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/* Kernel module to match connection tracking information. */
|
||||
|
||||
/* (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 <net/netfilter/nf_conntrack_compat.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_state.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
|
||||
MODULE_DESCRIPTION("iptables connection tracking state 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)
|
||||
{
|
||||
const struct ipt_state_info *sinfo = matchinfo;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
unsigned int statebit;
|
||||
|
||||
if (nf_ct_is_untracked(skb))
|
||||
statebit = IPT_STATE_UNTRACKED;
|
||||
else if (!nf_ct_get_ctinfo(skb, &ctinfo))
|
||||
statebit = IPT_STATE_INVALID;
|
||||
else
|
||||
statebit = IPT_STATE_BIT(ctinfo);
|
||||
|
||||
return (sinfo->statemask & statebit);
|
||||
}
|
||||
|
||||
static int check(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match state_match = {
|
||||
.name = "state",
|
||||
.match = &match,
|
||||
.checkentry = &check,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
need_ip_conntrack();
|
||||
return ipt_register_match(&state_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&state_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,91 +0,0 @@
|
||||
/* String matching match for iptables
|
||||
*
|
||||
* (C) 2005 Pablo Neira Ayuso <pablo@eurodev.net>
|
||||
*
|
||||
* 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/init.h>
|
||||
#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/textsearch.h>
|
||||
|
||||
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
|
||||
MODULE_DESCRIPTION("IP tables string match 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)
|
||||
{
|
||||
struct ts_state state;
|
||||
struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo;
|
||||
|
||||
memset(&state, 0, sizeof(struct ts_state));
|
||||
|
||||
return (skb_find_text((struct sk_buff *)skb, conf->from_offset,
|
||||
conf->to_offset, conf->config, &state)
|
||||
!= UINT_MAX) && !conf->invert;
|
||||
}
|
||||
|
||||
#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m)
|
||||
|
||||
static int checkentry(const char *tablename,
|
||||
const struct ipt_ip *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
struct ipt_string_info *conf = matchinfo;
|
||||
struct ts_config *ts_conf;
|
||||
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
|
||||
return 0;
|
||||
|
||||
/* Damn, can't handle this case properly with iptables... */
|
||||
if (conf->from_offset > conf->to_offset)
|
||||
return 0;
|
||||
|
||||
ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
|
||||
GFP_KERNEL, TS_AUTOLOAD);
|
||||
if (IS_ERR(ts_conf))
|
||||
return 0;
|
||||
|
||||
conf->config = ts_conf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void destroy(void *matchinfo, unsigned int matchsize)
|
||||
{
|
||||
textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
|
||||
}
|
||||
|
||||
static struct ipt_match string_match = {
|
||||
.name = "string",
|
||||
.match = match,
|
||||
.checkentry = checkentry,
|
||||
.destroy = destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&string_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&string_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -1,127 +0,0 @@
|
||||
/* Kernel module to match TCP MSS values. */
|
||||
|
||||
/* Copyright (C) 2000 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 <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter_ipv4/ipt_tcpmss.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
#define TH_SYN 0x02
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
|
||||
MODULE_DESCRIPTION("iptables TCP MSS match module");
|
||||
|
||||
/* 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,
|
||||
int invert,
|
||||
int *hotdrop)
|
||||
{
|
||||
struct tcphdr _tcph, *th;
|
||||
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
|
||||
u8 _opt[15 * 4 - sizeof(_tcph)], *op;
|
||||
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);
|
||||
if (th == NULL)
|
||||
goto dropit;
|
||||
|
||||
/* Malformed. */
|
||||
if (th->doff*4 < sizeof(*th))
|
||||
goto dropit;
|
||||
|
||||
optlen = th->doff*4 - sizeof(*th);
|
||||
if (!optlen)
|
||||
goto out;
|
||||
|
||||
/* Truncated options. */
|
||||
op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th),
|
||||
optlen, _opt);
|
||||
if (op == NULL)
|
||||
goto dropit;
|
||||
|
||||
for (i = 0; i < optlen; ) {
|
||||
if (op[i] == TCPOPT_MSS
|
||||
&& (optlen - i) >= TCPOLEN_MSS
|
||||
&& op[i+1] == TCPOLEN_MSS) {
|
||||
u_int16_t mssval;
|
||||
|
||||
mssval = (op[i+2] << 8) | op[i+3];
|
||||
|
||||
return (mssval >= min && mssval <= max) ^ invert;
|
||||
}
|
||||
if (op[i] < 2) i++;
|
||||
else i += op[i+1]?:1;
|
||||
}
|
||||
out:
|
||||
return invert;
|
||||
|
||||
dropit:
|
||||
*hotdrop = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_tcpmss_match_info *info = matchinfo;
|
||||
|
||||
return mssoption_match(info->mss_min, info->mss_max, skb,
|
||||
info->invert, hotdrop);
|
||||
}
|
||||
|
||||
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_tcpmss_match_info)))
|
||||
return 0;
|
||||
|
||||
/* Must specify -p tcp */
|
||||
if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
|
||||
printk("tcpmss: Only works on TCP packets\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ipt_match tcpmss_match = {
|
||||
.name = "tcpmss",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return ipt_register_match(&tcpmss_match);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
ipt_unregister_match(&tcpmss_match);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user