OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From: Felix Fietkau <nbd@nbd.name> |
2 | Subject: netfilter: match bypass default table |
||
3 | |||
4 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
||
5 | --- |
||
6 | net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- |
||
7 | 1 file changed, 58 insertions(+), 21 deletions(-) |
||
8 | |||
9 | --- a/net/ipv4/netfilter/ip_tables.c |
||
10 | +++ b/net/ipv4/netfilter/ip_tables.c |
||
11 | @@ -254,6 +254,33 @@ struct ipt_entry *ipt_next_entry(const s |
||
12 | return (void *)entry + entry->next_offset; |
||
13 | } |
||
14 | |||
15 | +static bool |
||
16 | +ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) |
||
17 | +{ |
||
18 | + struct xt_entry_target *t; |
||
19 | + struct xt_standard_target *st; |
||
20 | + |
||
21 | + if (e->target_offset != sizeof(struct ipt_entry)) |
||
22 | + return false; |
||
23 | + |
||
24 | + if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) |
||
25 | + return false; |
||
26 | + |
||
27 | + t = ipt_get_target(e); |
||
28 | + if (t->u.kernel.target->target) |
||
29 | + return false; |
||
30 | + |
||
31 | + st = (struct xt_standard_target *) t; |
||
32 | + if (st->verdict == XT_RETURN) |
||
33 | + return false; |
||
34 | + |
||
35 | + if (st->verdict >= 0) |
||
36 | + return false; |
||
37 | + |
||
38 | + *verdict = (unsigned)(-st->verdict) - 1; |
||
39 | + return true; |
||
40 | +} |
||
41 | + |
||
42 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
||
43 | unsigned int |
||
44 | ipt_do_table(struct sk_buff *skb, |
||
45 | @@ -274,28 +301,8 @@ ipt_do_table(struct sk_buff *skb, |
||
46 | unsigned int addend; |
||
47 | |||
48 | /* Initialization */ |
||
49 | - stackidx = 0; |
||
50 | - ip = ip_hdr(skb); |
||
51 | - indev = state->in ? state->in->name : nulldevname; |
||
52 | - outdev = state->out ? state->out->name : nulldevname; |
||
53 | - /* We handle fragments by dealing with the first fragment as |
||
54 | - * if it was a normal packet. All other fragments are treated |
||
55 | - * normally, except that they will NEVER match rules that ask |
||
56 | - * things we don't know, ie. tcp syn flag or ports). If the |
||
57 | - * rule is also a fragment-specific rule, non-fragments won't |
||
58 | - * match it. */ |
||
59 | - acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; |
||
60 | - acpar.thoff = ip_hdrlen(skb); |
||
61 | - acpar.hotdrop = false; |
||
62 | - acpar.net = state->net; |
||
63 | - acpar.in = state->in; |
||
64 | - acpar.out = state->out; |
||
65 | - acpar.family = NFPROTO_IPV4; |
||
66 | - acpar.hooknum = hook; |
||
67 | - |
||
68 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
||
69 | local_bh_disable(); |
||
70 | - addend = xt_write_recseq_begin(); |
||
71 | private = table->private; |
||
72 | cpu = smp_processor_id(); |
||
73 | /* |
||
74 | @@ -304,6 +311,23 @@ ipt_do_table(struct sk_buff *skb, |
||
75 | */ |
||
76 | smp_read_barrier_depends(); |
||
77 | table_base = private->entries; |
||
78 | + |
||
79 | + e = get_entry(table_base, private->hook_entry[hook]); |
||
80 | + if (ipt_handle_default_rule(e, &verdict)) { |
||
81 | + struct xt_counters *counter; |
||
82 | + |
||
83 | + counter = xt_get_this_cpu_counter(&e->counters); |
||
84 | + ADD_COUNTER(*counter, skb->len, 1); |
||
85 | + local_bh_enable(); |
||
86 | + return verdict; |
||
87 | + } |
||
88 | + |
||
89 | + stackidx = 0; |
||
90 | + ip = ip_hdr(skb); |
||
91 | + indev = state->in ? state->in->name : nulldevname; |
||
92 | + outdev = state->out ? state->out->name : nulldevname; |
||
93 | + |
||
94 | + addend = xt_write_recseq_begin(); |
||
95 | jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; |
||
96 | |||
97 | /* Switch to alternate jumpstack if we're being invoked via TEE. |
||
98 | @@ -316,7 +340,20 @@ ipt_do_table(struct sk_buff *skb, |
||
99 | if (static_key_false(&xt_tee_enabled)) |
||
100 | jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated); |
||
101 | |||
102 | - e = get_entry(table_base, private->hook_entry[hook]); |
||
103 | + /* We handle fragments by dealing with the first fragment as |
||
104 | + * if it was a normal packet. All other fragments are treated |
||
105 | + * normally, except that they will NEVER match rules that ask |
||
106 | + * things we don't know, ie. tcp syn flag or ports). If the |
||
107 | + * rule is also a fragment-specific rule, non-fragments won't |
||
108 | + * match it. */ |
||
109 | + acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; |
||
110 | + acpar.thoff = ip_hdrlen(skb); |
||
111 | + acpar.hotdrop = false; |
||
112 | + acpar.net = state->net; |
||
113 | + acpar.in = state->in; |
||
114 | + acpar.out = state->out; |
||
115 | + acpar.family = NFPROTO_IPV4; |
||
116 | + acpar.hooknum = hook; |
||
117 | |||
118 | do { |
||
119 | const struct xt_entry_target *t; |