Commit 83d213fd9d1a56108584cd812333462caa39a747

Authored by Florian Westphal
Committed by Pablo Neira Ayuso
1 parent 9976fc6e6e

netfilter: conntrack: deconstify packet callback skb pointer

Only two protocols need the ->error() function: icmp and icmpv6.
This is because icmp error mssages might be RELATED to an existing
connection (e.g. PMTUD, port unreachable and the like), and their
->error() handlers do this.

The error callback is already optional, so remove it for
udp and call them from ->packet() instead.

As the error() callback can call checksum functions that write to
skb->csum*, the const qualifier has to be removed as well.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 9 changed files with 95 additions and 64 deletions Side-by-side Diff

include/net/netfilter/nf_conntrack_l4proto.h
... ... @@ -43,7 +43,7 @@
43 43  
44 44 /* Returns verdict for packet, or -1 for invalid. */
45 45 int (*packet)(struct nf_conn *ct,
46   - const struct sk_buff *skb,
  46 + struct sk_buff *skb,
47 47 unsigned int dataoff,
48 48 enum ip_conntrack_info ctinfo,
49 49 const struct nf_hook_state *state);
net/netfilter/nf_conntrack_proto_dccp.c
... ... @@ -435,7 +435,7 @@
435 435 ntohl(dhack->dccph_ack_nr_low);
436 436 }
437 437  
438   -static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
  438 +static int dccp_packet(struct nf_conn *ct, struct sk_buff *skb,
439 439 unsigned int dataoff, enum ip_conntrack_info ctinfo,
440 440 const struct nf_hook_state *state)
441 441 {
net/netfilter/nf_conntrack_proto_generic.c
... ... @@ -44,7 +44,7 @@
44 44  
45 45 /* Returns verdict for packet, or -1 for invalid. */
46 46 static int generic_packet(struct nf_conn *ct,
47   - const struct sk_buff *skb,
  47 + struct sk_buff *skb,
48 48 unsigned int dataoff,
49 49 enum ip_conntrack_info ctinfo,
50 50 const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_gre.c
... ... @@ -233,7 +233,7 @@
233 233  
234 234 /* Returns verdict for packet, and may modify conntrack */
235 235 static int gre_packet(struct nf_conn *ct,
236   - const struct sk_buff *skb,
  236 + struct sk_buff *skb,
237 237 unsigned int dataoff,
238 238 enum ip_conntrack_info ctinfo,
239 239 const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_icmp.c
... ... @@ -74,7 +74,7 @@
74 74  
75 75 /* Returns verdict for packet, or -1 for invalid. */
76 76 static int icmp_packet(struct nf_conn *ct,
77   - const struct sk_buff *skb,
  77 + struct sk_buff *skb,
78 78 unsigned int dataoff,
79 79 enum ip_conntrack_info ctinfo,
80 80 const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_icmpv6.c
... ... @@ -92,10 +92,10 @@
92 92  
93 93 /* Returns verdict for packet, or -1 for invalid. */
94 94 static int icmpv6_packet(struct nf_conn *ct,
95   - const struct sk_buff *skb,
96   - unsigned int dataoff,
97   - enum ip_conntrack_info ctinfo,
98   - const struct nf_hook_state *state)
  95 + struct sk_buff *skb,
  96 + unsigned int dataoff,
  97 + enum ip_conntrack_info ctinfo,
  98 + const struct nf_hook_state *state)
99 99 {
100 100 unsigned int *timeout = nf_ct_timeout_lookup(ct);
101 101 static const u8 valid_new[] = {
net/netfilter/nf_conntrack_proto_sctp.c
... ... @@ -332,7 +332,7 @@
332 332  
333 333 /* Returns verdict for packet, or -NF_ACCEPT for invalid. */
334 334 static int sctp_packet(struct nf_conn *ct,
335   - const struct sk_buff *skb,
  335 + struct sk_buff *skb,
336 336 unsigned int dataoff,
337 337 enum ip_conntrack_info ctinfo,
338 338 const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_tcp.c
... ... @@ -844,7 +844,7 @@
844 844  
845 845 /* Returns verdict for packet, or -1 for invalid. */
846 846 static int tcp_packet(struct nf_conn *ct,
847   - const struct sk_buff *skb,
  847 + struct sk_buff *skb,
848 848 unsigned int dataoff,
849 849 enum ip_conntrack_info ctinfo,
850 850 const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_udp.c
... ... @@ -42,15 +42,65 @@
42 42 return udp_pernet(net)->timeouts;
43 43 }
44 44  
  45 +static void udp_error_log(const struct sk_buff *skb,
  46 + const struct nf_hook_state *state,
  47 + const char *msg)
  48 +{
  49 + nf_l4proto_log_invalid(skb, state->net, state->pf,
  50 + IPPROTO_UDP, "%s", msg);
  51 +}
  52 +
  53 +static bool udp_error(struct sk_buff *skb,
  54 + unsigned int dataoff,
  55 + const struct nf_hook_state *state)
  56 +{
  57 + unsigned int udplen = skb->len - dataoff;
  58 + const struct udphdr *hdr;
  59 + struct udphdr _hdr;
  60 +
  61 + /* Header is too small? */
  62 + hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  63 + if (!hdr) {
  64 + udp_error_log(skb, state, "short packet");
  65 + return true;
  66 + }
  67 +
  68 + /* Truncated/malformed packets */
  69 + if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
  70 + udp_error_log(skb, state, "truncated/malformed packet");
  71 + return true;
  72 + }
  73 +
  74 + /* Packet with no checksum */
  75 + if (!hdr->check)
  76 + return false;
  77 +
  78 + /* Checksum invalid? Ignore.
  79 + * We skip checking packets on the outgoing path
  80 + * because the checksum is assumed to be correct.
  81 + * FIXME: Source route IP option packets --RR */
  82 + if (state->hook == NF_INET_PRE_ROUTING &&
  83 + state->net->ct.sysctl_checksum &&
  84 + nf_checksum(skb, state->hook, dataoff, IPPROTO_UDP, state->pf)) {
  85 + udp_error_log(skb, state, "bad checksum");
  86 + return true;
  87 + }
  88 +
  89 + return false;
  90 +}
  91 +
45 92 /* Returns verdict for packet, and may modify conntracktype */
46 93 static int udp_packet(struct nf_conn *ct,
47   - const struct sk_buff *skb,
  94 + struct sk_buff *skb,
48 95 unsigned int dataoff,
49 96 enum ip_conntrack_info ctinfo,
50 97 const struct nf_hook_state *state)
51 98 {
52 99 unsigned int *timeouts;
53 100  
  101 + if (udp_error(skb, dataoff, state))
  102 + return -NF_ACCEPT;
  103 +
54 104 timeouts = nf_ct_timeout_lookup(ct);
55 105 if (!timeouts)
56 106 timeouts = udp_get_timeouts(nf_ct_net(ct));
... ... @@ -79,9 +129,9 @@
79 129 IPPROTO_UDPLITE, "%s", msg);
80 130 }
81 131  
82   -static int udplite_error(struct nf_conn *tmpl, struct sk_buff *skb,
83   - unsigned int dataoff,
84   - const struct nf_hook_state *state)
  132 +static bool udplite_error(struct sk_buff *skb,
  133 + unsigned int dataoff,
  134 + const struct nf_hook_state *state)
85 135 {
86 136 unsigned int udplen = skb->len - dataoff;
87 137 const struct udphdr *hdr;
... ... @@ -92,7 +142,7 @@
92 142 hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
93 143 if (!hdr) {
94 144 udplite_error_log(skb, state, "short packet");
95   - return -NF_ACCEPT;
  145 + return true;
96 146 }
97 147  
98 148 cscov = ntohs(hdr->len);
99 149  
... ... @@ -100,13 +150,13 @@
100 150 cscov = udplen;
101 151 } else if (cscov < sizeof(*hdr) || cscov > udplen) {
102 152 udplite_error_log(skb, state, "invalid checksum coverage");
103   - return -NF_ACCEPT;
  153 + return true;
104 154 }
105 155  
106 156 /* UDPLITE mandates checksums */
107 157 if (!hdr->check) {
108 158 udplite_error_log(skb, state, "checksum missing");
109   - return -NF_ACCEPT;
  159 + return true;
110 160 }
111 161  
112 162 /* Checksum invalid? Ignore. */
113 163  
114 164  
115 165  
116 166  
117 167  
118 168  
119 169  
120 170  
121 171  
122 172  
... ... @@ -115,58 +165,43 @@
115 165 nf_checksum_partial(skb, state->hook, dataoff, cscov, IPPROTO_UDP,
116 166 state->pf)) {
117 167 udplite_error_log(skb, state, "bad checksum");
118   - return -NF_ACCEPT;
  168 + return true;
119 169 }
120 170  
121   - return NF_ACCEPT;
  171 + return false;
122 172 }
123   -#endif
124 173  
125   -static void udp_error_log(const struct sk_buff *skb,
126   - const struct nf_hook_state *state,
127   - const char *msg)
  174 +/* Returns verdict for packet, and may modify conntracktype */
  175 +static int udplite_packet(struct nf_conn *ct,
  176 + struct sk_buff *skb,
  177 + unsigned int dataoff,
  178 + enum ip_conntrack_info ctinfo,
  179 + const struct nf_hook_state *state)
128 180 {
129   - nf_l4proto_log_invalid(skb, state->net, state->pf,
130   - IPPROTO_UDP, "%s", msg);
131   -}
  181 + unsigned int *timeouts;
132 182  
133   -static int udp_error(struct nf_conn *tmpl, struct sk_buff *skb,
134   - unsigned int dataoff,
135   - const struct nf_hook_state *state)
136   -{
137   - unsigned int udplen = skb->len - dataoff;
138   - const struct udphdr *hdr;
139   - struct udphdr _hdr;
140   -
141   - /* Header is too small? */
142   - hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
143   - if (hdr == NULL) {
144   - udp_error_log(skb, state, "short packet");
  183 + if (udplite_error(skb, dataoff, state))
145 184 return -NF_ACCEPT;
146   - }
147 185  
148   - /* Truncated/malformed packets */
149   - if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
150   - udp_error_log(skb, state, "truncated/malformed packet");
151   - return -NF_ACCEPT;
152   - }
  186 + timeouts = nf_ct_timeout_lookup(ct);
  187 + if (!timeouts)
  188 + timeouts = udp_get_timeouts(nf_ct_net(ct));
153 189  
154   - /* Packet with no checksum */
155   - if (!hdr->check)
156   - return NF_ACCEPT;
157   -
158   - /* Checksum invalid? Ignore.
159   - * We skip checking packets on the outgoing path
160   - * because the checksum is assumed to be correct.
161   - * FIXME: Source route IP option packets --RR */
162   - if (state->net->ct.sysctl_checksum && state->hook == NF_INET_PRE_ROUTING &&
163   - nf_checksum(skb, state->hook, dataoff, IPPROTO_UDP, state->pf)) {
164   - udp_error_log(skb, state, "bad checksum");
165   - return -NF_ACCEPT;
  190 + /* If we've seen traffic both ways, this is some kind of UDP
  191 + stream. Extend timeout. */
  192 + if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
  193 + nf_ct_refresh_acct(ct, ctinfo, skb,
  194 + timeouts[UDP_CT_REPLIED]);
  195 + /* Also, more likely to be important, and not a probe */
  196 + if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
  197 + nf_conntrack_event_cache(IPCT_ASSURED, ct);
  198 + } else {
  199 + nf_ct_refresh_acct(ct, ctinfo, skb,
  200 + timeouts[UDP_CT_UNREPLIED]);
166 201 }
167   -
168 202 return NF_ACCEPT;
169 203 }
  204 +#endif
170 205  
171 206 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
172 207  
... ... @@ -281,7 +316,6 @@
281 316 .l4proto = IPPROTO_UDP,
282 317 .allow_clash = true,
283 318 .packet = udp_packet,
284   - .error = udp_error,
285 319 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
286 320 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
287 321 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
... ... @@ -308,8 +342,7 @@
308 342 .l3proto = PF_INET,
309 343 .l4proto = IPPROTO_UDPLITE,
310 344 .allow_clash = true,
311   - .packet = udp_packet,
312   - .error = udplite_error,
  345 + .packet = udplite_packet,
313 346 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
314 347 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
315 348 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
... ... @@ -337,7 +370,6 @@
337 370 .l4proto = IPPROTO_UDP,
338 371 .allow_clash = true,
339 372 .packet = udp_packet,
340   - .error = udp_error,
341 373 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
342 374 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
343 375 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
... ... @@ -364,8 +396,7 @@
364 396 .l3proto = PF_INET6,
365 397 .l4proto = IPPROTO_UDPLITE,
366 398 .allow_clash = true,
367   - .packet = udp_packet,
368   - .error = udplite_error,
  399 + .packet = udplite_packet,
369 400 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
370 401 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
371 402 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,