diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2010-09-22 02:34:12 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-09-22 02:34:12 -0400 |
commit | 5b92b61f3891517d18d0573ad2c939c81b59ecfe (patch) | |
tree | 4d61d64041d559e6478a53f865fb779df99cedc9 /net/ipv4 | |
parent | 26c15cfd291f8b4ee40b4bbdf5e3772adfd704f5 (diff) |
netfilter: nf_nat: better error handling of nf_ct_expect_related() in helpers
This patch improves the situation in which the expectation table is
full for conntrack NAT helpers. Basically, we give up if we don't
find a place in the table instead of looping over nf_ct_expect_related()
with a different port (we should only do this if it returns -EBUSY, for
-EMFILE or -ESHUTDOWN I think that it's better to skip this).
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/nf_nat_amanda.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_ftp.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_h323.c | 53 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_irc.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_sip.c | 27 |
5 files changed, 93 insertions, 14 deletions
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c index c31b87668250..0f23b3f06df0 100644 --- a/net/ipv4/netfilter/nf_nat_amanda.c +++ b/net/ipv4/netfilter/nf_nat_amanda.c | |||
@@ -44,9 +44,16 @@ static unsigned int help(struct sk_buff *skb, | |||
44 | 44 | ||
45 | /* Try to get same port: if not, try to change it. */ | 45 | /* Try to get same port: if not, try to change it. */ |
46 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { | 46 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { |
47 | int ret; | ||
48 | |||
47 | exp->tuple.dst.u.tcp.port = htons(port); | 49 | exp->tuple.dst.u.tcp.port = htons(port); |
48 | if (nf_ct_expect_related(exp) == 0) | 50 | ret = nf_ct_expect_related(exp); |
51 | if (ret == 0) | ||
52 | break; | ||
53 | else if (ret != -EBUSY) { | ||
54 | port = 0; | ||
49 | break; | 55 | break; |
56 | } | ||
50 | } | 57 | } |
51 | 58 | ||
52 | if (port == 0) | 59 | if (port == 0) |
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index 86e0e84ff0a0..dc73abb3fe27 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c | |||
@@ -79,9 +79,16 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, | |||
79 | 79 | ||
80 | /* Try to get same port: if not, try to change it. */ | 80 | /* Try to get same port: if not, try to change it. */ |
81 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { | 81 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { |
82 | int ret; | ||
83 | |||
82 | exp->tuple.dst.u.tcp.port = htons(port); | 84 | exp->tuple.dst.u.tcp.port = htons(port); |
83 | if (nf_ct_expect_related(exp) == 0) | 85 | ret = nf_ct_expect_related(exp); |
86 | if (ret == 0) | ||
87 | break; | ||
88 | else if (ret != -EBUSY) { | ||
89 | port = 0; | ||
84 | break; | 90 | break; |
91 | } | ||
85 | } | 92 | } |
86 | 93 | ||
87 | if (port == 0) | 94 | if (port == 0) |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 5045196d853c..790f3160e012 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
@@ -222,13 +222,24 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
222 | /* Try to get a pair of ports. */ | 222 | /* Try to get a pair of ports. */ |
223 | for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); | 223 | for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); |
224 | nated_port != 0; nated_port += 2) { | 224 | nated_port != 0; nated_port += 2) { |
225 | int ret; | ||
226 | |||
225 | rtp_exp->tuple.dst.u.udp.port = htons(nated_port); | 227 | rtp_exp->tuple.dst.u.udp.port = htons(nated_port); |
226 | if (nf_ct_expect_related(rtp_exp) == 0) { | 228 | ret = nf_ct_expect_related(rtp_exp); |
229 | if (ret == 0) { | ||
227 | rtcp_exp->tuple.dst.u.udp.port = | 230 | rtcp_exp->tuple.dst.u.udp.port = |
228 | htons(nated_port + 1); | 231 | htons(nated_port + 1); |
229 | if (nf_ct_expect_related(rtcp_exp) == 0) | 232 | ret = nf_ct_expect_related(rtcp_exp); |
233 | if (ret == 0) | ||
234 | break; | ||
235 | else if (ret != -EBUSY) { | ||
236 | nf_ct_unexpect_related(rtp_exp); | ||
237 | nated_port = 0; | ||
230 | break; | 238 | break; |
231 | nf_ct_unexpect_related(rtp_exp); | 239 | } |
240 | } else if (ret != -EBUSY) { | ||
241 | nated_port = 0; | ||
242 | break; | ||
232 | } | 243 | } |
233 | } | 244 | } |
234 | 245 | ||
@@ -284,9 +295,16 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, | |||
284 | 295 | ||
285 | /* Try to get same port: if not, try to change it. */ | 296 | /* Try to get same port: if not, try to change it. */ |
286 | for (; nated_port != 0; nated_port++) { | 297 | for (; nated_port != 0; nated_port++) { |
298 | int ret; | ||
299 | |||
287 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 300 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
288 | if (nf_ct_expect_related(exp) == 0) | 301 | ret = nf_ct_expect_related(exp); |
302 | if (ret == 0) | ||
303 | break; | ||
304 | else if (ret != -EBUSY) { | ||
305 | nated_port = 0; | ||
289 | break; | 306 | break; |
307 | } | ||
290 | } | 308 | } |
291 | 309 | ||
292 | if (nated_port == 0) { /* No port available */ | 310 | if (nated_port == 0) { /* No port available */ |
@@ -334,9 +352,16 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, | |||
334 | 352 | ||
335 | /* Try to get same port: if not, try to change it. */ | 353 | /* Try to get same port: if not, try to change it. */ |
336 | for (; nated_port != 0; nated_port++) { | 354 | for (; nated_port != 0; nated_port++) { |
355 | int ret; | ||
356 | |||
337 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 357 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
338 | if (nf_ct_expect_related(exp) == 0) | 358 | ret = nf_ct_expect_related(exp); |
359 | if (ret == 0) | ||
339 | break; | 360 | break; |
361 | else if (ret != -EBUSY) { | ||
362 | nated_port = 0; | ||
363 | break; | ||
364 | } | ||
340 | } | 365 | } |
341 | 366 | ||
342 | if (nated_port == 0) { /* No port available */ | 367 | if (nated_port == 0) { /* No port available */ |
@@ -418,9 +443,16 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
418 | 443 | ||
419 | /* Try to get same port: if not, try to change it. */ | 444 | /* Try to get same port: if not, try to change it. */ |
420 | for (; nated_port != 0; nated_port++) { | 445 | for (; nated_port != 0; nated_port++) { |
446 | int ret; | ||
447 | |||
421 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 448 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
422 | if (nf_ct_expect_related(exp) == 0) | 449 | ret = nf_ct_expect_related(exp); |
450 | if (ret == 0) | ||
451 | break; | ||
452 | else if (ret != -EBUSY) { | ||
453 | nated_port = 0; | ||
423 | break; | 454 | break; |
455 | } | ||
424 | } | 456 | } |
425 | 457 | ||
426 | if (nated_port == 0) { /* No port available */ | 458 | if (nated_port == 0) { /* No port available */ |
@@ -500,9 +532,16 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, | |||
500 | 532 | ||
501 | /* Try to get same port: if not, try to change it. */ | 533 | /* Try to get same port: if not, try to change it. */ |
502 | for (nated_port = ntohs(port); nated_port != 0; nated_port++) { | 534 | for (nated_port = ntohs(port); nated_port != 0; nated_port++) { |
535 | int ret; | ||
536 | |||
503 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 537 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
504 | if (nf_ct_expect_related(exp) == 0) | 538 | ret = nf_ct_expect_related(exp); |
539 | if (ret == 0) | ||
505 | break; | 540 | break; |
541 | else if (ret != -EBUSY) { | ||
542 | nated_port = 0; | ||
543 | break; | ||
544 | } | ||
506 | } | 545 | } |
507 | 546 | ||
508 | if (nated_port == 0) { /* No port available */ | 547 | if (nated_port == 0) { /* No port available */ |
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c index ea83a886b03e..535e1a802356 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/ipv4/netfilter/nf_nat_irc.c | |||
@@ -45,9 +45,16 @@ static unsigned int help(struct sk_buff *skb, | |||
45 | 45 | ||
46 | /* Try to get same port: if not, try to change it. */ | 46 | /* Try to get same port: if not, try to change it. */ |
47 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { | 47 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { |
48 | int ret; | ||
49 | |||
48 | exp->tuple.dst.u.tcp.port = htons(port); | 50 | exp->tuple.dst.u.tcp.port = htons(port); |
49 | if (nf_ct_expect_related(exp) == 0) | 51 | ret = nf_ct_expect_related(exp); |
52 | if (ret == 0) | ||
53 | break; | ||
54 | else if (ret != -EBUSY) { | ||
55 | port = 0; | ||
50 | break; | 56 | break; |
57 | } | ||
51 | } | 58 | } |
52 | 59 | ||
53 | if (port == 0) | 60 | if (port == 0) |
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 11b538deaaec..e40cf7816fdb 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
@@ -307,9 +307,16 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, | |||
307 | exp->expectfn = ip_nat_sip_expected; | 307 | exp->expectfn = ip_nat_sip_expected; |
308 | 308 | ||
309 | for (; port != 0; port++) { | 309 | for (; port != 0; port++) { |
310 | int ret; | ||
311 | |||
310 | exp->tuple.dst.u.udp.port = htons(port); | 312 | exp->tuple.dst.u.udp.port = htons(port); |
311 | if (nf_ct_expect_related(exp) == 0) | 313 | ret = nf_ct_expect_related(exp); |
314 | if (ret == 0) | ||
315 | break; | ||
316 | else if (ret != -EBUSY) { | ||
317 | port = 0; | ||
312 | break; | 318 | break; |
319 | } | ||
313 | } | 320 | } |
314 | 321 | ||
315 | if (port == 0) | 322 | if (port == 0) |
@@ -480,13 +487,25 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, | |||
480 | /* Try to get same pair of ports: if not, try to change them. */ | 487 | /* Try to get same pair of ports: if not, try to change them. */ |
481 | for (port = ntohs(rtp_exp->tuple.dst.u.udp.port); | 488 | for (port = ntohs(rtp_exp->tuple.dst.u.udp.port); |
482 | port != 0; port += 2) { | 489 | port != 0; port += 2) { |
490 | int ret; | ||
491 | |||
483 | rtp_exp->tuple.dst.u.udp.port = htons(port); | 492 | rtp_exp->tuple.dst.u.udp.port = htons(port); |
484 | if (nf_ct_expect_related(rtp_exp) != 0) | 493 | ret = nf_ct_expect_related(rtp_exp); |
494 | if (ret == -EBUSY) | ||
485 | continue; | 495 | continue; |
496 | else if (ret < 0) { | ||
497 | port = 0; | ||
498 | break; | ||
499 | } | ||
486 | rtcp_exp->tuple.dst.u.udp.port = htons(port + 1); | 500 | rtcp_exp->tuple.dst.u.udp.port = htons(port + 1); |
487 | if (nf_ct_expect_related(rtcp_exp) == 0) | 501 | ret = nf_ct_expect_related(rtcp_exp); |
502 | if (ret == 0) | ||
488 | break; | 503 | break; |
489 | nf_ct_unexpect_related(rtp_exp); | 504 | else if (ret != -EBUSY) { |
505 | nf_ct_unexpect_related(rtp_exp); | ||
506 | port = 0; | ||
507 | break; | ||
508 | } | ||
490 | } | 509 | } |
491 | 510 | ||
492 | if (port == 0) | 511 | if (port == 0) |