Commit 9976fc6e6edbb0372f084a2ae8c1b8103b3bff1d
Committed by
Pablo Neira Ayuso
1 parent
93e66024b0
netfilter: conntrack: remove the l4proto->new() function
->new() gets invoked after ->error() and before ->packet() if a conntrack lookup has found no result for the tuple. We can fold it into ->packet() -- the packet() implementations can check if the conntrack is confirmed (new) or not (already in hash). If its unconfirmed, the conntrack isn't in the hash yet so current skb created a new conntrack entry. Only relevant side effect -- if packet() doesn't return NF_ACCEPT but -NF_ACCEPT (or drop), while the conntrack was just created, then the newly allocated conntrack is freed right away, rather than not created in the first place. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Showing 10 changed files with 194 additions and 263 deletions Side-by-side Diff
- include/net/netfilter/nf_conntrack_l4proto.h
- net/netfilter/nf_conntrack_core.c
- net/netfilter/nf_conntrack_proto_dccp.c
- net/netfilter/nf_conntrack_proto_generic.c
- net/netfilter/nf_conntrack_proto_gre.c
- net/netfilter/nf_conntrack_proto_icmp.c
- net/netfilter/nf_conntrack_proto_icmpv6.c
- net/netfilter/nf_conntrack_proto_sctp.c
- net/netfilter/nf_conntrack_proto_tcp.c
- net/netfilter/nf_conntrack_proto_udp.c
include/net/netfilter/nf_conntrack_l4proto.h
... | ... | @@ -48,11 +48,6 @@ |
48 | 48 | enum ip_conntrack_info ctinfo, |
49 | 49 | const struct nf_hook_state *state); |
50 | 50 | |
51 | - /* Called when a new connection for this protocol found; | |
52 | - * returns TRUE if it's OK. If so, packet() called next. */ | |
53 | - bool (*new)(struct nf_conn *ct, const struct sk_buff *skb, | |
54 | - unsigned int dataoff); | |
55 | - | |
56 | 51 | /* Called when a conntrack entry is destroyed */ |
57 | 52 | void (*destroy)(struct nf_conn *ct); |
58 | 53 |
net/netfilter/nf_conntrack_core.c
... | ... | @@ -1370,12 +1370,6 @@ |
1370 | 1370 | |
1371 | 1371 | timeout_ext = tmpl ? nf_ct_timeout_find(tmpl) : NULL; |
1372 | 1372 | |
1373 | - if (!l4proto->new(ct, skb, dataoff)) { | |
1374 | - nf_conntrack_free(ct); | |
1375 | - pr_debug("can't track with proto module\n"); | |
1376 | - return NULL; | |
1377 | - } | |
1378 | - | |
1379 | 1373 | if (timeout_ext) |
1380 | 1374 | nf_ct_timeout_ext_add(ct, rcu_dereference(timeout_ext->timeout), |
1381 | 1375 | GFP_ATOMIC); |
net/netfilter/nf_conntrack_proto_dccp.c
... | ... | @@ -389,18 +389,15 @@ |
389 | 389 | return &net->ct.nf_ct_proto.dccp; |
390 | 390 | } |
391 | 391 | |
392 | -static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
393 | - unsigned int dataoff) | |
392 | +static noinline bool | |
393 | +dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
394 | + const struct dccp_hdr *dh) | |
394 | 395 | { |
395 | 396 | struct net *net = nf_ct_net(ct); |
396 | 397 | struct nf_dccp_net *dn; |
397 | - struct dccp_hdr _dh, *dh; | |
398 | 398 | const char *msg; |
399 | 399 | u_int8_t state; |
400 | 400 | |
401 | - dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); | |
402 | - BUG_ON(dh == NULL); | |
403 | - | |
404 | 401 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; |
405 | 402 | switch (state) { |
406 | 403 | default: |
407 | 404 | |
... | ... | @@ -449,8 +446,12 @@ |
449 | 446 | unsigned int *timeouts; |
450 | 447 | |
451 | 448 | dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); |
452 | - BUG_ON(dh == NULL); | |
449 | + if (!dh) | |
450 | + return NF_DROP; | |
451 | + | |
453 | 452 | type = dh->dccph_type; |
453 | + if (!nf_ct_is_confirmed(ct) && !dccp_new(ct, skb, dh)) | |
454 | + return -NF_ACCEPT; | |
454 | 455 | |
455 | 456 | if (type == DCCP_PKT_RESET && |
456 | 457 | !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
... | ... | @@ -850,7 +851,6 @@ |
850 | 851 | const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { |
851 | 852 | .l3proto = AF_INET, |
852 | 853 | .l4proto = IPPROTO_DCCP, |
853 | - .new = dccp_new, | |
854 | 854 | .packet = dccp_packet, |
855 | 855 | .error = dccp_error, |
856 | 856 | .can_early_drop = dccp_can_early_drop, |
... | ... | @@ -883,7 +883,6 @@ |
883 | 883 | const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { |
884 | 884 | .l3proto = AF_INET6, |
885 | 885 | .l4proto = IPPROTO_DCCP, |
886 | - .new = dccp_new, | |
887 | 886 | .packet = dccp_packet, |
888 | 887 | .error = dccp_error, |
889 | 888 | .can_early_drop = dccp_can_early_drop, |
net/netfilter/nf_conntrack_proto_generic.c
... | ... | @@ -51,6 +51,12 @@ |
51 | 51 | { |
52 | 52 | const unsigned int *timeout = nf_ct_timeout_lookup(ct); |
53 | 53 | |
54 | + if (!nf_generic_should_process(nf_ct_protonum(ct))) { | |
55 | + pr_warn_once("conntrack: generic helper won't handle protocol %d. Please consider loading the specific helper module.\n", | |
56 | + nf_ct_protonum(ct)); | |
57 | + return -NF_ACCEPT; | |
58 | + } | |
59 | + | |
54 | 60 | if (!timeout) |
55 | 61 | timeout = &generic_pernet(nf_ct_net(ct))->timeout; |
56 | 62 | |
... | ... | @@ -58,19 +64,6 @@ |
58 | 64 | return NF_ACCEPT; |
59 | 65 | } |
60 | 66 | |
61 | -/* Called when a new connection for this protocol found. */ | |
62 | -static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, | |
63 | - unsigned int dataoff) | |
64 | -{ | |
65 | - bool ret; | |
66 | - | |
67 | - ret = nf_generic_should_process(nf_ct_protonum(ct)); | |
68 | - if (!ret) | |
69 | - pr_warn_once("conntrack: generic helper won't handle protocol %d. Please consider loading the specific helper module.\n", | |
70 | - nf_ct_protonum(ct)); | |
71 | - return ret; | |
72 | -} | |
73 | - | |
74 | 67 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
75 | 68 | |
76 | 69 | #include <linux/netfilter/nfnetlink.h> |
... | ... | @@ -164,7 +157,6 @@ |
164 | 157 | .l4proto = 255, |
165 | 158 | .pkt_to_tuple = generic_pkt_to_tuple, |
166 | 159 | .packet = generic_packet, |
167 | - .new = generic_new, | |
168 | 160 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
169 | 161 | .ctnl_timeout = { |
170 | 162 | .nlattr_to_obj = generic_timeout_nlattr_to_obj, |
net/netfilter/nf_conntrack_proto_gre.c
... | ... | @@ -238,6 +238,18 @@ |
238 | 238 | enum ip_conntrack_info ctinfo, |
239 | 239 | const struct nf_hook_state *state) |
240 | 240 | { |
241 | + if (!nf_ct_is_confirmed(ct)) { | |
242 | + unsigned int *timeouts = nf_ct_timeout_lookup(ct); | |
243 | + | |
244 | + if (!timeouts) | |
245 | + timeouts = gre_get_timeouts(nf_ct_net(ct)); | |
246 | + | |
247 | + /* initialize to sane value. Ideally a conntrack helper | |
248 | + * (e.g. in case of pptp) is increasing them */ | |
249 | + ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED]; | |
250 | + ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED]; | |
251 | + } | |
252 | + | |
241 | 253 | /* If we've seen traffic both ways, this is a GRE connection. |
242 | 254 | * Extend timeout. */ |
243 | 255 | if (ct->status & IPS_SEEN_REPLY) { |
... | ... | @@ -253,26 +265,6 @@ |
253 | 265 | return NF_ACCEPT; |
254 | 266 | } |
255 | 267 | |
256 | -/* Called when a new connection for this protocol found. */ | |
257 | -static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb, | |
258 | - unsigned int dataoff) | |
259 | -{ | |
260 | - unsigned int *timeouts = nf_ct_timeout_lookup(ct); | |
261 | - | |
262 | - if (!timeouts) | |
263 | - timeouts = gre_get_timeouts(nf_ct_net(ct)); | |
264 | - | |
265 | - pr_debug(": "); | |
266 | - nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | |
267 | - | |
268 | - /* initialize to sane value. Ideally a conntrack helper | |
269 | - * (e.g. in case of pptp) is increasing them */ | |
270 | - ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED]; | |
271 | - ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED]; | |
272 | - | |
273 | - return true; | |
274 | -} | |
275 | - | |
276 | 268 | /* Called when a conntrack entry has already been removed from the hashes |
277 | 269 | * and is about to be deleted from memory */ |
278 | 270 | static void gre_destroy(struct nf_conn *ct) |
... | ... | @@ -359,7 +351,6 @@ |
359 | 351 | .print_conntrack = gre_print_conntrack, |
360 | 352 | #endif |
361 | 353 | .packet = gre_packet, |
362 | - .new = gre_new, | |
363 | 354 | .destroy = gre_destroy, |
364 | 355 | .me = THIS_MODULE, |
365 | 356 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
net/netfilter/nf_conntrack_proto_icmp.c
... | ... | @@ -72,11 +72,6 @@ |
72 | 72 | return true; |
73 | 73 | } |
74 | 74 | |
75 | -static unsigned int *icmp_get_timeouts(struct net *net) | |
76 | -{ | |
77 | - return &icmp_pernet(net)->timeout; | |
78 | -} | |
79 | - | |
80 | 75 | /* Returns verdict for packet, or -1 for invalid. */ |
81 | 76 | static int icmp_packet(struct nf_conn *ct, |
82 | 77 | const struct sk_buff *skb, |
... | ... | @@ -88,19 +83,6 @@ |
88 | 83 | successful reply to avoid excessive conntrackd traffic |
89 | 84 | and also to handle correctly ICMP echo reply duplicates. */ |
90 | 85 | unsigned int *timeout = nf_ct_timeout_lookup(ct); |
91 | - | |
92 | - if (!timeout) | |
93 | - timeout = icmp_get_timeouts(nf_ct_net(ct)); | |
94 | - | |
95 | - nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); | |
96 | - | |
97 | - return NF_ACCEPT; | |
98 | -} | |
99 | - | |
100 | -/* Called when a new connection for this protocol found. */ | |
101 | -static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
102 | - unsigned int dataoff) | |
103 | -{ | |
104 | 86 | static const u_int8_t valid_new[] = { |
105 | 87 | [ICMP_ECHO] = 1, |
106 | 88 | [ICMP_TIMESTAMP] = 1, |
107 | 89 | |
... | ... | @@ -114,9 +96,14 @@ |
114 | 96 | pr_debug("icmp: can't create new conn with type %u\n", |
115 | 97 | ct->tuplehash[0].tuple.dst.u.icmp.type); |
116 | 98 | nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple); |
117 | - return false; | |
99 | + return -NF_ACCEPT; | |
118 | 100 | } |
119 | - return true; | |
101 | + | |
102 | + if (!timeout) | |
103 | + timeout = &icmp_pernet(nf_ct_net(ct))->timeout; | |
104 | + | |
105 | + nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); | |
106 | + return NF_ACCEPT; | |
120 | 107 | } |
121 | 108 | |
122 | 109 | /* Returns conntrack if it dealt with ICMP, and filled in skb fields */ |
... | ... | @@ -368,7 +355,6 @@ |
368 | 355 | .pkt_to_tuple = icmp_pkt_to_tuple, |
369 | 356 | .invert_tuple = icmp_invert_tuple, |
370 | 357 | .packet = icmp_packet, |
371 | - .new = icmp_new, | |
372 | 358 | .error = icmp_error, |
373 | 359 | .destroy = NULL, |
374 | 360 | .me = NULL, |
net/netfilter/nf_conntrack_proto_icmpv6.c
... | ... | @@ -98,7 +98,23 @@ |
98 | 98 | const struct nf_hook_state *state) |
99 | 99 | { |
100 | 100 | unsigned int *timeout = nf_ct_timeout_lookup(ct); |
101 | + static const u8 valid_new[] = { | |
102 | + [ICMPV6_ECHO_REQUEST - 128] = 1, | |
103 | + [ICMPV6_NI_QUERY - 128] = 1 | |
104 | + }; | |
101 | 105 | |
106 | + if (!nf_ct_is_confirmed(ct)) { | |
107 | + int type = ct->tuplehash[0].tuple.dst.u.icmp.type - 128; | |
108 | + | |
109 | + if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) { | |
110 | + /* Can't create a new ICMPv6 `conn' with this. */ | |
111 | + pr_debug("icmpv6: can't create new conn with type %u\n", | |
112 | + type + 128); | |
113 | + nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); | |
114 | + return -NF_ACCEPT; | |
115 | + } | |
116 | + } | |
117 | + | |
102 | 118 | if (!timeout) |
103 | 119 | timeout = icmpv6_get_timeouts(nf_ct_net(ct)); |
104 | 120 | |
... | ... | @@ -110,26 +126,6 @@ |
110 | 126 | return NF_ACCEPT; |
111 | 127 | } |
112 | 128 | |
113 | -/* Called when a new connection for this protocol found. */ | |
114 | -static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | |
115 | - unsigned int dataoff) | |
116 | -{ | |
117 | - static const u_int8_t valid_new[] = { | |
118 | - [ICMPV6_ECHO_REQUEST - 128] = 1, | |
119 | - [ICMPV6_NI_QUERY - 128] = 1 | |
120 | - }; | |
121 | - int type = ct->tuplehash[0].tuple.dst.u.icmp.type - 128; | |
122 | - | |
123 | - if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) { | |
124 | - /* Can't create a new ICMPv6 `conn' with this. */ | |
125 | - pr_debug("icmpv6: can't create new conn with type %u\n", | |
126 | - type + 128); | |
127 | - nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); | |
128 | - return false; | |
129 | - } | |
130 | - return true; | |
131 | -} | |
132 | - | |
133 | 129 | static int |
134 | 130 | icmpv6_error_message(struct net *net, struct nf_conn *tmpl, |
135 | 131 | struct sk_buff *skb, |
... | ... | @@ -370,7 +366,6 @@ |
370 | 366 | .pkt_to_tuple = icmpv6_pkt_to_tuple, |
371 | 367 | .invert_tuple = icmpv6_invert_tuple, |
372 | 368 | .packet = icmpv6_packet, |
373 | - .new = icmpv6_new, | |
374 | 369 | .error = icmpv6_error, |
375 | 370 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
376 | 371 | .tuple_to_nlattr = icmpv6_tuple_to_nlattr, |
net/netfilter/nf_conntrack_proto_sctp.c
... | ... | @@ -273,6 +273,63 @@ |
273 | 273 | return sctp_conntracks[dir][i][cur_state]; |
274 | 274 | } |
275 | 275 | |
276 | +/* Don't need lock here: this conntrack not in circulation yet */ | |
277 | +static noinline bool | |
278 | +sctp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
279 | + const struct sctphdr *sh, unsigned int dataoff) | |
280 | +{ | |
281 | + enum sctp_conntrack new_state; | |
282 | + const struct sctp_chunkhdr *sch; | |
283 | + struct sctp_chunkhdr _sch; | |
284 | + u32 offset, count; | |
285 | + | |
286 | + memset(&ct->proto.sctp, 0, sizeof(ct->proto.sctp)); | |
287 | + new_state = SCTP_CONNTRACK_MAX; | |
288 | + for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) { | |
289 | + new_state = sctp_new_state(IP_CT_DIR_ORIGINAL, | |
290 | + SCTP_CONNTRACK_NONE, sch->type); | |
291 | + | |
292 | + /* Invalid: delete conntrack */ | |
293 | + if (new_state == SCTP_CONNTRACK_NONE || | |
294 | + new_state == SCTP_CONNTRACK_MAX) { | |
295 | + pr_debug("nf_conntrack_sctp: invalid new deleting.\n"); | |
296 | + return false; | |
297 | + } | |
298 | + | |
299 | + /* Copy the vtag into the state info */ | |
300 | + if (sch->type == SCTP_CID_INIT) { | |
301 | + struct sctp_inithdr _inithdr, *ih; | |
302 | + /* Sec 8.5.1 (A) */ | |
303 | + if (sh->vtag) | |
304 | + return false; | |
305 | + | |
306 | + ih = skb_header_pointer(skb, offset + sizeof(_sch), | |
307 | + sizeof(_inithdr), &_inithdr); | |
308 | + if (!ih) | |
309 | + return false; | |
310 | + | |
311 | + pr_debug("Setting vtag %x for new conn\n", | |
312 | + ih->init_tag); | |
313 | + | |
314 | + ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = ih->init_tag; | |
315 | + } else if (sch->type == SCTP_CID_HEARTBEAT) { | |
316 | + pr_debug("Setting vtag %x for secondary conntrack\n", | |
317 | + sh->vtag); | |
318 | + ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag; | |
319 | + } else { | |
320 | + /* If it is a shutdown ack OOTB packet, we expect a return | |
321 | + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ | |
322 | + pr_debug("Setting vtag %x for new conn OOTB\n", | |
323 | + sh->vtag); | |
324 | + ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; | |
325 | + } | |
326 | + | |
327 | + ct->proto.sctp.state = new_state; | |
328 | + } | |
329 | + | |
330 | + return true; | |
331 | +} | |
332 | + | |
276 | 333 | /* Returns verdict for packet, or -NF_ACCEPT for invalid. */ |
277 | 334 | static int sctp_packet(struct nf_conn *ct, |
278 | 335 | const struct sk_buff *skb, |
... | ... | @@ -297,6 +354,17 @@ |
297 | 354 | if (do_basic_checks(ct, skb, dataoff, map) != 0) |
298 | 355 | goto out; |
299 | 356 | |
357 | + if (!nf_ct_is_confirmed(ct)) { | |
358 | + /* If an OOTB packet has any of these chunks discard (Sec 8.4) */ | |
359 | + if (test_bit(SCTP_CID_ABORT, map) || | |
360 | + test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) || | |
361 | + test_bit(SCTP_CID_COOKIE_ACK, map)) | |
362 | + return -NF_ACCEPT; | |
363 | + | |
364 | + if (!sctp_new(ct, skb, sh, dataoff)) | |
365 | + return -NF_ACCEPT; | |
366 | + } | |
367 | + | |
300 | 368 | /* Check the verification tag (Sec 8.5) */ |
301 | 369 | if (!test_bit(SCTP_CID_INIT, map) && |
302 | 370 | !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) && |
... | ... | @@ -398,80 +466,6 @@ |
398 | 466 | return -NF_ACCEPT; |
399 | 467 | } |
400 | 468 | |
401 | -/* Called when a new connection for this protocol found. */ | |
402 | -static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
403 | - unsigned int dataoff) | |
404 | -{ | |
405 | - enum sctp_conntrack new_state; | |
406 | - const struct sctphdr *sh; | |
407 | - struct sctphdr _sctph; | |
408 | - const struct sctp_chunkhdr *sch; | |
409 | - struct sctp_chunkhdr _sch; | |
410 | - u_int32_t offset, count; | |
411 | - unsigned long map[256 / sizeof(unsigned long)] = { 0 }; | |
412 | - | |
413 | - sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); | |
414 | - if (sh == NULL) | |
415 | - return false; | |
416 | - | |
417 | - if (do_basic_checks(ct, skb, dataoff, map) != 0) | |
418 | - return false; | |
419 | - | |
420 | - /* If an OOTB packet has any of these chunks discard (Sec 8.4) */ | |
421 | - if (test_bit(SCTP_CID_ABORT, map) || | |
422 | - test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) || | |
423 | - test_bit(SCTP_CID_COOKIE_ACK, map)) | |
424 | - return false; | |
425 | - | |
426 | - memset(&ct->proto.sctp, 0, sizeof(ct->proto.sctp)); | |
427 | - new_state = SCTP_CONNTRACK_MAX; | |
428 | - for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { | |
429 | - /* Don't need lock here: this conntrack not in circulation yet */ | |
430 | - new_state = sctp_new_state(IP_CT_DIR_ORIGINAL, | |
431 | - SCTP_CONNTRACK_NONE, sch->type); | |
432 | - | |
433 | - /* Invalid: delete conntrack */ | |
434 | - if (new_state == SCTP_CONNTRACK_NONE || | |
435 | - new_state == SCTP_CONNTRACK_MAX) { | |
436 | - pr_debug("nf_conntrack_sctp: invalid new deleting.\n"); | |
437 | - return false; | |
438 | - } | |
439 | - | |
440 | - /* Copy the vtag into the state info */ | |
441 | - if (sch->type == SCTP_CID_INIT) { | |
442 | - struct sctp_inithdr _inithdr, *ih; | |
443 | - /* Sec 8.5.1 (A) */ | |
444 | - if (sh->vtag) | |
445 | - return false; | |
446 | - | |
447 | - ih = skb_header_pointer(skb, offset + sizeof(_sch), | |
448 | - sizeof(_inithdr), &_inithdr); | |
449 | - if (!ih) | |
450 | - return false; | |
451 | - | |
452 | - pr_debug("Setting vtag %x for new conn\n", | |
453 | - ih->init_tag); | |
454 | - | |
455 | - ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = ih->init_tag; | |
456 | - } else if (sch->type == SCTP_CID_HEARTBEAT) { | |
457 | - pr_debug("Setting vtag %x for secondary conntrack\n", | |
458 | - sh->vtag); | |
459 | - ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag; | |
460 | - } | |
461 | - /* If it is a shutdown ack OOTB packet, we expect a return | |
462 | - shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ | |
463 | - else { | |
464 | - pr_debug("Setting vtag %x for new conn OOTB\n", | |
465 | - sh->vtag); | |
466 | - ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; | |
467 | - } | |
468 | - | |
469 | - ct->proto.sctp.state = new_state; | |
470 | - } | |
471 | - | |
472 | - return true; | |
473 | -} | |
474 | - | |
475 | 469 | static int sctp_error(struct nf_conn *tpl, struct sk_buff *skb, |
476 | 470 | unsigned int dataoff, |
477 | 471 | const struct nf_hook_state *state) |
... | ... | @@ -769,7 +763,6 @@ |
769 | 763 | .print_conntrack = sctp_print_conntrack, |
770 | 764 | #endif |
771 | 765 | .packet = sctp_packet, |
772 | - .new = sctp_new, | |
773 | 766 | .error = sctp_error, |
774 | 767 | .can_early_drop = sctp_can_early_drop, |
775 | 768 | .me = THIS_MODULE, |
... | ... | @@ -803,7 +796,6 @@ |
803 | 796 | .print_conntrack = sctp_print_conntrack, |
804 | 797 | #endif |
805 | 798 | .packet = sctp_packet, |
806 | - .new = sctp_new, | |
807 | 799 | .error = sctp_error, |
808 | 800 | .can_early_drop = sctp_can_early_drop, |
809 | 801 | .me = THIS_MODULE, |
net/netfilter/nf_conntrack_proto_tcp.c
... | ... | @@ -770,6 +770,78 @@ |
770 | 770 | return NF_ACCEPT; |
771 | 771 | } |
772 | 772 | |
773 | +static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
774 | + unsigned int dataoff, | |
775 | + const struct tcphdr *th) | |
776 | +{ | |
777 | + enum tcp_conntrack new_state; | |
778 | + struct net *net = nf_ct_net(ct); | |
779 | + const struct nf_tcp_net *tn = tcp_pernet(net); | |
780 | + const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0]; | |
781 | + const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1]; | |
782 | + | |
783 | + /* Don't need lock here: this conntrack not in circulation yet */ | |
784 | + new_state = tcp_conntracks[0][get_conntrack_index(th)][TCP_CONNTRACK_NONE]; | |
785 | + | |
786 | + /* Invalid: delete conntrack */ | |
787 | + if (new_state >= TCP_CONNTRACK_MAX) { | |
788 | + pr_debug("nf_ct_tcp: invalid new deleting.\n"); | |
789 | + return false; | |
790 | + } | |
791 | + | |
792 | + if (new_state == TCP_CONNTRACK_SYN_SENT) { | |
793 | + memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp)); | |
794 | + /* SYN packet */ | |
795 | + ct->proto.tcp.seen[0].td_end = | |
796 | + segment_seq_plus_len(ntohl(th->seq), skb->len, | |
797 | + dataoff, th); | |
798 | + ct->proto.tcp.seen[0].td_maxwin = ntohs(th->window); | |
799 | + if (ct->proto.tcp.seen[0].td_maxwin == 0) | |
800 | + ct->proto.tcp.seen[0].td_maxwin = 1; | |
801 | + ct->proto.tcp.seen[0].td_maxend = | |
802 | + ct->proto.tcp.seen[0].td_end; | |
803 | + | |
804 | + tcp_options(skb, dataoff, th, &ct->proto.tcp.seen[0]); | |
805 | + } else if (tn->tcp_loose == 0) { | |
806 | + /* Don't try to pick up connections. */ | |
807 | + return false; | |
808 | + } else { | |
809 | + memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp)); | |
810 | + /* | |
811 | + * We are in the middle of a connection, | |
812 | + * its history is lost for us. | |
813 | + * Let's try to use the data from the packet. | |
814 | + */ | |
815 | + ct->proto.tcp.seen[0].td_end = | |
816 | + segment_seq_plus_len(ntohl(th->seq), skb->len, | |
817 | + dataoff, th); | |
818 | + ct->proto.tcp.seen[0].td_maxwin = ntohs(th->window); | |
819 | + if (ct->proto.tcp.seen[0].td_maxwin == 0) | |
820 | + ct->proto.tcp.seen[0].td_maxwin = 1; | |
821 | + ct->proto.tcp.seen[0].td_maxend = | |
822 | + ct->proto.tcp.seen[0].td_end + | |
823 | + ct->proto.tcp.seen[0].td_maxwin; | |
824 | + | |
825 | + /* We assume SACK and liberal window checking to handle | |
826 | + * window scaling */ | |
827 | + ct->proto.tcp.seen[0].flags = | |
828 | + ct->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM | | |
829 | + IP_CT_TCP_FLAG_BE_LIBERAL; | |
830 | + } | |
831 | + | |
832 | + /* tcp_packet will set them */ | |
833 | + ct->proto.tcp.last_index = TCP_NONE_SET; | |
834 | + | |
835 | + pr_debug("%s: sender end=%u maxend=%u maxwin=%u scale=%i " | |
836 | + "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | |
837 | + __func__, | |
838 | + sender->td_end, sender->td_maxend, sender->td_maxwin, | |
839 | + sender->td_scale, | |
840 | + receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | |
841 | + receiver->td_scale); | |
842 | + return true; | |
843 | +} | |
844 | + | |
773 | 845 | /* Returns verdict for packet, or -1 for invalid. */ |
774 | 846 | static int tcp_packet(struct nf_conn *ct, |
775 | 847 | const struct sk_buff *skb, |
776 | 848 | |
... | ... | @@ -788,8 +860,12 @@ |
788 | 860 | unsigned long timeout; |
789 | 861 | |
790 | 862 | th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); |
791 | - BUG_ON(th == NULL); | |
863 | + if (th == NULL) | |
864 | + return -NF_ACCEPT; | |
792 | 865 | |
866 | + if (!nf_ct_is_confirmed(ct) && !tcp_new(ct, skb, dataoff, th)) | |
867 | + return -NF_ACCEPT; | |
868 | + | |
793 | 869 | spin_lock_bh(&ct->lock); |
794 | 870 | old_state = ct->proto.tcp.state; |
795 | 871 | dir = CTINFO2DIR(ctinfo); |
... | ... | @@ -1069,82 +1145,6 @@ |
1069 | 1145 | return NF_ACCEPT; |
1070 | 1146 | } |
1071 | 1147 | |
1072 | -/* Called when a new connection for this protocol found. */ | |
1073 | -static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
1074 | - unsigned int dataoff) | |
1075 | -{ | |
1076 | - enum tcp_conntrack new_state; | |
1077 | - const struct tcphdr *th; | |
1078 | - struct tcphdr _tcph; | |
1079 | - struct net *net = nf_ct_net(ct); | |
1080 | - struct nf_tcp_net *tn = tcp_pernet(net); | |
1081 | - const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0]; | |
1082 | - const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1]; | |
1083 | - | |
1084 | - th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); | |
1085 | - BUG_ON(th == NULL); | |
1086 | - | |
1087 | - /* Don't need lock here: this conntrack not in circulation yet */ | |
1088 | - new_state = tcp_conntracks[0][get_conntrack_index(th)][TCP_CONNTRACK_NONE]; | |
1089 | - | |
1090 | - /* Invalid: delete conntrack */ | |
1091 | - if (new_state >= TCP_CONNTRACK_MAX) { | |
1092 | - pr_debug("nf_ct_tcp: invalid new deleting.\n"); | |
1093 | - return false; | |
1094 | - } | |
1095 | - | |
1096 | - if (new_state == TCP_CONNTRACK_SYN_SENT) { | |
1097 | - memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp)); | |
1098 | - /* SYN packet */ | |
1099 | - ct->proto.tcp.seen[0].td_end = | |
1100 | - segment_seq_plus_len(ntohl(th->seq), skb->len, | |
1101 | - dataoff, th); | |
1102 | - ct->proto.tcp.seen[0].td_maxwin = ntohs(th->window); | |
1103 | - if (ct->proto.tcp.seen[0].td_maxwin == 0) | |
1104 | - ct->proto.tcp.seen[0].td_maxwin = 1; | |
1105 | - ct->proto.tcp.seen[0].td_maxend = | |
1106 | - ct->proto.tcp.seen[0].td_end; | |
1107 | - | |
1108 | - tcp_options(skb, dataoff, th, &ct->proto.tcp.seen[0]); | |
1109 | - } else if (tn->tcp_loose == 0) { | |
1110 | - /* Don't try to pick up connections. */ | |
1111 | - return false; | |
1112 | - } else { | |
1113 | - memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp)); | |
1114 | - /* | |
1115 | - * We are in the middle of a connection, | |
1116 | - * its history is lost for us. | |
1117 | - * Let's try to use the data from the packet. | |
1118 | - */ | |
1119 | - ct->proto.tcp.seen[0].td_end = | |
1120 | - segment_seq_plus_len(ntohl(th->seq), skb->len, | |
1121 | - dataoff, th); | |
1122 | - ct->proto.tcp.seen[0].td_maxwin = ntohs(th->window); | |
1123 | - if (ct->proto.tcp.seen[0].td_maxwin == 0) | |
1124 | - ct->proto.tcp.seen[0].td_maxwin = 1; | |
1125 | - ct->proto.tcp.seen[0].td_maxend = | |
1126 | - ct->proto.tcp.seen[0].td_end + | |
1127 | - ct->proto.tcp.seen[0].td_maxwin; | |
1128 | - | |
1129 | - /* We assume SACK and liberal window checking to handle | |
1130 | - * window scaling */ | |
1131 | - ct->proto.tcp.seen[0].flags = | |
1132 | - ct->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM | | |
1133 | - IP_CT_TCP_FLAG_BE_LIBERAL; | |
1134 | - } | |
1135 | - | |
1136 | - /* tcp_packet will set them */ | |
1137 | - ct->proto.tcp.last_index = TCP_NONE_SET; | |
1138 | - | |
1139 | - pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i " | |
1140 | - "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | |
1141 | - sender->td_end, sender->td_maxend, sender->td_maxwin, | |
1142 | - sender->td_scale, | |
1143 | - receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | |
1144 | - receiver->td_scale); | |
1145 | - return true; | |
1146 | -} | |
1147 | - | |
1148 | 1148 | static bool tcp_can_early_drop(const struct nf_conn *ct) |
1149 | 1149 | { |
1150 | 1150 | switch (ct->proto.tcp.state) { |
... | ... | @@ -1548,7 +1548,6 @@ |
1548 | 1548 | .print_conntrack = tcp_print_conntrack, |
1549 | 1549 | #endif |
1550 | 1550 | .packet = tcp_packet, |
1551 | - .new = tcp_new, | |
1552 | 1551 | .error = tcp_error, |
1553 | 1552 | .can_early_drop = tcp_can_early_drop, |
1554 | 1553 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
... | ... | @@ -1583,7 +1582,6 @@ |
1583 | 1582 | .print_conntrack = tcp_print_conntrack, |
1584 | 1583 | #endif |
1585 | 1584 | .packet = tcp_packet, |
1586 | - .new = tcp_new, | |
1587 | 1585 | .error = tcp_error, |
1588 | 1586 | .can_early_drop = tcp_can_early_drop, |
1589 | 1587 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
net/netfilter/nf_conntrack_proto_udp.c
... | ... | @@ -70,13 +70,6 @@ |
70 | 70 | return NF_ACCEPT; |
71 | 71 | } |
72 | 72 | |
73 | -/* Called when a new connection for this protocol found. */ | |
74 | -static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb, | |
75 | - unsigned int dataoff) | |
76 | -{ | |
77 | - return true; | |
78 | -} | |
79 | - | |
80 | 73 | #ifdef CONFIG_NF_CT_PROTO_UDPLITE |
81 | 74 | static void udplite_error_log(const struct sk_buff *skb, |
82 | 75 | const struct nf_hook_state *state, |
... | ... | @@ -288,7 +281,6 @@ |
288 | 281 | .l4proto = IPPROTO_UDP, |
289 | 282 | .allow_clash = true, |
290 | 283 | .packet = udp_packet, |
291 | - .new = udp_new, | |
292 | 284 | .error = udp_error, |
293 | 285 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
294 | 286 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
... | ... | @@ -317,7 +309,6 @@ |
317 | 309 | .l4proto = IPPROTO_UDPLITE, |
318 | 310 | .allow_clash = true, |
319 | 311 | .packet = udp_packet, |
320 | - .new = udp_new, | |
321 | 312 | .error = udplite_error, |
322 | 313 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
323 | 314 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
... | ... | @@ -346,7 +337,6 @@ |
346 | 337 | .l4proto = IPPROTO_UDP, |
347 | 338 | .allow_clash = true, |
348 | 339 | .packet = udp_packet, |
349 | - .new = udp_new, | |
350 | 340 | .error = udp_error, |
351 | 341 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
352 | 342 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
... | ... | @@ -375,7 +365,6 @@ |
375 | 365 | .l4proto = IPPROTO_UDPLITE, |
376 | 366 | .allow_clash = true, |
377 | 367 | .packet = udp_packet, |
378 | - .new = udp_new, | |
379 | 368 | .error = udplite_error, |
380 | 369 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
381 | 370 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |