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