netfilter: xtables: move extension arguments into compound structure (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 <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Jan Engelhardt
2008-10-08 11:35:18 +02:00
committed by Patrick McHardy
parent c2df73de24
commit f7108a20de
59 changed files with 286 additions and 487 deletions

View File

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

View File

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

View File

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

View File

@ -67,12 +67,9 @@ static inline bool match_tcp(const struct sk_buff *skb,
return true;
}
static bool
ecn_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 ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ipt_ecn_info *info = matchinfo;
const struct ipt_ecn_info *info = par->matchinfo;
if (info->operation & IPT_ECN_OP_MATCH_IP)
if (!match_ip(skb, info))
@ -81,7 +78,7 @@ ecn_mt(const struct sk_buff *skb, const struct net_device *in,
if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
if (ip_hdr(skb)->protocol != IPPROTO_TCP)
return false;
if (!match_tcp(skb, info, hotdrop))
if (!match_tcp(skb, info, par->hotdrop))
return false;
}

View File

@ -18,12 +18,9 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("Xtables: IPv4 TTL field match");
MODULE_LICENSE("GPL");
static bool
ttl_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 ttl_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ipt_ttl_info *info = matchinfo;
const struct ipt_ttl_info *info = par->matchinfo;
const u8 ttl = ip_hdr(skb)->ttl;
switch (info->mode) {