Bug Summary

File:net/pf_lb.c
Warning:line 669, column 4
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pf_lb.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/net/pf_lb.c
1/* $OpenBSD: pf_lb.c,v 1.74 2023/05/10 22:42:51 sashan 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#include "bpfilter.h"
39#include "pflog.h"
40#include "pfsync.h"
41#include "pflow.h"
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/mbuf.h>
46#include <sys/filio.h>
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/kernel.h>
50#include <sys/time.h>
51#include <sys/pool.h>
52#include <sys/rwlock.h>
53#include <sys/syslog.h>
54#include <sys/stdint.h>
55
56#include <crypto/siphash.h>
57
58#include <net/if.h>
59#include <net/bpf.h>
60#include <net/route.h>
61
62#include <netinet/in.h>
63#include <netinet/ip.h>
64#include <netinet/in_pcb.h>
65#include <netinet/ip_var.h>
66#include <netinet/ip_icmp.h>
67#include <netinet/icmp_var.h>
68#include <netinet/tcp.h>
69#include <netinet/tcp_seq.h>
70#include <netinet/tcp_timer.h>
71#include <netinet/udp.h>
72#include <netinet/udp_var.h>
73#include <netinet/if_ether.h>
74
75#ifdef INET61
76#include <netinet/ip6.h>
77#include <netinet/icmp6.h>
78#endif /* INET6 */
79
80#include <net/pfvar.h>
81#include <net/pfvar_priv.h>
82
83#if NPFLOG1 > 0
84#include <net/if_pflog.h>
85#endif /* NPFLOG > 0 */
86
87#if NPFLOW1 > 0
88#include <net/if_pflow.h>
89#endif /* NPFLOW > 0 */
90
91#if NPFSYNC1 > 0
92#include <net/if_pfsync.h>
93#endif /* NPFSYNC > 0 */
94
95u_int64_t pf_hash(struct pf_addr *, struct pf_addr *,
96 struct pf_poolhashkey *, sa_family_t);
97int pf_get_sport(struct pf_pdesc *, struct pf_rule *,
98 struct pf_addr *, u_int16_t *, u_int16_t,
99 u_int16_t, struct pf_src_node **);
100int pf_map_addr_states_increase(sa_family_t,
101 struct pf_pool *, struct pf_addr *);
102int pf_get_transaddr_af(struct pf_rule *,
103 struct pf_pdesc *, struct pf_src_node **);
104int pf_map_addr_sticky(sa_family_t, struct pf_rule *,
105 struct pf_addr *, struct pf_addr *,
106 struct pf_src_node **, struct pf_pool *,
107 enum pf_sn_types);
108
109u_int64_t
110pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
111 struct pf_poolhashkey *key, sa_family_t af)
112{
113 uint64_t res = 0;
114#ifdef INET61
115 union {
116 uint64_t hash64;
117 uint32_t hash32[2];
118 } h;
119#endif /* INET6 */
120
121 switch (af) {
122 case AF_INET2:
123 res = SipHash24((SIPHASH_KEY *)key,SipHash(((SIPHASH_KEY *)key), 2, 4, (&inaddr->pfa.addr32
[0]), (sizeof(inaddr->pfa.addr32[0])))
124 &inaddr->addr32[0], sizeof(inaddr->addr32[0]))SipHash(((SIPHASH_KEY *)key), 2, 4, (&inaddr->pfa.addr32
[0]), (sizeof(inaddr->pfa.addr32[0])))
;
125 hash->addr32pfa.addr32[0] = res;
126 break;
127#ifdef INET61
128 case AF_INET624:
129 res = SipHash24((SIPHASH_KEY *)key, &inaddr->addr32[0],SipHash(((SIPHASH_KEY *)key), 2, 4, (&inaddr->pfa.addr32
[0]), (4 * sizeof(inaddr->pfa.addr32[0])))
130 4 * sizeof(inaddr->addr32[0]))SipHash(((SIPHASH_KEY *)key), 2, 4, (&inaddr->pfa.addr32
[0]), (4 * sizeof(inaddr->pfa.addr32[0])))
;
131 h.hash64 = res;
132 hash->addr32pfa.addr32[0] = h.hash32[0];
133 hash->addr32pfa.addr32[1] = h.hash32[1];
134 /*
135 * siphash isn't big enough, but flipping it around is
136 * good enough here.
137 */
138 hash->addr32pfa.addr32[2] = ~h.hash32[1];
139 hash->addr32pfa.addr32[3] = ~h.hash32[0];
140 break;
141#endif /* INET6 */
142 default:
143 unhandled_af(af);
144 }
145 return (res);
146}
147
148int
149pf_get_sport(struct pf_pdesc *pd, struct pf_rule *r,
150 struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
151 struct pf_src_node **sn)
152{
153 struct pf_state_key_cmp key;
154 struct pf_addr init_addr;
155 u_int16_t cut;
156 int dir = (pd->dir == PF_IN) ? PF_OUT : PF_IN;
157 int sidx = pd->sidx;
158 int didx = pd->didx;
159
160 memset(&init_addr, 0, sizeof(init_addr))__builtin_memset((&init_addr), (0), (sizeof(init_addr)));
161 if (pf_map_addr(pd->naf, r, &pd->nsaddr, naddr, &init_addr, sn, &r->nat,
162 PF_SN_NAT))
163 return (1);
164
165 if (pd->proto == IPPROTO_ICMP1) {
166 if (pd->ndport == htons(ICMP_ECHO)(__uint16_t)(__builtin_constant_p(8) ? (__uint16_t)(((__uint16_t
)(8) & 0xffU) << 8 | ((__uint16_t)(8) & 0xff00U
) >> 8) : __swap16md(8))
) {
167 low = 1;
168 high = 65535;
169 } else
170 return (0); /* Don't try to modify non-echo ICMP */
171 }
172#ifdef INET61
173 if (pd->proto == IPPROTO_ICMPV658) {
174 if (pd->ndport == htons(ICMP6_ECHO_REQUEST)(__uint16_t)(__builtin_constant_p(128) ? (__uint16_t)(((__uint16_t
)(128) & 0xffU) << 8 | ((__uint16_t)(128) & 0xff00U
) >> 8) : __swap16md(128))
) {
175 low = 1;
176 high = 65535;
177 } else
178 return (0); /* Don't try to modify non-echo ICMP */
179 }
180#endif /* INET6 */
181
182 do {
183 key.af = pd->naf;
184 key.proto = pd->proto;
185 key.rdomain = pd->rdomain;
186 pf_addrcpy(&key.addr[didx], &pd->ndaddr, key.af);
187 pf_addrcpy(&key.addr[sidx], naddr, key.af);
188 key.port[didx] = pd->ndport;
189
190 /*
191 * port search; start random, step;
192 * similar 2 portloop in in_pcbbind
193 */
194 if (!(pd->proto == IPPROTO_TCP6 || pd->proto == IPPROTO_UDP17 ||
195 pd->proto == IPPROTO_ICMP1 || pd->proto == IPPROTO_ICMPV658)) {
196 /* XXX bug: icmp states dont use the id on both
197 * XXX sides (traceroute -I through nat) */
198 key.port[sidx] = pd->nsport;
199 key.hash = pf_pkt_hash(key.af, key.proto, &key.addr[0],
200 &key.addr[1], key.port[0], key.port[1]);
201 if (pf_find_state_all(&key, dir, NULL((void *)0)) == NULL((void *)0)) {
202 *nport = pd->nsport;
203 return (0);
204 }
205 } else if (low == 0 && high == 0) {
206 key.port[sidx] = pd->nsport;
207 key.hash = pf_pkt_hash(key.af, key.proto, &key.addr[0],
208 &key.addr[1], key.port[0], key.port[1]);
209 if (pf_find_state_all(&key, dir, NULL((void *)0)) == NULL((void *)0)) {
210 *nport = pd->nsport;
211 return (0);
212 }
213 } else if (low == high) {
214 key.port[sidx] = htons(low)(__uint16_t)(__builtin_constant_p(low) ? (__uint16_t)(((__uint16_t
)(low) & 0xffU) << 8 | ((__uint16_t)(low) & 0xff00U
) >> 8) : __swap16md(low))
;
215 key.hash = pf_pkt_hash(key.af, key.proto, &key.addr[0],
216 &key.addr[1], key.port[0], key.port[1]);
217 if (pf_find_state_all(&key, dir, NULL((void *)0)) == NULL((void *)0)) {
218 *nport = htons(low)(__uint16_t)(__builtin_constant_p(low) ? (__uint16_t)(((__uint16_t
)(low) & 0xffU) << 8 | ((__uint16_t)(low) & 0xff00U
) >> 8) : __swap16md(low))
;
219 return (0);
220 }
221 } else {
222 u_int32_t tmp;
223
224 if (low > high) {
225 tmp = low;
226 low = high;
227 high = tmp;
228 }
229 /* low < high */
230 cut = arc4random_uniform(1 + high - low) + low;
231 /* low <= cut <= high */
232 for (tmp = cut; tmp <= high && tmp <= 0xffff; ++tmp) {
233 key.port[sidx] = htons(tmp)(__uint16_t)(__builtin_constant_p(tmp) ? (__uint16_t)(((__uint16_t
)(tmp) & 0xffU) << 8 | ((__uint16_t)(tmp) & 0xff00U
) >> 8) : __swap16md(tmp))
;
234 key.hash = pf_pkt_hash(key.af, key.proto,
235 &key.addr[0], &key.addr[1], key.port[0],
236 key.port[1]);
237 if (pf_find_state_all(&key, dir, NULL((void *)0)) ==
238 NULL((void *)0) && !in_baddynamic(tmp, pd->proto)) {
239 *nport = htons(tmp)(__uint16_t)(__builtin_constant_p(tmp) ? (__uint16_t)(((__uint16_t
)(tmp) & 0xffU) << 8 | ((__uint16_t)(tmp) & 0xff00U
) >> 8) : __swap16md(tmp))
;
240 return (0);
241 }
242 }
243 tmp = cut;
244 for (tmp -= 1; tmp >= low && tmp <= 0xffff; --tmp) {
245 key.port[sidx] = htons(tmp)(__uint16_t)(__builtin_constant_p(tmp) ? (__uint16_t)(((__uint16_t
)(tmp) & 0xffU) << 8 | ((__uint16_t)(tmp) & 0xff00U
) >> 8) : __swap16md(tmp))
;
246 key.hash = pf_pkt_hash(key.af, key.proto,
247 &key.addr[0], &key.addr[1], key.port[0],
248 key.port[1]);
249 if (pf_find_state_all(&key, dir, NULL((void *)0)) ==
250 NULL((void *)0) && !in_baddynamic(tmp, pd->proto)) {
251 *nport = htons(tmp)(__uint16_t)(__builtin_constant_p(tmp) ? (__uint16_t)(((__uint16_t
)(tmp) & 0xffU) << 8 | ((__uint16_t)(tmp) & 0xff00U
) >> 8) : __swap16md(tmp))
;
252 return (0);
253 }
254 }
255 }
256
257 switch (r->nat.opts & PF_POOL_TYPEMASK0x0f) {
258 case PF_POOL_RANDOM:
259 case PF_POOL_ROUNDROBIN:
260 case PF_POOL_LEASTSTATES:
261 /*
262 * pick a different source address since we're out
263 * of free port choices for the current one.
264 */
265 if (pf_map_addr(pd->naf, r, &pd->nsaddr, naddr,
266 &init_addr, sn, &r->nat, PF_SN_NAT))
267 return (1);
268 break;
269 case PF_POOL_NONE:
270 case PF_POOL_SRCHASH:
271 case PF_POOL_BITMASK:
272 default:
273 return (1);
274 }
275 } while (! PF_AEQ(&init_addr, naddr, pd->naf)((pd->naf == 2 && (&init_addr)->pfa.addr32[
0] == (naddr)->pfa.addr32[0]) || (pd->naf == 24 &&
(&init_addr)->pfa.addr32[3] == (naddr)->pfa.addr32
[3] && (&init_addr)->pfa.addr32[2] == (naddr)->
pfa.addr32[2] && (&init_addr)->pfa.addr32[1] ==
(naddr)->pfa.addr32[1] && (&init_addr)->pfa
.addr32[0] == (naddr)->pfa.addr32[0]))
);
276 return (1); /* none available */
277}
278
279int
280pf_map_addr_sticky(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
281 struct pf_addr *naddr, struct pf_src_node **sns, struct pf_pool *rpool,
282 enum pf_sn_types type)
283{
284 struct pf_addr *raddr, *rmask, *cached;
285 struct pf_state *s;
286 struct pf_src_node k;
287 int valid;
288
289 k.af = af;
290 k.type = type;
291 pf_addrcpy(&k.addr, saddr, af);
292 k.rule.ptr = r;
293 pf_status.scounters[SCNT_SRC_NODE_SEARCH0]++;
294 sns[type] = RB_FIND(pf_src_tree, &tree_src_tracking, &k)pf_src_tree_RB_FIND(&tree_src_tracking, &k);
295 if (sns[type] == NULL((void *)0))
296 return (-1);
297
298 /* check if the cached entry is still valid */
299 cached = &(sns[type])->raddr;
300 valid = 0;
301 if (PF_AZERO(cached, af)((af == 2 && !(cached)->pfa.addr32[0]) || (af == 24
&& !(cached)->pfa.addr32[0] && !(cached)->
pfa.addr32[1] && !(cached)->pfa.addr32[2] &&
!(cached)->pfa.addr32[3] ))
) {
302 valid = 1;
303 } else if (rpool->addr.type == PF_ADDR_DYNIFTL) {
304 if (pfr_kentry_byaddr(rpool->addr.p.dyn->pfid_kt, cached,
305 af, 0))
306 valid = 1;
307 } else if (rpool->addr.type == PF_ADDR_TABLE) {
308 if (pfr_kentry_byaddr(rpool->addr.p.tbl, cached, af, 0))
309 valid = 1;
310 } else if (rpool->addr.type != PF_ADDR_NOROUTE) {
311 raddr = &rpool->addr.v.a.addr;
312 rmask = &rpool->addr.v.a.mask;
313 valid = pf_match_addr(0, raddr, rmask, cached, af);
314 }
315 if (!valid) {
316 if (pf_status.debug >= LOG_DEBUG7) {
317 log(LOG_DEBUG7, "pf: pf_map_addr: "
318 "stale src tracking (%u) ", type);
319 pf_print_host(&k.addr, 0, af);
320 addlog(" to ");
321 pf_print_host(cached, 0, af);
322 addlog("\n");
323 }
324 if (sns[type]->states != 0) {
325 /* XXX expensive */
326 RBT_FOREACH(s, pf_state_tree_id, &tree_id)for ((s) = pf_state_tree_id_RBT_MIN((&tree_id)); (s) != (
(void *)0); (s) = pf_state_tree_id_RBT_NEXT((s)))
327 pf_state_rm_src_node(s, sns[type]);
328 }
329 sns[type]->expire = 1;
330 pf_remove_src_node(sns[type]);
331 sns[type] = NULL((void *)0);
332 return (-1);
333 }
334
335
336 if (!PF_AZERO(cached, af)((af == 2 && !(cached)->pfa.addr32[0]) || (af == 24
&& !(cached)->pfa.addr32[0] && !(cached)->
pfa.addr32[1] && !(cached)->pfa.addr32[2] &&
!(cached)->pfa.addr32[3] ))
) {
337 pf_addrcpy(naddr, cached, af);
338 if ((rpool->opts & PF_POOL_TYPEMASK0x0f) == PF_POOL_LEASTSTATES &&
339 pf_map_addr_states_increase(af, rpool, cached) == -1)
340 return (-1);
341 }
342 if (pf_status.debug >= LOG_DEBUG7) {
343 log(LOG_DEBUG7, "pf: pf_map_addr: "
344 "src tracking (%u) maps ", type);
345 pf_print_host(&k.addr, 0, af);
346 addlog(" to ");
347 pf_print_host(naddr, 0, af);
348 addlog("\n");
349 }
350
351 if (sns[type]->kif != NULL((void *)0))
352 rpool->kif = sns[type]->kif;
353
354 return (0);
355}
356
357uint32_t
358pf_rand_addr(uint32_t mask)
359{
360 uint32_t addr;
361
362 mask = ~ntohl(mask)(__uint32_t)(__builtin_constant_p(mask) ? (__uint32_t)(((__uint32_t
)(mask) & 0xff) << 24 | ((__uint32_t)(mask) & 0xff00
) << 8 | ((__uint32_t)(mask) & 0xff0000) >> 8
| ((__uint32_t)(mask) & 0xff000000) >> 24) : __swap32md
(mask))
;
363 addr = arc4random_uniform(mask + 1);
364
365 return (htonl(addr)(__uint32_t)(__builtin_constant_p(addr) ? (__uint32_t)(((__uint32_t
)(addr) & 0xff) << 24 | ((__uint32_t)(addr) & 0xff00
) << 8 | ((__uint32_t)(addr) & 0xff0000) >> 8
| ((__uint32_t)(addr) & 0xff000000) >> 24) : __swap32md
(addr))
);
366}
367
368int
369pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
370 struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sns,
371 struct pf_pool *rpool, enum pf_sn_types type)
372{
373 struct pf_addr hash;
374 struct pf_addr faddr;
375 struct pf_addr *raddr = &rpool->addr.v.a.addr;
376 struct pf_addr *rmask = &rpool->addr.v.a.mask;
377 struct pfr_ktable *kt;
378 struct pfi_kif *kif;
379 u_int64_t states;
1
'states' declared without an initial value
380 u_int16_t weight;
381 u_int64_t load;
382 u_int64_t cload;
383 u_int64_t hashidx;
384 int cnt;
385
386 if (sns[type] == NULL((void *)0) && rpool->opts & PF_POOL_STICKYADDR0x20 &&
2
Assuming the condition is false
387 (rpool->opts & PF_POOL_TYPEMASK0x0f) != PF_POOL_NONE &&
388 pf_map_addr_sticky(af, r, saddr, naddr, sns, rpool, type) == 0)
389 return (0);
390
391 if (rpool->addr.type == PF_ADDR_NOROUTE)
3
Assuming field 'type' is not equal to PF_ADDR_NOROUTE
4
Taking false branch
392 return (1);
393 if (rpool->addr.type == PF_ADDR_DYNIFTL) {
5
Assuming field 'type' is not equal to PF_ADDR_DYNIFTL
6
Taking false branch
394 switch (af) {
395 case AF_INET2:
396 if (rpool->addr.p.dyn->pfid_acnt4 < 1 &&
397 !PF_POOL_DYNTYPE(rpool->opts)((((rpool->opts) & 0x0f) == PF_POOL_ROUNDROBIN) || (((
rpool->opts) & 0x0f) == PF_POOL_LEASTSTATES) || (((rpool
->opts) & 0x0f) == PF_POOL_RANDOM) || (((rpool->opts
) & 0x0f) == PF_POOL_SRCHASH))
)
398 return (1);
399 raddr = &rpool->addr.p.dyn->pfid_addr4;
400 rmask = &rpool->addr.p.dyn->pfid_mask4;
401 break;
402#ifdef INET61
403 case AF_INET624:
404 if (rpool->addr.p.dyn->pfid_acnt6 < 1 &&
405 !PF_POOL_DYNTYPE(rpool->opts)((((rpool->opts) & 0x0f) == PF_POOL_ROUNDROBIN) || (((
rpool->opts) & 0x0f) == PF_POOL_LEASTSTATES) || (((rpool
->opts) & 0x0f) == PF_POOL_RANDOM) || (((rpool->opts
) & 0x0f) == PF_POOL_SRCHASH))
)
406 return (1);
407 raddr = &rpool->addr.p.dyn->pfid_addr6;
408 rmask = &rpool->addr.p.dyn->pfid_mask6;
409 break;
410#endif /* INET6 */
411 default:
412 unhandled_af(af);
413 }
414 } else if (rpool->addr.type == PF_ADDR_TABLE) {
7
Assuming field 'type' is not equal to PF_ADDR_TABLE
8
Taking false branch
415 if (!PF_POOL_DYNTYPE(rpool->opts)((((rpool->opts) & 0x0f) == PF_POOL_ROUNDROBIN) || (((
rpool->opts) & 0x0f) == PF_POOL_LEASTSTATES) || (((rpool
->opts) & 0x0f) == PF_POOL_RANDOM) || (((rpool->opts
) & 0x0f) == PF_POOL_SRCHASH))
)
416 return (1); /* unsupported */
417 } else {
418 raddr = &rpool->addr.v.a.addr;
419 rmask = &rpool->addr.v.a.mask;
420 }
421
422 switch (rpool->opts & PF_POOL_TYPEMASK0x0f) {
9
Control jumps to 'case PF_POOL_NONE:' at line 423
423 case PF_POOL_NONE:
424 pf_addrcpy(naddr, raddr, af);
425 break;
426 case PF_POOL_BITMASK:
427 pf_poolmask(naddr, raddr, rmask, saddr, af);
428 break;
429 case PF_POOL_RANDOM:
430 if (rpool->addr.type == PF_ADDR_TABLE ||
431 rpool->addr.type == PF_ADDR_DYNIFTL) {
432 if (rpool->addr.type == PF_ADDR_TABLE)
433 kt = rpool->addr.p.tbl;
434 else
435 kt = rpool->addr.p.dyn->pfid_kt;
436 kt = pfr_ktable_select_active(kt);
437 if (kt == NULL((void *)0))
438 return (1);
439
440 cnt = kt->pfrkt_cntpfrkt_ts.pfrts_cnt;
441 if (cnt == 0)
442 rpool->tblidx = 0;
443 else
444 rpool->tblidx = (int)arc4random_uniform(cnt);
445 memset(&rpool->counter, 0, sizeof(rpool->counter))__builtin_memset((&rpool->counter), (0), (sizeof(rpool
->counter)))
;
446 if (pfr_pool_get(rpool, &raddr, &rmask, af))
447 return (1);
448 pf_addrcpy(naddr, &rpool->counter, af);
449 } else if (init_addr != NULL((void *)0) && PF_AZERO(init_addr, af)((af == 2 && !(init_addr)->pfa.addr32[0]) || (af ==
24 && !(init_addr)->pfa.addr32[0] && !(init_addr
)->pfa.addr32[1] && !(init_addr)->pfa.addr32[2]
&& !(init_addr)->pfa.addr32[3] ))
) {
450 switch (af) {
451 case AF_INET2:
452 rpool->counter.addr32pfa.addr32[0] = pf_rand_addr(
453 rmask->addr32pfa.addr32[0]);
454 break;
455#ifdef INET61
456 case AF_INET624:
457 if (rmask->addr32pfa.addr32[3] != 0xffffffff)
458 rpool->counter.addr32pfa.addr32[3] = pf_rand_addr(
459 rmask->addr32pfa.addr32[3]);
460 else
461 break;
462 if (rmask->addr32pfa.addr32[2] != 0xffffffff)
463 rpool->counter.addr32pfa.addr32[2] = pf_rand_addr(
464 rmask->addr32pfa.addr32[2]);
465 else
466 break;
467 if (rmask->addr32pfa.addr32[1] != 0xffffffff)
468 rpool->counter.addr32pfa.addr32[1] = pf_rand_addr(
469 rmask->addr32pfa.addr32[1]);
470 else
471 break;
472 if (rmask->addr32pfa.addr32[0] != 0xffffffff)
473 rpool->counter.addr32pfa.addr32[0] = pf_rand_addr(
474 rmask->addr32pfa.addr32[0]);
475 break;
476#endif /* INET6 */
477 default:
478 unhandled_af(af);
479 }
480 pf_poolmask(naddr, raddr, rmask, &rpool->counter, af);
481 pf_addrcpy(init_addr, naddr, af);
482
483 } else {
484 pf_addr_inc(&rpool->counter, af);
485 pf_poolmask(naddr, raddr, rmask, &rpool->counter, af);
486 }
487 break;
488 case PF_POOL_SRCHASH:
489 hashidx = pf_hash(saddr, &hash, &rpool->key, af);
490
491 if (rpool->addr.type == PF_ADDR_TABLE ||
492 rpool->addr.type == PF_ADDR_DYNIFTL) {
493 if (rpool->addr.type == PF_ADDR_TABLE)
494 kt = rpool->addr.p.tbl;
495 else
496 kt = rpool->addr.p.dyn->pfid_kt;
497 kt = pfr_ktable_select_active(kt);
498 if (kt == NULL((void *)0))
499 return (1);
500
501 cnt = kt->pfrkt_cntpfrkt_ts.pfrts_cnt;
502 if (cnt == 0)
503 rpool->tblidx = 0;
504 else
505 rpool->tblidx = (int)(hashidx % cnt);
506 memset(&rpool->counter, 0, sizeof(rpool->counter))__builtin_memset((&rpool->counter), (0), (sizeof(rpool
->counter)))
;
507 if (pfr_pool_get(rpool, &raddr, &rmask, af))
508 return (1);
509 pf_addrcpy(naddr, &rpool->counter, af);
510 } else {
511 pf_poolmask(naddr, raddr, rmask, &hash, af);
512 }
513 break;
514 case PF_POOL_ROUNDROBIN:
515 if (rpool->addr.type == PF_ADDR_TABLE ||
516 rpool->addr.type == PF_ADDR_DYNIFTL) {
517 if (pfr_pool_get(rpool, &raddr, &rmask, af)) {
518 /*
519 * reset counter in case its value
520 * has been removed from the pool.
521 */
522 memset(&rpool->counter, 0,__builtin_memset((&rpool->counter), (0), (sizeof(rpool
->counter)))
523 sizeof(rpool->counter))__builtin_memset((&rpool->counter), (0), (sizeof(rpool
->counter)))
;
524 if (pfr_pool_get(rpool, &raddr, &rmask, af))
525 return (1);
526 }
527 } else if (PF_AZERO(&rpool->counter, af)((af == 2 && !(&rpool->counter)->pfa.addr32
[0]) || (af == 24 && !(&rpool->counter)->pfa
.addr32[0] && !(&rpool->counter)->pfa.addr32
[1] && !(&rpool->counter)->pfa.addr32[2] &&
!(&rpool->counter)->pfa.addr32[3] ))
) {
528 /*
529 * fall back to POOL_NONE if there is a single host
530 * address in pool.
531 */
532 if (af == AF_INET2 &&
533 rmask->addr32pfa.addr32[0] == INADDR_BROADCAST((u_int32_t) (__uint32_t)(__builtin_constant_p((u_int32_t)(0xffffffff
)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0xffffffff)) &
0xff) << 24 | ((__uint32_t)((u_int32_t)(0xffffffff)) &
0xff00) << 8 | ((__uint32_t)((u_int32_t)(0xffffffff)) &
0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0xffffffff)
) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0xffffffff
))))
) {
534 pf_addrcpy(naddr, raddr, af);
535 break;
536 }
537#ifdef INET61
538 if (af == AF_INET624 &&
539 IN6_ARE_ADDR_EQUAL(&rmask->v6, &in6mask128)(__builtin_memcmp((&(&rmask->pfa.v6)->__u6_addr
.__u6_addr8[0]), (&(&in6mask128)->__u6_addr.__u6_addr8
[0]), (sizeof(struct in6_addr))) == 0)
) {
540 pf_addrcpy(naddr, raddr, af);
541 break;
542 }
543#endif
544 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
545 return (1);
546
547 /* iterate over table if it contains entries which are weighted */
548 if ((rpool->addr.type == PF_ADDR_TABLE &&
549 rpool->addr.p.tbl->pfrkt_refcntcost > 0) ||
550 (rpool->addr.type == PF_ADDR_DYNIFTL &&
551 rpool->addr.p.dyn->pfid_kt->pfrkt_refcntcost > 0)) {
552 do {
553 if (rpool->addr.type == PF_ADDR_TABLE ||
554 rpool->addr.type == PF_ADDR_DYNIFTL) {
555 if (pfr_pool_get(rpool,
556 &raddr, &rmask, af))
557 return (1);
558 } else {
559 log(LOG_ERR3, "pf: pf_map_addr: "
560 "weighted RR failure");
561 return (1);
562 }
563 if (rpool->weight >= rpool->curweight)
564 break;
565 pf_addr_inc(&rpool->counter, af);
566 } while (1);
567
568 weight = rpool->weight;
569 }
570
571 pf_poolmask(naddr, raddr, rmask, &rpool->counter, af);
572 if (init_addr != NULL((void *)0) && PF_AZERO(init_addr, af)((af == 2 && !(init_addr)->pfa.addr32[0]) || (af ==
24 && !(init_addr)->pfa.addr32[0] && !(init_addr
)->pfa.addr32[1] && !(init_addr)->pfa.addr32[2]
&& !(init_addr)->pfa.addr32[3] ))
)
573 pf_addrcpy(init_addr, &rpool->counter, af);
574 pf_addr_inc(&rpool->counter, af);
575 break;
576 case PF_POOL_LEASTSTATES:
577 /* retrieve an address first */
578 if (rpool->addr.type == PF_ADDR_TABLE ||
579 rpool->addr.type == PF_ADDR_DYNIFTL) {
580 if (pfr_pool_get(rpool, &raddr, &rmask, af)) {
581 /* see PF_POOL_ROUNDROBIN */
582 memset(&rpool->counter, 0,__builtin_memset((&rpool->counter), (0), (sizeof(rpool
->counter)))
583 sizeof(rpool->counter))__builtin_memset((&rpool->counter), (0), (sizeof(rpool
->counter)))
;
584 if (pfr_pool_get(rpool, &raddr, &rmask, af))
585 return (1);
586 }
587 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
588 return (1);
589
590 states = rpool->states;
591 weight = rpool->weight;
592 kif = rpool->kif;
593
594 if ((rpool->addr.type == PF_ADDR_TABLE &&
595 rpool->addr.p.tbl->pfrkt_refcntcost > 0) ||
596 (rpool->addr.type == PF_ADDR_DYNIFTL &&
597 rpool->addr.p.dyn->pfid_kt->pfrkt_refcntcost > 0))
598 load = ((UINT16_MAX0xffff * rpool->states) / rpool->weight);
599 else
600 load = states;
601
602 pf_addrcpy(&faddr, &rpool->counter, af);
603
604 pf_addrcpy(naddr, &rpool->counter, af);
605 if (init_addr != NULL((void *)0) && PF_AZERO(init_addr, af)((af == 2 && !(init_addr)->pfa.addr32[0]) || (af ==
24 && !(init_addr)->pfa.addr32[0] && !(init_addr
)->pfa.addr32[1] && !(init_addr)->pfa.addr32[2]
&& !(init_addr)->pfa.addr32[3] ))
)
606 pf_addrcpy(init_addr, naddr, af);
607
608 /*
609 * iterate *once* over whole table and find destination with
610 * least connection
611 */
612 do {
613 pf_addr_inc(&rpool->counter, af);
614 if (rpool->addr.type == PF_ADDR_TABLE ||
615 rpool->addr.type == PF_ADDR_DYNIFTL) {
616 if (pfr_pool_get(rpool, &raddr, &rmask, af))
617 return (1);
618 } else if (pf_match_addr(0, raddr, rmask,
619 &rpool->counter, af))
620 return (1);
621
622 if ((rpool->addr.type == PF_ADDR_TABLE &&
623 rpool->addr.p.tbl->pfrkt_refcntcost > 0) ||
624 (rpool->addr.type == PF_ADDR_DYNIFTL &&
625 rpool->addr.p.dyn->pfid_kt->pfrkt_refcntcost > 0))
626 cload = ((UINT16_MAX0xffff * rpool->states)
627 / rpool->weight);
628 else
629 cload = rpool->states;
630
631 /* find lc minimum */
632 if (cload < load) {
633 states = rpool->states;
634 weight = rpool->weight;
635 kif = rpool->kif;
636 load = cload;
637
638 pf_addrcpy(naddr, &rpool->counter, af);
639 if (init_addr != NULL((void *)0) &&
640 PF_AZERO(init_addr, af)((af == 2 && !(init_addr)->pfa.addr32[0]) || (af ==
24 && !(init_addr)->pfa.addr32[0] && !(init_addr
)->pfa.addr32[1] && !(init_addr)->pfa.addr32[2]
&& !(init_addr)->pfa.addr32[3] ))
)
641 pf_addrcpy(init_addr, naddr, af);
642 }
643 } while (pf_match_addr(1, &faddr, rmask, &rpool->counter, af) &&
644 (states > 0));
645
646 if (pf_map_addr_states_increase(af, rpool, naddr) == -1)
647 return (1);
648 /* revert the kif which was set by pfr_pool_get() */
649 rpool->kif = kif;
650 break;
651 }
652
653 if (rpool->opts & PF_POOL_STICKYADDR0x20) {
10
Execution continues on line 653
11
Assuming the condition is false
654 if (sns[type] != NULL((void *)0)) {
655 pf_remove_src_node(sns[type]);
656 sns[type] = NULL((void *)0);
657 }
658 if (pf_insert_src_node(&sns[type], r, type, af, saddr, naddr,
659 rpool->kif))
660 return (1);
661 }
662
663 if (pf_status.debug >= LOG_INFO6 &&
12
Assuming field 'debug' is >= LOG_INFO
14
Taking true branch
664 (rpool->opts & PF_POOL_TYPEMASK0x0f) != PF_POOL_NONE) {
13
Assuming the condition is true
665 log(LOG_INFO6, "pf: pf_map_addr: selected address ");
666 pf_print_host(naddr, 0, af);
667 if ((rpool->opts & PF_POOL_TYPEMASK0x0f) ==
15
Assuming the condition is true
16
Taking true branch
668 PF_POOL_LEASTSTATES)
669 addlog(" with state count %llu", states);
17
2nd function call argument is an uninitialized value
670 if ((rpool->addr.type == PF_ADDR_TABLE &&
671 rpool->addr.p.tbl->pfrkt_refcntcost > 0) ||
672 (rpool->addr.type == PF_ADDR_DYNIFTL &&
673 rpool->addr.p.dyn->pfid_kt->pfrkt_refcntcost > 0))
674 addlog(" with weight %u", weight);
675 addlog("\n");
676 }
677
678 return (0);
679}
680
681int
682pf_map_addr_states_increase(sa_family_t af, struct pf_pool *rpool,
683 struct pf_addr *naddr)
684{
685 if (rpool->addr.type == PF_ADDR_TABLE) {
686 if (pfr_states_increase(rpool->addr.p.tbl,
687 naddr, af) == -1) {
688 if (pf_status.debug >= LOG_DEBUG7) {
689 log(LOG_DEBUG7,
690 "pf: pf_map_addr_states_increase: "
691 "selected address ");
692 pf_print_host(naddr, 0, af);
693 addlog(". Failed to increase count!\n");
694 }
695 return (-1);
696 }
697 } else if (rpool->addr.type == PF_ADDR_DYNIFTL) {
698 if (pfr_states_increase(rpool->addr.p.dyn->pfid_kt,
699 naddr, af) == -1) {
700 if (pf_status.debug >= LOG_DEBUG7) {
701 log(LOG_DEBUG7,
702 "pf: pf_map_addr_states_increase: "
703 "selected address ");
704 pf_print_host(naddr, 0, af);
705 addlog(". Failed to increase count!\n");
706 }
707 return (-1);
708 }
709 }
710 return (0);
711}
712
713int
714pf_get_transaddr(struct pf_rule *r, struct pf_pdesc *pd,
715 struct pf_src_node **sns, struct pf_rule **nr)
716{
717 struct pf_addr naddr;
718 u_int16_t nport;
719
720#ifdef INET61
721 if (pd->af != pd->naf)
722 return (pf_get_transaddr_af(r, pd, sns));
723#endif /* INET6 */
724
725 if (r->nat.addr.type != PF_ADDR_NONE) {
726 /* XXX is this right? what if rtable is changed at the same
727 * XXX time? where do I need to figure out the sport? */
728 nport = 0;
729 if (pf_get_sport(pd, r, &naddr, &nport,
730 r->nat.proxy_port[0], r->nat.proxy_port[1], sns)) {
731 DPFPRINTF(LOG_NOTICE,do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: NAT proxy port allocation (%u-%u) failed", r->nat.proxy_port
[0], r->nat.proxy_port[1]); addlog("\n"); } } while (0)
732 "pf: NAT proxy port allocation (%u-%u) failed",do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: NAT proxy port allocation (%u-%u) failed", r->nat.proxy_port
[0], r->nat.proxy_port[1]); addlog("\n"); } } while (0)
733 r->nat.proxy_port[0],do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: NAT proxy port allocation (%u-%u) failed", r->nat.proxy_port
[0], r->nat.proxy_port[1]); addlog("\n"); } } while (0)
734 r->nat.proxy_port[1])do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: NAT proxy port allocation (%u-%u) failed", r->nat.proxy_port
[0], r->nat.proxy_port[1]); addlog("\n"); } } while (0)
;
735 return (-1);
736 }
737 *nr = r;
738 pf_addrcpy(&pd->nsaddr, &naddr, pd->af);
739 pd->nsport = nport;
740 }
741 if (r->rdr.addr.type != PF_ADDR_NONE) {
742 if (pf_map_addr(pd->af, r, &pd->nsaddr, &naddr, NULL((void *)0), sns,
743 &r->rdr, PF_SN_RDR))
744 return (-1);
745 if ((r->rdr.opts & PF_POOL_TYPEMASK0x0f) == PF_POOL_BITMASK)
746 pf_poolmask(&naddr, &naddr, &r->rdr.addr.v.a.mask,
747 &pd->ndaddr, pd->af);
748
749 nport = 0;
750 if (r->rdr.proxy_port[1]) {
751 u_int32_t tmp_nport;
752 u_int16_t div;
753
754 div = r->rdr.proxy_port[1] - r->rdr.proxy_port[0] + 1;
755 div = (div == 0) ? 1 : div;
756
757 tmp_nport = ((ntohs(pd->ndport)(__uint16_t)(__builtin_constant_p(pd->ndport) ? (__uint16_t
)(((__uint16_t)(pd->ndport) & 0xffU) << 8 | ((__uint16_t
)(pd->ndport) & 0xff00U) >> 8) : __swap16md(pd->
ndport))
- ntohs(r->dst.port[0])(__uint16_t)(__builtin_constant_p(r->dst.port[0]) ? (__uint16_t
)(((__uint16_t)(r->dst.port[0]) & 0xffU) << 8 | (
(__uint16_t)(r->dst.port[0]) & 0xff00U) >> 8) : __swap16md
(r->dst.port[0]))
) % div) +
758 r->rdr.proxy_port[0];
759
760 /* wrap around if necessary */
761 if (tmp_nport > 65535)
762 tmp_nport -= 65535;
763 nport = htons((u_int16_t)tmp_nport)(__uint16_t)(__builtin_constant_p((u_int16_t)tmp_nport) ? (__uint16_t
)(((__uint16_t)((u_int16_t)tmp_nport) & 0xffU) << 8
| ((__uint16_t)((u_int16_t)tmp_nport) & 0xff00U) >>
8) : __swap16md((u_int16_t)tmp_nport))
;
764 } else if (r->rdr.proxy_port[0])
765 nport = htons(r->rdr.proxy_port[0])(__uint16_t)(__builtin_constant_p(r->rdr.proxy_port[0]) ? (
__uint16_t)(((__uint16_t)(r->rdr.proxy_port[0]) & 0xffU
) << 8 | ((__uint16_t)(r->rdr.proxy_port[0]) & 0xff00U
) >> 8) : __swap16md(r->rdr.proxy_port[0]))
;
766 *nr = r;
767 pf_addrcpy(&pd->ndaddr, &naddr, pd->af);
768 if (nport)
769 pd->ndport = nport;
770 }
771
772 return (0);
773}
774
775#ifdef INET61
776int
777pf_get_transaddr_af(struct pf_rule *r, struct pf_pdesc *pd,
778 struct pf_src_node **sns)
779{
780 struct pf_addr ndaddr, nsaddr, naddr;
781 u_int16_t nport;
782 int prefixlen = 96;
783
784 if (pf_status.debug >= LOG_INFO6) {
785 log(LOG_INFO6, "pf: af-to %s %s, ",
786 pd->naf == AF_INET2 ? "inet" : "inet6",
787 r->rdr.addr.type == PF_ADDR_NONE ? "nat" : "rdr");
788 pf_print_host(&pd->nsaddr, pd->nsport, pd->af);
789 addlog(" -> ");
790 pf_print_host(&pd->ndaddr, pd->ndport, pd->af);
791 addlog("\n");
792 }
793
794 if (r->nat.addr.type == PF_ADDR_NONE)
795 panic("pf_get_transaddr_af: no nat pool for source address");
796
797 /* get source address and port */
798 nport = 0;
799 if (pf_get_sport(pd, r, &nsaddr, &nport,
800 r->nat.proxy_port[0], r->nat.proxy_port[1], sns)) {
801 DPFPRINTF(LOG_NOTICE,do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: af-to NAT proxy port allocation (%u-%u) failed", r->nat
.proxy_port[0], r->nat.proxy_port[1]); addlog("\n"); } } while
(0)
802 "pf: af-to NAT proxy port allocation (%u-%u) failed",do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: af-to NAT proxy port allocation (%u-%u) failed", r->nat
.proxy_port[0], r->nat.proxy_port[1]); addlog("\n"); } } while
(0)
803 r->nat.proxy_port[0],do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: af-to NAT proxy port allocation (%u-%u) failed", r->nat
.proxy_port[0], r->nat.proxy_port[1]); addlog("\n"); } } while
(0)
804 r->nat.proxy_port[1])do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: af-to NAT proxy port allocation (%u-%u) failed", r->nat
.proxy_port[0], r->nat.proxy_port[1]); addlog("\n"); } } while
(0)
;
805 return (-1);
806 }
807 pd->nsport = nport;
808
809 if (pd->proto == IPPROTO_ICMPV658 && pd->naf == AF_INET2) {
810 if (pd->dir == PF_IN) {
811 pd->ndport = ntohs(pd->ndport)(__uint16_t)(__builtin_constant_p(pd->ndport) ? (__uint16_t
)(((__uint16_t)(pd->ndport) & 0xffU) << 8 | ((__uint16_t
)(pd->ndport) & 0xff00U) >> 8) : __swap16md(pd->
ndport))
;
812 if (pd->ndport == ICMP6_ECHO_REQUEST128)
813 pd->ndport = ICMP_ECHO8;
814 else if (pd->ndport == ICMP6_ECHO_REPLY129)
815 pd->ndport = ICMP_ECHOREPLY0;
816 pd->ndport = htons(pd->ndport)(__uint16_t)(__builtin_constant_p(pd->ndport) ? (__uint16_t
)(((__uint16_t)(pd->ndport) & 0xffU) << 8 | ((__uint16_t
)(pd->ndport) & 0xff00U) >> 8) : __swap16md(pd->
ndport))
;
817 } else {
818 pd->nsport = ntohs(pd->nsport)(__uint16_t)(__builtin_constant_p(pd->nsport) ? (__uint16_t
)(((__uint16_t)(pd->nsport) & 0xffU) << 8 | ((__uint16_t
)(pd->nsport) & 0xff00U) >> 8) : __swap16md(pd->
nsport))
;
819 if (pd->nsport == ICMP6_ECHO_REQUEST128)
820 pd->nsport = ICMP_ECHO8;
821 else if (pd->nsport == ICMP6_ECHO_REPLY129)
822 pd->nsport = ICMP_ECHOREPLY0;
823 pd->nsport = htons(pd->nsport)(__uint16_t)(__builtin_constant_p(pd->nsport) ? (__uint16_t
)(((__uint16_t)(pd->nsport) & 0xffU) << 8 | ((__uint16_t
)(pd->nsport) & 0xff00U) >> 8) : __swap16md(pd->
nsport))
;
824 }
825 } else if (pd->proto == IPPROTO_ICMP1 && pd->naf == AF_INET624) {
826 if (pd->dir == PF_IN) {
827 pd->ndport = ntohs(pd->ndport)(__uint16_t)(__builtin_constant_p(pd->ndport) ? (__uint16_t
)(((__uint16_t)(pd->ndport) & 0xffU) << 8 | ((__uint16_t
)(pd->ndport) & 0xff00U) >> 8) : __swap16md(pd->
ndport))
;
828 if (pd->ndport == ICMP_ECHO8)
829 pd->ndport = ICMP6_ECHO_REQUEST128;
830 else if (pd->ndport == ICMP_ECHOREPLY0)
831 pd->ndport = ICMP6_ECHO_REPLY129;
832 pd->ndport = htons(pd->ndport)(__uint16_t)(__builtin_constant_p(pd->ndport) ? (__uint16_t
)(((__uint16_t)(pd->ndport) & 0xffU) << 8 | ((__uint16_t
)(pd->ndport) & 0xff00U) >> 8) : __swap16md(pd->
ndport))
;
833 } else {
834 pd->nsport = ntohs(pd->nsport)(__uint16_t)(__builtin_constant_p(pd->nsport) ? (__uint16_t
)(((__uint16_t)(pd->nsport) & 0xffU) << 8 | ((__uint16_t
)(pd->nsport) & 0xff00U) >> 8) : __swap16md(pd->
nsport))
;
835 if (pd->nsport == ICMP_ECHO8)
836 pd->nsport = ICMP6_ECHO_REQUEST128;
837 else if (pd->nsport == ICMP_ECHOREPLY0)
838 pd->nsport = ICMP6_ECHO_REPLY129;
839 pd->nsport = htons(pd->nsport)(__uint16_t)(__builtin_constant_p(pd->nsport) ? (__uint16_t
)(((__uint16_t)(pd->nsport) & 0xffU) << 8 | ((__uint16_t
)(pd->nsport) & 0xff00U) >> 8) : __swap16md(pd->
nsport))
;
840 }
841 }
842
843 /* get the destination address and port */
844 if (r->rdr.addr.type != PF_ADDR_NONE) {
845 if (pf_map_addr(pd->naf, r, &nsaddr, &naddr, NULL((void *)0), sns,
846 &r->rdr, PF_SN_RDR))
847 return (-1);
848 if (r->rdr.proxy_port[0])
849 pd->ndport = htons(r->rdr.proxy_port[0])(__uint16_t)(__builtin_constant_p(r->rdr.proxy_port[0]) ? (
__uint16_t)(((__uint16_t)(r->rdr.proxy_port[0]) & 0xffU
) << 8 | ((__uint16_t)(r->rdr.proxy_port[0]) & 0xff00U
) >> 8) : __swap16md(r->rdr.proxy_port[0]))
;
850
851 if (pd->naf == AF_INET2) {
852 /* The prefix is the IPv4 rdr address */
853 prefixlen = in_mask2len((struct in_addr *)
854 &r->rdr.addr.v.a.mask);
855 inet_nat46(pd->naf, &pd->ndaddr,
856 &ndaddr, &naddr, prefixlen);
857 } else {
858 /* The prefix is the IPv6 rdr address */
859 prefixlen =
860 in6_mask2len((struct in6_addr *)
861 &r->rdr.addr.v.a.mask, NULL((void *)0));
862 inet_nat64(pd->naf, &pd->ndaddr,
863 &ndaddr, &naddr, prefixlen);
864 }
865 } else {
866 if (pd->naf == AF_INET2) {
867 /* The prefix is the IPv6 dst address */
868 prefixlen =
869 in6_mask2len((struct in6_addr *)
870 &r->dst.addr.v.a.mask, NULL((void *)0));
871 if (prefixlen < 32)
872 prefixlen = 96;
873 inet_nat64(pd->naf, &pd->ndaddr,
874 &ndaddr, &pd->ndaddr, prefixlen);
875 } else {
876 /*
877 * The prefix is the IPv6 nat address
878 * (that was stored in pd->nsaddr)
879 */
880 prefixlen = in6_mask2len((struct in6_addr *)
881 &r->nat.addr.v.a.mask, NULL((void *)0));
882 if (prefixlen > 96)
883 prefixlen = 96;
884 inet_nat64(pd->naf, &pd->ndaddr,
885 &ndaddr, &nsaddr, prefixlen);
886 }
887 }
888
889 pf_addrcpy(&pd->nsaddr, &nsaddr, pd->naf);
890 pf_addrcpy(&pd->ndaddr, &ndaddr, pd->naf);
891
892 if (pf_status.debug >= LOG_INFO6) {
893 log(LOG_INFO6, "pf: af-to %s %s done, prefixlen %d, ",
894 pd->naf == AF_INET2 ? "inet" : "inet6",
895 r->rdr.addr.type == PF_ADDR_NONE ? "nat" : "rdr",
896 prefixlen);
897 pf_print_host(&pd->nsaddr, pd->nsport, pd->naf);
898 addlog(" -> ");
899 pf_print_host(&pd->ndaddr, pd->ndport, pd->naf);
900 addlog("\n");
901 }
902
903 return (0);
904}
905#endif /* INET6 */
906
907int
908pf_postprocess_addr(struct pf_state *cur)
909{
910 struct pf_rule *nr;
911 struct pf_state_key *sks;
912 struct pf_pool rpool;
913 struct pf_addr lookup_addr;
914 int slbcount = -1;
915
916 nr = cur->natrule.ptr;
917
918 if (nr == NULL((void *)0))
919 return (0);
920
921 /* decrease counter */
922
923 sks = cur->key[PF_SK_STACK];
924
925 /* check for outgoing or ingoing balancing */
926 if (nr->rt == PF_ROUTETO)
927 lookup_addr = cur->rt_addr;
928 else if (sks != NULL((void *)0))
929 lookup_addr = sks->addr[1];
930 else {
931 if (pf_status.debug >= LOG_DEBUG7) {
932 log(LOG_DEBUG7, "pf: %s: unable to obtain address",
933 __func__);
934 }
935 return (1);
936 }
937
938 /* check for appropriate pool */
939 if (nr->rdr.addr.type != PF_ADDR_NONE)
940 rpool = nr->rdr;
941 else if (nr->nat.addr.type != PF_ADDR_NONE)
942 rpool = nr->nat;
943 else if (nr->route.addr.type != PF_ADDR_NONE)
944 rpool = nr->route;
945 else
946 return (0);
947
948 if (((rpool.opts & PF_POOL_TYPEMASK0x0f) != PF_POOL_LEASTSTATES))
949 return (0);
950
951 if (rpool.addr.type == PF_ADDR_TABLE) {
952 if ((slbcount = pfr_states_decrease(
953 rpool.addr.p.tbl,
954 &lookup_addr, sks->af)) == -1) {
955 if (pf_status.debug >= LOG_DEBUG7) {
956 log(LOG_DEBUG7, "pf: %s: selected address ",
957 __func__);
958 pf_print_host(&lookup_addr,
959 sks->port[0], sks->af);
960 addlog(". Failed to "
961 "decrease count!\n");
962 }
963 return (1);
964 }
965 } else if (rpool.addr.type == PF_ADDR_DYNIFTL) {
966 if ((slbcount = pfr_states_decrease(
967 rpool.addr.p.dyn->pfid_kt,
968 &lookup_addr, sks->af)) == -1) {
969 if (pf_status.debug >= LOG_DEBUG7) {
970 log(LOG_DEBUG7, "pf: %s: selected address ",
971 __func__);
972 pf_print_host(&lookup_addr,
973 sks->port[0], sks->af);
974 addlog(". Failed to "
975 "decrease count!\n");
976 }
977 return (1);
978 }
979 }
980 if (slbcount > -1) {
981 if (pf_status.debug >= LOG_INFO6) {
982 log(LOG_INFO6, "pf: %s: selected address ", __func__);
983 pf_print_host(&lookup_addr, sks->port[0],
984 sks->af);
985 addlog(" decreased state count to %u\n",
986 slbcount);
987 }
988 }
989 return (0);
990}