Bug Summary

File:net/pf_ioctl.c
Warning:line 1165, column 5
Value stored to 'flags' is never read

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_ioctl.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_ioctl.c
1/* $OpenBSD: pf_ioctl.c,v 1.415 2023/07/06 04:55:05 dlg Exp $ */
2
3/*
4 * Copyright (c) 2001 Daniel Hartmeier
5 * Copyright (c) 2002 - 2018 Henning Brauer <henning@openbsd.org>
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 "pfsync.h"
39#include "pflog.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/sysctl.h>
44#include <sys/mbuf.h>
45#include <sys/filio.h>
46#include <sys/fcntl.h>
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/kernel.h>
50#include <sys/time.h>
51#include <sys/timeout.h>
52#include <sys/pool.h>
53#include <sys/malloc.h>
54#include <sys/proc.h>
55#include <sys/rwlock.h>
56#include <sys/syslog.h>
57#include <sys/specdev.h>
58#include <uvm/uvm_extern.h>
59
60#include <crypto/md5.h>
61
62#include <net/if.h>
63#include <net/if_var.h>
64#include <net/route.h>
65#include <net/hfsc.h>
66#include <net/fq_codel.h>
67
68#include <netinet/in.h>
69#include <netinet/ip.h>
70#include <netinet/in_pcb.h>
71#include <netinet/ip_var.h>
72#include <netinet/ip_icmp.h>
73#include <netinet/tcp.h>
74#include <netinet/udp.h>
75
76#ifdef INET61
77#include <netinet/ip6.h>
78#include <netinet/icmp6.h>
79#endif /* INET6 */
80
81#include <net/pfvar.h>
82#include <net/pfvar_priv.h>
83
84#if NPFSYNC1 > 0
85#include <netinet/ip_ipsp.h>
86#include <net/if_pfsync.h>
87#endif /* NPFSYNC > 0 */
88
89struct pool pf_tag_pl;
90
91void pfattach(int);
92void pf_thread_create(void *);
93int pfopen(dev_t, int, int, struct proc *);
94int pfclose(dev_t, int, int, struct proc *);
95int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
96int pf_begin_rules(u_int32_t *, const char *);
97void pf_rollback_rules(u_int32_t, char *);
98void pf_remove_queues(void);
99int pf_commit_queues(void);
100void pf_free_queues(struct pf_queuehead *);
101void pf_calc_chksum(struct pf_ruleset *);
102void pf_hash_rule(MD5_CTX *, struct pf_rule *);
103void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
104int pf_commit_rules(u_int32_t, char *);
105int pf_addr_setup(struct pf_ruleset *,
106 struct pf_addr_wrap *, sa_family_t);
107struct pfi_kif *pf_kif_setup(struct pfi_kif *);
108void pf_addr_copyout(struct pf_addr_wrap *);
109void pf_trans_set_commit(void);
110void pf_pool_copyin(struct pf_pool *, struct pf_pool *);
111int pf_validate_range(u_int8_t, u_int16_t[2], int);
112int pf_rule_copyin(struct pf_rule *, struct pf_rule *);
113int pf_rule_checkaf(struct pf_rule *);
114u_int16_t pf_qname2qid(char *, int);
115void pf_qid2qname(u_int16_t, char *);
116void pf_qid_unref(u_int16_t);
117int pf_states_clr(struct pfioc_state_kill *);
118int pf_states_get(struct pfioc_states *);
119
120struct pf_trans *pf_open_trans(uint32_t);
121struct pf_trans *pf_find_trans(uint32_t, uint64_t);
122void pf_free_trans(struct pf_trans *);
123void pf_rollback_trans(struct pf_trans *);
124
125void pf_init_tgetrule(struct pf_trans *,
126 struct pf_anchor *, uint32_t, struct pf_rule *);
127void pf_cleanup_tgetrule(struct pf_trans *t);
128
129struct pf_rule pf_default_rule, pf_default_rule_new;
130
131struct {
132 char statusif[IFNAMSIZ16];
133 u_int32_t debug;
134 u_int32_t hostid;
135 u_int32_t reass;
136 u_int32_t mask;
137} pf_trans_set;
138
139#define PF_ORDER_HOST0 0
140#define PF_ORDER_NET1 1
141
142#define PF_TSET_STATUSIF0x01 0x01
143#define PF_TSET_DEBUG0x02 0x02
144#define PF_TSET_HOSTID0x04 0x04
145#define PF_TSET_REASS0x08 0x08
146
147#define TAGID_MAX50000 50000
148TAILQ_HEAD(pf_tags, pf_tagname)struct pf_tags { struct pf_tagname *tqh_first; struct pf_tagname
**tqh_last; }
pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags){ ((void *)0), &(pf_tags).tqh_first },
149 pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids){ ((void *)0), &(pf_qids).tqh_first };
150
151/*
152 * pf_lock protects consistency of PF data structures, which don't have
153 * their dedicated lock yet. The pf_lock currently protects:
154 * - rules,
155 * - radix tables,
156 * - source nodes
157 * All callers must grab pf_lock exclusively.
158 *
159 * pf_state_lock protects consistency of state table. Packets, which do state
160 * look up grab the lock as readers. If packet must create state, then it must
161 * grab the lock as writer. Whenever packet creates state it grabs pf_lock
162 * first then it locks pf_state_lock as the writer.
163 */
164struct rwlock pf_lock = RWLOCK_INITIALIZER("pf_lock"){ 0, "pf_lock" };
165struct rwlock pf_state_lock = RWLOCK_INITIALIZER("pf_state_lock"){ 0, "pf_state_lock" };
166struct rwlock pfioctl_rw = RWLOCK_INITIALIZER("pfioctl_rw"){ 0, "pfioctl_rw" };
167
168struct cpumem *pf_anchor_stack;
169
170#if (PF_QNAME_SIZE64 != PF_TAG_NAME_SIZE64)
171#error PF_QNAME_SIZE64 must be equal to PF_TAG_NAME_SIZE64
172#endif
173u_int16_t tagname2tag(struct pf_tags *, char *, int);
174void tag2tagname(struct pf_tags *, u_int16_t, char *);
175void tag_unref(struct pf_tags *, u_int16_t);
176int pf_rtlabel_add(struct pf_addr_wrap *);
177void pf_rtlabel_remove(struct pf_addr_wrap *);
178void pf_rtlabel_copyout(struct pf_addr_wrap *);
179
180LIST_HEAD(, pf_trans)struct { struct pf_trans *lh_first; } pf_ioctl_trans = LIST_HEAD_INITIALIZER(pf_trans){ ((void *)0) };
181
182/* counts transactions opened by a device */
183unsigned int pf_tcount[CLONE_MAPSZ128 * NBBY8];
184#define pf_unit2idx(_unit_)((_unit_) >> 8) ((_unit_) >> CLONE_SHIFT8)
185
186void
187pfattach(int num)
188{
189 u_int32_t *timeout = pf_default_rule.timeout;
190 struct pf_anchor_stackframe *sf;
191 struct cpumem_iter cmi;
192
193 pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0,
194 IPL_SOFTNET0x2, 0, "pfrule", NULL((void *)0));
195 pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0,
196 IPL_SOFTNET0x2, 0, "pfsrctr", NULL((void *)0));
197 pool_init(&pf_sn_item_pl, sizeof(struct pf_sn_item), 0,
198 IPL_SOFTNET0x2, 0, "pfsnitem", NULL((void *)0));
199 pool_init(&pf_state_pl, sizeof(struct pf_state), 0,
200 IPL_SOFTNET0x2, 0, "pfstate", NULL((void *)0));
201 pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0,
202 IPL_SOFTNET0x2, 0, "pfstkey", NULL((void *)0));
203 pool_init(&pf_state_item_pl, sizeof(struct pf_state_item), 0,
204 IPL_SOFTNET0x2, 0, "pfstitem", NULL((void *)0));
205 pool_init(&pf_rule_item_pl, sizeof(struct pf_rule_item), 0,
206 IPL_SOFTNET0x2, 0, "pfruleitem", NULL((void *)0));
207 pool_init(&pf_queue_pl, sizeof(struct pf_queuespec), 0,
208 IPL_SOFTNET0x2, 0, "pfqueue", NULL((void *)0));
209 pool_init(&pf_tag_pl, sizeof(struct pf_tagname), 0,
210 IPL_SOFTNET0x2, 0, "pftag", NULL((void *)0));
211 pool_init(&pf_pktdelay_pl, sizeof(struct pf_pktdelay), 0,
212 IPL_SOFTNET0x2, 0, "pfpktdelay", NULL((void *)0));
213 pool_init(&pf_anchor_pl, sizeof(struct pf_anchor), 0,
214 IPL_SOFTNET0x2, 0, "pfanchor", NULL((void *)0));
215
216 hfsc_initialize();
217 pfr_initialize();
218 pfi_initialize();
219 pf_osfp_initialize();
220 pf_syncookies_init();
221
222 pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
223 pf_pool_limits[PF_LIMIT_STATES].limit, NULL((void *)0), 0);
224 pool_sethardlimit(pf_pool_limits[PF_LIMIT_ANCHORS].pp,
225 pf_pool_limits[PF_LIMIT_ANCHORS].limit, NULL((void *)0), 0);
226
227 if (physmem <= atop(100*1024*1024)((100*1024*1024) >> 12))
228 pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
229 PFR_KENTRY_HIWAT_SMALL100000;
230
231 RB_INIT(&tree_src_tracking)do { (&tree_src_tracking)->rbh_root = ((void *)0); } while
(0)
;
232 RB_INIT(&pf_anchors)do { (&pf_anchors)->rbh_root = ((void *)0); } while (0
)
;
233 pf_init_ruleset(&pf_main_rulesetpf_main_anchor.ruleset);
234 TAILQ_INIT(&pf_queues[0])do { (&pf_queues[0])->tqh_first = ((void *)0); (&pf_queues
[0])->tqh_last = &(&pf_queues[0])->tqh_first; }
while (0)
;
235 TAILQ_INIT(&pf_queues[1])do { (&pf_queues[1])->tqh_first = ((void *)0); (&pf_queues
[1])->tqh_last = &(&pf_queues[1])->tqh_first; }
while (0)
;
236 pf_queues_active = &pf_queues[0];
237 pf_queues_inactive = &pf_queues[1];
238
239 /* default rule should never be garbage collected */
240 pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
241 pf_default_rule.action = PF_PASS;
242 pf_default_rule.nr = (u_int32_t)-1;
243 pf_default_rule.rtableid = -1;
244
245 /* initialize default timeouts */
246 timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL120;
247 timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL30;
248 timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL24*60*60;
249 timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL15 * 60;
250 timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL45;
251 timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL90;
252 timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL60;
253 timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL30;
254 timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL60;
255 timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL20;
256 timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL10;
257 timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL60;
258 timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL30;
259 timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL60;
260 timeout[PFTM_FRAG] = PFTM_FRAG_VAL60;
261 timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL10;
262 timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL0;
263 timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL30;
264 timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START60000;
265 timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END120000;
266
267 pf_default_rule.src.addr.type = PF_ADDR_ADDRMASK;
268 pf_default_rule.dst.addr.type = PF_ADDR_ADDRMASK;
269 pf_default_rule.rdr.addr.type = PF_ADDR_NONE;
270 pf_default_rule.nat.addr.type = PF_ADDR_NONE;
271 pf_default_rule.route.addr.type = PF_ADDR_NONE;
272
273 pf_normalize_init();
274 memset(&pf_status, 0, sizeof(pf_status))__builtin_memset((&pf_status), (0), (sizeof(pf_status)));
275 pf_status.debug = LOG_ERR3;
276 pf_status.reass = PF_REASS_ENABLED0x01;
277
278 /* XXX do our best to avoid a conflict */
279 pf_status.hostid = arc4random();
280
281 pf_default_rule_new = pf_default_rule;
282
283 /*
284 * we waste two stack frames as meta-data.
285 * frame[0] always presents a top, which can not be used for data
286 * frame[PF_ANCHOR_STACK_MAX] denotes a bottom of the stack and keeps
287 * the pointer to currently used stack frame.
288 */
289 pf_anchor_stack = cpumem_malloc(
290 sizeof(struct pf_anchor_stackframe) * (PF_ANCHOR_STACK_MAX64 + 2),
291 M_WAITOK0x0001|M_ZERO0x0008);
292 CPUMEM_FOREACH(sf, &cmi, pf_anchor_stack)for ((sf) = cpumem_first((&cmi), (pf_anchor_stack)); (sf)
!= ((void *)0); (sf) = cpumem_next((&cmi), (pf_anchor_stack
)))
293 sf[PF_ANCHOR_STACK_MAX64].sf_stack_topu.u_stack_top = &sf[0];
294}
295
296int
297pfopen(dev_t dev, int flags, int fmt, struct proc *p)
298{
299 int unit = minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
;
300
301 if (unit & ((1 << CLONE_SHIFT8) - 1))
302 return (ENXIO6);
303
304 return (0);
305}
306
307int
308pfclose(dev_t dev, int flags, int fmt, struct proc *p)
309{
310 struct pf_trans *w, *s;
311 LIST_HEAD(, pf_trans)struct { struct pf_trans *lh_first; } tmp_list;
312 uint32_t unit = minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
;
313
314 LIST_INIT(&tmp_list)do { ((&tmp_list)->lh_first) = ((void *)0); } while (0
)
;
315 rw_enter_write(&pfioctl_rw);
316 LIST_FOREACH_SAFE(w, &pf_ioctl_trans, pft_entry, s)for ((w) = ((&pf_ioctl_trans)->lh_first); (w) &&
((s) = ((w)->pft_entry.le_next), 1); (w) = (s))
{
317 if (w->pft_unit == unit) {
318 LIST_REMOVE(w, pft_entry)do { if ((w)->pft_entry.le_next != ((void *)0)) (w)->pft_entry
.le_next->pft_entry.le_prev = (w)->pft_entry.le_prev; *
(w)->pft_entry.le_prev = (w)->pft_entry.le_next; ((w)->
pft_entry.le_prev) = ((void *)-1); ((w)->pft_entry.le_next
) = ((void *)-1); } while (0)
;
319 LIST_INSERT_HEAD(&tmp_list, w, pft_entry)do { if (((w)->pft_entry.le_next = (&tmp_list)->lh_first
) != ((void *)0)) (&tmp_list)->lh_first->pft_entry.
le_prev = &(w)->pft_entry.le_next; (&tmp_list)->
lh_first = (w); (w)->pft_entry.le_prev = &(&tmp_list
)->lh_first; } while (0)
;
320 }
321 }
322 rw_exit_write(&pfioctl_rw);
323
324 while ((w = LIST_FIRST(&tmp_list)((&tmp_list)->lh_first)) != NULL((void *)0)) {
325 LIST_REMOVE(w, pft_entry)do { if ((w)->pft_entry.le_next != ((void *)0)) (w)->pft_entry
.le_next->pft_entry.le_prev = (w)->pft_entry.le_prev; *
(w)->pft_entry.le_prev = (w)->pft_entry.le_next; ((w)->
pft_entry.le_prev) = ((void *)-1); ((w)->pft_entry.le_next
) = ((void *)-1); } while (0)
;
326 pf_free_trans(w);
327 }
328
329 return (0);
330}
331
332void
333pf_rule_free(struct pf_rule *rule)
334{
335 if (rule == NULL((void *)0))
336 return;
337
338 pfi_kif_free(rule->kif);
339 pfi_kif_free(rule->rcv_kif);
340 pfi_kif_free(rule->rdr.kif);
341 pfi_kif_free(rule->nat.kif);
342 pfi_kif_free(rule->route.kif);
343
344 pool_put(&pf_rule_pl, rule);
345}
346
347void
348pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
349{
350 if (rulequeue != NULL((void *)0)) {
351 if (rule->states_cur == 0 && rule->src_nodes == 0) {
352 /*
353 * XXX - we need to remove the table *before* detaching
354 * the rule to make sure the table code does not delete
355 * the anchor under our feet.
356 */
357 pf_tbladdr_remove(&rule->src.addr);
358 pf_tbladdr_remove(&rule->dst.addr);
359 pf_tbladdr_remove(&rule->rdr.addr);
360 pf_tbladdr_remove(&rule->nat.addr);
361 pf_tbladdr_remove(&rule->route.addr);
362 if (rule->overload_tbl)
363 pfr_detach_table(rule->overload_tbl);
364 }
365 TAILQ_REMOVE(rulequeue, rule, entries)do { if (((rule)->entries.tqe_next) != ((void *)0)) (rule)
->entries.tqe_next->entries.tqe_prev = (rule)->entries
.tqe_prev; else (rulequeue)->tqh_last = (rule)->entries
.tqe_prev; *(rule)->entries.tqe_prev = (rule)->entries.
tqe_next; ((rule)->entries.tqe_prev) = ((void *)-1); ((rule
)->entries.tqe_next) = ((void *)-1); } while (0)
;
366 rule->entries.tqe_prev = NULL((void *)0);
367 rule->nr = (u_int32_t)-1;
368 }
369
370 if (rule->states_cur > 0 || rule->src_nodes > 0 ||
371 rule->entries.tqe_prev != NULL((void *)0))
372 return;
373 pf_tag_unref(rule->tag);
374 pf_tag_unref(rule->match_tag);
375 pf_rtlabel_remove(&rule->src.addr);
376 pf_rtlabel_remove(&rule->dst.addr);
377 pfi_dynaddr_remove(&rule->src.addr);
378 pfi_dynaddr_remove(&rule->dst.addr);
379 pfi_dynaddr_remove(&rule->rdr.addr);
380 pfi_dynaddr_remove(&rule->nat.addr);
381 pfi_dynaddr_remove(&rule->route.addr);
382 if (rulequeue == NULL((void *)0)) {
383 pf_tbladdr_remove(&rule->src.addr);
384 pf_tbladdr_remove(&rule->dst.addr);
385 pf_tbladdr_remove(&rule->rdr.addr);
386 pf_tbladdr_remove(&rule->nat.addr);
387 pf_tbladdr_remove(&rule->route.addr);
388 if (rule->overload_tbl)
389 pfr_detach_table(rule->overload_tbl);
390 }
391 pfi_kif_unref(rule->rcv_kif, PFI_KIF_REF_RULE);
392 pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
393 pfi_kif_unref(rule->rdr.kif, PFI_KIF_REF_RULE);
394 pfi_kif_unref(rule->nat.kif, PFI_KIF_REF_RULE);
395 pfi_kif_unref(rule->route.kif, PFI_KIF_REF_RULE);
396 pf_remove_anchor(rule);
397 pool_put(&pf_rule_pl, rule);
398}
399
400u_int16_t
401tagname2tag(struct pf_tags *head, char *tagname, int create)
402{
403 struct pf_tagname *tag, *p = NULL((void *)0);
404 u_int16_t new_tagid = 1;
405
406 TAILQ_FOREACH(tag, head, entries)for((tag) = ((head)->tqh_first); (tag) != ((void *)0); (tag
) = ((tag)->entries.tqe_next))
407 if (strcmp(tagname, tag->name) == 0) {
408 tag->ref++;
409 return (tag->tag);
410 }
411
412 if (!create)
413 return (0);
414
415 /*
416 * to avoid fragmentation, we do a linear search from the beginning
417 * and take the first free slot we find. if there is none or the list
418 * is empty, append a new entry at the end.
419 */
420
421 /* new entry */
422 TAILQ_FOREACH(p, head, entries)for((p) = ((head)->tqh_first); (p) != ((void *)0); (p) = (
(p)->entries.tqe_next))
{
423 if (p->tag != new_tagid)
424 break;
425 new_tagid = p->tag + 1;
426 }
427
428 if (new_tagid > TAGID_MAX50000)
429 return (0);
430
431 /* allocate and fill new struct pf_tagname */
432 tag = pool_get(&pf_tag_pl, PR_NOWAIT0x0002 | PR_ZERO0x0008);
433 if (tag == NULL((void *)0))
434 return (0);
435 strlcpy(tag->name, tagname, sizeof(tag->name));
436 tag->tag = new_tagid;
437 tag->ref++;
438
439 if (p != NULL((void *)0)) /* insert new entry before p */
440 TAILQ_INSERT_BEFORE(p, tag, entries)do { (tag)->entries.tqe_prev = (p)->entries.tqe_prev; (
tag)->entries.tqe_next = (p); *(p)->entries.tqe_prev = (
tag); (p)->entries.tqe_prev = &(tag)->entries.tqe_next
; } while (0)
;
441 else /* either list empty or no free slot in between */
442 TAILQ_INSERT_TAIL(head, tag, entries)do { (tag)->entries.tqe_next = ((void *)0); (tag)->entries
.tqe_prev = (head)->tqh_last; *(head)->tqh_last = (tag)
; (head)->tqh_last = &(tag)->entries.tqe_next; } while
(0)
;
443
444 return (tag->tag);
445}
446
447void
448tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
449{
450 struct pf_tagname *tag;
451
452 TAILQ_FOREACH(tag, head, entries)for((tag) = ((head)->tqh_first); (tag) != ((void *)0); (tag
) = ((tag)->entries.tqe_next))
453 if (tag->tag == tagid) {
454 strlcpy(p, tag->name, PF_TAG_NAME_SIZE64);
455 return;
456 }
457}
458
459void
460tag_unref(struct pf_tags *head, u_int16_t tag)
461{
462 struct pf_tagname *p, *next;
463
464 if (tag == 0)
465 return;
466
467 TAILQ_FOREACH_SAFE(p, head, entries, next)for ((p) = ((head)->tqh_first); (p) != ((void *)0) &&
((next) = ((p)->entries.tqe_next), 1); (p) = (next))
{
468 if (tag == p->tag) {
469 if (--p->ref == 0) {
470 TAILQ_REMOVE(head, p, entries)do { if (((p)->entries.tqe_next) != ((void *)0)) (p)->entries
.tqe_next->entries.tqe_prev = (p)->entries.tqe_prev; else
(head)->tqh_last = (p)->entries.tqe_prev; *(p)->entries
.tqe_prev = (p)->entries.tqe_next; ((p)->entries.tqe_prev
) = ((void *)-1); ((p)->entries.tqe_next) = ((void *)-1); }
while (0)
;
471 pool_put(&pf_tag_pl, p);
472 }
473 break;
474 }
475 }
476}
477
478u_int16_t
479pf_tagname2tag(char *tagname, int create)
480{
481 return (tagname2tag(&pf_tags, tagname, create));
482}
483
484void
485pf_tag2tagname(u_int16_t tagid, char *p)
486{
487 tag2tagname(&pf_tags, tagid, p);
488}
489
490void
491pf_tag_ref(u_int16_t tag)
492{
493 struct pf_tagname *t;
494
495 TAILQ_FOREACH(t, &pf_tags, entries)for((t) = ((&pf_tags)->tqh_first); (t) != ((void *)0);
(t) = ((t)->entries.tqe_next))
496 if (t->tag == tag)
497 break;
498 if (t != NULL((void *)0))
499 t->ref++;
500}
501
502void
503pf_tag_unref(u_int16_t tag)
504{
505 tag_unref(&pf_tags, tag);
506}
507
508int
509pf_rtlabel_add(struct pf_addr_wrap *a)
510{
511 if (a->type == PF_ADDR_RTLABEL &&
512 (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0)
513 return (-1);
514 return (0);
515}
516
517void
518pf_rtlabel_remove(struct pf_addr_wrap *a)
519{
520 if (a->type == PF_ADDR_RTLABEL)
521 rtlabel_unref(a->v.rtlabel);
522}
523
524void
525pf_rtlabel_copyout(struct pf_addr_wrap *a)
526{
527 if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) {
528 if (rtlabel_id2name(a->v.rtlabel, a->v.rtlabelname,
529 sizeof(a->v.rtlabelname)) == NULL((void *)0))
530 strlcpy(a->v.rtlabelname, "?",
531 sizeof(a->v.rtlabelname));
532 }
533}
534
535u_int16_t
536pf_qname2qid(char *qname, int create)
537{
538 return (tagname2tag(&pf_qids, qname, create));
539}
540
541void
542pf_qid2qname(u_int16_t qid, char *p)
543{
544 tag2tagname(&pf_qids, qid, p);
545}
546
547void
548pf_qid_unref(u_int16_t qid)
549{
550 tag_unref(&pf_qids, (u_int16_t)qid);
551}
552
553int
554pf_begin_rules(u_int32_t *version, const char *anchor)
555{
556 struct pf_ruleset *rs;
557 struct pf_rule *rule;
558
559 if ((rs = pf_find_or_create_ruleset(anchor)) == NULL((void *)0))
560 return (EINVAL22);
561 while ((rule = TAILQ_FIRST(rs->rules.inactive.ptr)((rs->rules.inactive.ptr)->tqh_first)) != NULL((void *)0)) {
562 pf_rm_rule(rs->rules.inactive.ptr, rule);
563 rs->rules.inactive.rcount--;
564 }
565 *version = ++rs->rules.inactive.version;
566 rs->rules.inactive.open = 1;
567 return (0);
568}
569
570void
571pf_rollback_rules(u_int32_t version, char *anchor)
572{
573 struct pf_ruleset *rs;
574 struct pf_rule *rule;
575
576 rs = pf_find_ruleset(anchor);
577 if (rs == NULL((void *)0) || !rs->rules.inactive.open ||
578 rs->rules.inactive.version != version)
579 return;
580 while ((rule = TAILQ_FIRST(rs->rules.inactive.ptr)((rs->rules.inactive.ptr)->tqh_first)) != NULL((void *)0)) {
581 pf_rm_rule(rs->rules.inactive.ptr, rule);
582 rs->rules.inactive.rcount--;
583 }
584 rs->rules.inactive.open = 0;
585
586 /* queue defs only in the main ruleset */
587 if (anchor[0])
588 return;
589
590 pf_free_queues(pf_queues_inactive);
591}
592
593void
594pf_free_queues(struct pf_queuehead *where)
595{
596 struct pf_queuespec *q, *qtmp;
597
598 TAILQ_FOREACH_SAFE(q, where, entries, qtmp)for ((q) = ((where)->tqh_first); (q) != ((void *)0) &&
((qtmp) = ((q)->entries.tqe_next), 1); (q) = (qtmp))
{
599 TAILQ_REMOVE(where, q, entries)do { if (((q)->entries.tqe_next) != ((void *)0)) (q)->entries
.tqe_next->entries.tqe_prev = (q)->entries.tqe_prev; else
(where)->tqh_last = (q)->entries.tqe_prev; *(q)->entries
.tqe_prev = (q)->entries.tqe_next; ((q)->entries.tqe_prev
) = ((void *)-1); ((q)->entries.tqe_next) = ((void *)-1); }
while (0)
;
600 pfi_kif_unref(q->kif, PFI_KIF_REF_RULE);
601 pool_put(&pf_queue_pl, q);
602 }
603}
604
605void
606pf_remove_queues(void)
607{
608 struct pf_queuespec *q;
609 struct ifnet *ifp;
610
611 /* put back interfaces in normal queueing mode */
612 TAILQ_FOREACH(q, pf_queues_active, entries)for((q) = ((pf_queues_active)->tqh_first); (q) != ((void *
)0); (q) = ((q)->entries.tqe_next))
{
613 if (q->parent_qid != 0)
614 continue;
615
616 ifp = q->kif->pfik_ifp;
617 if (ifp == NULL((void *)0))
618 continue;
619
620 ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL((void *)0));
621 }
622}
623
624struct pf_queue_if {
625 struct ifnet *ifp;
626 const struct ifq_ops *ifqops;
627 const struct pfq_ops *pfqops;
628 void *disc;
629 struct pf_queue_if *next;
630};
631
632static inline struct pf_queue_if *
633pf_ifp2q(struct pf_queue_if *list, struct ifnet *ifp)
634{
635 struct pf_queue_if *qif = list;
636
637 while (qif != NULL((void *)0)) {
638 if (qif->ifp == ifp)
639 return (qif);
640
641 qif = qif->next;
642 }
643
644 return (qif);
645}
646
647int
648pf_create_queues(void)
649{
650 struct pf_queuespec *q;
651 struct ifnet *ifp;
652 struct pf_queue_if *list = NULL((void *)0), *qif;
653 int error;
654
655 /*
656 * Find root queues and allocate traffic conditioner
657 * private data for these interfaces
658 */
659 TAILQ_FOREACH(q, pf_queues_active, entries)for((q) = ((pf_queues_active)->tqh_first); (q) != ((void *
)0); (q) = ((q)->entries.tqe_next))
{
660 if (q->parent_qid != 0)
661 continue;
662
663 ifp = q->kif->pfik_ifp;
664 if (ifp == NULL((void *)0))
665 continue;
666
667 qif = malloc(sizeof(*qif), M_PF6, M_WAITOK0x0001);
668 qif->ifp = ifp;
669
670 if (q->flags & PFQS_ROOTCLASS0x0002) {
671 qif->ifqops = ifq_hfsc_ops;
672 qif->pfqops = pfq_hfsc_ops;
673 } else {
674 qif->ifqops = ifq_fqcodel_ops;
675 qif->pfqops = pfq_fqcodel_ops;
676 }
677
678 qif->disc = qif->pfqops->pfq_alloc(ifp);
679
680 qif->next = list;
681 list = qif;
682 }
683
684 /* and now everything */
685 TAILQ_FOREACH(q, pf_queues_active, entries)for((q) = ((pf_queues_active)->tqh_first); (q) != ((void *
)0); (q) = ((q)->entries.tqe_next))
{
686 ifp = q->kif->pfik_ifp;
687 if (ifp == NULL((void *)0))
688 continue;
689
690 qif = pf_ifp2q(list, ifp);
691 KASSERT(qif != NULL)((qif != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/pf_ioctl.c"
, 691, "qif != NULL"))
;
692
693 error = qif->pfqops->pfq_addqueue(qif->disc, q);
694 if (error != 0)
695 goto error;
696 }
697
698 /* find root queues in old list to disable them if necessary */
699 TAILQ_FOREACH(q, pf_queues_inactive, entries)for((q) = ((pf_queues_inactive)->tqh_first); (q) != ((void
*)0); (q) = ((q)->entries.tqe_next))
{
700 if (q->parent_qid != 0)
701 continue;
702
703 ifp = q->kif->pfik_ifp;
704 if (ifp == NULL((void *)0))
705 continue;
706
707 qif = pf_ifp2q(list, ifp);
708 if (qif != NULL((void *)0))
709 continue;
710
711 ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL((void *)0));
712 }
713
714 /* commit the new queues */
715 while (list != NULL((void *)0)) {
716 qif = list;
717 list = qif->next;
718
719 ifp = qif->ifp;
720
721 ifq_attach(&ifp->if_snd, qif->ifqops, qif->disc);
722 free(qif, M_PF6, sizeof(*qif));
723 }
724
725 return (0);
726
727error:
728 while (list != NULL((void *)0)) {
729 qif = list;
730 list = qif->next;
731
732 qif->pfqops->pfq_free(qif->disc);
733 free(qif, M_PF6, sizeof(*qif));
734 }
735
736 return (error);
737}
738
739int
740pf_commit_queues(void)
741{
742 struct pf_queuehead *qswap;
743 int error;
744
745 /* swap */
746 qswap = pf_queues_active;
747 pf_queues_active = pf_queues_inactive;
748 pf_queues_inactive = qswap;
749
750 error = pf_create_queues();
751 if (error != 0) {
752 pf_queues_inactive = pf_queues_active;
753 pf_queues_active = qswap;
754 return (error);
755 }
756
757 pf_free_queues(pf_queues_inactive);
758
759 return (0);
760}
761
762const struct pfq_ops *
763pf_queue_manager(struct pf_queuespec *q)
764{
765 if (q->flags & PFQS_FLOWQUEUE0x0001)
766 return pfq_fqcodel_ops;
767 return (/* pfq_default_ops */ NULL((void *)0));
768}
769
770#define PF_MD5_UPD(st, elm)MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->
elm))
\
771 MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
772
773#define PF_MD5_UPD_STR(st, elm)MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm
))
\
774 MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
775
776#define PF_MD5_UPD_HTONL(st, elm, stor)do { (stor) = (__uint32_t)(__builtin_constant_p((st)->elm)
? (__uint32_t)(((__uint32_t)((st)->elm) & 0xff) <<
24 | ((__uint32_t)((st)->elm) & 0xff00) << 8 | (
(__uint32_t)((st)->elm) & 0xff0000) >> 8 | ((__uint32_t
)((st)->elm) & 0xff000000) >> 24) : __swap32md((
st)->elm)); MD5Update(ctx, (u_int8_t *) &(stor), sizeof
(u_int32_t));} while (0)
do { \
777 (stor) = htonl((st)->elm)(__uint32_t)(__builtin_constant_p((st)->elm) ? (__uint32_t
)(((__uint32_t)((st)->elm) & 0xff) << 24 | ((__uint32_t
)((st)->elm) & 0xff00) << 8 | ((__uint32_t)((st)
->elm) & 0xff0000) >> 8 | ((__uint32_t)((st)->
elm) & 0xff000000) >> 24) : __swap32md((st)->elm
))
; \
778 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
779} while (0)
780
781#define PF_MD5_UPD_HTONS(st, elm, stor)do { (stor) = (__uint16_t)(__builtin_constant_p((st)->elm)
? (__uint16_t)(((__uint16_t)((st)->elm) & 0xffU) <<
8 | ((__uint16_t)((st)->elm) & 0xff00U) >> 8) :
__swap16md((st)->elm)); MD5Update(ctx, (u_int8_t *) &
(stor), sizeof(u_int16_t));} while (0)
do { \
782 (stor) = htons((st)->elm)(__uint16_t)(__builtin_constant_p((st)->elm) ? (__uint16_t
)(((__uint16_t)((st)->elm) & 0xffU) << 8 | ((__uint16_t
)((st)->elm) & 0xff00U) >> 8) : __swap16md((st)->
elm))
; \
783 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
784} while (0)
785
786void
787pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
788{
789 PF_MD5_UPD(pfr, addr.type)MD5Update(ctx, (u_int8_t *) &(pfr)->addr.type, sizeof(
(pfr)->addr.type))
;
790 switch (pfr->addr.type) {
791 case PF_ADDR_DYNIFTL:
792 PF_MD5_UPD(pfr, addr.v.ifname)MD5Update(ctx, (u_int8_t *) &(pfr)->addr.v.ifname, sizeof
((pfr)->addr.v.ifname))
;
793 PF_MD5_UPD(pfr, addr.iflags)MD5Update(ctx, (u_int8_t *) &(pfr)->addr.iflags, sizeof
((pfr)->addr.iflags))
;
794 break;
795 case PF_ADDR_TABLE:
796 if (strncmp(pfr->addr.v.tblname, PF_OPTIMIZER_TABLE_PFX"__automatic_",
797 strlen(PF_OPTIMIZER_TABLE_PFX"__automatic_")))
798 PF_MD5_UPD(pfr, addr.v.tblname)MD5Update(ctx, (u_int8_t *) &(pfr)->addr.v.tblname, sizeof
((pfr)->addr.v.tblname))
;
799 break;
800 case PF_ADDR_ADDRMASK:
801 /* XXX ignore af? */
802 PF_MD5_UPD(pfr, addr.v.a.addr.addr32)MD5Update(ctx, (u_int8_t *) &(pfr)->addr.v.a.addr.pfa.
addr32, sizeof((pfr)->addr.v.a.addr.pfa.addr32))
;
803 PF_MD5_UPD(pfr, addr.v.a.mask.addr32)MD5Update(ctx, (u_int8_t *) &(pfr)->addr.v.a.mask.pfa.
addr32, sizeof((pfr)->addr.v.a.mask.pfa.addr32))
;
804 break;
805 case PF_ADDR_RTLABEL:
806 PF_MD5_UPD(pfr, addr.v.rtlabelname)MD5Update(ctx, (u_int8_t *) &(pfr)->addr.v.rtlabelname
, sizeof((pfr)->addr.v.rtlabelname))
;
807 break;
808 }
809
810 PF_MD5_UPD(pfr, port[0])MD5Update(ctx, (u_int8_t *) &(pfr)->port[0], sizeof((pfr
)->port[0]))
;
811 PF_MD5_UPD(pfr, port[1])MD5Update(ctx, (u_int8_t *) &(pfr)->port[1], sizeof((pfr
)->port[1]))
;
812 PF_MD5_UPD(pfr, neg)MD5Update(ctx, (u_int8_t *) &(pfr)->neg, sizeof((pfr)->
neg))
;
813 PF_MD5_UPD(pfr, port_op)MD5Update(ctx, (u_int8_t *) &(pfr)->port_op, sizeof((pfr
)->port_op))
;
814}
815
816void
817pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule)
818{
819 u_int16_t x;
820 u_int32_t y;
821
822 pf_hash_rule_addr(ctx, &rule->src);
823 pf_hash_rule_addr(ctx, &rule->dst);
824 PF_MD5_UPD_STR(rule, label)MD5Update(ctx, (u_int8_t *) (rule)->label, strlen((rule)->
label))
;
825 PF_MD5_UPD_STR(rule, ifname)MD5Update(ctx, (u_int8_t *) (rule)->ifname, strlen((rule)->
ifname))
;
826 PF_MD5_UPD_STR(rule, rcv_ifname)MD5Update(ctx, (u_int8_t *) (rule)->rcv_ifname, strlen((rule
)->rcv_ifname))
;
827 PF_MD5_UPD_STR(rule, match_tagname)MD5Update(ctx, (u_int8_t *) (rule)->match_tagname, strlen(
(rule)->match_tagname))
;
828 PF_MD5_UPD_HTONS(rule, match_tag, x)do { (x) = (__uint16_t)(__builtin_constant_p((rule)->match_tag
) ? (__uint16_t)(((__uint16_t)((rule)->match_tag) & 0xffU
) << 8 | ((__uint16_t)((rule)->match_tag) & 0xff00U
) >> 8) : __swap16md((rule)->match_tag)); MD5Update(
ctx, (u_int8_t *) &(x), sizeof(u_int16_t));} while (0)
; /* dup? */
829 PF_MD5_UPD_HTONL(rule, os_fingerprint, y)do { (y) = (__uint32_t)(__builtin_constant_p((rule)->os_fingerprint
) ? (__uint32_t)(((__uint32_t)((rule)->os_fingerprint) &
0xff) << 24 | ((__uint32_t)((rule)->os_fingerprint)
& 0xff00) << 8 | ((__uint32_t)((rule)->os_fingerprint
) & 0xff0000) >> 8 | ((__uint32_t)((rule)->os_fingerprint
) & 0xff000000) >> 24) : __swap32md((rule)->os_fingerprint
)); MD5Update(ctx, (u_int8_t *) &(y), sizeof(u_int32_t));
} while (0)
;
830 PF_MD5_UPD_HTONL(rule, prob, y)do { (y) = (__uint32_t)(__builtin_constant_p((rule)->prob)
? (__uint32_t)(((__uint32_t)((rule)->prob) & 0xff) <<
24 | ((__uint32_t)((rule)->prob) & 0xff00) << 8
| ((__uint32_t)((rule)->prob) & 0xff0000) >> 8 |
((__uint32_t)((rule)->prob) & 0xff000000) >> 24
) : __swap32md((rule)->prob)); MD5Update(ctx, (u_int8_t *)
&(y), sizeof(u_int32_t));} while (0)
;
831 PF_MD5_UPD_HTONL(rule, uid.uid[0], y)do { (y) = (__uint32_t)(__builtin_constant_p((rule)->uid.uid
[0]) ? (__uint32_t)(((__uint32_t)((rule)->uid.uid[0]) &
0xff) << 24 | ((__uint32_t)((rule)->uid.uid[0]) &
0xff00) << 8 | ((__uint32_t)((rule)->uid.uid[0]) &
0xff0000) >> 8 | ((__uint32_t)((rule)->uid.uid[0]) &
0xff000000) >> 24) : __swap32md((rule)->uid.uid[0])
); MD5Update(ctx, (u_int8_t *) &(y), sizeof(u_int32_t));}
while (0)
;
832 PF_MD5_UPD_HTONL(rule, uid.uid[1], y)do { (y) = (__uint32_t)(__builtin_constant_p((rule)->uid.uid
[1]) ? (__uint32_t)(((__uint32_t)((rule)->uid.uid[1]) &
0xff) << 24 | ((__uint32_t)((rule)->uid.uid[1]) &
0xff00) << 8 | ((__uint32_t)((rule)->uid.uid[1]) &
0xff0000) >> 8 | ((__uint32_t)((rule)->uid.uid[1]) &
0xff000000) >> 24) : __swap32md((rule)->uid.uid[1])
); MD5Update(ctx, (u_int8_t *) &(y), sizeof(u_int32_t));}
while (0)
;
833 PF_MD5_UPD(rule, uid.op)MD5Update(ctx, (u_int8_t *) &(rule)->uid.op, sizeof((rule
)->uid.op))
;
834 PF_MD5_UPD_HTONL(rule, gid.gid[0], y)do { (y) = (__uint32_t)(__builtin_constant_p((rule)->gid.gid
[0]) ? (__uint32_t)(((__uint32_t)((rule)->gid.gid[0]) &
0xff) << 24 | ((__uint32_t)((rule)->gid.gid[0]) &
0xff00) << 8 | ((__uint32_t)((rule)->gid.gid[0]) &
0xff0000) >> 8 | ((__uint32_t)((rule)->gid.gid[0]) &
0xff000000) >> 24) : __swap32md((rule)->gid.gid[0])
); MD5Update(ctx, (u_int8_t *) &(y), sizeof(u_int32_t));}
while (0)
;
835 PF_MD5_UPD_HTONL(rule, gid.gid[1], y)do { (y) = (__uint32_t)(__builtin_constant_p((rule)->gid.gid
[1]) ? (__uint32_t)(((__uint32_t)((rule)->gid.gid[1]) &
0xff) << 24 | ((__uint32_t)((rule)->gid.gid[1]) &
0xff00) << 8 | ((__uint32_t)((rule)->gid.gid[1]) &
0xff0000) >> 8 | ((__uint32_t)((rule)->gid.gid[1]) &
0xff000000) >> 24) : __swap32md((rule)->gid.gid[1])
); MD5Update(ctx, (u_int8_t *) &(y), sizeof(u_int32_t));}
while (0)
;
836 PF_MD5_UPD(rule, gid.op)MD5Update(ctx, (u_int8_t *) &(rule)->gid.op, sizeof((rule
)->gid.op))
;
837 PF_MD5_UPD_HTONL(rule, rule_flag, y)do { (y) = (__uint32_t)(__builtin_constant_p((rule)->rule_flag
) ? (__uint32_t)(((__uint32_t)((rule)->rule_flag) & 0xff
) << 24 | ((__uint32_t)((rule)->rule_flag) & 0xff00
) << 8 | ((__uint32_t)((rule)->rule_flag) & 0xff0000
) >> 8 | ((__uint32_t)((rule)->rule_flag) & 0xff000000
) >> 24) : __swap32md((rule)->rule_flag)); MD5Update
(ctx, (u_int8_t *) &(y), sizeof(u_int32_t));} while (0)
;
838 PF_MD5_UPD(rule, action)MD5Update(ctx, (u_int8_t *) &(rule)->action, sizeof((rule
)->action))
;
839 PF_MD5_UPD(rule, direction)MD5Update(ctx, (u_int8_t *) &(rule)->direction, sizeof
((rule)->direction))
;
840 PF_MD5_UPD(rule, af)MD5Update(ctx, (u_int8_t *) &(rule)->af, sizeof((rule)
->af))
;
841 PF_MD5_UPD(rule, quick)MD5Update(ctx, (u_int8_t *) &(rule)->quick, sizeof((rule
)->quick))
;
842 PF_MD5_UPD(rule, ifnot)MD5Update(ctx, (u_int8_t *) &(rule)->ifnot, sizeof((rule
)->ifnot))
;
843 PF_MD5_UPD(rule, rcvifnot)MD5Update(ctx, (u_int8_t *) &(rule)->rcvifnot, sizeof(
(rule)->rcvifnot))
;
844 PF_MD5_UPD(rule, match_tag_not)MD5Update(ctx, (u_int8_t *) &(rule)->match_tag_not, sizeof
((rule)->match_tag_not))
;
845 PF_MD5_UPD(rule, keep_state)MD5Update(ctx, (u_int8_t *) &(rule)->keep_state, sizeof
((rule)->keep_state))
;
846 PF_MD5_UPD(rule, proto)MD5Update(ctx, (u_int8_t *) &(rule)->proto, sizeof((rule
)->proto))
;
847 PF_MD5_UPD(rule, type)MD5Update(ctx, (u_int8_t *) &(rule)->type, sizeof((rule
)->type))
;
848 PF_MD5_UPD(rule, code)MD5Update(ctx, (u_int8_t *) &(rule)->code, sizeof((rule
)->code))
;
849 PF_MD5_UPD(rule, flags)MD5Update(ctx, (u_int8_t *) &(rule)->flags, sizeof((rule
)->flags))
;
850 PF_MD5_UPD(rule, flagset)MD5Update(ctx, (u_int8_t *) &(rule)->flagset, sizeof((
rule)->flagset))
;
851 PF_MD5_UPD(rule, allow_opts)MD5Update(ctx, (u_int8_t *) &(rule)->allow_opts, sizeof
((rule)->allow_opts))
;
852 PF_MD5_UPD(rule, rt)MD5Update(ctx, (u_int8_t *) &(rule)->rt, sizeof((rule)
->rt))
;
853 PF_MD5_UPD(rule, tos)MD5Update(ctx, (u_int8_t *) &(rule)->tos, sizeof((rule
)->tos))
;
854}
855
856int
857pf_commit_rules(u_int32_t version, char *anchor)
858{
859 struct pf_ruleset *rs;
860 struct pf_rule *rule;
861 struct pf_rulequeue *old_rules;
862 u_int32_t old_rcount;
863
864 PF_ASSERT_LOCKED()do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail(
0x0001UL, rw_status(&pf_lock),__func__); } while (0)
;
865
866 rs = pf_find_ruleset(anchor);
867 if (rs == NULL((void *)0) || !rs->rules.inactive.open ||
868 version != rs->rules.inactive.version)
869 return (EBUSY16);
870
871 if (rs == &pf_main_rulesetpf_main_anchor.ruleset)
872 pf_calc_chksum(rs);
873
874 /* Swap rules, keep the old. */
875 old_rules = rs->rules.active.ptr;
876 old_rcount = rs->rules.active.rcount;
877
878 rs->rules.active.ptr = rs->rules.inactive.ptr;
879 rs->rules.active.rcount = rs->rules.inactive.rcount;
880 rs->rules.inactive.ptr = old_rules;
881 rs->rules.inactive.rcount = old_rcount;
882
883 rs->rules.active.version = rs->rules.inactive.version;
884 pf_calc_skip_steps(rs->rules.active.ptr);
885
886
887 /* Purge the old rule list. */
888 while ((rule = TAILQ_FIRST(old_rules)((old_rules)->tqh_first)) != NULL((void *)0))
889 pf_rm_rule(old_rules, rule);
890 rs->rules.inactive.rcount = 0;
891 rs->rules.inactive.open = 0;
892 pf_remove_if_empty_ruleset(rs);
893
894 /* queue defs only in the main ruleset */
895 if (anchor[0])
896 return (0);
897 return (pf_commit_queues());
898}
899
900void
901pf_calc_chksum(struct pf_ruleset *rs)
902{
903 MD5_CTX ctx;
904 struct pf_rule *rule;
905 u_int8_t digest[PF_MD5_DIGEST_LENGTH16];
906
907 MD5Init(&ctx);
908
909 if (rs->rules.inactive.rcount) {
910 TAILQ_FOREACH(rule, rs->rules.inactive.ptr, entries)for((rule) = ((rs->rules.inactive.ptr)->tqh_first); (rule
) != ((void *)0); (rule) = ((rule)->entries.tqe_next))
{
911 pf_hash_rule(&ctx, rule);
912 }
913 }
914
915 MD5Final(digest, &ctx);
916 memcpy(pf_status.pf_chksum, digest, sizeof(pf_status.pf_chksum))__builtin_memcpy((pf_status.pf_chksum), (digest), (sizeof(pf_status
.pf_chksum)))
;
917}
918
919int
920pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr,
921 sa_family_t af)
922{
923 if (pfi_dynaddr_setup(addr, af, PR_WAITOK0x0001) ||
924 pf_tbladdr_setup(ruleset, addr, PR_WAITOK0x0001) ||
925 pf_rtlabel_add(addr))
926 return (EINVAL22);
927
928 return (0);
929}
930
931struct pfi_kif *
932pf_kif_setup(struct pfi_kif *kif_buf)
933{
934 struct pfi_kif *kif;
935
936 if (kif_buf == NULL((void *)0))
937 return (NULL((void *)0));
938
939 KASSERT(kif_buf->pfik_name[0] != '\0')((kif_buf->pfik_name[0] != '\0') ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/pf_ioctl.c", 939, "kif_buf->pfik_name[0] != '\\0'"
))
;
940
941 kif = pfi_kif_get(kif_buf->pfik_name, &kif_buf);
942 if (kif_buf != NULL((void *)0))
943 pfi_kif_free(kif_buf);
944 pfi_kif_ref(kif, PFI_KIF_REF_RULE);
945
946 return (kif);
947}
948
949void
950pf_addr_copyout(struct pf_addr_wrap *addr)
951{
952 pfi_dynaddr_copyout(addr);
953 pf_tbladdr_copyout(addr);
954 pf_rtlabel_copyout(addr);
955}
956
957int
958pf_states_clr(struct pfioc_state_kill *psk)
959{
960 struct pf_state *st, *nextst;
961 struct pf_state *head, *tail;
962 u_int killed = 0;
963 int error;
964
965 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
966
967 /* lock against the gc removing an item from the list */
968 error = rw_enter(&pf_state_list.pfs_rwl, RW_READ0x0002UL|RW_INTR0x0010UL);
969 if (error != 0)
970 goto unlock;
971
972 /* get a snapshot view of the ends of the list to traverse between */
973 mtx_enter(&pf_state_list.pfs_mtx);
974 head = TAILQ_FIRST(&pf_state_list.pfs_list)((&pf_state_list.pfs_list)->tqh_first);
975 tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue)(*(((struct pf_state_queue *)((&pf_state_list.pfs_list)->
tqh_last))->tqh_last))
;
976 mtx_leave(&pf_state_list.pfs_mtx);
977
978 st = NULL((void *)0);
979 nextst = head;
980
981 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
982 PF_STATE_ENTER_WRITE()do { rw_enter_write(&pf_state_lock); } while (0);
983
984 while (st != tail) {
985 st = nextst;
986 nextst = TAILQ_NEXT(st, entry_list)((st)->entry_list.tqe_next);
987
988 if (st->timeout == PFTM_UNLINKED)
989 continue;
990
991 if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
992 st->kif->pfik_name)) {
993#if NPFSYNC1 > 0
994 /* don't send out individual delete messages */
995 SET(st->state_flags, PFSTATE_NOSYNC)((st->state_flags) |= (0x0008));
996#endif /* NPFSYNC > 0 */
997 pf_remove_state(st);
998 killed++;
999 }
1000 }
1001
1002 PF_STATE_EXIT_WRITE()do { do { if (rw_status(&pf_state_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_state_lock), __func__); } while (
0); rw_exit_write(&pf_state_lock); } while (0)
;
1003 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1004 rw_exit(&pf_state_list.pfs_rwl);
1005
1006 psk->psk_killed = killed;
1007
1008#if NPFSYNC1 > 0
1009 pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
1010#endif /* NPFSYNC > 0 */
1011unlock:
1012 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1013
1014 return (error);
1015}
1016
1017int
1018pf_states_get(struct pfioc_states *ps)
1019{
1020 struct pf_state *st, *nextst;
1021 struct pf_state *head, *tail;
1022 struct pfsync_state *p, pstore;
1023 u_int32_t nr = 0;
1024 int error;
1025
1026 if (ps->ps_len == 0) {
1027 nr = pf_status.states;
1028 ps->ps_len = sizeof(struct pfsync_state) * nr;
1029 return (0);
1030 }
1031
1032 p = ps->ps_statesps_u.psu_states;
1033
1034 /* lock against the gc removing an item from the list */
1035 error = rw_enter(&pf_state_list.pfs_rwl, RW_READ0x0002UL|RW_INTR0x0010UL);
1036 if (error != 0)
1037 return (error);
1038
1039 /* get a snapshot view of the ends of the list to traverse between */
1040 mtx_enter(&pf_state_list.pfs_mtx);
1041 head = TAILQ_FIRST(&pf_state_list.pfs_list)((&pf_state_list.pfs_list)->tqh_first);
1042 tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue)(*(((struct pf_state_queue *)((&pf_state_list.pfs_list)->
tqh_last))->tqh_last))
;
1043 mtx_leave(&pf_state_list.pfs_mtx);
1044
1045 st = NULL((void *)0);
1046 nextst = head;
1047
1048 while (st != tail) {
1049 st = nextst;
1050 nextst = TAILQ_NEXT(st, entry_list)((st)->entry_list.tqe_next);
1051
1052 if (st->timeout == PFTM_UNLINKED)
1053 continue;
1054
1055 if ((nr+1) * sizeof(*p) > ps->ps_len)
1056 break;
1057
1058 pf_state_export(&pstore, st);
1059 error = copyout(&pstore, p, sizeof(*p));
1060 if (error)
1061 goto fail;
1062
1063 p++;
1064 nr++;
1065 }
1066 ps->ps_len = sizeof(struct pfsync_state) * nr;
1067
1068fail:
1069 rw_exit(&pf_state_list.pfs_rwl);
1070
1071 return (error);
1072}
1073
1074int
1075pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
1076{
1077 int error = 0;
1078
1079 /* XXX keep in sync with switch() below */
1080 if (securelevel > 1)
1081 switch (cmd) {
1082 case DIOCGETRULES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((6)))
:
1083 case DIOCGETRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((7)))
:
1084 case DIOCGETSTATE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state) & 0x1fff) << 16) | ((('D')) <<
8) | ((19)))
:
1085 case DIOCSETSTATUSIF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((20)))
:
1086 case DIOCGETSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_status) & 0x1fff) << 16) | ((('D')) <<
8) | ((21)))
:
1087 case DIOCCLRSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((22)))
:
1088 case DIOCNATLOOK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_natlook) & 0x1fff) << 16) | ((('D')) <<
8) | ((23)))
:
1089 case DIOCSETDEBUG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((24)))
:
1090 case DIOCGETSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_states) & 0x1fff) << 16) | ((('D')) <<
8) | ((25)))
:
1091 case DIOCGETTIMEOUT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_tm) & 0x1fff) << 16) | ((('D')) <<
8) | ((30)))
:
1092 case DIOCGETLIMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_limit) & 0x1fff) << 16) | ((('D')) <<
8) | ((39)))
:
1093 case DIOCGETRULESETS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((58)))
:
1094 case DIOCGETRULESET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((59)))
:
1095 case DIOCGETQUEUES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((94)))
:
1096 case DIOCGETQUEUE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((95)))
:
1097 case DIOCGETQSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_qstats) & 0x1fff) << 16) | ((('D')) <<
8) | ((96)))
:
1098 case DIOCRGETTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((63)))
:
1099 case DIOCRGETTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((64)))
:
1100 case DIOCRCLRTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((65)))
:
1101 case DIOCRCLRADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((66)))
:
1102 case DIOCRADDADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((67)))
:
1103 case DIOCRDELADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((68)))
:
1104 case DIOCRSETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((69)))
:
1105 case DIOCRGETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((70)))
:
1106 case DIOCRGETASTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((71)))
:
1107 case DIOCRCLRASTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((72)))
:
1108 case DIOCRTSTADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((73)))
:
1109 case DIOCOSFPGET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_osfp_ioctl) & 0x1fff) << 16) | ((('D')) <<
8) | ((80)))
:
1110 case DIOCGETSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_src_nodes) & 0x1fff) << 16) | ((('D')
) << 8) | ((84)))
:
1111 case DIOCCLRSRCNODES((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((85)))
:
1112 case DIOCIGETIFACES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((87)))
:
1113 case DIOCSETIFFLAG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((89)))
:
1114 case DIOCCLRIFFLAG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((90)))
:
1115 case DIOCGETSYNFLWATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_synflwats) & 0x1fff) << 16) | ((('D')
) << 8) | ((99)))
:
1116 break;
1117 case DIOCRCLRTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((60)))
:
1118 case DIOCRADDTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((61)))
:
1119 case DIOCRDELTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((62)))
:
1120 case DIOCRSETTFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((74)))
:
1121 if (((struct pfioc_table *)addr)->pfrio_flags &
1122 PFR_FLAG_DUMMY0x00000002)
1123 break; /* dummy operation ok */
1124 return (EPERM1);
1125 default:
1126 return (EPERM1);
1127 }
1128
1129 if (!(flags & FWRITE0x0002))
1130 switch (cmd) {
1131 case DIOCGETRULES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((6)))
:
1132 case DIOCGETSTATE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state) & 0x1fff) << 16) | ((('D')) <<
8) | ((19)))
:
1133 case DIOCGETSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_status) & 0x1fff) << 16) | ((('D')) <<
8) | ((21)))
:
1134 case DIOCGETSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_states) & 0x1fff) << 16) | ((('D')) <<
8) | ((25)))
:
1135 case DIOCGETTIMEOUT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_tm) & 0x1fff) << 16) | ((('D')) <<
8) | ((30)))
:
1136 case DIOCGETLIMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_limit) & 0x1fff) << 16) | ((('D')) <<
8) | ((39)))
:
1137 case DIOCGETRULESETS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((58)))
:
1138 case DIOCGETRULESET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((59)))
:
1139 case DIOCGETQUEUES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((94)))
:
1140 case DIOCGETQUEUE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((95)))
:
1141 case DIOCGETQSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_qstats) & 0x1fff) << 16) | ((('D')) <<
8) | ((96)))
:
1142 case DIOCNATLOOK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_natlook) & 0x1fff) << 16) | ((('D')) <<
8) | ((23)))
:
1143 case DIOCRGETTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((63)))
:
1144 case DIOCRGETTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((64)))
:
1145 case DIOCRGETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((70)))
:
1146 case DIOCRGETASTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((71)))
:
1147 case DIOCRTSTADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((73)))
:
1148 case DIOCOSFPGET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_osfp_ioctl) & 0x1fff) << 16) | ((('D')) <<
8) | ((80)))
:
1149 case DIOCGETSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_src_nodes) & 0x1fff) << 16) | ((('D')
) << 8) | ((84)))
:
1150 case DIOCIGETIFACES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((87)))
:
1151 case DIOCGETSYNFLWATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_synflwats) & 0x1fff) << 16) | ((('D')
) << 8) | ((99)))
:
1152 case DIOCXEND(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((100)))
:
1153 break;
1154 case DIOCRCLRTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((60)))
:
1155 case DIOCRADDTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((61)))
:
1156 case DIOCRDELTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((62)))
:
1157 case DIOCRCLRTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((65)))
:
1158 case DIOCRCLRADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((66)))
:
1159 case DIOCRADDADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((67)))
:
1160 case DIOCRDELADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((68)))
:
1161 case DIOCRSETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((69)))
:
1162 case DIOCRSETTFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((74)))
:
1163 if (((struct pfioc_table *)addr)->pfrio_flags &
1164 PFR_FLAG_DUMMY0x00000002) {
1165 flags |= FWRITE0x0002; /* need write lock for dummy */
Value stored to 'flags' is never read
1166 break; /* dummy operation ok */
1167 }
1168 return (EACCES13);
1169 case DIOCGETRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((7)))
:
1170 if (((struct pfioc_rule *)addr)->action ==
1171 PF_GET_CLR_CNTR)
1172 return (EACCES13);
1173 break;
1174 default:
1175 return (EACCES13);
1176 }
1177
1178 rw_enter_write(&pfioctl_rw);
1179
1180 switch (cmd) {
1181
1182 case DIOCSTART((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((1)))
:
1183 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1184 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1185 if (pf_status.running)
1186 error = EEXIST17;
1187 else {
1188 pf_status.running = 1;
1189 pf_status.since = getuptime();
1190 if (pf_status.stateid == 0) {
1191 pf_status.stateid = gettime();
1192 pf_status.stateid = pf_status.stateid << 32;
1193 }
1194 timeout_add_sec(&pf_purge_states_to, 1);
1195 timeout_add_sec(&pf_purge_to, 1);
1196 pf_create_queues();
1197 DPFPRINTF(LOG_NOTICE, "pf: started")do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: started"); addlog("\n"); } } while (0)
;
1198 }
1199 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1200 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1201 break;
1202
1203 case DIOCSTOP((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((2)))
:
1204 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1205 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1206 if (!pf_status.running)
1207 error = ENOENT2;
1208 else {
1209 pf_status.running = 0;
1210 pf_status.since = getuptime();
1211 pf_remove_queues();
1212 DPFPRINTF(LOG_NOTICE, "pf: stopped")do { if (pf_status.debug >= (5)) { log(5, "pf: "); addlog(
"pf: stopped"); addlog("\n"); } } while (0)
;
1213 }
1214 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1215 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1216 break;
1217
1218 case DIOCGETQUEUES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((94)))
: {
1219 struct pfioc_queue *pq = (struct pfioc_queue *)addr;
1220 struct pf_queuespec *qs;
1221 u_int32_t nr = 0;
1222
1223 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1224 pq->ticket = pf_main_rulesetpf_main_anchor.ruleset.rules.active.version;
1225
1226 /* save state to not run over them all each time? */
1227 qs = TAILQ_FIRST(pf_queues_active)((pf_queues_active)->tqh_first);
1228 while (qs != NULL((void *)0)) {
1229 qs = TAILQ_NEXT(qs, entries)((qs)->entries.tqe_next);
1230 nr++;
1231 }
1232 pq->nr = nr;
1233 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1234 break;
1235 }
1236
1237 case DIOCGETQUEUE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((95)))
: {
1238 struct pfioc_queue *pq = (struct pfioc_queue *)addr;
1239 struct pf_queuespec *qs;
1240 u_int32_t nr = 0;
1241
1242 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1243 if (pq->ticket != pf_main_rulesetpf_main_anchor.ruleset.rules.active.version) {
1244 error = EBUSY16;
1245 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1246 goto fail;
1247 }
1248
1249 /* save state to not run over them all each time? */
1250 qs = TAILQ_FIRST(pf_queues_active)((pf_queues_active)->tqh_first);
1251 while ((qs != NULL((void *)0)) && (nr++ < pq->nr))
1252 qs = TAILQ_NEXT(qs, entries)((qs)->entries.tqe_next);
1253 if (qs == NULL((void *)0)) {
1254 error = EBUSY16;
1255 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1256 goto fail;
1257 }
1258 memcpy(&pq->queue, qs, sizeof(pq->queue))__builtin_memcpy((&pq->queue), (qs), (sizeof(pq->queue
)))
;
1259 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1260 break;
1261 }
1262
1263 case DIOCGETQSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_qstats) & 0x1fff) << 16) | ((('D')) <<
8) | ((96)))
: {
1264 struct pfioc_qstats *pq = (struct pfioc_qstats *)addr;
1265 struct pf_queuespec *qs;
1266 u_int32_t nr;
1267 int nbytes;
1268
1269 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1270 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1271 if (pq->ticket != pf_main_rulesetpf_main_anchor.ruleset.rules.active.version) {
1272 error = EBUSY16;
1273 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1274 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1275 goto fail;
1276 }
1277 nbytes = pq->nbytes;
1278 nr = 0;
1279
1280 /* save state to not run over them all each time? */
1281 qs = TAILQ_FIRST(pf_queues_active)((pf_queues_active)->tqh_first);
1282 while ((qs != NULL((void *)0)) && (nr++ < pq->nr))
1283 qs = TAILQ_NEXT(qs, entries)((qs)->entries.tqe_next);
1284 if (qs == NULL((void *)0)) {
1285 error = EBUSY16;
1286 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1287 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1288 goto fail;
1289 }
1290 memcpy(&pq->queue, qs, sizeof(pq->queue))__builtin_memcpy((&pq->queue), (qs), (sizeof(pq->queue
)))
;
1291 /* It's a root flow queue but is not an HFSC root class */
1292 if ((qs->flags & PFQS_FLOWQUEUE0x0001) && qs->parent_qid == 0 &&
1293 !(qs->flags & PFQS_ROOTCLASS0x0002))
1294 error = pfq_fqcodel_ops->pfq_qstats(qs, pq->buf,
1295 &nbytes);
1296 else
1297 error = pfq_hfsc_ops->pfq_qstats(qs, pq->buf,
1298 &nbytes);
1299 if (error == 0)
1300 pq->nbytes = nbytes;
1301 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1302 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1303 break;
1304 }
1305
1306 case DIOCADDQUEUE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((93)))
: {
1307 struct pfioc_queue *q = (struct pfioc_queue *)addr;
1308 struct pf_queuespec *qs;
1309
1310 qs = pool_get(&pf_queue_pl, PR_WAITOK0x0001|PR_LIMITFAIL0x0004|PR_ZERO0x0008);
1311 if (qs == NULL((void *)0)) {
1312 error = ENOMEM12;
1313 goto fail;
1314 }
1315
1316 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1317 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1318 if (q->ticket != pf_main_rulesetpf_main_anchor.ruleset.rules.inactive.version) {
1319 error = EBUSY16;
1320 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1321 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1322 pool_put(&pf_queue_pl, qs);
1323 goto fail;
1324 }
1325 memcpy(qs, &q->queue, sizeof(*qs))__builtin_memcpy((qs), (&q->queue), (sizeof(*qs)));
1326 qs->qid = pf_qname2qid(qs->qname, 1);
1327 if (qs->qid == 0) {
1328 error = EBUSY16;
1329 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1330 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1331 pool_put(&pf_queue_pl, qs);
1332 goto fail;
1333 }
1334 if (qs->parent[0] && (qs->parent_qid =
1335 pf_qname2qid(qs->parent, 0)) == 0) {
1336 error = ESRCH3;
1337 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1338 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1339 pool_put(&pf_queue_pl, qs);
1340 goto fail;
1341 }
1342 qs->kif = pfi_kif_get(qs->ifname, NULL((void *)0));
1343 if (qs->kif == NULL((void *)0)) {
1344 error = ESRCH3;
1345 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1346 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1347 pool_put(&pf_queue_pl, qs);
1348 goto fail;
1349 }
1350 /* XXX resolve bw percentage specs */
1351 pfi_kif_ref(qs->kif, PFI_KIF_REF_RULE);
1352
1353 TAILQ_INSERT_TAIL(pf_queues_inactive, qs, entries)do { (qs)->entries.tqe_next = ((void *)0); (qs)->entries
.tqe_prev = (pf_queues_inactive)->tqh_last; *(pf_queues_inactive
)->tqh_last = (qs); (pf_queues_inactive)->tqh_last = &
(qs)->entries.tqe_next; } while (0)
;
1354 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1355 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1356
1357 break;
1358 }
1359
1360 case DIOCADDRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((4)))
: {
1361 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1362 struct pf_ruleset *ruleset;
1363 struct pf_rule *rule, *tail;
1364
1365 rule = pool_get(&pf_rule_pl, PR_WAITOK0x0001|PR_LIMITFAIL0x0004|PR_ZERO0x0008);
1366 if (rule == NULL((void *)0)) {
1367 error = ENOMEM12;
1368 goto fail;
1369 }
1370
1371 if ((error = pf_rule_copyin(&pr->rule, rule))) {
1372 pf_rule_free(rule);
1373 rule = NULL((void *)0);
1374 goto fail;
1375 }
1376
1377 if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE40) {
1378 error = EINVAL22;
1379 pf_rule_free(rule);
1380 rule = NULL((void *)0);
1381 goto fail;
1382 }
1383 if ((error = pf_rule_checkaf(rule))) {
1384 pf_rule_free(rule);
1385 rule = NULL((void *)0);
1386 goto fail;
1387 }
1388 if (rule->src.addr.type == PF_ADDR_NONE ||
1389 rule->dst.addr.type == PF_ADDR_NONE) {
1390 error = EINVAL22;
1391 pf_rule_free(rule);
1392 rule = NULL((void *)0);
1393 goto fail;
1394 }
1395
1396 if (rule->rt && !rule->direction) {
1397 error = EINVAL22;
1398 pf_rule_free(rule);
1399 rule = NULL((void *)0);
1400 goto fail;
1401 }
1402
1403 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1404 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1405 pr->anchor[sizeof(pr->anchor) - 1] = '\0';
1406 ruleset = pf_find_ruleset(pr->anchor);
1407 if (ruleset == NULL((void *)0)) {
1408 error = EINVAL22;
1409 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1410 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1411 pf_rule_free(rule);
1412 goto fail;
1413 }
1414 if (pr->ticket != ruleset->rules.inactive.version) {
1415 error = EBUSY16;
1416 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1417 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1418 pf_rule_free(rule);
1419 goto fail;
1420 }
1421 rule->cuid = p->p_ucred->cr_ruid;
1422 rule->cpid = p->p_p->ps_pid;
1423
1424 tail = TAILQ_LAST(ruleset->rules.inactive.ptr,(*(((struct pf_rulequeue *)((ruleset->rules.inactive.ptr)->
tqh_last))->tqh_last))
1425 pf_rulequeue)(*(((struct pf_rulequeue *)((ruleset->rules.inactive.ptr)->
tqh_last))->tqh_last))
;
1426 if (tail)
1427 rule->nr = tail->nr + 1;
1428 else
1429 rule->nr = 0;
1430
1431 rule->kif = pf_kif_setup(rule->kif);
1432 rule->rcv_kif = pf_kif_setup(rule->rcv_kif);
1433 rule->rdr.kif = pf_kif_setup(rule->rdr.kif);
1434 rule->nat.kif = pf_kif_setup(rule->nat.kif);
1435 rule->route.kif = pf_kif_setup(rule->route.kif);
1436
1437 if (rule->overload_tblname[0]) {
1438 if ((rule->overload_tbl = pfr_attach_table(ruleset,
1439 rule->overload_tblname, PR_WAITOK0x0001)) == NULL((void *)0))
1440 error = EINVAL22;
1441 else
1442 rule->overload_tbl->pfrkt_flagspfrkt_ts.pfrts_t.pfrt_flags |= PFR_TFLAG_ACTIVE0x00000004;
1443 }
1444
1445 if (pf_addr_setup(ruleset, &rule->src.addr, rule->af))
1446 error = EINVAL22;
1447 if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
1448 error = EINVAL22;
1449 if (pf_addr_setup(ruleset, &rule->rdr.addr, rule->af))
1450 error = EINVAL22;
1451 if (pf_addr_setup(ruleset, &rule->nat.addr, rule->af))
1452 error = EINVAL22;
1453 if (pf_addr_setup(ruleset, &rule->route.addr, rule->af))
1454 error = EINVAL22;
1455 if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
1456 error = EINVAL22;
1457
1458 if (error) {
1459 pf_rm_rule(NULL((void *)0), rule);
1460 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1461 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1462 goto fail;
1463 }
1464 TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr,do { (rule)->entries.tqe_next = ((void *)0); (rule)->entries
.tqe_prev = (ruleset->rules.inactive.ptr)->tqh_last; *(
ruleset->rules.inactive.ptr)->tqh_last = (rule); (ruleset
->rules.inactive.ptr)->tqh_last = &(rule)->entries
.tqe_next; } while (0)
1465 rule, entries)do { (rule)->entries.tqe_next = ((void *)0); (rule)->entries
.tqe_prev = (ruleset->rules.inactive.ptr)->tqh_last; *(
ruleset->rules.inactive.ptr)->tqh_last = (rule); (ruleset
->rules.inactive.ptr)->tqh_last = &(rule)->entries
.tqe_next; } while (0)
;
1466 ruleset->rules.inactive.rcount++;
1467 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1468 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1469 break;
1470 }
1471
1472 case DIOCGETRULES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((6)))
: {
1473 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1474 struct pf_ruleset *ruleset;
1475 struct pf_rule *rule;
1476 struct pf_trans *t;
1477 u_int32_t ruleset_version;
1478
1479 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1480 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1481 pr->anchor[sizeof(pr->anchor) - 1] = '\0';
1482 ruleset = pf_find_ruleset(pr->anchor);
1483 if (ruleset == NULL((void *)0)) {
1484 error = EINVAL22;
1485 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1486 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1487 goto fail;
1488 }
1489 rule = TAILQ_LAST(ruleset->rules.active.ptr, pf_rulequeue)(*(((struct pf_rulequeue *)((ruleset->rules.active.ptr)->
tqh_last))->tqh_last))
;
1490 if (rule)
1491 pr->nr = rule->nr + 1;
1492 else
1493 pr->nr = 0;
1494 ruleset_version = ruleset->rules.active.version;
1495 pf_anchor_take(ruleset->anchor);
1496 rule = TAILQ_FIRST(ruleset->rules.active.ptr)((ruleset->rules.active.ptr)->tqh_first);
1497 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1498 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1499
1500 t = pf_open_trans(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
1501 if (t == NULL((void *)0)) {
1502 error = EBUSY16;
1503 goto fail;
1504 }
1505 pf_init_tgetrule(t, ruleset->anchor, ruleset_version, rule);
1506 pr->ticket = t->pft_ticket;
1507
1508 break;
1509 }
1510
1511 case DIOCGETRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((7)))
: {
1512 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1513 struct pf_ruleset *ruleset;
1514 struct pf_rule *rule;
1515 struct pf_trans *t;
1516 int i;
1517
1518 t = pf_find_trans(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
, pr->ticket);
1519 if (t == NULL((void *)0)) {
1520 error = ENXIO6;
1521 goto fail;
1522 }
1523 KASSERT(t->pft_unit == minor(dev))((t->pft_unit == ((unsigned)((dev) & 0xff) | (((dev) &
0xffff0000) >> 8))) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/pf_ioctl.c", 1523, "t->pft_unit == minor(dev)"
))
;
1524 if (t->pft_type != PF_TRANS_GETRULE) {
1525 error = EINVAL22;
1526 goto fail;
1527 }
1528
1529 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1530 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1531 KASSERT(t->pftgr_anchor != NULL)((t->u.u_getrule.gr_anchor != ((void *)0)) ? (void)0 : __assert
("diagnostic ", "/usr/src/sys/net/pf_ioctl.c", 1531, "t->pftgr_anchor != NULL"
))
;
1532 ruleset = &t->pftgr_anchoru.u_getrule.gr_anchor->ruleset;
1533 if (t->pftgr_versionu.u_getrule.gr_version != ruleset->rules.active.version) {
1534 error = EBUSY16;
1535 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1536 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1537 goto fail;
1538 }
1539 rule = t->pftgr_ruleu.u_getrule.gr_rule;
1540 if (rule == NULL((void *)0)) {
1541 error = ENOENT2;
1542 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1543 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1544 goto fail;
1545 }
1546 memcpy(&pr->rule, rule, sizeof(struct pf_rule))__builtin_memcpy((&pr->rule), (rule), (sizeof(struct pf_rule
)))
;
1547 memset(&pr->rule.entries, 0, sizeof(pr->rule.entries))__builtin_memset((&pr->rule.entries), (0), (sizeof(pr->
rule.entries)))
;
1548 pr->rule.kif = NULL((void *)0);
1549 pr->rule.nat.kif = NULL((void *)0);
1550 pr->rule.rdr.kif = NULL((void *)0);
1551 pr->rule.route.kif = NULL((void *)0);
1552 pr->rule.rcv_kif = NULL((void *)0);
1553 pr->rule.anchor = NULL((void *)0);
1554 pr->rule.overload_tbl = NULL((void *)0);
1555 pr->rule.pktrate.limit /= PF_THRESHOLD_MULT1000;
1556 if (pf_anchor_copyout(ruleset, rule, pr)) {
1557 error = EBUSY16;
1558 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1559 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1560 goto fail;
1561 }
1562 pf_addr_copyout(&pr->rule.src.addr);
1563 pf_addr_copyout(&pr->rule.dst.addr);
1564 pf_addr_copyout(&pr->rule.rdr.addr);
1565 pf_addr_copyout(&pr->rule.nat.addr);
1566 pf_addr_copyout(&pr->rule.route.addr);
1567 for (i = 0; i < PF_SKIP_COUNT9; ++i)
1568 if (rule->skip[i].ptr == NULL((void *)0))
1569 pr->rule.skip[i].nr = (u_int32_t)-1;
1570 else
1571 pr->rule.skip[i].nr =
1572 rule->skip[i].ptr->nr;
1573
1574 if (pr->action == PF_GET_CLR_CNTR) {
1575 rule->evaluations = 0;
1576 rule->packets[0] = rule->packets[1] = 0;
1577 rule->bytes[0] = rule->bytes[1] = 0;
1578 rule->states_tot = 0;
1579 }
1580 pr->nr = rule->nr;
1581 t->pftgr_ruleu.u_getrule.gr_rule = TAILQ_NEXT(rule, entries)((rule)->entries.tqe_next);
1582 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1583 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1584 break;
1585 }
1586
1587 case DIOCCHANGERULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((26)))
: {
1588 struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
1589 struct pf_ruleset *ruleset;
1590 struct pf_rule *oldrule = NULL((void *)0), *newrule = NULL((void *)0);
1591 u_int32_t nr = 0;
1592
1593 if (pcr->action < PF_CHANGE_ADD_HEAD ||
1594 pcr->action > PF_CHANGE_GET_TICKET) {
1595 error = EINVAL22;
1596 goto fail;
1597 }
1598
1599 if (pcr->action == PF_CHANGE_GET_TICKET) {
1600 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1601 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1602
1603 ruleset = pf_find_ruleset(pcr->anchor);
1604 if (ruleset == NULL((void *)0))
1605 error = EINVAL22;
1606 else
1607 pcr->ticket = ++ruleset->rules.active.version;
1608
1609 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1610 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1611 goto fail;
1612 }
1613
1614 if (pcr->action != PF_CHANGE_REMOVE) {
1615 newrule = pool_get(&pf_rule_pl,
1616 PR_WAITOK0x0001|PR_LIMITFAIL0x0004|PR_ZERO0x0008);
1617 if (newrule == NULL((void *)0)) {
1618 error = ENOMEM12;
1619 goto fail;
1620 }
1621
1622 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE40) {
1623 error = EINVAL22;
1624 pool_put(&pf_rule_pl, newrule);
1625 goto fail;
1626 }
1627 error = pf_rule_copyin(&pcr->rule, newrule);
1628 if (error != 0) {
1629 pf_rule_free(newrule);
1630 newrule = NULL((void *)0);
1631 goto fail;
1632 }
1633 if ((error = pf_rule_checkaf(newrule))) {
1634 pf_rule_free(newrule);
1635 newrule = NULL((void *)0);
1636 goto fail;
1637 }
1638 if (newrule->rt && !newrule->direction) {
1639 pf_rule_free(newrule);
1640 error = EINVAL22;
1641 newrule = NULL((void *)0);
1642 goto fail;
1643 }
1644 }
1645
1646 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1647 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1648 ruleset = pf_find_ruleset(pcr->anchor);
1649 if (ruleset == NULL((void *)0)) {
1650 error = EINVAL22;
1651 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1652 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1653 pf_rule_free(newrule);
1654 goto fail;
1655 }
1656
1657 if (pcr->ticket != ruleset->rules.active.version) {
1658 error = EINVAL22;
1659 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1660 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1661 pf_rule_free(newrule);
1662 goto fail;
1663 }
1664
1665 if (pcr->action != PF_CHANGE_REMOVE) {
1666 KASSERT(newrule != NULL)((newrule != ((void *)0)) ? (void)0 : __assert("diagnostic ",
"/usr/src/sys/net/pf_ioctl.c", 1666, "newrule != NULL"))
;
1667 newrule->cuid = p->p_ucred->cr_ruid;
1668 newrule->cpid = p->p_p->ps_pid;
1669
1670 newrule->kif = pf_kif_setup(newrule->kif);
1671 newrule->rcv_kif = pf_kif_setup(newrule->rcv_kif);
1672 newrule->rdr.kif = pf_kif_setup(newrule->rdr.kif);
1673 newrule->nat.kif = pf_kif_setup(newrule->nat.kif);
1674 newrule->route.kif = pf_kif_setup(newrule->route.kif);
1675
1676 if (newrule->overload_tblname[0]) {
1677 newrule->overload_tbl = pfr_attach_table(
1678 ruleset, newrule->overload_tblname,
1679 PR_WAITOK0x0001);
1680 if (newrule->overload_tbl == NULL((void *)0))
1681 error = EINVAL22;
1682 else
1683 newrule->overload_tbl->pfrkt_flagspfrkt_ts.pfrts_t.pfrt_flags |=
1684 PFR_TFLAG_ACTIVE0x00000004;
1685 }
1686
1687 if (pf_addr_setup(ruleset, &newrule->src.addr,
1688 newrule->af))
1689 error = EINVAL22;
1690 if (pf_addr_setup(ruleset, &newrule->dst.addr,
1691 newrule->af))
1692 error = EINVAL22;
1693 if (pf_addr_setup(ruleset, &newrule->rdr.addr,
1694 newrule->af))
1695 error = EINVAL22;
1696 if (pf_addr_setup(ruleset, &newrule->nat.addr,
1697 newrule->af))
1698 error = EINVAL22;
1699 if (pf_addr_setup(ruleset, &newrule->route.addr,
1700 newrule->af))
1701 error = EINVAL22;
1702 if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
1703 error = EINVAL22;
1704
1705 if (error) {
1706 pf_rm_rule(NULL((void *)0), newrule);
1707 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1708 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1709 goto fail;
1710 }
1711 }
1712
1713 if (pcr->action == PF_CHANGE_ADD_HEAD)
1714 oldrule = TAILQ_FIRST(ruleset->rules.active.ptr)((ruleset->rules.active.ptr)->tqh_first);
1715 else if (pcr->action == PF_CHANGE_ADD_TAIL)
1716 oldrule = TAILQ_LAST(ruleset->rules.active.ptr,(*(((struct pf_rulequeue *)((ruleset->rules.active.ptr)->
tqh_last))->tqh_last))
1717 pf_rulequeue)(*(((struct pf_rulequeue *)((ruleset->rules.active.ptr)->
tqh_last))->tqh_last))
;
1718 else {
1719 oldrule = TAILQ_FIRST(ruleset->rules.active.ptr)((ruleset->rules.active.ptr)->tqh_first);
1720 while ((oldrule != NULL((void *)0)) && (oldrule->nr != pcr->nr))
1721 oldrule = TAILQ_NEXT(oldrule, entries)((oldrule)->entries.tqe_next);
1722 if (oldrule == NULL((void *)0)) {
1723 if (newrule != NULL((void *)0))
1724 pf_rm_rule(NULL((void *)0), newrule);
1725 error = EINVAL22;
1726 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1727 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1728 goto fail;
1729 }
1730 }
1731
1732 if (pcr->action == PF_CHANGE_REMOVE) {
1733 pf_rm_rule(ruleset->rules.active.ptr, oldrule);
1734 ruleset->rules.active.rcount--;
1735 } else {
1736 if (oldrule == NULL((void *)0))
1737 TAILQ_INSERT_TAIL(do { (newrule)->entries.tqe_next = ((void *)0); (newrule)->
entries.tqe_prev = (ruleset->rules.active.ptr)->tqh_last
; *(ruleset->rules.active.ptr)->tqh_last = (newrule); (
ruleset->rules.active.ptr)->tqh_last = &(newrule)->
entries.tqe_next; } while (0)
1738 ruleset->rules.active.ptr,do { (newrule)->entries.tqe_next = ((void *)0); (newrule)->
entries.tqe_prev = (ruleset->rules.active.ptr)->tqh_last
; *(ruleset->rules.active.ptr)->tqh_last = (newrule); (
ruleset->rules.active.ptr)->tqh_last = &(newrule)->
entries.tqe_next; } while (0)
1739 newrule, entries)do { (newrule)->entries.tqe_next = ((void *)0); (newrule)->
entries.tqe_prev = (ruleset->rules.active.ptr)->tqh_last
; *(ruleset->rules.active.ptr)->tqh_last = (newrule); (
ruleset->rules.active.ptr)->tqh_last = &(newrule)->
entries.tqe_next; } while (0)
;
1740 else if (pcr->action == PF_CHANGE_ADD_HEAD ||
1741 pcr->action == PF_CHANGE_ADD_BEFORE)
1742 TAILQ_INSERT_BEFORE(oldrule, newrule, entries)do { (newrule)->entries.tqe_prev = (oldrule)->entries.tqe_prev
; (newrule)->entries.tqe_next = (oldrule); *(oldrule)->
entries.tqe_prev = (newrule); (oldrule)->entries.tqe_prev =
&(newrule)->entries.tqe_next; } while (0)
;
1743 else
1744 TAILQ_INSERT_AFTER(do { if (((newrule)->entries.tqe_next = (oldrule)->entries
.tqe_next) != ((void *)0)) (newrule)->entries.tqe_next->
entries.tqe_prev = &(newrule)->entries.tqe_next; else (
ruleset->rules.active.ptr)->tqh_last = &(newrule)->
entries.tqe_next; (oldrule)->entries.tqe_next = (newrule);
(newrule)->entries.tqe_prev = &(oldrule)->entries.
tqe_next; } while (0)
1745 ruleset->rules.active.ptr,do { if (((newrule)->entries.tqe_next = (oldrule)->entries
.tqe_next) != ((void *)0)) (newrule)->entries.tqe_next->
entries.tqe_prev = &(newrule)->entries.tqe_next; else (
ruleset->rules.active.ptr)->tqh_last = &(newrule)->
entries.tqe_next; (oldrule)->entries.tqe_next = (newrule);
(newrule)->entries.tqe_prev = &(oldrule)->entries.
tqe_next; } while (0)
1746 oldrule, newrule, entries)do { if (((newrule)->entries.tqe_next = (oldrule)->entries
.tqe_next) != ((void *)0)) (newrule)->entries.tqe_next->
entries.tqe_prev = &(newrule)->entries.tqe_next; else (
ruleset->rules.active.ptr)->tqh_last = &(newrule)->
entries.tqe_next; (oldrule)->entries.tqe_next = (newrule);
(newrule)->entries.tqe_prev = &(oldrule)->entries.
tqe_next; } while (0)
;
1747 ruleset->rules.active.rcount++;
1748 }
1749
1750 nr = 0;
1751 TAILQ_FOREACH(oldrule, ruleset->rules.active.ptr, entries)for((oldrule) = ((ruleset->rules.active.ptr)->tqh_first
); (oldrule) != ((void *)0); (oldrule) = ((oldrule)->entries
.tqe_next))
1752 oldrule->nr = nr++;
1753
1754 ruleset->rules.active.version++;
1755
1756 pf_calc_skip_steps(ruleset->rules.active.ptr);
1757 pf_remove_if_empty_ruleset(ruleset);
1758
1759 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1760 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1761 break;
1762 }
1763
1764 case DIOCCLRSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((18)))
:
1765 error = pf_states_clr((struct pfioc_state_kill *)addr);
1766 break;
1767
1768 case DIOCKILLSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((41)))
: {
1769 struct pf_state *st, *nextst;
1770 struct pf_state_item *si, *sit;
1771 struct pf_state_key *sk, key;
1772 struct pf_addr *srcaddr, *dstaddr;
1773 u_int16_t srcport, dstport;
1774 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
1775 u_int i, killed = 0;
1776 const int dirs[] = { PF_IN, PF_OUT };
1777 int sidx, didx;
1778
1779 if (psk->psk_pfcmp.id) {
1780 if (psk->psk_pfcmp.creatorid == 0)
1781 psk->psk_pfcmp.creatorid = pf_status.hostid;
1782 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1783 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1784 PF_STATE_ENTER_WRITE()do { rw_enter_write(&pf_state_lock); } while (0);
1785 if ((st = pf_find_state_byid(&psk->psk_pfcmp))) {
1786 pf_remove_state(st);
1787 psk->psk_killed = 1;
1788 }
1789 PF_STATE_EXIT_WRITE()do { do { if (rw_status(&pf_state_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_state_lock), __func__); } while (
0); rw_exit_write(&pf_state_lock); } while (0)
;
1790 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1791 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1792 goto fail;
1793 }
1794
1795 if (psk->psk_af && psk->psk_proto &&
1796 psk->psk_src.port_op == PF_OP_EQ &&
1797 psk->psk_dst.port_op == PF_OP_EQ) {
1798
1799 key.af = psk->psk_af;
1800 key.proto = psk->psk_proto;
1801 key.rdomain = psk->psk_rdomain;
1802
1803 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1804 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1805 PF_STATE_ENTER_WRITE()do { rw_enter_write(&pf_state_lock); } while (0);
1806 for (i = 0; i < nitems(dirs)(sizeof((dirs)) / sizeof((dirs)[0])); i++) {
1807 if (dirs[i] == PF_IN) {
1808 sidx = 0;
1809 didx = 1;
1810 } else {
1811 sidx = 1;
1812 didx = 0;
1813 }
1814 pf_addrcpy(&key.addr[sidx],
1815 &psk->psk_src.addr.v.a.addr, key.af);
1816 pf_addrcpy(&key.addr[didx],
1817 &psk->psk_dst.addr.v.a.addr, key.af);
1818 key.port[sidx] = psk->psk_src.port[0];
1819 key.port[didx] = psk->psk_dst.port[0];
1820
1821 sk = RBT_FIND(pf_state_tree, &pf_statetbl,pf_state_tree_RBT_FIND(&pf_statetbl, &key)
1822 &key)pf_state_tree_RBT_FIND(&pf_statetbl, &key);
1823 if (sk == NULL((void *)0))
1824 continue;
1825
1826 TAILQ_FOREACH_SAFE(si, &sk->sk_states,for ((si) = ((&sk->sk_states)->tqh_first); (si) != (
(void *)0) && ((sit) = ((si)->si_entry.tqe_next), 1
); (si) = (sit))
1827 si_entry, sit)for ((si) = ((&sk->sk_states)->tqh_first); (si) != (
(void *)0) && ((sit) = ((si)->si_entry.tqe_next), 1
); (si) = (sit))
{
1828 struct pf_state *sist = si->si_st;
1829 if (((sist->key[PF_SK_WIRE]->af ==
1830 sist->key[PF_SK_STACK]->af &&
1831 sk == (dirs[i] == PF_IN ?
1832 sist->key[PF_SK_WIRE] :
1833 sist->key[PF_SK_STACK])) ||
1834 (sist->key[PF_SK_WIRE]->af !=
1835 sist->key[PF_SK_STACK]->af &&
1836 dirs[i] == PF_IN &&
1837 (sk == sist->key[PF_SK_STACK] ||
1838 sk == sist->key[PF_SK_WIRE]))) &&
1839 (!psk->psk_ifname[0] ||
1840 (sist->kif != pfi_all &&
1841 !strcmp(psk->psk_ifname,
1842 sist->kif->pfik_name)))) {
1843 pf_remove_state(sist);
1844 killed++;
1845 }
1846 }
1847 }
1848 if (killed)
1849 psk->psk_killed = killed;
1850 PF_STATE_EXIT_WRITE()do { do { if (rw_status(&pf_state_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_state_lock), __func__); } while (
0); rw_exit_write(&pf_state_lock); } while (0)
;
1851 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1852 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1853 goto fail;
1854 }
1855
1856 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1857 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1858 PF_STATE_ENTER_WRITE()do { rw_enter_write(&pf_state_lock); } while (0);
1859 RBT_FOREACH_SAFE(st, pf_state_tree_id, &tree_id, nextst)for ((st) = pf_state_tree_id_RBT_MIN((&tree_id)); (st) !=
((void *)0) && ((nextst) = pf_state_tree_id_RBT_NEXT
((st)), 1); (st) = (nextst))
{
1860 if (st->direction == PF_OUT) {
1861 sk = st->key[PF_SK_STACK];
1862 srcaddr = &sk->addr[1];
1863 dstaddr = &sk->addr[0];
1864 srcport = sk->port[1];
1865 dstport = sk->port[0];
1866 } else {
1867 sk = st->key[PF_SK_WIRE];
1868 srcaddr = &sk->addr[0];
1869 dstaddr = &sk->addr[1];
1870 srcport = sk->port[0];
1871 dstport = sk->port[1];
1872 }
1873 if ((!psk->psk_af || sk->af == psk->psk_af)
1874 && (!psk->psk_proto || psk->psk_proto ==
1875 sk->proto) && psk->psk_rdomain == sk->rdomain &&
1876 pf_match_addr(psk->psk_src.neg,
1877 &psk->psk_src.addr.v.a.addr,
1878 &psk->psk_src.addr.v.a.mask,
1879 srcaddr, sk->af) &&
1880 pf_match_addr(psk->psk_dst.neg,
1881 &psk->psk_dst.addr.v.a.addr,
1882 &psk->psk_dst.addr.v.a.mask,
1883 dstaddr, sk->af) &&
1884 (psk->psk_src.port_op == 0 ||
1885 pf_match_port(psk->psk_src.port_op,
1886 psk->psk_src.port[0], psk->psk_src.port[1],
1887 srcport)) &&
1888 (psk->psk_dst.port_op == 0 ||
1889 pf_match_port(psk->psk_dst.port_op,
1890 psk->psk_dst.port[0], psk->psk_dst.port[1],
1891 dstport)) &&
1892 (!psk->psk_label[0] || (st->rule.ptr->label[0] &&
1893 !strcmp(psk->psk_label, st->rule.ptr->label))) &&
1894 (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
1895 st->kif->pfik_name))) {
1896 pf_remove_state(st);
1897 killed++;
1898 }
1899 }
1900 psk->psk_killed = killed;
1901 PF_STATE_EXIT_WRITE()do { do { if (rw_status(&pf_state_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_state_lock), __func__); } while (
0); rw_exit_write(&pf_state_lock); } while (0)
;
1902 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1903 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1904 break;
1905 }
1906
1907#if NPFSYNC1 > 0
1908 case DIOCADDSTATE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state) & 0x1fff) << 16) | ((('D')) <<
8) | ((37)))
: {
1909 struct pfioc_state *ps = (struct pfioc_state *)addr;
1910 struct pfsync_state *sp = &ps->state;
1911
1912 if (sp->timeout >= PFTM_MAX) {
1913 error = EINVAL22;
1914 goto fail;
1915 }
1916 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1917 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1918 error = pf_state_import(sp, PFSYNC_SI_IOCTL0x01);
1919 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1920 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1921 break;
1922 }
1923#endif /* NPFSYNC > 0 */
1924
1925 case DIOCGETSTATE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state) & 0x1fff) << 16) | ((('D')) <<
8) | ((19)))
: {
1926 struct pfioc_state *ps = (struct pfioc_state *)addr;
1927 struct pf_state *st;
1928 struct pf_state_cmp id_key;
1929
1930 memset(&id_key, 0, sizeof(id_key))__builtin_memset((&id_key), (0), (sizeof(id_key)));
1931 id_key.id = ps->state.id;
1932 id_key.creatorid = ps->state.creatorid;
1933
1934 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1935 PF_STATE_ENTER_READ()do { rw_enter_read(&pf_state_lock); } while (0);
1936 st = pf_find_state_byid(&id_key);
1937 st = pf_state_ref(st);
1938 PF_STATE_EXIT_READ()do { rw_exit_read(&pf_state_lock); } while (0);
1939 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1940 if (st == NULL((void *)0)) {
1941 error = ENOENT2;
1942 goto fail;
1943 }
1944
1945 pf_state_export(&ps->state, st);
1946 pf_state_unref(st);
1947 break;
1948 }
1949
1950 case DIOCGETSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_states) & 0x1fff) << 16) | ((('D')) <<
8) | ((25)))
:
1951 error = pf_states_get((struct pfioc_states *)addr);
1952 break;
1953
1954 case DIOCGETSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_status) & 0x1fff) << 16) | ((('D')) <<
8) | ((21)))
: {
1955 struct pf_status *s = (struct pf_status *)addr;
1956 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1957 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1958 memcpy(s, &pf_status, sizeof(struct pf_status))__builtin_memcpy((s), (&pf_status), (sizeof(struct pf_status
)))
;
1959 pfi_update_status(s->ifname, s);
1960 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1961 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1962 break;
1963 }
1964
1965 case DIOCSETSTATUSIF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((20)))
: {
1966 struct pfioc_iface *pi = (struct pfioc_iface *)addr;
1967
1968 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1969 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1970 if (pi->pfiio_name[0] == 0) {
1971 memset(pf_status.ifname, 0, IFNAMSIZ)__builtin_memset((pf_status.ifname), (0), (16));
1972 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1973 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1974 goto fail;
1975 }
1976 strlcpy(pf_trans_set.statusif, pi->pfiio_name, IFNAMSIZ16);
1977 pf_trans_set.mask |= PF_TSET_STATUSIF0x01;
1978 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1979 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1980 break;
1981 }
1982
1983 case DIOCCLRSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((22)))
: {
1984 struct pfioc_iface *pi = (struct pfioc_iface *)addr;
1985
1986 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1987 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
1988 /* if ifname is specified, clear counters there only */
1989 if (pi->pfiio_name[0]) {
1990 pfi_update_status(pi->pfiio_name, NULL((void *)0));
1991 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
1992 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1993 goto fail;
1994 }
1995
1996 memset(pf_status.counters, 0, sizeof(pf_status.counters))__builtin_memset((pf_status.counters), (0), (sizeof(pf_status
.counters)))
;
1997 memset(pf_status.fcounters, 0, sizeof(pf_status.fcounters))__builtin_memset((pf_status.fcounters), (0), (sizeof(pf_status
.fcounters)))
;
1998 memset(pf_status.scounters, 0, sizeof(pf_status.scounters))__builtin_memset((pf_status.scounters), (0), (sizeof(pf_status
.scounters)))
;
1999 pf_status.since = getuptime();
2000
2001 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2002 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2003 break;
2004 }
2005
2006 case DIOCNATLOOK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_natlook) & 0x1fff) << 16) | ((('D')) <<
8) | ((23)))
: {
2007 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
2008 struct pf_state_key *sk;
2009 struct pf_state *st;
2010 struct pf_state_key_cmp key;
2011 int m = 0, direction = pnl->direction;
2012 int sidx, didx;
2013
2014 switch (pnl->af) {
2015 case AF_INET2:
2016 break;
2017#ifdef INET61
2018 case AF_INET624:
2019 break;
2020#endif /* INET6 */
2021 default:
2022 error = EAFNOSUPPORT47;
2023 goto fail;
2024 }
2025
2026 /* NATLOOK src and dst are reversed, so reverse sidx/didx */
2027 sidx = (direction == PF_IN) ? 1 : 0;
2028 didx = (direction == PF_IN) ? 0 : 1;
2029
2030 if (!pnl->proto ||
2031 PF_AZERO(&pnl->saddr, pnl->af)((pnl->af == 2 && !(&pnl->saddr)->pfa.addr32
[0]) || (pnl->af == 24 && !(&pnl->saddr)->
pfa.addr32[0] && !(&pnl->saddr)->pfa.addr32
[1] && !(&pnl->saddr)->pfa.addr32[2] &&
!(&pnl->saddr)->pfa.addr32[3] ))
||
2032 PF_AZERO(&pnl->daddr, pnl->af)((pnl->af == 2 && !(&pnl->daddr)->pfa.addr32
[0]) || (pnl->af == 24 && !(&pnl->daddr)->
pfa.addr32[0] && !(&pnl->daddr)->pfa.addr32
[1] && !(&pnl->daddr)->pfa.addr32[2] &&
!(&pnl->daddr)->pfa.addr32[3] ))
||
2033 ((pnl->proto == IPPROTO_TCP6 ||
2034 pnl->proto == IPPROTO_UDP17) &&
2035 (!pnl->dport || !pnl->sport)) ||
2036 pnl->rdomain > RT_TABLEID_MAX255)
2037 error = EINVAL22;
2038 else {
2039 key.af = pnl->af;
2040 key.proto = pnl->proto;
2041 key.rdomain = pnl->rdomain;
2042 pf_addrcpy(&key.addr[sidx], &pnl->saddr, pnl->af);
2043 key.port[sidx] = pnl->sport;
2044 pf_addrcpy(&key.addr[didx], &pnl->daddr, pnl->af);
2045 key.port[didx] = pnl->dport;
2046
2047 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2048 PF_STATE_ENTER_READ()do { rw_enter_read(&pf_state_lock); } while (0);
2049 st = pf_find_state_all(&key, direction, &m);
2050 st = pf_state_ref(st);
2051 PF_STATE_EXIT_READ()do { rw_exit_read(&pf_state_lock); } while (0);
2052 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2053
2054 if (m > 1)
2055 error = E2BIG7; /* more than one state */
2056 else if (st != NULL((void *)0)) {
2057 sk = st->key[sidx];
2058 pf_addrcpy(&pnl->rsaddr, &sk->addr[sidx],
2059 sk->af);
2060 pnl->rsport = sk->port[sidx];
2061 pf_addrcpy(&pnl->rdaddr, &sk->addr[didx],
2062 sk->af);
2063 pnl->rdport = sk->port[didx];
2064 pnl->rrdomain = sk->rdomain;
2065 } else
2066 error = ENOENT2;
2067 pf_state_unref(st);
2068 }
2069 break;
2070 }
2071
2072 case DIOCSETTIMEOUT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_tm) & 0x1fff) << 16) | ((('D')) <<
8) | ((29)))
: {
2073 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
2074
2075 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
2076 pt->seconds < 0) {
2077 error = EINVAL22;
2078 goto fail;
2079 }
2080 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2081 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2082 if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
2083 pt->seconds = 1;
2084 pf_default_rule_new.timeout[pt->timeout] = pt->seconds;
2085 pt->seconds = pf_default_rule.timeout[pt->timeout];
2086 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2087 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2088 break;
2089 }
2090
2091 case DIOCGETTIMEOUT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_tm) & 0x1fff) << 16) | ((('D')) <<
8) | ((30)))
: {
2092 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
2093
2094 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
2095 error = EINVAL22;
2096 goto fail;
2097 }
2098 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2099 pt->seconds = pf_default_rule.timeout[pt->timeout];
2100 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2101 break;
2102 }
2103
2104 case DIOCGETLIMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_limit) & 0x1fff) << 16) | ((('D')) <<
8) | ((39)))
: {
2105 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
2106
2107 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
2108 error = EINVAL22;
2109 goto fail;
2110 }
2111 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2112 pl->limit = pf_pool_limits[pl->index].limit;
2113 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2114 break;
2115 }
2116
2117 case DIOCSETLIMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_limit) & 0x1fff) << 16) | ((('D')) <<
8) | ((40)))
: {
2118 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
2119
2120 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2121 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
2122 error = EINVAL22;
2123 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2124 goto fail;
2125 }
2126 if (((struct pool *)pf_pool_limits[pl->index].pp)->pr_nout >
2127 pl->limit) {
2128 error = EBUSY16;
2129 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2130 goto fail;
2131 }
2132 /* Fragments reference mbuf clusters. */
2133 if (pl->index == PF_LIMIT_FRAGS && pl->limit > nmbclust) {
2134 error = EINVAL22;
2135 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2136 goto fail;
2137 }
2138
2139 pf_pool_limits[pl->index].limit_new = pl->limit;
2140 pl->limit = pf_pool_limits[pl->index].limit;
2141 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2142 break;
2143 }
2144
2145 case DIOCSETDEBUG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((24)))
: {
2146 u_int32_t *level = (u_int32_t *)addr;
2147
2148 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2149 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2150 pf_trans_set.debug = *level;
2151 pf_trans_set.mask |= PF_TSET_DEBUG0x02;
2152 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2153 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2154 break;
2155 }
2156
2157 case DIOCGETRULESETS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((58)))
: {
2158 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
2159 struct pf_ruleset *ruleset;
2160 struct pf_anchor *anchor;
2161
2162 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2163 pr->path[sizeof(pr->path) - 1] = '\0';
2164 if ((ruleset = pf_find_ruleset(pr->path)) == NULL((void *)0)) {
2165 error = EINVAL22;
2166 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2167 goto fail;
2168 }
2169 pr->nr = 0;
2170 if (ruleset == &pf_main_rulesetpf_main_anchor.ruleset) {
2171 /* XXX kludge for pf_main_ruleset */
2172 RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)for ((anchor) = pf_anchor_global_RB_MINMAX(&pf_anchors, -
1); (anchor) != ((void *)0); (anchor) = pf_anchor_global_RB_NEXT
(anchor))
2173 if (anchor->parent == NULL((void *)0))
2174 pr->nr++;
2175 } else {
2176 RB_FOREACH(anchor, pf_anchor_node,for ((anchor) = pf_anchor_node_RB_MINMAX(&ruleset->anchor
->children, -1); (anchor) != ((void *)0); (anchor) = pf_anchor_node_RB_NEXT
(anchor))
2177 &ruleset->anchor->children)for ((anchor) = pf_anchor_node_RB_MINMAX(&ruleset->anchor
->children, -1); (anchor) != ((void *)0); (anchor) = pf_anchor_node_RB_NEXT
(anchor))
2178 pr->nr++;
2179 }
2180 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2181 break;
2182 }
2183
2184 case DIOCGETRULESET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((59)))
: {
2185 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
2186 struct pf_ruleset *ruleset;
2187 struct pf_anchor *anchor;
2188 u_int32_t nr = 0;
2189
2190 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2191 pr->path[sizeof(pr->path) - 1] = '\0';
2192 if ((ruleset = pf_find_ruleset(pr->path)) == NULL((void *)0)) {
2193 error = EINVAL22;
2194 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2195 goto fail;
2196 }
2197 pr->name[0] = '\0';
2198 if (ruleset == &pf_main_rulesetpf_main_anchor.ruleset) {
2199 /* XXX kludge for pf_main_ruleset */
2200 RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)for ((anchor) = pf_anchor_global_RB_MINMAX(&pf_anchors, -
1); (anchor) != ((void *)0); (anchor) = pf_anchor_global_RB_NEXT
(anchor))
2201 if (anchor->parent == NULL((void *)0) && nr++ == pr->nr) {
2202 strlcpy(pr->name, anchor->name,
2203 sizeof(pr->name));
2204 break;
2205 }
2206 } else {
2207 RB_FOREACH(anchor, pf_anchor_node,for ((anchor) = pf_anchor_node_RB_MINMAX(&ruleset->anchor
->children, -1); (anchor) != ((void *)0); (anchor) = pf_anchor_node_RB_NEXT
(anchor))
2208 &ruleset->anchor->children)for ((anchor) = pf_anchor_node_RB_MINMAX(&ruleset->anchor
->children, -1); (anchor) != ((void *)0); (anchor) = pf_anchor_node_RB_NEXT
(anchor))
2209 if (nr++ == pr->nr) {
2210 strlcpy(pr->name, anchor->name,
2211 sizeof(pr->name));
2212 break;
2213 }
2214 }
2215 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2216 if (!pr->name[0])
2217 error = EBUSY16;
2218 break;
2219 }
2220
2221 case DIOCRCLRTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((60)))
: {
2222 struct pfioc_table *io = (struct pfioc_table *)addr;
2223
2224 if (io->pfrio_esize != 0) {
2225 error = ENODEV19;
2226 goto fail;
2227 }
2228 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2229 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2230 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
2231 io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2232 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2233 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2234 break;
2235 }
2236
2237 case DIOCRADDTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((61)))
: {
2238 struct pfioc_table *io = (struct pfioc_table *)addr;
2239
2240 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2241 error = ENODEV19;
2242 goto fail;
2243 }
2244 error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
2245 &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2246 break;
2247 }
2248
2249 case DIOCRDELTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((62)))
: {
2250 struct pfioc_table *io = (struct pfioc_table *)addr;
2251
2252 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2253 error = ENODEV19;
2254 goto fail;
2255 }
2256 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2257 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2258 error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
2259 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2260 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2261 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2262 break;
2263 }
2264
2265 case DIOCRGETTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((63)))
: {
2266 struct pfioc_table *io = (struct pfioc_table *)addr;
2267
2268 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2269 error = ENODEV19;
2270 goto fail;
2271 }
2272 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2273 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2274 error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
2275 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2276 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2277 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2278 break;
2279 }
2280
2281 case DIOCRGETTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((64)))
: {
2282 struct pfioc_table *io = (struct pfioc_table *)addr;
2283
2284 if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
2285 error = ENODEV19;
2286 goto fail;
2287 }
2288 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2289 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2290 error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
2291 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2292 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2293 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2294 break;
2295 }
2296
2297 case DIOCRCLRTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((65)))
: {
2298 struct pfioc_table *io = (struct pfioc_table *)addr;
2299
2300 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2301 error = ENODEV19;
2302 goto fail;
2303 }
2304 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2305 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2306 error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
2307 &io->pfrio_nzeropfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2308 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2309 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2310 break;
2311 }
2312
2313 case DIOCRSETTFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((74)))
: {
2314 struct pfioc_table *io = (struct pfioc_table *)addr;
2315
2316 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2317 error = ENODEV19;
2318 goto fail;
2319 }
2320 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2321 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2322 error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
2323 io->pfrio_setflagpfrio_size2, io->pfrio_clrflagpfrio_nadd, &io->pfrio_nchange,
2324 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2325 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2326 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2327 break;
2328 }
2329
2330 case DIOCRCLRADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((66)))
: {
2331 struct pfioc_table *io = (struct pfioc_table *)addr;
2332
2333 if (io->pfrio_esize != 0) {
2334 error = ENODEV19;
2335 goto fail;
2336 }
2337 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2338 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2339 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
2340 io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2341 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2342 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2343 break;
2344 }
2345
2346 case DIOCRADDADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((67)))
: {
2347 struct pfioc_table *io = (struct pfioc_table *)addr;
2348
2349 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2350 error = ENODEV19;
2351 goto fail;
2352 }
2353 error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
2354 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
2355 PFR_FLAG_USERIOCTL0x10000000);
2356 break;
2357 }
2358
2359 case DIOCRDELADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((68)))
: {
2360 struct pfioc_table *io = (struct pfioc_table *)addr;
2361
2362 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2363 error = ENODEV19;
2364 goto fail;
2365 }
2366 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2367 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2368 error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
2369 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
2370 PFR_FLAG_USERIOCTL0x10000000);
2371 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2372 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2373 break;
2374 }
2375
2376 case DIOCRSETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((69)))
: {
2377 struct pfioc_table *io = (struct pfioc_table *)addr;
2378
2379 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2380 error = ENODEV19;
2381 goto fail;
2382 }
2383 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2384 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2385 error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
2386 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
2387 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
2388 PFR_FLAG_USERIOCTL0x10000000, 0);
2389 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2390 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2391 break;
2392 }
2393
2394 case DIOCRGETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((70)))
: {
2395 struct pfioc_table *io = (struct pfioc_table *)addr;
2396
2397 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2398 error = ENODEV19;
2399 goto fail;
2400 }
2401 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2402 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2403 error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
2404 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2405 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2406 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2407 break;
2408 }
2409
2410 case DIOCRGETASTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((71)))
: {
2411 struct pfioc_table *io = (struct pfioc_table *)addr;
2412
2413 if (io->pfrio_esize != sizeof(struct pfr_astats)) {
2414 error = ENODEV19;
2415 goto fail;
2416 }
2417 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2418 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2419 error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
2420 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2421 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2422 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2423 break;
2424 }
2425
2426 case DIOCRCLRASTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((72)))
: {
2427 struct pfioc_table *io = (struct pfioc_table *)addr;
2428
2429 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2430 error = ENODEV19;
2431 goto fail;
2432 }
2433 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2434 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2435 error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
2436 io->pfrio_size, &io->pfrio_nzeropfrio_nadd, io->pfrio_flags |
2437 PFR_FLAG_USERIOCTL0x10000000);
2438 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2439 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2440 break;
2441 }
2442
2443 case DIOCRTSTADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((73)))
: {
2444 struct pfioc_table *io = (struct pfioc_table *)addr;
2445
2446 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2447 error = ENODEV19;
2448 goto fail;
2449 }
2450 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2451 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2452 error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
2453 io->pfrio_size, &io->pfrio_nmatchpfrio_nadd, io->pfrio_flags |
2454 PFR_FLAG_USERIOCTL0x10000000);
2455 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2456 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2457 break;
2458 }
2459
2460 case DIOCRINADEFINE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_table) & 0x1fff) << 16) | ((('D')) <<
8) | ((77)))
: {
2461 struct pfioc_table *io = (struct pfioc_table *)addr;
2462
2463 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2464 error = ENODEV19;
2465 goto fail;
2466 }
2467 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2468 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2469 error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
2470 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddrpfrio_size2,
2471 io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL0x10000000);
2472 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2473 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2474 break;
2475 }
2476
2477 case DIOCOSFPADD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_osfp_ioctl) & 0x1fff) << 16) | ((('D')) <<
8) | ((79)))
: {
2478 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2479 error = pf_osfp_add(io);
2480 break;
2481 }
2482
2483 case DIOCOSFPGET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_osfp_ioctl) & 0x1fff) << 16) | ((('D')) <<
8) | ((80)))
: {
2484 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2485 error = pf_osfp_get(io);
2486 break;
2487 }
2488
2489 case DIOCXBEGIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((81)))
: {
2490 struct pfioc_trans *io = (struct pfioc_trans *)addr;
2491 struct pfioc_trans_e *ioe;
2492 struct pfr_table *table;
2493 int i;
2494
2495 if (io->esize != sizeof(*ioe)) {
2496 error = ENODEV19;
2497 goto fail;
2498 }
2499 ioe = malloc(sizeof(*ioe), M_PF6, M_WAITOK0x0001);
2500 table = malloc(sizeof(*table), M_PF6, M_WAITOK0x0001);
2501 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2502 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2503 pf_default_rule_new = pf_default_rule;
2504 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2505 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2506 memset(&pf_trans_set, 0, sizeof(pf_trans_set))__builtin_memset((&pf_trans_set), (0), (sizeof(pf_trans_set
)))
;
2507 for (i = 0; i < io->size; i++) {
2508 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2509 free(table, M_PF6, sizeof(*table));
2510 free(ioe, M_PF6, sizeof(*ioe));
2511 error = EFAULT14;
2512 goto fail;
2513 }
2514 if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
2515 sizeof(ioe->anchor)) {
2516 free(table, M_PF6, sizeof(*table));
2517 free(ioe, M_PF6, sizeof(*ioe));
2518 error = ENAMETOOLONG63;
2519 goto fail;
2520 }
2521 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2522 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2523 switch (ioe->type) {
2524 case PF_TRANS_TABLE:
2525 memset(table, 0, sizeof(*table))__builtin_memset((table), (0), (sizeof(*table)));
2526 strlcpy(table->pfrt_anchor, ioe->anchor,
2527 sizeof(table->pfrt_anchor));
2528 if ((error = pfr_ina_begin(table,
2529 &ioe->ticket, NULL((void *)0), 0))) {
2530 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2531 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2532 free(table, M_PF6, sizeof(*table));
2533 free(ioe, M_PF6, sizeof(*ioe));
2534 goto fail;
2535 }
2536 break;
2537 case PF_TRANS_RULESET:
2538 if ((error = pf_begin_rules(&ioe->ticket,
2539 ioe->anchor))) {
2540 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2541 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2542 free(table, M_PF6, sizeof(*table));
2543 free(ioe, M_PF6, sizeof(*ioe));
2544 goto fail;
2545 }
2546 break;
2547 default:
2548 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2549 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2550 free(table, M_PF6, sizeof(*table));
2551 free(ioe, M_PF6, sizeof(*ioe));
2552 error = EINVAL22;
2553 goto fail;
2554 }
2555 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2556 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2557 if (copyout(ioe, io->array+i, sizeof(io->array[i]))) {
2558 free(table, M_PF6, sizeof(*table));
2559 free(ioe, M_PF6, sizeof(*ioe));
2560 error = EFAULT14;
2561 goto fail;
2562 }
2563 }
2564 free(table, M_PF6, sizeof(*table));
2565 free(ioe, M_PF6, sizeof(*ioe));
2566 break;
2567 }
2568
2569 case DIOCXROLLBACK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((83)))
: {
2570 struct pfioc_trans *io = (struct pfioc_trans *)addr;
2571 struct pfioc_trans_e *ioe;
2572 struct pfr_table *table;
2573 int i;
2574
2575 if (io->esize != sizeof(*ioe)) {
2576 error = ENODEV19;
2577 goto fail;
2578 }
2579 ioe = malloc(sizeof(*ioe), M_PF6, M_WAITOK0x0001);
2580 table = malloc(sizeof(*table), M_PF6, M_WAITOK0x0001);
2581 for (i = 0; i < io->size; i++) {
2582 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2583 free(table, M_PF6, sizeof(*table));
2584 free(ioe, M_PF6, sizeof(*ioe));
2585 error = EFAULT14;
2586 goto fail;
2587 }
2588 if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
2589 sizeof(ioe->anchor)) {
2590 free(table, M_PF6, sizeof(*table));
2591 free(ioe, M_PF6, sizeof(*ioe));
2592 error = ENAMETOOLONG63;
2593 goto fail;
2594 }
2595 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2596 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2597 switch (ioe->type) {
2598 case PF_TRANS_TABLE:
2599 memset(table, 0, sizeof(*table))__builtin_memset((table), (0), (sizeof(*table)));
2600 strlcpy(table->pfrt_anchor, ioe->anchor,
2601 sizeof(table->pfrt_anchor));
2602 if ((error = pfr_ina_rollback(table,
2603 ioe->ticket, NULL((void *)0), 0))) {
2604 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2605 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2606 free(table, M_PF6, sizeof(*table));
2607 free(ioe, M_PF6, sizeof(*ioe));
2608 goto fail; /* really bad */
2609 }
2610 break;
2611 case PF_TRANS_RULESET:
2612 pf_rollback_rules(ioe->ticket, ioe->anchor);
2613 break;
2614 default:
2615 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2616 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2617 free(table, M_PF6, sizeof(*table));
2618 free(ioe, M_PF6, sizeof(*ioe));
2619 error = EINVAL22;
2620 goto fail; /* really bad */
2621 }
2622 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2623 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2624 }
2625 free(table, M_PF6, sizeof(*table));
2626 free(ioe, M_PF6, sizeof(*ioe));
2627 break;
2628 }
2629
2630 case DIOCXCOMMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((82)))
: {
2631 struct pfioc_trans *io = (struct pfioc_trans *)addr;
2632 struct pfioc_trans_e *ioe;
2633 struct pfr_table *table;
2634 struct pf_ruleset *rs;
2635 int i;
2636
2637 if (io->esize != sizeof(*ioe)) {
2638 error = ENODEV19;
2639 goto fail;
2640 }
2641 ioe = malloc(sizeof(*ioe), M_PF6, M_WAITOK0x0001);
2642 table = malloc(sizeof(*table), M_PF6, M_WAITOK0x0001);
2643 /* first makes sure everything will succeed */
2644 for (i = 0; i < io->size; i++) {
2645 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2646 free(table, M_PF6, sizeof(*table));
2647 free(ioe, M_PF6, sizeof(*ioe));
2648 error = EFAULT14;
2649 goto fail;
2650 }
2651 if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
2652 sizeof(ioe->anchor)) {
2653 free(table, M_PF6, sizeof(*table));
2654 free(ioe, M_PF6, sizeof(*ioe));
2655 error = ENAMETOOLONG63;
2656 goto fail;
2657 }
2658 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2659 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2660 switch (ioe->type) {
2661 case PF_TRANS_TABLE:
2662 rs = pf_find_ruleset(ioe->anchor);
2663 if (rs == NULL((void *)0) || !rs->topen || ioe->ticket !=
2664 rs->tticket) {
2665 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2666 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2667 free(table, M_PF6, sizeof(*table));
2668 free(ioe, M_PF6, sizeof(*ioe));
2669 error = EBUSY16;
2670 goto fail;
2671 }
2672 break;
2673 case PF_TRANS_RULESET:
2674 rs = pf_find_ruleset(ioe->anchor);
2675 if (rs == NULL((void *)0) ||
2676 !rs->rules.inactive.open ||
2677 rs->rules.inactive.version !=
2678 ioe->ticket) {
2679 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2680 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2681 free(table, M_PF6, sizeof(*table));
2682 free(ioe, M_PF6, sizeof(*ioe));
2683 error = EBUSY16;
2684 goto fail;
2685 }
2686 break;
2687 default:
2688 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2689 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2690 free(table, M_PF6, sizeof(*table));
2691 free(ioe, M_PF6, sizeof(*ioe));
2692 error = EINVAL22;
2693 goto fail;
2694 }
2695 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2696 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2697 }
2698 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2699 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2700
2701 /*
2702 * Checked already in DIOCSETLIMIT, but check again as the
2703 * situation might have changed.
2704 */
2705 for (i = 0; i < PF_LIMIT_MAX; i++) {
2706 if (((struct pool *)pf_pool_limits[i].pp)->pr_nout >
2707 pf_pool_limits[i].limit_new) {
2708 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2709 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2710 free(table, M_PF6, sizeof(*table));
2711 free(ioe, M_PF6, sizeof(*ioe));
2712 error = EBUSY16;
2713 goto fail;
2714 }
2715 }
2716 /* now do the commit - no errors should happen here */
2717 for (i = 0; i < io->size; i++) {
2718 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2719 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2720 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2721 free(table, M_PF6, sizeof(*table));
2722 free(ioe, M_PF6, sizeof(*ioe));
2723 error = EFAULT14;
2724 goto fail;
2725 }
2726 if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
2727 sizeof(ioe->anchor)) {
2728 free(table, M_PF6, sizeof(*table));
2729 free(ioe, M_PF6, sizeof(*ioe));
2730 error = ENAMETOOLONG63;
2731 goto fail;
2732 }
2733 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2734 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2735 switch (ioe->type) {
2736 case PF_TRANS_TABLE:
2737 memset(table, 0, sizeof(*table))__builtin_memset((table), (0), (sizeof(*table)));
2738 strlcpy(table->pfrt_anchor, ioe->anchor,
2739 sizeof(table->pfrt_anchor));
2740 if ((error = pfr_ina_commit(table, ioe->ticket,
2741 NULL((void *)0), NULL((void *)0), 0))) {
2742 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2743 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2744 free(table, M_PF6, sizeof(*table));
2745 free(ioe, M_PF6, sizeof(*ioe));
2746 goto fail; /* really bad */
2747 }
2748 break;
2749 case PF_TRANS_RULESET:
2750 if ((error = pf_commit_rules(ioe->ticket,
2751 ioe->anchor))) {
2752 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2753 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2754 free(table, M_PF6, sizeof(*table));
2755 free(ioe, M_PF6, sizeof(*ioe));
2756 goto fail; /* really bad */
2757 }
2758 break;
2759 default:
2760 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2761 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2762 free(table, M_PF6, sizeof(*table));
2763 free(ioe, M_PF6, sizeof(*ioe));
2764 error = EINVAL22;
2765 goto fail; /* really bad */
2766 }
2767 }
2768 for (i = 0; i < PF_LIMIT_MAX; i++) {
2769 if (pf_pool_limits[i].limit_new !=
2770 pf_pool_limits[i].limit &&
2771 pool_sethardlimit(pf_pool_limits[i].pp,
2772 pf_pool_limits[i].limit_new, NULL((void *)0), 0) != 0) {
2773 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2774 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2775 free(table, M_PF6, sizeof(*table));
2776 free(ioe, M_PF6, sizeof(*ioe));
2777 error = EBUSY16;
2778 goto fail; /* really bad */
2779 }
2780 pf_pool_limits[i].limit = pf_pool_limits[i].limit_new;
2781 }
2782 for (i = 0; i < PFTM_MAX; i++) {
2783 int old = pf_default_rule.timeout[i];
2784
2785 pf_default_rule.timeout[i] =
2786 pf_default_rule_new.timeout[i];
2787 if (pf_default_rule.timeout[i] == PFTM_INTERVAL &&
2788 pf_default_rule.timeout[i] < old &&
2789 timeout_del(&pf_purge_to))
2790 task_add(systqmp, &pf_purge_task);
2791 }
2792 pfi_xcommit();
2793 pf_trans_set_commit();
2794 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2795 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2796 free(table, M_PF6, sizeof(*table));
2797 free(ioe, M_PF6, sizeof(*ioe));
2798 break;
2799 }
2800
2801 case DIOCXEND(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((100)))
: {
2802 u_int32_t *ticket = (u_int32_t *)addr;
2803 struct pf_trans *t;
2804
2805 t = pf_find_trans(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
, *ticket);
2806 if (t != NULL((void *)0))
2807 pf_rollback_trans(t);
2808 else
2809 error = ENXIO6;
2810 break;
2811 }
2812
2813 case DIOCGETSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_src_nodes) & 0x1fff) << 16) | ((('D')
) << 8) | ((84)))
: {
2814 struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
2815 struct pf_src_node *n, *p, *pstore;
2816 u_int32_t nr = 0;
2817 size_t space = psn->psn_len;
2818
2819 pstore = malloc(sizeof(*pstore), M_PF6, M_WAITOK0x0001);
2820
2821 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2822 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2823 if (space == 0) {
2824 RB_FOREACH(n, pf_src_tree, &tree_src_tracking)for ((n) = pf_src_tree_RB_MINMAX(&tree_src_tracking, -1);
(n) != ((void *)0); (n) = pf_src_tree_RB_NEXT(n))
2825 nr++;
2826 psn->psn_len = sizeof(struct pf_src_node) * nr;
2827 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2828 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2829 free(pstore, M_PF6, sizeof(*pstore));
2830 goto fail;
2831 }
2832
2833 p = psn->psn_src_nodespsn_u.psu_src_nodes;
2834 RB_FOREACH(n, pf_src_tree, &tree_src_tracking)for ((n) = pf_src_tree_RB_MINMAX(&tree_src_tracking, -1);
(n) != ((void *)0); (n) = pf_src_tree_RB_NEXT(n))
{
2835 int secs = getuptime(), diff;
2836
2837 if ((nr + 1) * sizeof(*p) > psn->psn_len)
2838 break;
2839
2840 memcpy(pstore, n, sizeof(*pstore))__builtin_memcpy((pstore), (n), (sizeof(*pstore)));
2841 memset(&pstore->entry, 0, sizeof(pstore->entry))__builtin_memset((&pstore->entry), (0), (sizeof(pstore
->entry)))
;
2842 pstore->rule.ptr = NULL((void *)0);
2843 pstore->kif = NULL((void *)0);
2844 pstore->rule.nr = n->rule.ptr->nr;
2845 pstore->creation = secs - pstore->creation;
2846 if (pstore->expire > secs)
2847 pstore->expire -= secs;
2848 else
2849 pstore->expire = 0;
2850
2851 /* adjust the connection rate estimate */
2852 diff = secs - n->conn_rate.last;
2853 if (diff >= n->conn_rate.seconds)
2854 pstore->conn_rate.count = 0;
2855 else
2856 pstore->conn_rate.count -=
2857 n->conn_rate.count * diff /
2858 n->conn_rate.seconds;
2859
2860 error = copyout(pstore, p, sizeof(*p));
2861 if (error) {
2862 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2863 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2864 free(pstore, M_PF6, sizeof(*pstore));
2865 goto fail;
2866 }
2867 p++;
2868 nr++;
2869 }
2870 psn->psn_len = sizeof(struct pf_src_node) * nr;
2871
2872 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2873 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2874 free(pstore, M_PF6, sizeof(*pstore));
2875 break;
2876 }
2877
2878 case DIOCCLRSRCNODES((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((85)))
: {
2879 struct pf_src_node *n;
2880 struct pf_state *st;
2881
2882 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2883 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2884 PF_STATE_ENTER_WRITE()do { rw_enter_write(&pf_state_lock); } while (0);
2885 RBT_FOREACH(st, pf_state_tree_id, &tree_id)for ((st) = pf_state_tree_id_RBT_MIN((&tree_id)); (st) !=
((void *)0); (st) = pf_state_tree_id_RBT_NEXT((st)))
2886 pf_src_tree_remove_state(st);
2887 PF_STATE_EXIT_WRITE()do { do { if (rw_status(&pf_state_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_state_lock), __func__); } while (
0); rw_exit_write(&pf_state_lock); } while (0)
;
2888 RB_FOREACH(n, pf_src_tree, &tree_src_tracking)for ((n) = pf_src_tree_RB_MINMAX(&tree_src_tracking, -1);
(n) != ((void *)0); (n) = pf_src_tree_RB_NEXT(n))
2889 n->expire = 1;
2890 pf_purge_expired_src_nodes();
2891 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2892 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2893 break;
2894 }
2895
2896 case DIOCKILLSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_src_node_kill) & 0x1fff) << 16) | (((
'D')) << 8) | ((91)))
: {
2897 struct pf_src_node *sn;
2898 struct pf_state *st;
2899 struct pfioc_src_node_kill *psnk =
2900 (struct pfioc_src_node_kill *)addr;
2901 u_int killed = 0;
2902
2903 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2904 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2905 RB_FOREACH(sn, pf_src_tree, &tree_src_tracking)for ((sn) = pf_src_tree_RB_MINMAX(&tree_src_tracking, -1)
; (sn) != ((void *)0); (sn) = pf_src_tree_RB_NEXT(sn))
{
2906 if (pf_match_addr(psnk->psnk_src.neg,
2907 &psnk->psnk_src.addr.v.a.addr,
2908 &psnk->psnk_src.addr.v.a.mask,
2909 &sn->addr, sn->af) &&
2910 pf_match_addr(psnk->psnk_dst.neg,
2911 &psnk->psnk_dst.addr.v.a.addr,
2912 &psnk->psnk_dst.addr.v.a.mask,
2913 &sn->raddr, sn->af)) {
2914 /* Handle state to src_node linkage */
2915 if (sn->states != 0) {
2916 PF_ASSERT_LOCKED()do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail(
0x0001UL, rw_status(&pf_lock),__func__); } while (0)
;
2917 PF_STATE_ENTER_WRITE()do { rw_enter_write(&pf_state_lock); } while (0);
2918 RBT_FOREACH(st, pf_state_tree_id,for ((st) = pf_state_tree_id_RBT_MIN((&tree_id)); (st) !=
((void *)0); (st) = pf_state_tree_id_RBT_NEXT((st)))
2919 &tree_id)for ((st) = pf_state_tree_id_RBT_MIN((&tree_id)); (st) !=
((void *)0); (st) = pf_state_tree_id_RBT_NEXT((st)))
2920 pf_state_rm_src_node(st, sn);
2921 PF_STATE_EXIT_WRITE()do { do { if (rw_status(&pf_state_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_state_lock), __func__); } while (
0); rw_exit_write(&pf_state_lock); } while (0)
;
2922 }
2923 sn->expire = 1;
2924 killed++;
2925 }
2926 }
2927
2928 if (killed > 0)
2929 pf_purge_expired_src_nodes();
2930
2931 psnk->psnk_killed = killed;
2932 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2933 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2934 break;
2935 }
2936
2937 case DIOCSETHOSTID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((86)))
: {
2938 u_int32_t *hostid = (u_int32_t *)addr;
2939
2940 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2941 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2942 if (*hostid == 0)
2943 pf_trans_set.hostid = arc4random();
2944 else
2945 pf_trans_set.hostid = *hostid;
2946 pf_trans_set.mask |= PF_TSET_HOSTID0x04;
2947 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2948 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2949 break;
2950 }
2951
2952 case DIOCOSFPFLUSH((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((78)))
:
2953 pf_osfp_flush();
2954 break;
2955
2956 case DIOCIGETIFACES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((87)))
: {
2957 struct pfioc_iface *io = (struct pfioc_iface *)addr;
2958 struct pfi_kif *kif_buf;
2959 int apfiio_size = io->pfiio_size;
2960
2961 if (io->pfiio_esize != sizeof(struct pfi_kif)) {
2962 error = ENODEV19;
2963 goto fail;
2964 }
2965
2966 if ((kif_buf = mallocarray(sizeof(*kif_buf), apfiio_size,
2967 M_PF6, M_WAITOK0x0001|M_CANFAIL0x0004)) == NULL((void *)0)) {
2968 error = EINVAL22;
2969 goto fail;
2970 }
2971
2972 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
2973 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2974 pfi_get_ifaces(io->pfiio_name, kif_buf, &io->pfiio_size);
2975 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2976 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
2977 if (copyout(kif_buf, io->pfiio_buffer, sizeof(*kif_buf) *
2978 io->pfiio_size))
2979 error = EFAULT14;
2980 free(kif_buf, M_PF6, sizeof(*kif_buf) * apfiio_size);
2981 break;
2982 }
2983
2984 case DIOCSETIFFLAG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((89)))
: {
2985 struct pfioc_iface *io = (struct pfioc_iface *)addr;
2986
2987 if (io == NULL((void *)0)) {
2988 error = EINVAL22;
2989 goto fail;
2990 }
2991
2992 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
2993 error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
2994 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
2995 break;
2996 }
2997
2998 case DIOCCLRIFFLAG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((90)))
: {
2999 struct pfioc_iface *io = (struct pfioc_iface *)addr;
3000
3001 if (io == NULL((void *)0)) {
3002 error = EINVAL22;
3003 goto fail;
3004 }
3005
3006 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
3007 error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
3008 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
3009 break;
3010 }
3011
3012 case DIOCSETREASS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((92)))
: {
3013 u_int32_t *reass = (u_int32_t *)addr;
3014
3015 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
3016 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
3017 pf_trans_set.reass = *reass;
3018 pf_trans_set.mask |= PF_TSET_REASS0x08;
3019 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
3020 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
3021 break;
3022 }
3023
3024 case DIOCSETSYNFLWATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_synflwats) & 0x1fff) << 16) | ((('D')
) << 8) | ((97)))
: {
3025 struct pfioc_synflwats *io = (struct pfioc_synflwats *)addr;
3026
3027 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
3028 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
3029 error = pf_syncookies_setwats(io->hiwat, io->lowat);
3030 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
3031 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
3032 break;
3033 }
3034
3035 case DIOCGETSYNFLWATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_synflwats) & 0x1fff) << 16) | ((('D')
) << 8) | ((99)))
: {
3036 struct pfioc_synflwats *io = (struct pfioc_synflwats *)addr;
3037
3038 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
3039 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
3040 error = pf_syncookies_getwats(io);
3041 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
3042 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
3043 break;
3044 }
3045
3046 case DIOCSETSYNCOOKIES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int8_t) & 0x1fff) << 16) | ((('D')) << 8) |
((98)))
: {
3047 u_int8_t *mode = (u_int8_t *)addr;
3048
3049 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
3050 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
3051 error = pf_syncookies_setmode(*mode);
3052 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
3053 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
3054 break;
3055 }
3056
3057 default:
3058 error = ENODEV19;
3059 break;
3060 }
3061fail:
3062 rw_exit_write(&pfioctl_rw);
3063
3064 return (error);
3065}
3066
3067void
3068pf_trans_set_commit(void)
3069{
3070 if (pf_trans_set.mask & PF_TSET_STATUSIF0x01)
3071 strlcpy(pf_status.ifname, pf_trans_set.statusif, IFNAMSIZ16);
3072 if (pf_trans_set.mask & PF_TSET_DEBUG0x02)
3073 pf_status.debug = pf_trans_set.debug;
3074 if (pf_trans_set.mask & PF_TSET_HOSTID0x04)
3075 pf_status.hostid = pf_trans_set.hostid;
3076 if (pf_trans_set.mask & PF_TSET_REASS0x08)
3077 pf_status.reass = pf_trans_set.reass;
3078}
3079
3080void
3081pf_pool_copyin(struct pf_pool *from, struct pf_pool *to)
3082{
3083 memmove(to, from, sizeof(*to))__builtin_memmove((to), (from), (sizeof(*to)));
3084 to->kif = NULL((void *)0);
3085 to->addr.p.tbl = NULL((void *)0);
3086}
3087
3088int
3089pf_validate_range(u_int8_t op, u_int16_t port[2], int order)
3090{
3091 u_int16_t a = (order == PF_ORDER_NET1) ? ntohs(port[0])(__uint16_t)(__builtin_constant_p(port[0]) ? (__uint16_t)(((__uint16_t
)(port[0]) & 0xffU) << 8 | ((__uint16_t)(port[0]) &
0xff00U) >> 8) : __swap16md(port[0]))
: port[0];
3092 u_int16_t b = (order == PF_ORDER_NET1) ? ntohs(port[1])(__uint16_t)(__builtin_constant_p(port[1]) ? (__uint16_t)(((__uint16_t
)(port[1]) & 0xffU) << 8 | ((__uint16_t)(port[1]) &
0xff00U) >> 8) : __swap16md(port[1]))
: port[1];
3093
3094 if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */
3095 (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */
3096 (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */
3097 return 1;
3098 return 0;
3099}
3100
3101int
3102pf_rule_copyin(struct pf_rule *from, struct pf_rule *to)
3103{
3104 int i;
3105
3106 if (from->scrub_flags & PFSTATE_SETPRIO0x0200 &&
3107 (from->set_prio[0] > IFQ_MAXPRIO8 - 1 ||
3108 from->set_prio[1] > IFQ_MAXPRIO8 - 1))
3109 return (EINVAL22);
3110
3111 to->src = from->src;
3112 to->src.addr.p.tbl = NULL((void *)0);
3113 to->dst = from->dst;
3114 to->dst.addr.p.tbl = NULL((void *)0);
3115
3116 if (pf_validate_range(to->src.port_op, to->src.port, PF_ORDER_NET1))
3117 return (EINVAL22);
3118 if (pf_validate_range(to->dst.port_op, to->dst.port, PF_ORDER_NET1))
3119 return (EINVAL22);
3120
3121 /* XXX union skip[] */
3122
3123 strlcpy(to->label, from->label, sizeof(to->label));
3124 strlcpy(to->ifname, from->ifname, sizeof(to->ifname));
3125 strlcpy(to->rcv_ifname, from->rcv_ifname, sizeof(to->rcv_ifname));
3126 strlcpy(to->qname, from->qname, sizeof(to->qname));
3127 strlcpy(to->pqname, from->pqname, sizeof(to->pqname));
3128 strlcpy(to->tagname, from->tagname, sizeof(to->tagname));
3129 strlcpy(to->match_tagname, from->match_tagname,
3130 sizeof(to->match_tagname));
3131 strlcpy(to->overload_tblname, from->overload_tblname,
3132 sizeof(to->overload_tblname));
3133
3134 pf_pool_copyin(&from->nat, &to->nat);
3135 pf_pool_copyin(&from->rdr, &to->rdr);
3136 pf_pool_copyin(&from->route, &to->route);
3137
3138 if (pf_validate_range(to->rdr.port_op, to->rdr.proxy_port,
3139 PF_ORDER_HOST0))
3140 return (EINVAL22);
3141
3142 to->kif = (to->ifname[0]) ?
3143 pfi_kif_alloc(to->ifname, M_WAITOK0x0001) : NULL((void *)0);
3144 to->rcv_kif = (to->rcv_ifname[0]) ?
3145 pfi_kif_alloc(to->rcv_ifname, M_WAITOK0x0001) : NULL((void *)0);
3146 to->rdr.kif = (to->rdr.ifname[0]) ?
3147 pfi_kif_alloc(to->rdr.ifname, M_WAITOK0x0001) : NULL((void *)0);
3148 to->nat.kif = (to->nat.ifname[0]) ?
3149 pfi_kif_alloc(to->nat.ifname, M_WAITOK0x0001) : NULL((void *)0);
3150 to->route.kif = (to->route.ifname[0]) ?
3151 pfi_kif_alloc(to->route.ifname, M_WAITOK0x0001) : NULL((void *)0);
3152
3153 to->os_fingerprint = from->os_fingerprint;
3154
3155 to->rtableid = from->rtableid;
3156 if (to->rtableid >= 0 && !rtable_exists(to->rtableid))
3157 return (EBUSY16);
3158 to->onrdomain = from->onrdomain;
3159 if (to->onrdomain != -1 && (to->onrdomain < 0 ||
3160 to->onrdomain > RT_TABLEID_MAX255))
3161 return (EINVAL22);
3162
3163 for (i = 0; i < PFTM_MAX; i++)
3164 to->timeout[i] = from->timeout[i];
3165 to->states_tot = from->states_tot;
3166 to->max_states = from->max_states;
3167 to->max_src_nodes = from->max_src_nodes;
3168 to->max_src_states = from->max_src_states;
3169 to->max_src_conn = from->max_src_conn;
3170 to->max_src_conn_rate.limit = from->max_src_conn_rate.limit;
3171 to->max_src_conn_rate.seconds = from->max_src_conn_rate.seconds;
3172 pf_init_threshold(&to->pktrate, from->pktrate.limit,
3173 from->pktrate.seconds);
3174
3175 if (to->qname[0] != 0) {
3176 if ((to->qid = pf_qname2qid(to->qname, 0)) == 0)
3177 return (EBUSY16);
3178 if (to->pqname[0] != 0) {
3179 if ((to->pqid = pf_qname2qid(to->pqname, 0)) == 0)
3180 return (EBUSY16);
3181 } else
3182 to->pqid = to->qid;
3183 }
3184 to->rt_listid = from->rt_listid;
3185 to->prob = from->prob;
3186 to->return_icmp = from->return_icmp;
3187 to->return_icmp6 = from->return_icmp6;
3188 to->max_mss = from->max_mss;
3189 if (to->tagname[0])
3190 if ((to->tag = pf_tagname2tag(to->tagname, 1)) == 0)
3191 return (EBUSY16);
3192 if (to->match_tagname[0])
3193 if ((to->match_tag = pf_tagname2tag(to->match_tagname, 1)) == 0)
3194 return (EBUSY16);
3195 to->scrub_flags = from->scrub_flags;
3196 to->delay = from->delay;
3197 to->uid = from->uid;
3198 to->gid = from->gid;
3199 to->rule_flag = from->rule_flag;
3200 to->action = from->action;
3201 to->direction = from->direction;
3202 to->log = from->log;
3203 to->logif = from->logif;
3204#if NPFLOG1 > 0
3205 if (!to->log)
3206 to->logif = 0;
3207#endif /* NPFLOG > 0 */
3208 to->quick = from->quick;
3209 to->ifnot = from->ifnot;
3210 to->rcvifnot = from->rcvifnot;
3211 to->match_tag_not = from->match_tag_not;
3212 to->keep_state = from->keep_state;
3213 to->af = from->af;
3214 to->naf = from->naf;
3215 to->proto = from->proto;
3216 to->type = from->type;
3217 to->code = from->code;
3218 to->flags = from->flags;
3219 to->flagset = from->flagset;
3220 to->min_ttl = from->min_ttl;
3221 to->allow_opts = from->allow_opts;
3222 to->rt = from->rt;
3223 to->return_ttl = from->return_ttl;
3224 to->tos = from->tos;
3225 to->set_tos = from->set_tos;
3226 to->anchor_relative = from->anchor_relative; /* XXX */
3227 to->anchor_wildcard = from->anchor_wildcard; /* XXX */
3228 to->flush = from->flush;
3229 to->divert.addr = from->divert.addr;
3230 to->divert.port = from->divert.port;
3231 to->divert.type = from->divert.type;
3232 to->prio = from->prio;
3233 to->set_prio[0] = from->set_prio[0];
3234 to->set_prio[1] = from->set_prio[1];
3235
3236 return (0);
3237}
3238
3239int
3240pf_rule_checkaf(struct pf_rule *r)
3241{
3242 switch (r->af) {
3243 case 0:
3244 if (r->rule_flag & PFRULE_AFTO0x00200000)
3245 return (EPFNOSUPPORT46);
3246 break;
3247 case AF_INET2:
3248 if ((r->rule_flag & PFRULE_AFTO0x00200000) && r->naf != AF_INET624)
3249 return (EPFNOSUPPORT46);
3250 break;
3251#ifdef INET61
3252 case AF_INET624:
3253 if ((r->rule_flag & PFRULE_AFTO0x00200000) && r->naf != AF_INET2)
3254 return (EPFNOSUPPORT46);
3255 break;
3256#endif /* INET6 */
3257 default:
3258 return (EPFNOSUPPORT46);
3259 }
3260
3261 if ((r->rule_flag & PFRULE_AFTO0x00200000) == 0 && r->naf != 0)
3262 return (EPFNOSUPPORT46);
3263
3264 return (0);
3265}
3266
3267int
3268pf_sysctl(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
3269{
3270 struct pf_status pfs;
3271
3272 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
3273 PF_LOCK()do { rw_enter_write(&pf_lock); } while (0);
3274 memcpy(&pfs, &pf_status, sizeof(struct pf_status))__builtin_memcpy((&pfs), (&pf_status), (sizeof(struct
pf_status)))
;
3275 pfi_update_status(pfs.ifname, &pfs);
3276 PF_UNLOCK()do { do { if (rw_status(&pf_lock) != 0x0001UL) splassert_fail
(0x0001UL, rw_status(&pf_lock),__func__); } while (0); rw_exit_write
(&pf_lock); } while (0)
;
3277 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
3278
3279 return sysctl_rdstruct(oldp, oldlenp, newp, &pfs, sizeof(pfs));
3280}
3281
3282struct pf_trans *
3283pf_open_trans(uint32_t unit)
3284{
3285 static uint64_t ticket = 1;
3286 struct pf_trans *t;
3287
3288 rw_assert_wrlock(&pfioctl_rw);
3289
3290 KASSERT(pf_unit2idx(unit) < nitems(pf_tcount))((((unit) >> 8) < (sizeof((pf_tcount)) / sizeof((pf_tcount
)[0]))) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/pf_ioctl.c"
, 3290, "pf_unit2idx(unit) < nitems(pf_tcount)"))
;
3291 if (pf_tcount[pf_unit2idx(unit)((unit) >> 8)] >= (PF_ANCHOR_STACK_MAX64 * 8))
3292 return (NULL((void *)0));
3293
3294 t = malloc(sizeof(*t), M_PF6, M_WAITOK0x0001|M_ZERO0x0008);
3295 t->pft_unit = unit;
3296 t->pft_ticket = ticket++;
3297 pf_tcount[pf_unit2idx(unit)((unit) >> 8)]++;
3298
3299 LIST_INSERT_HEAD(&pf_ioctl_trans, t, pft_entry)do { if (((t)->pft_entry.le_next = (&pf_ioctl_trans)->
lh_first) != ((void *)0)) (&pf_ioctl_trans)->lh_first->
pft_entry.le_prev = &(t)->pft_entry.le_next; (&pf_ioctl_trans
)->lh_first = (t); (t)->pft_entry.le_prev = &(&
pf_ioctl_trans)->lh_first; } while (0)
;
3300
3301 return (t);
3302}
3303
3304struct pf_trans *
3305pf_find_trans(uint32_t unit, uint64_t ticket)
3306{
3307 struct pf_trans *t;
3308
3309 rw_assert_anylock(&pfioctl_rw);
3310
3311 LIST_FOREACH(t, &pf_ioctl_trans, pft_entry)for((t) = ((&pf_ioctl_trans)->lh_first); (t)!= ((void *
)0); (t) = ((t)->pft_entry.le_next))
{
3312 if (t->pft_ticket == ticket && t->pft_unit == unit)
3313 break;
3314 }
3315
3316 return (t);
3317}
3318
3319void
3320pf_init_tgetrule(struct pf_trans *t, struct pf_anchor *a,
3321 uint32_t rs_version, struct pf_rule *r)
3322{
3323 t->pft_type = PF_TRANS_GETRULE;
3324 if (a == NULL((void *)0))
3325 t->pftgr_anchoru.u_getrule.gr_anchor = &pf_main_anchor;
3326 else
3327 t->pftgr_anchoru.u_getrule.gr_anchor = a;
3328
3329 t->pftgr_versionu.u_getrule.gr_version = rs_version;
3330 t->pftgr_ruleu.u_getrule.gr_rule = r;
3331}
3332
3333void
3334pf_cleanup_tgetrule(struct pf_trans *t)
3335{
3336 KASSERT(t->pft_type == PF_TRANS_GETRULE)((t->pft_type == PF_TRANS_GETRULE) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/pf_ioctl.c", 3336, "t->pft_type == PF_TRANS_GETRULE"
))
;
3337 pf_anchor_rele(t->pftgr_anchoru.u_getrule.gr_anchor);
3338}
3339
3340void
3341pf_free_trans(struct pf_trans *t)
3342{
3343 switch (t->pft_type) {
3344 case PF_TRANS_GETRULE:
3345 pf_cleanup_tgetrule(t);
3346 break;
3347 default:
3348 log(LOG_ERR3, "%s unknown transaction type: %d\n",
3349 __func__, t->pft_type);
3350 }
3351
3352 KASSERT(pf_unit2idx(t->pft_unit) < nitems(pf_tcount))((((t->pft_unit) >> 8) < (sizeof((pf_tcount)) / sizeof
((pf_tcount)[0]))) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/pf_ioctl.c"
, 3352, "pf_unit2idx(t->pft_unit) < nitems(pf_tcount)")
)
;
3353 KASSERT(pf_tcount[pf_unit2idx(t->pft_unit)] >= 1)((pf_tcount[((t->pft_unit) >> 8)] >= 1) ? (void)0
: __assert("diagnostic ", "/usr/src/sys/net/pf_ioctl.c", 3353
, "pf_tcount[pf_unit2idx(t->pft_unit)] >= 1"))
;
3354 pf_tcount[pf_unit2idx(t->pft_unit)((t->pft_unit) >> 8)]--;
3355
3356 free(t, M_PF6, sizeof(*t));
3357}
3358
3359void
3360pf_rollback_trans(struct pf_trans *t)
3361{
3362 if (t != NULL((void *)0)) {
3363 rw_assert_wrlock(&pfioctl_rw);
3364 LIST_REMOVE(t, pft_entry)do { if ((t)->pft_entry.le_next != ((void *)0)) (t)->pft_entry
.le_next->pft_entry.le_prev = (t)->pft_entry.le_prev; *
(t)->pft_entry.le_prev = (t)->pft_entry.le_next; ((t)->
pft_entry.le_prev) = ((void *)-1); ((t)->pft_entry.le_next
) = ((void *)-1); } while (0)
;
3365 pf_free_trans(t);
3366 }
3367}