]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/pf/net/pf_lb.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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 *, struct pf_addr *, u_int16_t,
169                             struct pf_addr *, u_int16_t*, u_int16_t, u_int16_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, struct pf_addr *daddr, u_int16_t dport,
322     struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
323     struct pf_src_node **sn)
324 {
325         struct pf_state_key_cmp key;
326         struct pf_addr          init_addr;
327         u_int16_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         do {
339                 key.af = af;
340                 key.proto = proto;
341                 PF_ACPY(&key.addr[1], daddr, key.af);
342                 PF_ACPY(&key.addr[0], naddr, key.af);
343                 key.port[1] = dport;
344
345                 /*
346                  * port search; start random, step;
347                  * similar 2 portloop in in_pcbbind
348                  */
349                 if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
350                     proto == IPPROTO_ICMP)) {
351                         key.port[0] = dport;
352                         if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
353                                 return (0);
354                 } else if (low == 0 && high == 0) {
355                         key.port[0] = *nport;
356                         if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
357                                 return (0);
358                 } else if (low == high) {
359                         key.port[0] = htons(low);
360                         if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
361                                 *nport = htons(low);
362                                 return (0);
363                         }
364                 } else {
365                         u_int16_t tmp;
366
367                         if (low > high) {
368                                 tmp = low;
369                                 low = high;
370                                 high = tmp;
371                         }
372                         /* low < high */
373 #ifdef __FreeBSD__
374                         cut = htonl(arc4random()) % (1 + high - low) + low;
375 #else
376                         cut = arc4random_uniform(1 + high - low) + low;
377 #endif
378                         /* low <= cut <= high */
379                         for (tmp = cut; tmp <= high; ++(tmp)) {
380                                 key.port[0] = htons(tmp);
381                                 if (pf_find_state_all(&key, PF_IN, NULL) ==
382 #ifdef __FreeBSD__
383                                     NULL) {
384 #else
385                                     NULL && !in_baddynamic(tmp, proto)) {
386 #endif
387                                         *nport = htons(tmp);
388                                         return (0);
389                                 }
390                         }
391                         for (tmp = cut - 1; tmp >= low; --(tmp)) {
392                                 key.port[0] = htons(tmp);
393                                 if (pf_find_state_all(&key, PF_IN, NULL) ==
394 #ifdef __FreeBSD__
395                                     NULL) {
396 #else
397                                     NULL && !in_baddynamic(tmp, proto)) {
398 #endif
399                                         *nport = htons(tmp);
400                                         return (0);
401                                 }
402                         }
403                 }
404
405                 switch (r->rpool.opts & PF_POOL_TYPEMASK) {
406                 case PF_POOL_RANDOM:
407                 case PF_POOL_ROUNDROBIN:
408                         if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
409                                 return (1);
410                         break;
411                 case PF_POOL_NONE:
412                 case PF_POOL_SRCHASH:
413                 case PF_POOL_BITMASK:
414                 default:
415                         return (1);
416                 }
417         } while (! PF_AEQ(&init_addr, naddr, af) );
418         return (1);                                     /* none available */
419 }
420
421 int
422 pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
423     struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
424 {
425         unsigned char            hash[16];
426         struct pf_pool          *rpool = &r->rpool;
427         struct pf_addr          *raddr = &rpool->cur->addr.v.a.addr;
428         struct pf_addr          *rmask = &rpool->cur->addr.v.a.mask;
429         struct pf_pooladdr      *acur = rpool->cur;
430         struct pf_src_node       k;
431
432         if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
433             (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
434                 k.af = af;
435                 PF_ACPY(&k.addr, saddr, af);
436                 if (r->rule_flag & PFRULE_RULESRCTRACK ||
437                     r->rpool.opts & PF_POOL_STICKYADDR)
438                         k.rule.ptr = r;
439                 else
440                         k.rule.ptr = NULL;
441 #ifdef __FreeBSD__
442                 V_pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
443                 *sn = RB_FIND(pf_src_tree, &V_tree_src_tracking, &k);
444 #else
445                 pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
446                 *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
447 #endif
448                 if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
449                         PF_ACPY(naddr, &(*sn)->raddr, af);
450 #ifdef __FreeBSD__
451                         if (V_pf_status.debug >= PF_DEBUG_MISC) {
452 #else
453                         if (pf_status.debug >= PF_DEBUG_MISC) {
454 #endif
455                                 printf("pf_map_addr: src tracking maps ");
456                                 pf_print_host(&k.addr, 0, af);
457                                 printf(" to ");
458                                 pf_print_host(naddr, 0, af);
459                                 printf("\n");
460                         }
461                         return (0);
462                 }
463         }
464
465         if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
466                 return (1);
467         if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
468                 switch (af) {
469 #ifdef INET
470                 case AF_INET:
471                         if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
472                             (rpool->opts & PF_POOL_TYPEMASK) !=
473                             PF_POOL_ROUNDROBIN)
474                                 return (1);
475                          raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
476                          rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
477                         break;
478 #endif /* INET */
479 #ifdef INET6
480                 case AF_INET6:
481                         if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
482                             (rpool->opts & PF_POOL_TYPEMASK) !=
483                             PF_POOL_ROUNDROBIN)
484                                 return (1);
485                         raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
486                         rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
487                         break;
488 #endif /* INET6 */
489                 }
490         } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
491                 if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
492                         return (1); /* unsupported */
493         } else {
494                 raddr = &rpool->cur->addr.v.a.addr;
495                 rmask = &rpool->cur->addr.v.a.mask;
496         }
497
498         switch (rpool->opts & PF_POOL_TYPEMASK) {
499         case PF_POOL_NONE:
500                 PF_ACPY(naddr, raddr, af);
501                 break;
502         case PF_POOL_BITMASK:
503                 PF_POOLMASK(naddr, raddr, rmask, saddr, af);
504                 break;
505         case PF_POOL_RANDOM:
506                 if (init_addr != NULL && PF_AZERO(init_addr, af)) {
507                         switch (af) {
508 #ifdef INET
509                         case AF_INET:
510                                 rpool->counter.addr32[0] = htonl(arc4random());
511                                 break;
512 #endif /* INET */
513 #ifdef INET6
514                         case AF_INET6:
515                                 if (rmask->addr32[3] != 0xffffffff)
516                                         rpool->counter.addr32[3] =
517                                             htonl(arc4random());
518                                 else
519                                         break;
520                                 if (rmask->addr32[2] != 0xffffffff)
521                                         rpool->counter.addr32[2] =
522                                             htonl(arc4random());
523                                 else
524                                         break;
525                                 if (rmask->addr32[1] != 0xffffffff)
526                                         rpool->counter.addr32[1] =
527                                             htonl(arc4random());
528                                 else
529                                         break;
530                                 if (rmask->addr32[0] != 0xffffffff)
531                                         rpool->counter.addr32[0] =
532                                             htonl(arc4random());
533                                 break;
534 #endif /* INET6 */
535                         }
536                         PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
537                         PF_ACPY(init_addr, naddr, af);
538
539                 } else {
540                         PF_AINC(&rpool->counter, af);
541                         PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
542                 }
543                 break;
544         case PF_POOL_SRCHASH:
545                 pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
546                 PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
547                 break;
548         case PF_POOL_ROUNDROBIN:
549                 if (rpool->cur->addr.type == PF_ADDR_TABLE) {
550                         if (!pfr_pool_get(rpool->cur->addr.p.tbl,
551                             &rpool->tblidx, &rpool->counter,
552                             &raddr, &rmask, af))
553                                 goto get_addr;
554                 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
555                         if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
556                             &rpool->tblidx, &rpool->counter,
557                             &raddr, &rmask, af))
558                                 goto get_addr;
559                 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
560                         goto get_addr;
561
562         try_next:
563                 if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL)
564                         rpool->cur = TAILQ_FIRST(&rpool->list);
565                 if (rpool->cur->addr.type == PF_ADDR_TABLE) {
566                         rpool->tblidx = -1;
567                         if (pfr_pool_get(rpool->cur->addr.p.tbl,
568                             &rpool->tblidx, &rpool->counter,
569                             &raddr, &rmask, af)) {
570                                 /* table contains no address of type 'af' */
571                                 if (rpool->cur != acur)
572                                         goto try_next;
573                                 return (1);
574                         }
575                 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
576                         rpool->tblidx = -1;
577                         if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
578                             &rpool->tblidx, &rpool->counter,
579                             &raddr, &rmask, af)) {
580                                 /* table contains no address of type 'af' */
581                                 if (rpool->cur != acur)
582                                         goto try_next;
583                                 return (1);
584                         }
585                 } else {
586                         raddr = &rpool->cur->addr.v.a.addr;
587                         rmask = &rpool->cur->addr.v.a.mask;
588                         PF_ACPY(&rpool->counter, raddr, af);
589                 }
590
591         get_addr:
592                 PF_ACPY(naddr, &rpool->counter, af);
593                 if (init_addr != NULL && PF_AZERO(init_addr, af))
594                         PF_ACPY(init_addr, naddr, af);
595                 PF_AINC(&rpool->counter, af);
596                 break;
597         }
598         if (*sn != NULL)
599                 PF_ACPY(&(*sn)->raddr, naddr, af);
600
601 #ifdef __FreeBSD__
602         if (V_pf_status.debug >= PF_DEBUG_MISC &&
603 #else
604         if (pf_status.debug >= PF_DEBUG_MISC &&
605 #endif
606             (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
607                 printf("pf_map_addr: selected address ");
608                 pf_print_host(naddr, 0, af);
609                 printf("\n");
610         }
611
612         return (0);
613 }
614
615 struct pf_rule *
616 pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
617     struct pfi_kif *kif, struct pf_src_node **sn,
618     struct pf_state_key **skw, struct pf_state_key **sks,
619     struct pf_state_key **skp, struct pf_state_key **nkp,
620     struct pf_addr *saddr, struct pf_addr *daddr,
621     u_int16_t sport, u_int16_t dport)
622 {
623         struct pf_rule  *r = NULL;
624
625
626         if (direction == PF_OUT) {
627                 r = pf_match_translation(pd, m, off, direction, kif, saddr,
628                     sport, daddr, dport, PF_RULESET_BINAT);
629                 if (r == NULL)
630                         r = pf_match_translation(pd, m, off, direction, kif,
631                             saddr, sport, daddr, dport, PF_RULESET_NAT);
632         } else {
633                 r = pf_match_translation(pd, m, off, direction, kif, saddr,
634                     sport, daddr, dport, PF_RULESET_RDR);
635                 if (r == NULL)
636                         r = pf_match_translation(pd, m, off, direction, kif,
637                             saddr, sport, daddr, dport, PF_RULESET_BINAT);
638         }
639
640         if (r != NULL) {
641                 struct pf_addr  *naddr;
642                 u_int16_t       *nport;
643
644                 if (pf_state_key_setup(pd, r, skw, sks, skp, nkp,
645                     saddr, daddr, sport, dport))
646                         return r;
647
648                 /* XXX We only modify one side for now. */
649                 naddr = &(*nkp)->addr[1];
650                 nport = &(*nkp)->port[1];
651
652                 switch (r->action) {
653                 case PF_NONAT:
654                 case PF_NOBINAT:
655                 case PF_NORDR:
656                         return (NULL);
657                 case PF_NAT:
658                         if (pf_get_sport(pd->af, pd->proto, r, saddr,
659                             daddr, dport, naddr, nport, r->rpool.proxy_port[0],
660                             r->rpool.proxy_port[1], sn)) {
661                                 DPFPRINTF(PF_DEBUG_MISC,
662                                     ("pf: NAT proxy port allocation "
663                                     "(%u-%u) failed\n",
664                                     r->rpool.proxy_port[0],
665                                     r->rpool.proxy_port[1]));
666                                 return (NULL);
667                         }
668                         break;
669                 case PF_BINAT:
670                         switch (direction) {
671                         case PF_OUT:
672                                 if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
673                                         switch (pd->af) {
674 #ifdef INET
675                                         case AF_INET:
676                                                 if (r->rpool.cur->addr.p.dyn->
677                                                     pfid_acnt4 < 1)
678                                                         return (NULL);
679                                                 PF_POOLMASK(naddr,
680                                                     &r->rpool.cur->addr.p.dyn->
681                                                     pfid_addr4,
682                                                     &r->rpool.cur->addr.p.dyn->
683                                                     pfid_mask4,
684                                                     saddr, AF_INET);
685                                                 break;
686 #endif /* INET */
687 #ifdef INET6
688                                         case AF_INET6:
689                                                 if (r->rpool.cur->addr.p.dyn->
690                                                     pfid_acnt6 < 1)
691                                                         return (NULL);
692                                                 PF_POOLMASK(naddr,
693                                                     &r->rpool.cur->addr.p.dyn->
694                                                     pfid_addr6,
695                                                     &r->rpool.cur->addr.p.dyn->
696                                                     pfid_mask6,
697                                                     saddr, AF_INET6);
698                                                 break;
699 #endif /* INET6 */
700                                         }
701                                 } else
702                                         PF_POOLMASK(naddr,
703                                             &r->rpool.cur->addr.v.a.addr,
704                                             &r->rpool.cur->addr.v.a.mask,
705                                             saddr, pd->af);
706                                 break;
707                         case PF_IN:
708                                 if (r->src.addr.type == PF_ADDR_DYNIFTL) {
709                                         switch (pd->af) {
710 #ifdef INET
711                                         case AF_INET:
712                                                 if (r->src.addr.p.dyn->
713                                                     pfid_acnt4 < 1)
714                                                         return (NULL);
715                                                 PF_POOLMASK(naddr,
716                                                     &r->src.addr.p.dyn->
717                                                     pfid_addr4,
718                                                     &r->src.addr.p.dyn->
719                                                     pfid_mask4,
720                                                     daddr, AF_INET);
721                                                 break;
722 #endif /* INET */
723 #ifdef INET6
724                                         case AF_INET6:
725                                                 if (r->src.addr.p.dyn->
726                                                     pfid_acnt6 < 1)
727                                                         return (NULL);
728                                                 PF_POOLMASK(naddr,
729                                                     &r->src.addr.p.dyn->
730                                                     pfid_addr6,
731                                                     &r->src.addr.p.dyn->
732                                                     pfid_mask6,
733                                                     daddr, AF_INET6);
734                                                 break;
735 #endif /* INET6 */
736                                         }
737                                 } else
738                                         PF_POOLMASK(naddr,
739                                             &r->src.addr.v.a.addr,
740                                             &r->src.addr.v.a.mask, daddr,
741                                             pd->af);
742                                 break;
743                         }
744                         break;
745                 case PF_RDR: {
746                         if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
747                                 return (NULL);
748                         if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
749                             PF_POOL_BITMASK)
750                                 PF_POOLMASK(naddr, naddr,
751                                     &r->rpool.cur->addr.v.a.mask, daddr,
752                                     pd->af);
753
754                         if (r->rpool.proxy_port[1]) {
755                                 u_int32_t       tmp_nport;
756
757                                 tmp_nport = ((ntohs(dport) -
758                                     ntohs(r->dst.port[0])) %
759                                     (r->rpool.proxy_port[1] -
760                                     r->rpool.proxy_port[0] + 1)) +
761                                     r->rpool.proxy_port[0];
762
763                                 /* wrap around if necessary */
764                                 if (tmp_nport > 65535)
765                                         tmp_nport -= 65535;
766                                 *nport = htons((u_int16_t)tmp_nport);
767                         } else if (r->rpool.proxy_port[0])
768                                 *nport = htons(r->rpool.proxy_port[0]);
769                         break;
770                 }
771                 default:
772                         return (NULL);
773                 }
774                 /* 
775                  * Translation was a NOP.
776                  * Pretend there was no match.
777                  */
778                 if (!bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp))) {
779 #ifdef __FreeBSD__
780                         pool_put(&V_pf_state_key_pl, *nkp);
781                         pool_put(&V_pf_state_key_pl, *skp);
782 #else
783                         pool_put(&pf_state_key_pl, *nkp);
784                         pool_put(&pf_state_key_pl, *skp);
785 #endif
786                         *skw = *sks = *nkp = *skp = NULL;
787                         return (NULL);
788                 }
789         }
790
791         return (r);
792 }
793