]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - sys/contrib/pf/net/pf_lb.c
Copy stable/9 to releng/9.3 as part of the 9.3-RELEASE cycle.
[FreeBSD/releng/9.3.git] / sys / contrib / pf / net / pf_lb.c
1 /*      $OpenBSD: pf_lb.c,v 1.2 2009/02/12 02:13:15 sthen Exp $ */
2
3 /*
4  * Copyright (c) 2001 Daniel Hartmeier
5  * Copyright (c) 2002 - 2008 Henning Brauer
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *    - Redistributions of source code must retain the above copyright
13  *      notice, this list of conditions and the following disclaimer.
14  *    - Redistributions in binary form must reproduce the above
15  *      copyright notice, this list of conditions and the following
16  *      disclaimer in the documentation and/or other materials provided
17  *      with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  * Effort sponsored in part by the Defense Advanced Research Projects
33  * Agency (DARPA) and Air Force Research Laboratory, Air Force
34  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
35  *
36  */
37
38 #ifdef __FreeBSD__
39 #include "opt_inet.h"
40 #include "opt_inet6.h"
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44 #endif
45
46 #ifdef __FreeBSD__
47 #include "opt_bpf.h"
48 #include "opt_pf.h"
49
50 #ifdef DEV_BPF
51 #define NBPFILTER       DEV_BPF
52 #else
53 #define NBPFILTER       0
54 #endif
55
56 #ifdef DEV_PFLOG
57 #define NPFLOG          DEV_PFLOG
58 #else
59 #define NPFLOG          0
60 #endif
61
62 #ifdef DEV_PFSYNC
63 #define NPFSYNC         DEV_PFSYNC
64 #else
65 #define NPFSYNC         0
66 #endif
67
68 #ifdef DEV_PFLOW
69 #define NPFLOW  DEV_PFLOW
70 #else
71 #define NPFLOW  0
72 #endif
73
74 #else
75 #include "bpfilter.h"
76 #include "pflog.h"
77 #include "pfsync.h"
78 #include "pflow.h"
79 #endif
80
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/mbuf.h>
84 #include <sys/filio.h>
85 #include <sys/socket.h>
86 #include <sys/socketvar.h>
87 #include <sys/kernel.h>
88 #include <sys/time.h>
89 #ifdef  __FreeBSD__
90 #include <sys/sysctl.h>
91 #endif
92 #ifndef __FreeBSD__
93 #include <sys/pool.h>
94 #endif
95 #include <sys/proc.h>
96 #ifdef __FreeBSD__
97 #include <sys/kthread.h>
98 #include <sys/lock.h>
99 #include <sys/sx.h>
100 #else
101 #include <sys/rwlock.h>
102 #endif
103
104 #ifdef __FreeBSD__
105 #include <sys/md5.h>
106 #else
107 #include <crypto/md5.h>
108 #endif
109
110 #include <net/if.h>
111 #include <net/if_types.h>
112 #include <net/bpf.h>
113 #include <net/route.h>
114 #include <net/radix_mpath.h>
115
116 #include <netinet/in.h>
117 #include <netinet/in_var.h>
118 #include <netinet/in_systm.h>
119 #include <netinet/ip.h>
120 #include <netinet/ip_var.h>
121 #include <netinet/tcp.h>
122 #include <netinet/tcp_seq.h>
123 #include <netinet/udp.h>
124 #include <netinet/ip_icmp.h>
125 #include <netinet/in_pcb.h>
126 #include <netinet/tcp_timer.h>
127 #include <netinet/tcp_var.h>
128 #include <netinet/udp_var.h>
129 #include <netinet/icmp_var.h>
130 #include <netinet/if_ether.h>
131
132 #ifndef __FreeBSD__
133 #include <dev/rndvar.h>
134 #endif
135 #include <net/pfvar.h>
136 #include <net/if_pflog.h>
137 #include <net/if_pflow.h>
138
139 #if NPFSYNC > 0
140 #include <net/if_pfsync.h>
141 #endif /* NPFSYNC > 0 */
142
143 #ifdef INET6
144 #include <netinet/ip6.h>
145 #include <netinet/in_pcb.h>
146 #include <netinet/icmp6.h>
147 #include <netinet6/nd6.h>
148 #endif /* INET6 */
149
150
151 #ifdef __FreeBSD__
152 #define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
153 #else
154 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
155 #endif
156
157 /*
158  * Global variables
159  */
160
161 void                     pf_hash(struct pf_addr *, struct pf_addr *,
162                             struct pf_poolhashkey *, sa_family_t);
163 struct pf_rule          *pf_match_translation(struct pf_pdesc *, struct mbuf *,
164                             int, int, struct pfi_kif *,
165                             struct pf_addr *, u_int16_t, struct pf_addr *,
166                             u_int16_t, int);
167 int                      pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
168                             struct pf_addr *, uint16_t, struct pf_addr *, uint16_t,
169                             struct pf_addr *, uint16_t*, uint16_t, uint16_t,
170                             struct pf_src_node **);
171
172 #define mix(a,b,c) \
173         do {                                    \
174                 a -= b; a -= c; a ^= (c >> 13); \
175                 b -= c; b -= a; b ^= (a << 8);  \
176                 c -= a; c -= b; c ^= (b >> 13); \
177                 a -= b; a -= c; a ^= (c >> 12); \
178                 b -= c; b -= a; b ^= (a << 16); \
179                 c -= a; c -= b; c ^= (b >> 5);  \
180                 a -= b; a -= c; a ^= (c >> 3);  \
181                 b -= c; b -= a; b ^= (a << 10); \
182                 c -= a; c -= b; c ^= (b >> 15); \
183         } while (0)
184
185 /*
186  * hash function based on bridge_hash in if_bridge.c
187  */
188 void
189 pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
190     struct pf_poolhashkey *key, sa_family_t af)
191 {
192         u_int32_t       a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
193
194         switch (af) {
195 #ifdef INET
196         case AF_INET:
197                 a += inaddr->addr32[0];
198                 b += key->key32[1];
199                 mix(a, b, c);
200                 hash->addr32[0] = c + key->key32[2];
201                 break;
202 #endif /* INET */
203 #ifdef INET6
204         case AF_INET6:
205                 a += inaddr->addr32[0];
206                 b += inaddr->addr32[2];
207                 mix(a, b, c);
208                 hash->addr32[0] = c;
209                 a += inaddr->addr32[1];
210                 b += inaddr->addr32[3];
211                 c += key->key32[1];
212                 mix(a, b, c);
213                 hash->addr32[1] = c;
214                 a += inaddr->addr32[2];
215                 b += inaddr->addr32[1];
216                 c += key->key32[2];
217                 mix(a, b, c);
218                 hash->addr32[2] = c;
219                 a += inaddr->addr32[3];
220                 b += inaddr->addr32[0];
221                 c += key->key32[3];
222                 mix(a, b, c);
223                 hash->addr32[3] = c;
224                 break;
225 #endif /* INET6 */
226         }
227 }
228
229 struct pf_rule *
230 pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
231     int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
232     struct pf_addr *daddr, u_int16_t dport, int rs_num)
233 {
234         struct pf_rule          *r, *rm = NULL;
235         struct pf_ruleset       *ruleset = NULL;
236         int                      tag = -1;
237         int                      rtableid = -1;
238         int                      asd = 0;
239
240         r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
241         while (r && rm == NULL) {
242                 struct pf_rule_addr     *src = NULL, *dst = NULL;
243                 struct pf_addr_wrap     *xdst = NULL;
244
245                 if (r->action == PF_BINAT && direction == PF_IN) {
246                         src = &r->dst;
247                         if (r->rpool.cur != NULL)
248                                 xdst = &r->rpool.cur->addr;
249                 } else {
250                         src = &r->src;
251                         dst = &r->dst;
252                 }
253
254                 r->evaluations++;
255                 if (pfi_kif_match(r->kif, kif) == r->ifnot)
256                         r = r->skip[PF_SKIP_IFP].ptr;
257                 else if (r->direction && r->direction != direction)
258                         r = r->skip[PF_SKIP_DIR].ptr;
259                 else if (r->af && r->af != pd->af)
260                         r = r->skip[PF_SKIP_AF].ptr;
261                 else if (r->proto && r->proto != pd->proto)
262                         r = r->skip[PF_SKIP_PROTO].ptr;
263                 else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
264                     src->neg, kif, M_GETFIB(m)))
265                         r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
266                             PF_SKIP_DST_ADDR].ptr;
267                 else if (src->port_op && !pf_match_port(src->port_op,
268                     src->port[0], src->port[1], sport))
269                         r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
270                             PF_SKIP_DST_PORT].ptr;
271                 else if (dst != NULL &&
272                     PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL,
273                     M_GETFIB(m)))
274                         r = r->skip[PF_SKIP_DST_ADDR].ptr;
275                 else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
276                     0, NULL, M_GETFIB(m)))
277                         r = TAILQ_NEXT(r, entries);
278                 else if (dst != NULL && dst->port_op &&
279                     !pf_match_port(dst->port_op, dst->port[0],
280                     dst->port[1], dport))
281                         r = r->skip[PF_SKIP_DST_PORT].ptr;
282 #ifdef __FreeBSD__
283                 else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
284 #else
285                 else if (r->match_tag && !pf_match_tag(m, r, &tag))
286 #endif
287                         r = TAILQ_NEXT(r, entries);
288                 else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
289                     IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
290                     off, pd->hdr.tcp), r->os_fingerprint)))
291                         r = TAILQ_NEXT(r, entries);
292                 else {
293                         if (r->tag)
294                                 tag = r->tag;
295                         if (r->rtableid >= 0)
296                                 rtableid = r->rtableid;
297                         if (r->anchor == NULL) {
298                                 rm = r;
299                         } else
300                                 pf_step_into_anchor(&asd, &ruleset, rs_num,
301                                     &r, NULL, NULL);
302                 }
303                 if (r == NULL)
304                         pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
305                             NULL, NULL);
306         }
307 #ifdef __FreeBSD__
308         if (pf_tag_packet(m, tag, rtableid, pd->pf_mtag))
309 #else
310         if (pf_tag_packet(m, tag, rtableid))
311 #endif
312                 return (NULL);
313         if (rm != NULL && (rm->action == PF_NONAT ||
314             rm->action == PF_NORDR || rm->action == PF_NOBINAT))
315                 return (NULL);
316         return (rm);
317 }
318
319 int
320 pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
321     struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
322     uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low,
323     uint16_t high, struct pf_src_node **sn)
324 {
325         struct pf_state_key_cmp key;
326         struct pf_addr          init_addr;
327         uint16_t                cut;
328
329         bzero(&init_addr, sizeof(init_addr));
330         if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
331                 return (1);
332
333         if (proto == IPPROTO_ICMP) {
334                 low = 1;
335                 high = 65535;
336         }
337
338         bzero(&key,sizeof(key));
339         key.af = af;
340         key.proto = proto;
341         key.port[0] = dport;
342         PF_ACPY(&key.addr[0], daddr, key.af);
343
344         do {
345                 PF_ACPY(&key.addr[1], naddr, key.af);
346
347                 /*
348                  * port search; start random, step;
349                  * similar 2 portloop in in_pcbbind
350                  */
351                 if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
352                     proto == IPPROTO_ICMP) || (low == 0 && high == 0)) {
353                         /*
354                         * XXX bug: icmp state don't use the id on both sides.
355                         * (traceroute -l through nat)
356                         */
357                         key.port[1] = sport;
358                         if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
359                                 *nport = sport;
360                                 return (0);
361                         }
362                 } else if (low == high) {
363                         key.port[1] = htons(low);
364                         if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
365                                 *nport = htons(low);
366                                 return (0);
367                         }
368                 } else {
369                         uint16_t tmp;
370
371                         if (low > high) {
372                                 tmp = low;
373                                 low = high;
374                                 high = tmp;
375                         }
376                         /* low < high */
377 #ifdef __FreeBSD__
378                         cut = htonl(arc4random()) % (1 + high - low) + low;
379 #else
380                         cut = arc4random_uniform(1 + high - low) + low;
381 #endif
382                         /* low <= cut <= high */
383                         for (tmp = cut; tmp <= high; ++(tmp)) {
384                                 key.port[1] = htons(tmp);
385                                 if (pf_find_state_all(&key, PF_IN, NULL) ==
386 #ifdef __FreeBSD__
387                                     NULL) {
388 #else
389                                     NULL && !in_baddynamic(tmp, proto)) {
390 #endif
391                                         *nport = htons(tmp);
392                                         return (0);
393                                 }
394                         }
395                         for (tmp = cut - 1; tmp >= low; --(tmp)) {
396                                 key.port[1] = htons(tmp);
397                                 if (pf_find_state_all(&key, PF_IN, NULL) ==
398 #ifdef __FreeBSD__
399                                     NULL) {
400 #else
401                                     NULL && !in_baddynamic(tmp, proto)) {
402 #endif
403                                         *nport = htons(tmp);
404                                         return (0);
405                                 }
406                         }
407                 }
408
409                 switch (r->rpool.opts & PF_POOL_TYPEMASK) {
410                 case PF_POOL_RANDOM:
411                 case PF_POOL_ROUNDROBIN:
412                         if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
413                                 return (1);
414                         break;
415                 case PF_POOL_NONE:
416                 case PF_POOL_SRCHASH:
417                 case PF_POOL_BITMASK:
418                 default:
419                         return (1);
420                 }
421         } while (! PF_AEQ(&init_addr, naddr, af) );
422         return (1);                                     /* none available */
423 }
424
425 int
426 pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
427     struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
428 {
429         unsigned char            hash[16];
430         struct pf_pool          *rpool = &r->rpool;
431         struct pf_addr          *raddr = &rpool->cur->addr.v.a.addr;
432         struct pf_addr          *rmask = &rpool->cur->addr.v.a.mask;
433         struct pf_pooladdr      *acur = rpool->cur;
434         struct pf_src_node       k;
435
436         if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
437             (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
438                 k.af = af;
439                 PF_ACPY(&k.addr, saddr, af);
440                 if (r->rule_flag & PFRULE_RULESRCTRACK ||
441                     r->rpool.opts & PF_POOL_STICKYADDR)
442                         k.rule.ptr = r;
443                 else
444                         k.rule.ptr = NULL;
445 #ifdef __FreeBSD__
446                 V_pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
447                 *sn = RB_FIND(pf_src_tree, &V_tree_src_tracking, &k);
448 #else
449                 pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
450                 *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
451 #endif
452                 if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
453                         PF_ACPY(naddr, &(*sn)->raddr, af);
454 #ifdef __FreeBSD__
455                         if (V_pf_status.debug >= PF_DEBUG_MISC) {
456 #else
457                         if (pf_status.debug >= PF_DEBUG_MISC) {
458 #endif
459                                 printf("pf_map_addr: src tracking maps ");
460                                 pf_print_host(&k.addr, 0, af);
461                                 printf(" to ");
462                                 pf_print_host(naddr, 0, af);
463                                 printf("\n");
464                         }
465                         return (0);
466                 }
467         }
468
469         if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
470                 return (1);
471         if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
472                 switch (af) {
473 #ifdef INET
474                 case AF_INET:
475                         if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
476                             (rpool->opts & PF_POOL_TYPEMASK) !=
477                             PF_POOL_ROUNDROBIN)
478                                 return (1);
479                          raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
480                          rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
481                         break;
482 #endif /* INET */
483 #ifdef INET6
484                 case AF_INET6:
485                         if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
486                             (rpool->opts & PF_POOL_TYPEMASK) !=
487                             PF_POOL_ROUNDROBIN)
488                                 return (1);
489                         raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
490                         rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
491                         break;
492 #endif /* INET6 */
493                 }
494         } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
495                 if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
496                         return (1); /* unsupported */
497         } else {
498                 raddr = &rpool->cur->addr.v.a.addr;
499                 rmask = &rpool->cur->addr.v.a.mask;
500         }
501
502         switch (rpool->opts & PF_POOL_TYPEMASK) {
503         case PF_POOL_NONE:
504                 PF_ACPY(naddr, raddr, af);
505                 break;
506         case PF_POOL_BITMASK:
507                 PF_POOLMASK(naddr, raddr, rmask, saddr, af);
508                 break;
509         case PF_POOL_RANDOM:
510                 if (init_addr != NULL && PF_AZERO(init_addr, af)) {
511                         switch (af) {
512 #ifdef INET
513                         case AF_INET:
514                                 rpool->counter.addr32[0] = htonl(arc4random());
515                                 break;
516 #endif /* INET */
517 #ifdef INET6
518                         case AF_INET6:
519                                 if (rmask->addr32[3] != 0xffffffff)
520                                         rpool->counter.addr32[3] =
521                                             htonl(arc4random());
522                                 else
523                                         break;
524                                 if (rmask->addr32[2] != 0xffffffff)
525                                         rpool->counter.addr32[2] =
526                                             htonl(arc4random());
527                                 else
528                                         break;
529                                 if (rmask->addr32[1] != 0xffffffff)
530                                         rpool->counter.addr32[1] =
531                                             htonl(arc4random());
532                                 else
533                                         break;
534                                 if (rmask->addr32[0] != 0xffffffff)
535                                         rpool->counter.addr32[0] =
536                                             htonl(arc4random());
537                                 break;
538 #endif /* INET6 */
539                         }
540                         PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
541                         PF_ACPY(init_addr, naddr, af);
542
543                 } else {
544                         PF_AINC(&rpool->counter, af);
545                         PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
546                 }
547                 break;
548         case PF_POOL_SRCHASH:
549                 pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
550                 PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
551                 break;
552         case PF_POOL_ROUNDROBIN:
553                 if (rpool->cur->addr.type == PF_ADDR_TABLE) {
554                         if (!pfr_pool_get(rpool->cur->addr.p.tbl,
555                             &rpool->tblidx, &rpool->counter,
556                             &raddr, &rmask, af))
557                                 goto get_addr;
558                 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
559                         if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
560                             &rpool->tblidx, &rpool->counter,
561                             &raddr, &rmask, af))
562                                 goto get_addr;
563                 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
564                         goto get_addr;
565
566         try_next:
567                 if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL)
568                         rpool->cur = TAILQ_FIRST(&rpool->list);
569                 if (rpool->cur->addr.type == PF_ADDR_TABLE) {
570                         rpool->tblidx = -1;
571                         if (pfr_pool_get(rpool->cur->addr.p.tbl,
572                             &rpool->tblidx, &rpool->counter,
573                             &raddr, &rmask, af)) {
574                                 /* table contains no address of type 'af' */
575                                 if (rpool->cur != acur)
576                                         goto try_next;
577                                 return (1);
578                         }
579                 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
580                         rpool->tblidx = -1;
581                         if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
582                             &rpool->tblidx, &rpool->counter,
583                             &raddr, &rmask, af)) {
584                                 /* table contains no address of type 'af' */
585                                 if (rpool->cur != acur)
586                                         goto try_next;
587                                 return (1);
588                         }
589                 } else {
590                         raddr = &rpool->cur->addr.v.a.addr;
591                         rmask = &rpool->cur->addr.v.a.mask;
592                         PF_ACPY(&rpool->counter, raddr, af);
593                 }
594
595         get_addr:
596                 PF_ACPY(naddr, &rpool->counter, af);
597                 if (init_addr != NULL && PF_AZERO(init_addr, af))
598                         PF_ACPY(init_addr, naddr, af);
599                 PF_AINC(&rpool->counter, af);
600                 break;
601         }
602         if (*sn != NULL)
603                 PF_ACPY(&(*sn)->raddr, naddr, af);
604
605 #ifdef __FreeBSD__
606         if (V_pf_status.debug >= PF_DEBUG_MISC &&
607 #else
608         if (pf_status.debug >= PF_DEBUG_MISC &&
609 #endif
610             (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
611                 printf("pf_map_addr: selected address ");
612                 pf_print_host(naddr, 0, af);
613                 printf("\n");
614         }
615
616         return (0);
617 }
618
619 struct pf_rule *
620 pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
621     struct pfi_kif *kif, struct pf_src_node **sn,
622     struct pf_state_key **skw, struct pf_state_key **sks,
623     struct pf_state_key **skp, struct pf_state_key **nkp,
624     struct pf_addr *saddr, struct pf_addr *daddr,
625     u_int16_t sport, u_int16_t dport)
626 {
627         struct pf_rule  *r = NULL;
628
629
630         if (direction == PF_OUT) {
631                 r = pf_match_translation(pd, m, off, direction, kif, saddr,
632                     sport, daddr, dport, PF_RULESET_BINAT);
633                 if (r == NULL)
634                         r = pf_match_translation(pd, m, off, direction, kif,
635                             saddr, sport, daddr, dport, PF_RULESET_NAT);
636         } else {
637                 r = pf_match_translation(pd, m, off, direction, kif, saddr,
638                     sport, daddr, dport, PF_RULESET_RDR);
639                 if (r == NULL)
640                         r = pf_match_translation(pd, m, off, direction, kif,
641                             saddr, sport, daddr, dport, PF_RULESET_BINAT);
642         }
643
644         if (r != NULL) {
645                 struct pf_addr  *naddr;
646                 u_int16_t       *nport;
647
648                 if (pf_state_key_setup(pd, r, skw, sks, skp, nkp,
649                     saddr, daddr, sport, dport))
650                         return r;
651
652                 /* XXX We only modify one side for now. */
653                 naddr = &(*nkp)->addr[1];
654                 nport = &(*nkp)->port[1];
655
656                 switch (r->action) {
657                 case PF_NONAT:
658                 case PF_NOBINAT:
659                 case PF_NORDR:
660                         return (NULL);
661                 case PF_NAT:
662                         if (pf_get_sport(pd->af, pd->proto, r, saddr, sport, daddr,
663                             dport, naddr, nport, r->rpool.proxy_port[0],
664                             r->rpool.proxy_port[1], sn)) {
665                                 DPFPRINTF(PF_DEBUG_MISC,
666                                     ("pf: NAT proxy port allocation "
667                                     "(%u-%u) failed\n",
668                                     r->rpool.proxy_port[0],
669                                     r->rpool.proxy_port[1]));
670                                 return (NULL);
671                         }
672                         break;
673                 case PF_BINAT:
674                         switch (direction) {
675                         case PF_OUT:
676                                 if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
677                                         switch (pd->af) {
678 #ifdef INET
679                                         case AF_INET:
680                                                 if (r->rpool.cur->addr.p.dyn->
681                                                     pfid_acnt4 < 1)
682                                                         return (NULL);
683                                                 PF_POOLMASK(naddr,
684                                                     &r->rpool.cur->addr.p.dyn->
685                                                     pfid_addr4,
686                                                     &r->rpool.cur->addr.p.dyn->
687                                                     pfid_mask4,
688                                                     saddr, AF_INET);
689                                                 break;
690 #endif /* INET */
691 #ifdef INET6
692                                         case AF_INET6:
693                                                 if (r->rpool.cur->addr.p.dyn->
694                                                     pfid_acnt6 < 1)
695                                                         return (NULL);
696                                                 PF_POOLMASK(naddr,
697                                                     &r->rpool.cur->addr.p.dyn->
698                                                     pfid_addr6,
699                                                     &r->rpool.cur->addr.p.dyn->
700                                                     pfid_mask6,
701                                                     saddr, AF_INET6);
702                                                 break;
703 #endif /* INET6 */
704                                         }
705                                 } else
706                                         PF_POOLMASK(naddr,
707                                             &r->rpool.cur->addr.v.a.addr,
708                                             &r->rpool.cur->addr.v.a.mask,
709                                             saddr, pd->af);
710                                 break;
711                         case PF_IN:
712                                 if (r->src.addr.type == PF_ADDR_DYNIFTL) {
713                                         switch (pd->af) {
714 #ifdef INET
715                                         case AF_INET:
716                                                 if (r->src.addr.p.dyn->
717                                                     pfid_acnt4 < 1)
718                                                         return (NULL);
719                                                 PF_POOLMASK(naddr,
720                                                     &r->src.addr.p.dyn->
721                                                     pfid_addr4,
722                                                     &r->src.addr.p.dyn->
723                                                     pfid_mask4,
724                                                     daddr, AF_INET);
725                                                 break;
726 #endif /* INET */
727 #ifdef INET6
728                                         case AF_INET6:
729                                                 if (r->src.addr.p.dyn->
730                                                     pfid_acnt6 < 1)
731                                                         return (NULL);
732                                                 PF_POOLMASK(naddr,
733                                                     &r->src.addr.p.dyn->
734                                                     pfid_addr6,
735                                                     &r->src.addr.p.dyn->
736                                                     pfid_mask6,
737                                                     daddr, AF_INET6);
738                                                 break;
739 #endif /* INET6 */
740                                         }
741                                 } else
742                                         PF_POOLMASK(naddr,
743                                             &r->src.addr.v.a.addr,
744                                             &r->src.addr.v.a.mask, daddr,
745                                             pd->af);
746                                 break;
747                         }
748                         break;
749                 case PF_RDR: {
750                         if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
751                                 return (NULL);
752                         if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
753                             PF_POOL_BITMASK)
754                                 PF_POOLMASK(naddr, naddr,
755                                     &r->rpool.cur->addr.v.a.mask, daddr,
756                                     pd->af);
757
758                         if (r->rpool.proxy_port[1]) {
759                                 u_int32_t       tmp_nport;
760
761                                 tmp_nport = ((ntohs(dport) -
762                                     ntohs(r->dst.port[0])) %
763                                     (r->rpool.proxy_port[1] -
764                                     r->rpool.proxy_port[0] + 1)) +
765                                     r->rpool.proxy_port[0];
766
767                                 /* wrap around if necessary */
768                                 if (tmp_nport > 65535)
769                                         tmp_nport -= 65535;
770                                 *nport = htons((u_int16_t)tmp_nport);
771                         } else if (r->rpool.proxy_port[0])
772                                 *nport = htons(r->rpool.proxy_port[0]);
773                         break;
774                 }
775                 default:
776                         return (NULL);
777                 }
778                 /* 
779                  * Translation was a NOP.
780                  * Pretend there was no match.
781                  */
782                 if (!bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp))) {
783 #ifdef __FreeBSD__
784                         pool_put(&V_pf_state_key_pl, *nkp);
785                         pool_put(&V_pf_state_key_pl, *skp);
786 #else
787                         pool_put(&pf_state_key_pl, *nkp);
788                         pool_put(&pf_state_key_pl, *skp);
789 #endif
790                         *skw = *sks = *nkp = *skp = NULL;
791                         *sn = NULL;
792                         return (NULL);
793                 }
794         }
795
796         return (r);
797 }
798