svn commit: r256882 - stable/9/sys/contrib/pf/net

Gleb Smirnoff glebius at FreeBSD.org
Tue Oct 22 09:58:32 UTC 2013


Author: glebius
Date: Tue Oct 22 09:58:31 2013
New Revision: 256882
URL: http://svnweb.freebsd.org/changeset/base/256882

Log:
  Merge r255143 from head:
    Merge 1.12 of pf_lb.c from OpenBSD, with some changes. Original commit:
  
      date: 2010/02/04 14:10:12;  author: sthen;  state: Exp;  lines: +24 -19;
      pf_get_sport() picks a random port from the port range specified in a
      nat rule. It should check to see if it's in-use (i.e. matches an existing
      PF state), if it is, it cycles sequentially through other ports until
      it finds a free one. However the check was being done with the state
      keys the wrong way round so it was never actually finding the state
      to be in-use.
  
      - switch the keys to correct this, avoiding random state collisions
      with nat. Fixes PR 6300 and problems reported by robert@ and viq.
  
      - check pf_get_sport() return code in pf_test(); if port allocation
      fails the packet should be dropped rather than sent out untranslated.
  
      Help/ok claudio at .
  
    Some additional changes to 1.12:
  
    - We also need to bzero() the key to zero padding, otherwise key
      won't match.
    - Collapse two if blocks into one with ||, since both conditions
      lead to the same processing.
    - Only naddr changes in the cycle, so move initialization of other
      fields above the cycle.
    - s/u_intXX_t/uintXX_t/g
  
    PR:             kern/181690
    Submitted by:   Olivier Cochard-Labbé <olivier cochard.me>
    Sponsored by:   Nginx, Inc.

Modified:
  stable/9/sys/contrib/pf/net/pf_lb.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/contrib/pf/   (props changed)

Modified: stable/9/sys/contrib/pf/net/pf_lb.c
==============================================================================
--- stable/9/sys/contrib/pf/net/pf_lb.c	Tue Oct 22 09:43:14 2013	(r256881)
+++ stable/9/sys/contrib/pf/net/pf_lb.c	Tue Oct 22 09:58:31 2013	(r256882)
@@ -165,8 +165,8 @@ struct pf_rule		*pf_match_translation(st
 			    struct pf_addr *, u_int16_t, struct pf_addr *,
 			    u_int16_t, int);
 int			 pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
-			    struct pf_addr *, struct pf_addr *, u_int16_t,
-			    struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
+			    struct pf_addr *, uint16_t, struct pf_addr *, uint16_t,
+			    struct pf_addr *, uint16_t*, uint16_t, uint16_t,
 			    struct pf_src_node **);
 
 #define mix(a,b,c) \
@@ -318,13 +318,13 @@ pf_match_translation(struct pf_pdesc *pd
 
 int
 pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
-    struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
-    struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
-    struct pf_src_node **sn)
+    struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
+    uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low,
+    uint16_t high, struct pf_src_node **sn)
 {
 	struct pf_state_key_cmp	key;
 	struct pf_addr		init_addr;
-	u_int16_t		cut;
+	uint16_t		cut;
 
 	bzero(&init_addr, sizeof(init_addr));
 	if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
@@ -335,34 +335,38 @@ pf_get_sport(sa_family_t af, u_int8_t pr
 		high = 65535;
 	}
 
+	bzero(&key,sizeof(key));
+	key.af = af;
+	key.proto = proto;
+	key.port[0] = dport;
+	PF_ACPY(&key.addr[0], daddr, key.af);
+
 	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[1], naddr, key.af);
 
 		/*
 		 * port search; start random, step;
 		 * similar 2 portloop in in_pcbbind
 		 */
 		if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
-		    proto == IPPROTO_ICMP)) {
-			key.port[0] = dport;
-			if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
-				return (0);
-		} else if (low == 0 && high == 0) {
-			key.port[0] = *nport;
-			if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
+		    proto == IPPROTO_ICMP) || (low == 0 && high == 0)) {
+			/*
+			* XXX bug: icmp state don't use the id on both sides.
+			* (traceroute -l through nat)
+			*/
+			key.port[1] = sport;
+			if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
+				*nport = sport;
 				return (0);
+			}
 		} else if (low == high) {
-			key.port[0] = htons(low);
+			key.port[1] = htons(low);
 			if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
 				*nport = htons(low);
 				return (0);
 			}
 		} else {
-			u_int16_t tmp;
+			uint16_t tmp;
 
 			if (low > high) {
 				tmp = low;
@@ -377,7 +381,7 @@ pf_get_sport(sa_family_t af, u_int8_t pr
 #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 +393,7 @@ pf_get_sport(sa_family_t af, u_int8_t pr
 				}
 			}
 			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) {
@@ -655,8 +659,8 @@ pf_get_translation(struct pf_pdesc *pd, 
 		case PF_NORDR:
 			return (NULL);
 		case PF_NAT:
-			if (pf_get_sport(pd->af, pd->proto, r, saddr,
-			    daddr, dport, naddr, nport, r->rpool.proxy_port[0],
+			if (pf_get_sport(pd->af, pd->proto, r, saddr, sport, daddr,
+			    dport, naddr, nport, r->rpool.proxy_port[0],
 			    r->rpool.proxy_port[1], sn)) {
 				DPFPRINTF(PF_DEBUG_MISC,
 				    ("pf: NAT proxy port allocation "


More information about the svn-src-stable-9 mailing list