Skip to content

Commit

Permalink
netfilter: xtables: move extension arguments into compound structure …
Browse files Browse the repository at this point in the history
…(1/6)

The function signatures for Xtables extensions have grown over time.
It involves a lot of typing/replication, and also a bit of stack space
even if they are not used. Realize an NFWS2008 idea and pack them into
structs. The skb remains outside of the struct so gcc can continue to
apply its optimizations.

This patch does this for match extensions' match functions.

A few ambiguities have also been addressed. The "offset" parameter for
example has been renamed to "fragoff" (there are so many different
offsets already) and "protoff" to "thoff" (there is more than just one
protocol here, so clarify).

Signed-off-by: Jan Engelhardt <[email protected]>
Signed-off-by: Patrick McHardy <[email protected]>
  • Loading branch information
Jan Engelhardt authored and kaber committed Oct 8, 2008
1 parent c2df73d commit f7108a2
Show file tree
Hide file tree
Showing 59 changed files with 286 additions and 487 deletions.
28 changes: 21 additions & 7 deletions include/linux/netfilter/x_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,26 @@ struct xt_counters_info

#include <linux/netdevice.h>

/**
* struct xt_match_param - parameters for match extensions' match functions
*
* @in: input netdevice
* @out: output netdevice
* @match: struct xt_match through which this function was invoked
* @matchinfo: per-match data
* @fragoff: packet is a fragment, this is the data offset
* @thoff: position of transport header relative to skb->data
* @hotdrop: drop packet if we had inspection problems
*/
struct xt_match_param {
const struct net_device *in, *out;
const struct xt_match *match;
const void *matchinfo;
int fragoff;
unsigned int thoff;
bool *hotdrop;
};

struct xt_match
{
struct list_head list;
Expand All @@ -185,13 +205,7 @@ struct xt_match
non-linear skb, using skb_header_pointer and
skb_ip_make_writable. */
bool (*match)(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct xt_match *match,
const void *matchinfo,
int offset,
unsigned int protoff,
bool *hotdrop);
const struct xt_match_param *);

/* Called when user tries to insert an entry of this type. */
/* Should return true or false. */
Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_802_3.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
#include <linux/netfilter_bridge/ebt_802_3.h>

static bool
ebt_802_3_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_802_3_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_802_3_info *info = data;
const struct ebt_802_3_info *info = par->matchinfo;
const struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
__be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;

Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_among.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,9 @@ static int get_ip_src(const struct sk_buff *skb, __be32 *addr)
}

static bool
ebt_among_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_among_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_among_info *info = data;
const struct ebt_among_info *info = par->matchinfo;
const char *dmac, *smac;
const struct ebt_mac_wormhash *wh_dst, *wh_src;
__be32 dip = 0, sip = 0;
Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_arp.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
#include <linux/netfilter_bridge/ebt_arp.h>

static bool
ebt_arp_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_arp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_arp_info *info = data;
const struct ebt_arp_info *info = par->matchinfo;
const struct arphdr *ah;
struct arphdr _arph;

Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ struct tcpudphdr {
};

static bool
ebt_ip_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_ip_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_ip_info *info = data;
const struct ebt_ip_info *info = par->matchinfo;
const struct iphdr *ih;
struct iphdr _iph;
const struct tcpudphdr *pptr;
Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_ip6.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ struct tcpudphdr {
};

static bool
ebt_ip6_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_ip6_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_ip6_info *info = data;
const struct ebt_ip6_info *info = par->matchinfo;
const struct ipv6hdr *ih6;
struct ipv6hdr _ip6h;
const struct tcpudphdr *pptr;
Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_limit.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ static DEFINE_SPINLOCK(limit_lock);
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)

static bool
ebt_limit_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_limit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
struct ebt_limit_info *info = (void *)data;
struct ebt_limit_info *info = (void *)par->matchinfo;
unsigned long now = jiffies;

spin_lock_bh(&limit_lock);
Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_mark_m.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
#include <linux/netfilter_bridge/ebt_mark_m.h>

static bool
ebt_mark_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_mark_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_mark_m_info *info = data;
const struct ebt_mark_m_info *info = par->matchinfo;

if (info->bitmask & EBT_MARK_OR)
return !!(skb->mark & info->mask) ^ info->invert;
Expand Down
7 changes: 2 additions & 5 deletions net/bridge/netfilter/ebt_pkttype.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@
#include <linux/netfilter_bridge/ebt_pkttype.h>

static bool
ebt_pkttype_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff,
bool *hotdrop)
ebt_pkttype_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_pkttype_info *info = data;
const struct ebt_pkttype_info *info = par->matchinfo;

return (skb->pkt_type == info->pkt_type) ^ info->invert;
}
Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_stp.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,9 @@ static bool ebt_filter_config(const struct ebt_stp_info *info,
}

static bool
ebt_stp_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_stp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_stp_info *info = data;
const struct ebt_stp_info *info = par->matchinfo;
const struct stp_header *sp;
struct stp_header _stph;
const uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
Expand Down
6 changes: 2 additions & 4 deletions net/bridge/netfilter/ebt_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@ MODULE_LICENSE("GPL");
#define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return false; }

static bool
ebt_vlan_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *data, int offset, unsigned int protoff, bool *hotdrop)
ebt_vlan_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ebt_vlan_info *info = data;
const struct ebt_vlan_info *info = par->matchinfo;
const struct vlan_hdr *fp;
struct vlan_hdr _frame;

Expand Down
16 changes: 10 additions & 6 deletions net/bridge/netfilter/ebtables.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
}

static inline int ebt_do_match (struct ebt_entry_match *m,
const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, bool *hotdrop)
const struct sk_buff *skb, struct xt_match_param *par)
{
return m->u.match->match(skb, in, out, m->u.match,
m->data, 0, 0, hotdrop);
par->match = m->u.match;
par->matchinfo = m->data;
return m->u.match->match(skb, par);
}

static inline int ebt_dev_check(char *entry, const struct net_device *device)
Expand Down Expand Up @@ -155,6 +155,11 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
char *base;
struct ebt_table_info *private;
bool hotdrop = false;
struct xt_match_param mtpar;

mtpar.in = in;
mtpar.out = out;
mtpar.hotdrop = &hotdrop;

read_lock_bh(&table->lock);
private = table->private;
Expand All @@ -175,8 +180,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
if (ebt_basic_match(point, eth_hdr(skb), in, out))
goto letscontinue;

if (EBT_MATCH_ITERATE(point, ebt_do_match, skb,
in, out, &hotdrop) != 0)
if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &mtpar) != 0)
goto letscontinue;
if (hotdrop) {
read_unlock_bh(&table->lock);
Expand Down
46 changes: 20 additions & 26 deletions net/ipv4/netfilter/ip_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,14 @@ ipt_error(struct sk_buff *skb,

/* Performance critical - called for every packet */
static inline bool
do_match(struct ipt_entry_match *m,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int offset,
bool *hotdrop)
do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
struct xt_match_param *par)
{
par->match = m->u.kernel.match;
par->matchinfo = m->data;

/* Stop iteration if it doesn't match */
if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
offset, ip_hdrlen(skb), hotdrop))
if (!m->u.kernel.match->match(skb, par))
return true;
else
return false;
Expand Down Expand Up @@ -326,7 +324,6 @@ ipt_do_table(struct sk_buff *skb,
struct xt_table *table)
{
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
u_int16_t offset;
const struct iphdr *ip;
u_int16_t datalen;
bool hotdrop = false;
Expand All @@ -336,6 +333,7 @@ ipt_do_table(struct sk_buff *skb,
void *table_base;
struct ipt_entry *e, *back;
struct xt_table_info *private;
struct xt_match_param mtpar;

/* Initialization */
ip = ip_hdr(skb);
Expand All @@ -348,7 +346,11 @@ ipt_do_table(struct sk_buff *skb,
* things we don't know, ie. tcp syn flag or ports). If the
* rule is also a fragment-specific rule, non-fragments won't
* match it. */
offset = ntohs(ip->frag_off) & IP_OFFSET;
mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
mtpar.thoff = ip_hdrlen(skb);
mtpar.hotdrop = &hotdrop;
mtpar.in = in;
mtpar.out = out;

read_lock_bh(&table->lock);
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
Expand All @@ -362,12 +364,11 @@ ipt_do_table(struct sk_buff *skb,
do {
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
if (ip_packet_match(ip, indev, outdev,
&e->ip, mtpar.fragoff)) {
struct ipt_entry_target *t;

if (IPT_MATCH_ITERATE(e, do_match,
skb, in, out,
offset, &hotdrop) != 0)
if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
goto no_match;

ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
Expand Down Expand Up @@ -2116,30 +2117,23 @@ icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
}

static bool
icmp_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct xt_match *match,
const void *matchinfo,
int offset,
unsigned int protoff,
bool *hotdrop)
icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct icmphdr *ic;
struct icmphdr _icmph;
const struct ipt_icmp *icmpinfo = matchinfo;
const struct ipt_icmp *icmpinfo = par->matchinfo;

/* Must not be a fragment. */
if (offset)
if (par->fragoff != 0)
return false;

ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
if (ic == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
*/
duprintf("Dropping evil ICMP tinygram.\n");
*hotdrop = true;
*par->hotdrop = true;
return false;
}

Expand Down
18 changes: 6 additions & 12 deletions net/ipv4/netfilter/ipt_addrtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,9 @@ static inline bool match_type(const struct net_device *dev, __be32 addr,
}

static bool
addrtype_mt_v0(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *matchinfo, int offset, unsigned int protoff,
bool *hotdrop)
addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ipt_addrtype_info *info = matchinfo;
const struct ipt_addrtype_info *info = par->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
bool ret = true;

Expand All @@ -50,20 +47,17 @@ addrtype_mt_v0(const struct sk_buff *skb, const struct net_device *in,
}

static bool
addrtype_mt_v1(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *matchinfo, int offset, unsigned int protoff,
bool *hotdrop)
addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ipt_addrtype_info_v1 *info = matchinfo;
const struct ipt_addrtype_info_v1 *info = par->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
const struct net_device *dev = NULL;
bool ret = true;

if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN)
dev = in;
dev = par->in;
else if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT)
dev = out;
dev = par->out;

if (info->source)
ret &= match_type(dev, iph->saddr, info->source) ^
Expand Down
14 changes: 5 additions & 9 deletions net/ipv4/netfilter/ipt_ah.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,23 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
return r;
}

static bool
ah_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
static bool ah_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
struct ip_auth_hdr _ahdr;
const struct ip_auth_hdr *ah;
const struct ipt_ah *ahinfo = matchinfo;
const struct ipt_ah *ahinfo = par->matchinfo;

/* Must not be a fragment. */
if (offset)
if (par->fragoff != 0)
return false;

ah = skb_header_pointer(skb, protoff,
sizeof(_ahdr), &_ahdr);
ah = skb_header_pointer(skb, par->thoff, sizeof(_ahdr), &_ahdr);
if (ah == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
*/
duprintf("Dropping evil AH tinygram.\n");
*hotdrop = true;
*par->hotdrop = true;
return 0;
}

Expand Down
Loading

0 comments on commit f7108a2

Please sign in to comment.