>Number:         181690
>Category:       kern
>Synopsis:       patch that fix pf "NAT proxy port allocation"
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Aug 30 19:00:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Olivier Cochard-Labbe
>Release:        9.2-RC3
>Organization:
BSD Router Project
>Environment:
FreeBSD bsdrp2.orange.bsdrp.net 9.2-RC3 FreeBSD 9.2-RC3 #0 r255043M: Fri Aug 30 
18:57:21 CEST 2013     
r...@orange.bsdrp.net:/usr/obj/BSDRP.amd64/usr/local/BSDRP/BSDRP/FreeBSD/src/sys/amd64
  amd64
>Description:
I've got some UDP packet loss with pf configured with NAT.

Here is my pf.conf:
ext_if = "igb3"
set skip on lo0
set debug loud
nat on $ext_if inet from any to any -> $ext_if port 50000:50003
pass

=> The NAT range port is limited to 4 port for an easy reproduction of this 
problem.

Then I generate 4 parallel UDP flow (with 4 netblast), but when I start the 3th 
flow I've got theses log message:
kernel: pf: wire key attach failed on all: UDP out wire: 2.2.2.3:4123 
2.2.2.2:50003 1:0, existing: UDP out wire: 2.2.2.3:4123 2.2.2.2
kernel: :50003 stack: 2.2.2.3:4123 1.1.1.1:39749 1:0

I've found this same error message regarding OpenBSD 4.6 here:
http://openbsd.7691.n7.nabble.com/kernel-6300-PF-NAT-UDP-port-reuse-wire-key-attach-failed-td195274.html

>From this thread, it seems that "pf_get_sport() was failing to notice that the 
>ports were in-use" and there is a proposed patch.
I've adapted this patch to FreeBSD (9.2) and do a try: No more "wire key attach 
failed", I've got this message in place:
Aug 30 19:40:37 bsdrp2 kernel: pf: NAT proxy port allocation (50000-50003) 
failed

Regards
>How-To-Repeat:
Use the pf.conf example file given on my full description, and try to generate 
more than 3 or 4 UDP flows that match the NAT condition.

>Fix:
By applying this patch.
But Warning: I didn't have any idea of what exactly this patch do!!!
I've just did a "dummy" adaptation and it magically works :-)

Patch attached with submission follows:

Index: sys/contrib/pf/net/pf_lb.c
===================================================================
--- sys/contrib/pf/net/pf_lb.c  (revision 255043)
+++ sys/contrib/pf/net/pf_lb.c  (working copy)
@@ -338,9 +338,9 @@
        do {
                key.af = af;
                key.proto = proto;
-               PF_ACPY(&key.addr[1], daddr, key.af);
-               PF_ACPY(&key.addr[0], naddr, key.af);
-               key.port[1] = dport;
+               PF_ACPY(&key.addr[0], daddr, key.af);
+               PF_ACPY(&key.addr[1], naddr, key.af);
+               key.port[0] = dport;
 
                /*
                 * port search; start random, step;
@@ -349,11 +349,11 @@
                if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
                    proto == IPPROTO_ICMP)) {
                        key.port[0] = dport;
-                       if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
+                       if (pf_find_state_all(&key, PF_OUT, NULL) == NULL)
                                return (0);
                } else if (low == 0 && high == 0) {
                        key.port[0] = *nport;
-                       if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
+                       if (pf_find_state_all(&key, PF_OUT, NULL) == NULL)
                                return (0);
                } else if (low == high) {
                        key.port[0] = htons(low);
@@ -377,7 +377,7 @@
 #endif
                        /* low <= cut <= high */
                        for (tmp = cut; tmp <= high; ++(tmp)) {
-                               key.port[0] = htons(tmp);
+                               key.port[1] = htons(tmp);
                                if (pf_find_state_all(&key, PF_IN, NULL) ==
 #ifdef __FreeBSD__
                                    NULL) {
@@ -389,7 +389,7 @@
                                }
                        }
                        for (tmp = cut - 1; tmp >= low; --(tmp)) {
-                               key.port[0] = htons(tmp);
+                               key.port[1] = htons(tmp);
                                if (pf_find_state_all(&key, PF_IN, NULL) ==
 #ifdef __FreeBSD__
                                    NULL) {


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to