1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2001 Daniel Hartmeier
5 * Copyright (c) 2002,2003 Henning Brauer
6 * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Effort sponsored in part by the Defense Advanced Research Projects
34 * Agency (DARPA) and Air Force Research Laboratory, Air Force
35 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
36 *
37 * $OpenBSD: pf_ioctl.c,v 1.213 2009/02/15 21:46:12 mbalmer Exp $
38 */
39
40 #include <sys/cdefs.h>
41 #include "opt_inet.h"
42 #include "opt_inet6.h"
43 #include "opt_bpf.h"
44 #include "opt_pf.h"
45
46 #include <sys/param.h>
47 #include <sys/_bitset.h>
48 #include <sys/bitset.h>
49 #include <sys/bus.h>
50 #include <sys/conf.h>
51 #include <sys/endian.h>
52 #include <sys/fcntl.h>
53 #include <sys/filio.h>
54 #include <sys/hash.h>
55 #include <sys/interrupt.h>
56 #include <sys/jail.h>
57 #include <sys/kernel.h>
58 #include <sys/kthread.h>
59 #include <sys/lock.h>
60 #include <sys/mbuf.h>
61 #include <sys/module.h>
62 #include <sys/nv.h>
63 #include <sys/proc.h>
64 #include <sys/sdt.h>
65 #include <sys/smp.h>
66 #include <sys/socket.h>
67 #include <sys/sysctl.h>
68 #include <sys/md5.h>
69 #include <sys/ucred.h>
70
71 #include <net/if.h>
72 #include <net/if_var.h>
73 #include <net/if_private.h>
74 #include <net/vnet.h>
75 #include <net/route.h>
76 #include <net/pfil.h>
77 #include <net/pfvar.h>
78 #include <net/if_pfsync.h>
79 #include <net/if_pflog.h>
80
81 #include <netinet/in.h>
82 #include <netinet/ip.h>
83 #include <netinet/ip_var.h>
84 #include <netinet6/ip6_var.h>
85 #include <netinet/ip_icmp.h>
86 #include <netpfil/pf/pf_nl.h>
87 #include <netpfil/pf/pf_nv.h>
88
89 #ifdef INET6
90 #include <netinet/ip6.h>
91 #endif /* INET6 */
92
93 #ifdef ALTQ
94 #include <net/altq/altq.h>
95 #endif
96
97 SDT_PROBE_DEFINE3(pf, ioctl, ioctl, error, "int", "int", "int");
98 SDT_PROBE_DEFINE3(pf, ioctl, function, error, "char *", "int", "int");
99 SDT_PROBE_DEFINE2(pf, ioctl, addrule, error, "int", "int");
100 SDT_PROBE_DEFINE2(pf, ioctl, nvchk, error, "int", "int");
101
102 static struct pf_kpool *pf_get_kpool(const char *, u_int32_t, u_int8_t,
103 u_int32_t, u_int8_t, u_int8_t, u_int8_t);
104
105 static void pf_mv_kpool(struct pf_kpalist *, struct pf_kpalist *);
106 static void pf_empty_kpool(struct pf_kpalist *);
107 static int pfioctl(struct cdev *, u_long, caddr_t, int,
108 struct thread *);
109 static int pf_begin_eth(uint32_t *, const char *);
110 static void pf_rollback_eth_cb(struct epoch_context *);
111 static int pf_rollback_eth(uint32_t, const char *);
112 static int pf_commit_eth(uint32_t, const char *);
113 static void pf_free_eth_rule(struct pf_keth_rule *);
114 #ifdef ALTQ
115 static int pf_begin_altq(u_int32_t *);
116 static int pf_rollback_altq(u_int32_t);
117 static int pf_commit_altq(u_int32_t);
118 static int pf_enable_altq(struct pf_altq *);
119 static int pf_disable_altq(struct pf_altq *);
120 static uint16_t pf_qname2qid(const char *);
121 static void pf_qid_unref(uint16_t);
122 #endif /* ALTQ */
123 static int pf_begin_rules(u_int32_t *, int, const char *);
124 static int pf_rollback_rules(u_int32_t, int, char *);
125 static int pf_setup_pfsync_matching(struct pf_kruleset *);
126 static void pf_hash_rule_rolling(MD5_CTX *, struct pf_krule *);
127 static void pf_hash_rule(struct pf_krule *);
128 static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
129 static int pf_commit_rules(u_int32_t, int, char *);
130 static int pf_addr_setup(struct pf_kruleset *,
131 struct pf_addr_wrap *, sa_family_t);
132 static void pf_addr_copyout(struct pf_addr_wrap *);
133 static void pf_src_node_copy(const struct pf_ksrc_node *,
134 struct pf_src_node *);
135 #ifdef ALTQ
136 static int pf_export_kaltq(struct pf_altq *,
137 struct pfioc_altq_v1 *, size_t);
138 static int pf_import_kaltq(struct pfioc_altq_v1 *,
139 struct pf_altq *, size_t);
140 #endif /* ALTQ */
141
142 VNET_DEFINE(struct pf_krule, pf_default_rule);
143
144 static __inline int pf_krule_compare(struct pf_krule *,
145 struct pf_krule *);
146
147 RB_GENERATE(pf_krule_global, pf_krule, entry_global, pf_krule_compare);
148
149 #ifdef ALTQ
150 VNET_DEFINE_STATIC(int, pf_altq_running);
151 #define V_pf_altq_running VNET(pf_altq_running)
152 #endif
153
154 #define TAGID_MAX 50000
155 struct pf_tagname {
156 TAILQ_ENTRY(pf_tagname) namehash_entries;
157 TAILQ_ENTRY(pf_tagname) taghash_entries;
158 char name[PF_TAG_NAME_SIZE];
159 uint16_t tag;
160 int ref;
161 };
162
163 struct pf_tagset {
164 TAILQ_HEAD(, pf_tagname) *namehash;
165 TAILQ_HEAD(, pf_tagname) *taghash;
166 unsigned int mask;
167 uint32_t seed;
168 BITSET_DEFINE(, TAGID_MAX) avail;
169 };
170
171 VNET_DEFINE(struct pf_tagset, pf_tags);
172 #define V_pf_tags VNET(pf_tags)
173 static unsigned int pf_rule_tag_hashsize;
174 #define PF_RULE_TAG_HASH_SIZE_DEFAULT 128
175 SYSCTL_UINT(_net_pf, OID_AUTO, rule_tag_hashsize, CTLFLAG_RDTUN,
176 &pf_rule_tag_hashsize, PF_RULE_TAG_HASH_SIZE_DEFAULT,
177 "Size of pf(4) rule tag hashtable");
178
179 #ifdef ALTQ
180 VNET_DEFINE(struct pf_tagset, pf_qids);
181 #define V_pf_qids VNET(pf_qids)
182 static unsigned int pf_queue_tag_hashsize;
183 #define PF_QUEUE_TAG_HASH_SIZE_DEFAULT 128
184 SYSCTL_UINT(_net_pf, OID_AUTO, queue_tag_hashsize, CTLFLAG_RDTUN,
185 &pf_queue_tag_hashsize, PF_QUEUE_TAG_HASH_SIZE_DEFAULT,
186 "Size of pf(4) queue tag hashtable");
187 #endif
188 VNET_DEFINE(uma_zone_t, pf_tag_z);
189 #define V_pf_tag_z VNET(pf_tag_z)
190 static MALLOC_DEFINE(M_PFALTQ, "pf_altq", "pf(4) altq configuration db");
191 static MALLOC_DEFINE(M_PFRULE, "pf_rule", "pf(4) rules");
192
193 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
194 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
195 #endif
196
197 VNET_DEFINE_STATIC(bool, pf_filter_local) = false;
198 #define V_pf_filter_local VNET(pf_filter_local)
199 SYSCTL_BOOL(_net_pf, OID_AUTO, filter_local, CTLFLAG_VNET | CTLFLAG_RW,
200 &VNET_NAME(pf_filter_local), false,
201 "Enable filtering for packets delivered to local network stack");
202
203 #ifdef PF_DEFAULT_TO_DROP
204 VNET_DEFINE_STATIC(bool, default_to_drop) = true;
205 #else
206 VNET_DEFINE_STATIC(bool, default_to_drop);
207 #endif
208 #define V_default_to_drop VNET(default_to_drop)
209 SYSCTL_BOOL(_net_pf, OID_AUTO, default_to_drop, CTLFLAG_RDTUN | CTLFLAG_VNET,
210 &VNET_NAME(default_to_drop), false,
211 "Make the default rule drop all packets.");
212
213 static void pf_init_tagset(struct pf_tagset *, unsigned int *,
214 unsigned int);
215 static void pf_cleanup_tagset(struct pf_tagset *);
216 static uint16_t tagname2hashindex(const struct pf_tagset *, const char *);
217 static uint16_t tag2hashindex(const struct pf_tagset *, uint16_t);
218 static u_int16_t tagname2tag(struct pf_tagset *, const char *);
219 static u_int16_t pf_tagname2tag(const char *);
220 static void tag_unref(struct pf_tagset *, u_int16_t);
221
222 #define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
223
224 struct cdev *pf_dev;
225
226 /*
227 * XXX - These are new and need to be checked when moveing to a new version
228 */
229 static void pf_clear_all_states(void);
230 static int pf_killstates_row(struct pf_kstate_kill *,
231 struct pf_idhash *);
232 static int pf_killstates_nv(struct pfioc_nv *);
233 static int pf_clearstates_nv(struct pfioc_nv *);
234 static int pf_getstate(struct pfioc_nv *);
235 static int pf_getstatus(struct pfioc_nv *);
236 static int pf_clear_tables(void);
237 static void pf_clear_srcnodes(struct pf_ksrc_node *);
238 static void pf_kill_srcnodes(struct pfioc_src_node_kill *);
239 static int pf_keepcounters(struct pfioc_nv *);
240 static void pf_tbladdr_copyout(struct pf_addr_wrap *);
241
242 /*
243 * Wrapper functions for pfil(9) hooks
244 */
245 static pfil_return_t pf_eth_check_in(struct mbuf **m, struct ifnet *ifp,
246 int flags, void *ruleset __unused, struct inpcb *inp);
247 static pfil_return_t pf_eth_check_out(struct mbuf **m, struct ifnet *ifp,
248 int flags, void *ruleset __unused, struct inpcb *inp);
249 #ifdef INET
250 static pfil_return_t pf_check_in(struct mbuf **m, struct ifnet *ifp,
251 int flags, void *ruleset __unused, struct inpcb *inp);
252 static pfil_return_t pf_check_out(struct mbuf **m, struct ifnet *ifp,
253 int flags, void *ruleset __unused, struct inpcb *inp);
254 #endif
255 #ifdef INET6
256 static pfil_return_t pf_check6_in(struct mbuf **m, struct ifnet *ifp,
257 int flags, void *ruleset __unused, struct inpcb *inp);
258 static pfil_return_t pf_check6_out(struct mbuf **m, struct ifnet *ifp,
259 int flags, void *ruleset __unused, struct inpcb *inp);
260 #endif
261
262 static void hook_pf_eth(void);
263 static void hook_pf(void);
264 static void dehook_pf_eth(void);
265 static void dehook_pf(void);
266 static int shutdown_pf(void);
267 static int pf_load(void);
268 static void pf_unload(void);
269
270 static struct cdevsw pf_cdevsw = {
271 .d_ioctl = pfioctl,
272 .d_name = PF_NAME,
273 .d_version = D_VERSION,
274 };
275
276 VNET_DEFINE_STATIC(bool, pf_pfil_hooked);
277 #define V_pf_pfil_hooked VNET(pf_pfil_hooked)
278 VNET_DEFINE_STATIC(bool, pf_pfil_eth_hooked);
279 #define V_pf_pfil_eth_hooked VNET(pf_pfil_eth_hooked)
280
281 /*
282 * We need a flag that is neither hooked nor running to know when
283 * the VNET is "valid". We primarily need this to control (global)
284 * external event, e.g., eventhandlers.
285 */
286 VNET_DEFINE(int, pf_vnet_active);
287 #define V_pf_vnet_active VNET(pf_vnet_active)
288
289 int pf_end_threads;
290 struct proc *pf_purge_proc;
291
292 VNET_DEFINE(struct rmlock, pf_rules_lock);
293 VNET_DEFINE_STATIC(struct sx, pf_ioctl_lock);
294 #define V_pf_ioctl_lock VNET(pf_ioctl_lock)
295 struct sx pf_end_lock;
296
297 /* pfsync */
298 VNET_DEFINE(pfsync_state_import_t *, pfsync_state_import_ptr);
299 VNET_DEFINE(pfsync_insert_state_t *, pfsync_insert_state_ptr);
300 VNET_DEFINE(pfsync_update_state_t *, pfsync_update_state_ptr);
301 VNET_DEFINE(pfsync_delete_state_t *, pfsync_delete_state_ptr);
302 VNET_DEFINE(pfsync_clear_states_t *, pfsync_clear_states_ptr);
303 VNET_DEFINE(pfsync_defer_t *, pfsync_defer_ptr);
304 VNET_DEFINE(pflow_export_state_t *, pflow_export_state_ptr);
305 pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr;
306
307 /* pflog */
308 pflog_packet_t *pflog_packet_ptr = NULL;
309
310 /*
311 * Copy a user-provided string, returning an error if truncation would occur.
312 * Avoid scanning past "sz" bytes in the source string since there's no
313 * guarantee that it's nul-terminated.
314 */
315 static int
pf_user_strcpy(char * dst,const char * src,size_t sz)316 pf_user_strcpy(char *dst, const char *src, size_t sz)
317 {
318 if (strnlen(src, sz) == sz)
319 return (EINVAL);
320 (void)strlcpy(dst, src, sz);
321 return (0);
322 }
323
324 static void
pfattach_vnet(void)325 pfattach_vnet(void)
326 {
327 u_int32_t *my_timeout = V_pf_default_rule.timeout;
328
329 bzero(&V_pf_status, sizeof(V_pf_status));
330
331 pf_initialize();
332 pfr_initialize();
333 pfi_initialize_vnet();
334 pf_normalize_init();
335 pf_syncookies_init();
336
337 V_pf_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
338 V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
339
340 RB_INIT(&V_pf_anchors);
341 pf_init_kruleset(&pf_main_ruleset);
342
343 pf_init_keth(V_pf_keth);
344
345 /* default rule should never be garbage collected */
346 V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next;
347 V_pf_default_rule.action = V_default_to_drop ? PF_DROP : PF_PASS;
348 V_pf_default_rule.nr = -1;
349 V_pf_default_rule.rtableid = -1;
350
351 pf_counter_u64_init(&V_pf_default_rule.evaluations, M_WAITOK);
352 for (int i = 0; i < 2; i++) {
353 pf_counter_u64_init(&V_pf_default_rule.packets[i], M_WAITOK);
354 pf_counter_u64_init(&V_pf_default_rule.bytes[i], M_WAITOK);
355 }
356 V_pf_default_rule.states_cur = counter_u64_alloc(M_WAITOK);
357 V_pf_default_rule.states_tot = counter_u64_alloc(M_WAITOK);
358 V_pf_default_rule.src_nodes = counter_u64_alloc(M_WAITOK);
359
360 V_pf_default_rule.timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
361 M_WAITOK | M_ZERO);
362
363 #ifdef PF_WANT_32_TO_64_COUNTER
364 V_pf_kifmarker = malloc(sizeof(*V_pf_kifmarker), PFI_MTYPE, M_WAITOK | M_ZERO);
365 V_pf_rulemarker = malloc(sizeof(*V_pf_rulemarker), M_PFRULE, M_WAITOK | M_ZERO);
366 PF_RULES_WLOCK();
367 LIST_INSERT_HEAD(&V_pf_allkiflist, V_pf_kifmarker, pfik_allkiflist);
368 LIST_INSERT_HEAD(&V_pf_allrulelist, &V_pf_default_rule, allrulelist);
369 V_pf_allrulecount++;
370 LIST_INSERT_HEAD(&V_pf_allrulelist, V_pf_rulemarker, allrulelist);
371 PF_RULES_WUNLOCK();
372 #endif
373
374 /* initialize default timeouts */
375 my_timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
376 my_timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
377 my_timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
378 my_timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
379 my_timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
380 my_timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
381 my_timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
382 my_timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL;
383 my_timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
384 my_timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL;
385 my_timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL;
386 my_timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
387 my_timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
388 my_timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
389 my_timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
390 my_timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
391 my_timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
392 my_timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
393 my_timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
394 my_timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
395 my_timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
396 my_timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
397 my_timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
398 my_timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
399 my_timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
400
401 V_pf_status.debug = PF_DEBUG_URGENT;
402 /*
403 * XXX This is different than in OpenBSD where reassembly is enabled by
404 * defult. In FreeBSD we expect people to still use scrub rules and
405 * switch to the new syntax later. Only when they switch they must
406 * explicitly enable reassemle. We could change the default once the
407 * scrub rule functionality is hopefully removed some day in future.
408 */
409 V_pf_status.reass = 0;
410
411 V_pf_pfil_hooked = false;
412 V_pf_pfil_eth_hooked = false;
413
414 /* XXX do our best to avoid a conflict */
415 V_pf_status.hostid = arc4random();
416
417 for (int i = 0; i < PFRES_MAX; i++)
418 V_pf_status.counters[i] = counter_u64_alloc(M_WAITOK);
419 for (int i = 0; i < KLCNT_MAX; i++)
420 V_pf_status.lcounters[i] = counter_u64_alloc(M_WAITOK);
421 for (int i = 0; i < FCNT_MAX; i++)
422 pf_counter_u64_init(&V_pf_status.fcounters[i], M_WAITOK);
423 for (int i = 0; i < SCNT_MAX; i++)
424 V_pf_status.scounters[i] = counter_u64_alloc(M_WAITOK);
425
426 if (swi_add(&V_pf_swi_ie, "pf send", pf_intr, curvnet, SWI_NET,
427 INTR_MPSAFE, &V_pf_swi_cookie) != 0)
428 /* XXXGL: leaked all above. */
429 return;
430 }
431
432 static struct pf_kpool *
pf_get_kpool(const char * anchor,u_int32_t ticket,u_int8_t rule_action,u_int32_t rule_number,u_int8_t r_last,u_int8_t active,u_int8_t check_ticket)433 pf_get_kpool(const char *anchor, u_int32_t ticket, u_int8_t rule_action,
434 u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
435 u_int8_t check_ticket)
436 {
437 struct pf_kruleset *ruleset;
438 struct pf_krule *rule;
439 int rs_num;
440
441 ruleset = pf_find_kruleset(anchor);
442 if (ruleset == NULL)
443 return (NULL);
444 rs_num = pf_get_ruleset_number(rule_action);
445 if (rs_num >= PF_RULESET_MAX)
446 return (NULL);
447 if (active) {
448 if (check_ticket && ticket !=
449 ruleset->rules[rs_num].active.ticket)
450 return (NULL);
451 if (r_last)
452 rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
453 pf_krulequeue);
454 else
455 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
456 } else {
457 if (check_ticket && ticket !=
458 ruleset->rules[rs_num].inactive.ticket)
459 return (NULL);
460 if (r_last)
461 rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
462 pf_krulequeue);
463 else
464 rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
465 }
466 if (!r_last) {
467 while ((rule != NULL) && (rule->nr != rule_number))
468 rule = TAILQ_NEXT(rule, entries);
469 }
470 if (rule == NULL)
471 return (NULL);
472
473 return (&rule->rpool);
474 }
475
476 static void
pf_mv_kpool(struct pf_kpalist * poola,struct pf_kpalist * poolb)477 pf_mv_kpool(struct pf_kpalist *poola, struct pf_kpalist *poolb)
478 {
479 struct pf_kpooladdr *mv_pool_pa;
480
481 while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
482 TAILQ_REMOVE(poola, mv_pool_pa, entries);
483 TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
484 }
485 }
486
487 static void
pf_empty_kpool(struct pf_kpalist * poola)488 pf_empty_kpool(struct pf_kpalist *poola)
489 {
490 struct pf_kpooladdr *pa;
491
492 while ((pa = TAILQ_FIRST(poola)) != NULL) {
493 switch (pa->addr.type) {
494 case PF_ADDR_DYNIFTL:
495 pfi_dynaddr_remove(pa->addr.p.dyn);
496 break;
497 case PF_ADDR_TABLE:
498 /* XXX: this could be unfinished pooladdr on pabuf */
499 if (pa->addr.p.tbl != NULL)
500 pfr_detach_table(pa->addr.p.tbl);
501 break;
502 }
503 if (pa->kif)
504 pfi_kkif_unref(pa->kif);
505 TAILQ_REMOVE(poola, pa, entries);
506 free(pa, M_PFRULE);
507 }
508 }
509
510 static void
pf_unlink_rule_locked(struct pf_krulequeue * rulequeue,struct pf_krule * rule)511 pf_unlink_rule_locked(struct pf_krulequeue *rulequeue, struct pf_krule *rule)
512 {
513
514 PF_RULES_WASSERT();
515 PF_UNLNKDRULES_ASSERT();
516
517 TAILQ_REMOVE(rulequeue, rule, entries);
518
519 rule->rule_ref |= PFRULE_REFS;
520 TAILQ_INSERT_TAIL(&V_pf_unlinked_rules, rule, entries);
521 }
522
523 static void
pf_unlink_rule(struct pf_krulequeue * rulequeue,struct pf_krule * rule)524 pf_unlink_rule(struct pf_krulequeue *rulequeue, struct pf_krule *rule)
525 {
526
527 PF_RULES_WASSERT();
528
529 PF_UNLNKDRULES_LOCK();
530 pf_unlink_rule_locked(rulequeue, rule);
531 PF_UNLNKDRULES_UNLOCK();
532 }
533
534 static void
pf_free_eth_rule(struct pf_keth_rule * rule)535 pf_free_eth_rule(struct pf_keth_rule *rule)
536 {
537 PF_RULES_WASSERT();
538
539 if (rule == NULL)
540 return;
541
542 if (rule->tag)
543 tag_unref(&V_pf_tags, rule->tag);
544 if (rule->match_tag)
545 tag_unref(&V_pf_tags, rule->match_tag);
546 #ifdef ALTQ
547 pf_qid_unref(rule->qid);
548 #endif
549
550 if (rule->bridge_to)
551 pfi_kkif_unref(rule->bridge_to);
552 if (rule->kif)
553 pfi_kkif_unref(rule->kif);
554
555 if (rule->ipsrc.addr.type == PF_ADDR_TABLE)
556 pfr_detach_table(rule->ipsrc.addr.p.tbl);
557 if (rule->ipdst.addr.type == PF_ADDR_TABLE)
558 pfr_detach_table(rule->ipdst.addr.p.tbl);
559
560 counter_u64_free(rule->evaluations);
561 for (int i = 0; i < 2; i++) {
562 counter_u64_free(rule->packets[i]);
563 counter_u64_free(rule->bytes[i]);
564 }
565 uma_zfree_pcpu(pf_timestamp_pcpu_zone, rule->timestamp);
566 pf_keth_anchor_remove(rule);
567
568 free(rule, M_PFRULE);
569 }
570
571 void
pf_free_rule(struct pf_krule * rule)572 pf_free_rule(struct pf_krule *rule)
573 {
574
575 PF_RULES_WASSERT();
576 PF_CONFIG_ASSERT();
577
578 if (rule->tag)
579 tag_unref(&V_pf_tags, rule->tag);
580 if (rule->match_tag)
581 tag_unref(&V_pf_tags, rule->match_tag);
582 #ifdef ALTQ
583 if (rule->pqid != rule->qid)
584 pf_qid_unref(rule->pqid);
585 pf_qid_unref(rule->qid);
586 #endif
587 switch (rule->src.addr.type) {
588 case PF_ADDR_DYNIFTL:
589 pfi_dynaddr_remove(rule->src.addr.p.dyn);
590 break;
591 case PF_ADDR_TABLE:
592 pfr_detach_table(rule->src.addr.p.tbl);
593 break;
594 }
595 switch (rule->dst.addr.type) {
596 case PF_ADDR_DYNIFTL:
597 pfi_dynaddr_remove(rule->dst.addr.p.dyn);
598 break;
599 case PF_ADDR_TABLE:
600 pfr_detach_table(rule->dst.addr.p.tbl);
601 break;
602 }
603 if (rule->overload_tbl)
604 pfr_detach_table(rule->overload_tbl);
605 if (rule->kif)
606 pfi_kkif_unref(rule->kif);
607 pf_kanchor_remove(rule);
608 pf_empty_kpool(&rule->rpool.list);
609
610 pf_krule_free(rule);
611 }
612
613 static void
pf_init_tagset(struct pf_tagset * ts,unsigned int * tunable_size,unsigned int default_size)614 pf_init_tagset(struct pf_tagset *ts, unsigned int *tunable_size,
615 unsigned int default_size)
616 {
617 unsigned int i;
618 unsigned int hashsize;
619
620 if (*tunable_size == 0 || !powerof2(*tunable_size))
621 *tunable_size = default_size;
622
623 hashsize = *tunable_size;
624 ts->namehash = mallocarray(hashsize, sizeof(*ts->namehash), M_PFHASH,
625 M_WAITOK);
626 ts->taghash = mallocarray(hashsize, sizeof(*ts->taghash), M_PFHASH,
627 M_WAITOK);
628 ts->mask = hashsize - 1;
629 ts->seed = arc4random();
630 for (i = 0; i < hashsize; i++) {
631 TAILQ_INIT(&ts->namehash[i]);
632 TAILQ_INIT(&ts->taghash[i]);
633 }
634 BIT_FILL(TAGID_MAX, &ts->avail);
635 }
636
637 static void
pf_cleanup_tagset(struct pf_tagset * ts)638 pf_cleanup_tagset(struct pf_tagset *ts)
639 {
640 unsigned int i;
641 unsigned int hashsize;
642 struct pf_tagname *t, *tmp;
643
644 /*
645 * Only need to clean up one of the hashes as each tag is hashed
646 * into each table.
647 */
648 hashsize = ts->mask + 1;
649 for (i = 0; i < hashsize; i++)
650 TAILQ_FOREACH_SAFE(t, &ts->namehash[i], namehash_entries, tmp)
651 uma_zfree(V_pf_tag_z, t);
652
653 free(ts->namehash, M_PFHASH);
654 free(ts->taghash, M_PFHASH);
655 }
656
657 static uint16_t
tagname2hashindex(const struct pf_tagset * ts,const char * tagname)658 tagname2hashindex(const struct pf_tagset *ts, const char *tagname)
659 {
660 size_t len;
661
662 len = strnlen(tagname, PF_TAG_NAME_SIZE - 1);
663 return (murmur3_32_hash(tagname, len, ts->seed) & ts->mask);
664 }
665
666 static uint16_t
tag2hashindex(const struct pf_tagset * ts,uint16_t tag)667 tag2hashindex(const struct pf_tagset *ts, uint16_t tag)
668 {
669
670 return (tag & ts->mask);
671 }
672
673 static u_int16_t
tagname2tag(struct pf_tagset * ts,const char * tagname)674 tagname2tag(struct pf_tagset *ts, const char *tagname)
675 {
676 struct pf_tagname *tag;
677 u_int32_t index;
678 u_int16_t new_tagid;
679
680 PF_RULES_WASSERT();
681
682 index = tagname2hashindex(ts, tagname);
683 TAILQ_FOREACH(tag, &ts->namehash[index], namehash_entries)
684 if (strcmp(tagname, tag->name) == 0) {
685 tag->ref++;
686 return (tag->tag);
687 }
688
689 /*
690 * new entry
691 *
692 * to avoid fragmentation, we do a linear search from the beginning
693 * and take the first free slot we find.
694 */
695 new_tagid = BIT_FFS(TAGID_MAX, &ts->avail);
696 /*
697 * Tags are 1-based, with valid tags in the range [1..TAGID_MAX].
698 * BIT_FFS() returns a 1-based bit number, with 0 indicating no bits
699 * set. It may also return a bit number greater than TAGID_MAX due
700 * to rounding of the number of bits in the vector up to a multiple
701 * of the vector word size at declaration/allocation time.
702 */
703 if ((new_tagid == 0) || (new_tagid > TAGID_MAX))
704 return (0);
705
706 /* Mark the tag as in use. Bits are 0-based for BIT_CLR() */
707 BIT_CLR(TAGID_MAX, new_tagid - 1, &ts->avail);
708
709 /* allocate and fill new struct pf_tagname */
710 tag = uma_zalloc(V_pf_tag_z, M_NOWAIT);
711 if (tag == NULL)
712 return (0);
713 strlcpy(tag->name, tagname, sizeof(tag->name));
714 tag->tag = new_tagid;
715 tag->ref = 1;
716
717 /* Insert into namehash */
718 TAILQ_INSERT_TAIL(&ts->namehash[index], tag, namehash_entries);
719
720 /* Insert into taghash */
721 index = tag2hashindex(ts, new_tagid);
722 TAILQ_INSERT_TAIL(&ts->taghash[index], tag, taghash_entries);
723
724 return (tag->tag);
725 }
726
727 static void
tag_unref(struct pf_tagset * ts,u_int16_t tag)728 tag_unref(struct pf_tagset *ts, u_int16_t tag)
729 {
730 struct pf_tagname *t;
731 uint16_t index;
732
733 PF_RULES_WASSERT();
734
735 index = tag2hashindex(ts, tag);
736 TAILQ_FOREACH(t, &ts->taghash[index], taghash_entries)
737 if (tag == t->tag) {
738 if (--t->ref == 0) {
739 TAILQ_REMOVE(&ts->taghash[index], t,
740 taghash_entries);
741 index = tagname2hashindex(ts, t->name);
742 TAILQ_REMOVE(&ts->namehash[index], t,
743 namehash_entries);
744 /* Bits are 0-based for BIT_SET() */
745 BIT_SET(TAGID_MAX, tag - 1, &ts->avail);
746 uma_zfree(V_pf_tag_z, t);
747 }
748 break;
749 }
750 }
751
752 static uint16_t
pf_tagname2tag(const char * tagname)753 pf_tagname2tag(const char *tagname)
754 {
755 return (tagname2tag(&V_pf_tags, tagname));
756 }
757
758 static int
pf_begin_eth(uint32_t * ticket,const char * anchor)759 pf_begin_eth(uint32_t *ticket, const char *anchor)
760 {
761 struct pf_keth_rule *rule, *tmp;
762 struct pf_keth_ruleset *rs;
763
764 PF_RULES_WASSERT();
765
766 rs = pf_find_or_create_keth_ruleset(anchor);
767 if (rs == NULL)
768 return (EINVAL);
769
770 /* Purge old inactive rules. */
771 TAILQ_FOREACH_SAFE(rule, rs->inactive.rules, entries,
772 tmp) {
773 TAILQ_REMOVE(rs->inactive.rules, rule,
774 entries);
775 pf_free_eth_rule(rule);
776 }
777
778 *ticket = ++rs->inactive.ticket;
779 rs->inactive.open = 1;
780
781 return (0);
782 }
783
784 static void
pf_rollback_eth_cb(struct epoch_context * ctx)785 pf_rollback_eth_cb(struct epoch_context *ctx)
786 {
787 struct pf_keth_ruleset *rs;
788
789 rs = __containerof(ctx, struct pf_keth_ruleset, epoch_ctx);
790
791 CURVNET_SET(rs->vnet);
792
793 PF_RULES_WLOCK();
794 pf_rollback_eth(rs->inactive.ticket,
795 rs->anchor ? rs->anchor->path : "");
796 PF_RULES_WUNLOCK();
797
798 CURVNET_RESTORE();
799 }
800
801 static int
pf_rollback_eth(uint32_t ticket,const char * anchor)802 pf_rollback_eth(uint32_t ticket, const char *anchor)
803 {
804 struct pf_keth_rule *rule, *tmp;
805 struct pf_keth_ruleset *rs;
806
807 PF_RULES_WASSERT();
808
809 rs = pf_find_keth_ruleset(anchor);
810 if (rs == NULL)
811 return (EINVAL);
812
813 if (!rs->inactive.open ||
814 ticket != rs->inactive.ticket)
815 return (0);
816
817 /* Purge old inactive rules. */
818 TAILQ_FOREACH_SAFE(rule, rs->inactive.rules, entries,
819 tmp) {
820 TAILQ_REMOVE(rs->inactive.rules, rule, entries);
821 pf_free_eth_rule(rule);
822 }
823
824 rs->inactive.open = 0;
825
826 pf_remove_if_empty_keth_ruleset(rs);
827
828 return (0);
829 }
830
831 #define PF_SET_SKIP_STEPS(i) \
832 do { \
833 while (head[i] != cur) { \
834 head[i]->skip[i].ptr = cur; \
835 head[i] = TAILQ_NEXT(head[i], entries); \
836 } \
837 } while (0)
838
839 static void
pf_eth_calc_skip_steps(struct pf_keth_ruleq * rules)840 pf_eth_calc_skip_steps(struct pf_keth_ruleq *rules)
841 {
842 struct pf_keth_rule *cur, *prev, *head[PFE_SKIP_COUNT];
843 int i;
844
845 cur = TAILQ_FIRST(rules);
846 prev = cur;
847 for (i = 0; i < PFE_SKIP_COUNT; ++i)
848 head[i] = cur;
849 while (cur != NULL) {
850 if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
851 PF_SET_SKIP_STEPS(PFE_SKIP_IFP);
852 if (cur->direction != prev->direction)
853 PF_SET_SKIP_STEPS(PFE_SKIP_DIR);
854 if (cur->proto != prev->proto)
855 PF_SET_SKIP_STEPS(PFE_SKIP_PROTO);
856 if (memcmp(&cur->src, &prev->src, sizeof(cur->src)) != 0)
857 PF_SET_SKIP_STEPS(PFE_SKIP_SRC_ADDR);
858 if (memcmp(&cur->dst, &prev->dst, sizeof(cur->dst)) != 0)
859 PF_SET_SKIP_STEPS(PFE_SKIP_DST_ADDR);
860 if (cur->ipsrc.neg != prev->ipsrc.neg ||
861 pf_addr_wrap_neq(&cur->ipsrc.addr, &prev->ipsrc.addr))
862 PF_SET_SKIP_STEPS(PFE_SKIP_SRC_IP_ADDR);
863 if (cur->ipdst.neg != prev->ipdst.neg ||
864 pf_addr_wrap_neq(&cur->ipdst.addr, &prev->ipdst.addr))
865 PF_SET_SKIP_STEPS(PFE_SKIP_DST_IP_ADDR);
866
867 prev = cur;
868 cur = TAILQ_NEXT(cur, entries);
869 }
870 for (i = 0; i < PFE_SKIP_COUNT; ++i)
871 PF_SET_SKIP_STEPS(i);
872 }
873
874 static int
pf_commit_eth(uint32_t ticket,const char * anchor)875 pf_commit_eth(uint32_t ticket, const char *anchor)
876 {
877 struct pf_keth_ruleq *rules;
878 struct pf_keth_ruleset *rs;
879
880 rs = pf_find_keth_ruleset(anchor);
881 if (rs == NULL) {
882 return (EINVAL);
883 }
884
885 if (!rs->inactive.open ||
886 ticket != rs->inactive.ticket)
887 return (EBUSY);
888
889 PF_RULES_WASSERT();
890
891 pf_eth_calc_skip_steps(rs->inactive.rules);
892
893 rules = rs->active.rules;
894 ck_pr_store_ptr(&rs->active.rules, rs->inactive.rules);
895 rs->inactive.rules = rules;
896 rs->inactive.ticket = rs->active.ticket;
897
898 /* Clean up inactive rules (i.e. previously active rules), only when
899 * we're sure they're no longer used. */
900 NET_EPOCH_CALL(pf_rollback_eth_cb, &rs->epoch_ctx);
901
902 return (0);
903 }
904
905 #ifdef ALTQ
906 static uint16_t
pf_qname2qid(const char * qname)907 pf_qname2qid(const char *qname)
908 {
909 return (tagname2tag(&V_pf_qids, qname));
910 }
911
912 static void
pf_qid_unref(uint16_t qid)913 pf_qid_unref(uint16_t qid)
914 {
915 tag_unref(&V_pf_qids, qid);
916 }
917
918 static int
pf_begin_altq(u_int32_t * ticket)919 pf_begin_altq(u_int32_t *ticket)
920 {
921 struct pf_altq *altq, *tmp;
922 int error = 0;
923
924 PF_RULES_WASSERT();
925
926 /* Purge the old altq lists */
927 TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
928 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
929 /* detach and destroy the discipline */
930 error = altq_remove(altq);
931 }
932 free(altq, M_PFALTQ);
933 }
934 TAILQ_INIT(V_pf_altq_ifs_inactive);
935 TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
936 pf_qid_unref(altq->qid);
937 free(altq, M_PFALTQ);
938 }
939 TAILQ_INIT(V_pf_altqs_inactive);
940 if (error)
941 return (error);
942 *ticket = ++V_ticket_altqs_inactive;
943 V_altqs_inactive_open = 1;
944 return (0);
945 }
946
947 static int
pf_rollback_altq(u_int32_t ticket)948 pf_rollback_altq(u_int32_t ticket)
949 {
950 struct pf_altq *altq, *tmp;
951 int error = 0;
952
953 PF_RULES_WASSERT();
954
955 if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
956 return (0);
957 /* Purge the old altq lists */
958 TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
959 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
960 /* detach and destroy the discipline */
961 error = altq_remove(altq);
962 }
963 free(altq, M_PFALTQ);
964 }
965 TAILQ_INIT(V_pf_altq_ifs_inactive);
966 TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
967 pf_qid_unref(altq->qid);
968 free(altq, M_PFALTQ);
969 }
970 TAILQ_INIT(V_pf_altqs_inactive);
971 V_altqs_inactive_open = 0;
972 return (error);
973 }
974
975 static int
pf_commit_altq(u_int32_t ticket)976 pf_commit_altq(u_int32_t ticket)
977 {
978 struct pf_altqqueue *old_altqs, *old_altq_ifs;
979 struct pf_altq *altq, *tmp;
980 int err, error = 0;
981
982 PF_RULES_WASSERT();
983
984 if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
985 return (EBUSY);
986
987 /* swap altqs, keep the old. */
988 old_altqs = V_pf_altqs_active;
989 old_altq_ifs = V_pf_altq_ifs_active;
990 V_pf_altqs_active = V_pf_altqs_inactive;
991 V_pf_altq_ifs_active = V_pf_altq_ifs_inactive;
992 V_pf_altqs_inactive = old_altqs;
993 V_pf_altq_ifs_inactive = old_altq_ifs;
994 V_ticket_altqs_active = V_ticket_altqs_inactive;
995
996 /* Attach new disciplines */
997 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
998 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
999 /* attach the discipline */
1000 error = altq_pfattach(altq);
1001 if (error == 0 && V_pf_altq_running)
1002 error = pf_enable_altq(altq);
1003 if (error != 0)
1004 return (error);
1005 }
1006 }
1007
1008 /* Purge the old altq lists */
1009 TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
1010 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
1011 /* detach and destroy the discipline */
1012 if (V_pf_altq_running)
1013 error = pf_disable_altq(altq);
1014 err = altq_pfdetach(altq);
1015 if (err != 0 && error == 0)
1016 error = err;
1017 err = altq_remove(altq);
1018 if (err != 0 && error == 0)
1019 error = err;
1020 }
1021 free(altq, M_PFALTQ);
1022 }
1023 TAILQ_INIT(V_pf_altq_ifs_inactive);
1024 TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
1025 pf_qid_unref(altq->qid);
1026 free(altq, M_PFALTQ);
1027 }
1028 TAILQ_INIT(V_pf_altqs_inactive);
1029
1030 V_altqs_inactive_open = 0;
1031 return (error);
1032 }
1033
1034 static int
pf_enable_altq(struct pf_altq * altq)1035 pf_enable_altq(struct pf_altq *altq)
1036 {
1037 struct ifnet *ifp;
1038 struct tb_profile tb;
1039 int error = 0;
1040
1041 if ((ifp = ifunit(altq->ifname)) == NULL)
1042 return (EINVAL);
1043
1044 if (ifp->if_snd.altq_type != ALTQT_NONE)
1045 error = altq_enable(&ifp->if_snd);
1046
1047 /* set tokenbucket regulator */
1048 if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
1049 tb.rate = altq->ifbandwidth;
1050 tb.depth = altq->tbrsize;
1051 error = tbr_set(&ifp->if_snd, &tb);
1052 }
1053
1054 return (error);
1055 }
1056
1057 static int
pf_disable_altq(struct pf_altq * altq)1058 pf_disable_altq(struct pf_altq *altq)
1059 {
1060 struct ifnet *ifp;
1061 struct tb_profile tb;
1062 int error;
1063
1064 if ((ifp = ifunit(altq->ifname)) == NULL)
1065 return (EINVAL);
1066
1067 /*
1068 * when the discipline is no longer referenced, it was overridden
1069 * by a new one. if so, just return.
1070 */
1071 if (altq->altq_disc != ifp->if_snd.altq_disc)
1072 return (0);
1073
1074 error = altq_disable(&ifp->if_snd);
1075
1076 if (error == 0) {
1077 /* clear tokenbucket regulator */
1078 tb.rate = 0;
1079 error = tbr_set(&ifp->if_snd, &tb);
1080 }
1081
1082 return (error);
1083 }
1084
1085 static int
pf_altq_ifnet_event_add(struct ifnet * ifp,int remove,u_int32_t ticket,struct pf_altq * altq)1086 pf_altq_ifnet_event_add(struct ifnet *ifp, int remove, u_int32_t ticket,
1087 struct pf_altq *altq)
1088 {
1089 struct ifnet *ifp1;
1090 int error = 0;
1091
1092 /* Deactivate the interface in question */
1093 altq->local_flags &= ~PFALTQ_FLAG_IF_REMOVED;
1094 if ((ifp1 = ifunit(altq->ifname)) == NULL ||
1095 (remove && ifp1 == ifp)) {
1096 altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
1097 } else {
1098 error = altq_add(ifp1, altq);
1099
1100 if (ticket != V_ticket_altqs_inactive)
1101 error = EBUSY;
1102
1103 if (error)
1104 free(altq, M_PFALTQ);
1105 }
1106
1107 return (error);
1108 }
1109
1110 void
pf_altq_ifnet_event(struct ifnet * ifp,int remove)1111 pf_altq_ifnet_event(struct ifnet *ifp, int remove)
1112 {
1113 struct pf_altq *a1, *a2, *a3;
1114 u_int32_t ticket;
1115 int error = 0;
1116
1117 /*
1118 * No need to re-evaluate the configuration for events on interfaces
1119 * that do not support ALTQ, as it's not possible for such
1120 * interfaces to be part of the configuration.
1121 */
1122 if (!ALTQ_IS_READY(&ifp->if_snd))
1123 return;
1124
1125 /* Interrupt userland queue modifications */
1126 if (V_altqs_inactive_open)
1127 pf_rollback_altq(V_ticket_altqs_inactive);
1128
1129 /* Start new altq ruleset */
1130 if (pf_begin_altq(&ticket))
1131 return;
1132
1133 /* Copy the current active set */
1134 TAILQ_FOREACH(a1, V_pf_altq_ifs_active, entries) {
1135 a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT);
1136 if (a2 == NULL) {
1137 error = ENOMEM;
1138 break;
1139 }
1140 bcopy(a1, a2, sizeof(struct pf_altq));
1141
1142 error = pf_altq_ifnet_event_add(ifp, remove, ticket, a2);
1143 if (error)
1144 break;
1145
1146 TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, a2, entries);
1147 }
1148 if (error)
1149 goto out;
1150 TAILQ_FOREACH(a1, V_pf_altqs_active, entries) {
1151 a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT);
1152 if (a2 == NULL) {
1153 error = ENOMEM;
1154 break;
1155 }
1156 bcopy(a1, a2, sizeof(struct pf_altq));
1157
1158 if ((a2->qid = pf_qname2qid(a2->qname)) == 0) {
1159 error = EBUSY;
1160 free(a2, M_PFALTQ);
1161 break;
1162 }
1163 a2->altq_disc = NULL;
1164 TAILQ_FOREACH(a3, V_pf_altq_ifs_inactive, entries) {
1165 if (strncmp(a3->ifname, a2->ifname,
1166 IFNAMSIZ) == 0) {
1167 a2->altq_disc = a3->altq_disc;
1168 break;
1169 }
1170 }
1171 error = pf_altq_ifnet_event_add(ifp, remove, ticket, a2);
1172 if (error)
1173 break;
1174
1175 TAILQ_INSERT_TAIL(V_pf_altqs_inactive, a2, entries);
1176 }
1177
1178 out:
1179 if (error != 0)
1180 pf_rollback_altq(ticket);
1181 else
1182 pf_commit_altq(ticket);
1183 }
1184 #endif /* ALTQ */
1185
1186 static struct pf_krule_global *
pf_rule_tree_alloc(int flags)1187 pf_rule_tree_alloc(int flags)
1188 {
1189 struct pf_krule_global *tree;
1190
1191 tree = malloc(sizeof(struct pf_krule_global), M_TEMP, flags);
1192 if (tree == NULL)
1193 return (NULL);
1194 RB_INIT(tree);
1195 return (tree);
1196 }
1197
1198 static void
pf_rule_tree_free(struct pf_krule_global * tree)1199 pf_rule_tree_free(struct pf_krule_global *tree)
1200 {
1201
1202 free(tree, M_TEMP);
1203 }
1204
1205 static int
pf_begin_rules(u_int32_t * ticket,int rs_num,const char * anchor)1206 pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
1207 {
1208 struct pf_krule_global *tree;
1209 struct pf_kruleset *rs;
1210 struct pf_krule *rule;
1211
1212 PF_RULES_WASSERT();
1213
1214 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1215 return (EINVAL);
1216 tree = pf_rule_tree_alloc(M_NOWAIT);
1217 if (tree == NULL)
1218 return (ENOMEM);
1219 rs = pf_find_or_create_kruleset(anchor);
1220 if (rs == NULL) {
1221 free(tree, M_TEMP);
1222 return (EINVAL);
1223 }
1224 pf_rule_tree_free(rs->rules[rs_num].inactive.tree);
1225 rs->rules[rs_num].inactive.tree = tree;
1226
1227 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
1228 pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule);
1229 rs->rules[rs_num].inactive.rcount--;
1230 }
1231 *ticket = ++rs->rules[rs_num].inactive.ticket;
1232 rs->rules[rs_num].inactive.open = 1;
1233 return (0);
1234 }
1235
1236 static int
pf_rollback_rules(u_int32_t ticket,int rs_num,char * anchor)1237 pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
1238 {
1239 struct pf_kruleset *rs;
1240 struct pf_krule *rule;
1241
1242 PF_RULES_WASSERT();
1243
1244 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1245 return (EINVAL);
1246 rs = pf_find_kruleset(anchor);
1247 if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1248 rs->rules[rs_num].inactive.ticket != ticket)
1249 return (0);
1250 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
1251 pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule);
1252 rs->rules[rs_num].inactive.rcount--;
1253 }
1254 rs->rules[rs_num].inactive.open = 0;
1255 return (0);
1256 }
1257
1258 #define PF_MD5_UPD(st, elm) \
1259 MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
1260
1261 #define PF_MD5_UPD_STR(st, elm) \
1262 MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
1263
1264 #define PF_MD5_UPD_HTONL(st, elm, stor) do { \
1265 (stor) = htonl((st)->elm); \
1266 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
1267 } while (0)
1268
1269 #define PF_MD5_UPD_HTONS(st, elm, stor) do { \
1270 (stor) = htons((st)->elm); \
1271 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
1272 } while (0)
1273
1274 static void
pf_hash_rule_addr(MD5_CTX * ctx,struct pf_rule_addr * pfr)1275 pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
1276 {
1277 PF_MD5_UPD(pfr, addr.type);
1278 switch (pfr->addr.type) {
1279 case PF_ADDR_DYNIFTL:
1280 PF_MD5_UPD(pfr, addr.v.ifname);
1281 PF_MD5_UPD(pfr, addr.iflags);
1282 break;
1283 case PF_ADDR_TABLE:
1284 PF_MD5_UPD(pfr, addr.v.tblname);
1285 break;
1286 case PF_ADDR_ADDRMASK:
1287 /* XXX ignore af? */
1288 PF_MD5_UPD(pfr, addr.v.a.addr.addr32);
1289 PF_MD5_UPD(pfr, addr.v.a.mask.addr32);
1290 break;
1291 }
1292
1293 PF_MD5_UPD(pfr, port[0]);
1294 PF_MD5_UPD(pfr, port[1]);
1295 PF_MD5_UPD(pfr, neg);
1296 PF_MD5_UPD(pfr, port_op);
1297 }
1298
1299 static void
pf_hash_rule_rolling(MD5_CTX * ctx,struct pf_krule * rule)1300 pf_hash_rule_rolling(MD5_CTX *ctx, struct pf_krule *rule)
1301 {
1302 u_int16_t x;
1303 u_int32_t y;
1304
1305 pf_hash_rule_addr(ctx, &rule->src);
1306 pf_hash_rule_addr(ctx, &rule->dst);
1307 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
1308 PF_MD5_UPD_STR(rule, label[i]);
1309 PF_MD5_UPD_STR(rule, ifname);
1310 PF_MD5_UPD_STR(rule, match_tagname);
1311 PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */
1312 PF_MD5_UPD_HTONL(rule, os_fingerprint, y);
1313 PF_MD5_UPD_HTONL(rule, prob, y);
1314 PF_MD5_UPD_HTONL(rule, uid.uid[0], y);
1315 PF_MD5_UPD_HTONL(rule, uid.uid[1], y);
1316 PF_MD5_UPD(rule, uid.op);
1317 PF_MD5_UPD_HTONL(rule, gid.gid[0], y);
1318 PF_MD5_UPD_HTONL(rule, gid.gid[1], y);
1319 PF_MD5_UPD(rule, gid.op);
1320 PF_MD5_UPD_HTONL(rule, rule_flag, y);
1321 PF_MD5_UPD(rule, action);
1322 PF_MD5_UPD(rule, direction);
1323 PF_MD5_UPD(rule, af);
1324 PF_MD5_UPD(rule, quick);
1325 PF_MD5_UPD(rule, ifnot);
1326 PF_MD5_UPD(rule, match_tag_not);
1327 PF_MD5_UPD(rule, natpass);
1328 PF_MD5_UPD(rule, keep_state);
1329 PF_MD5_UPD(rule, proto);
1330 PF_MD5_UPD(rule, type);
1331 PF_MD5_UPD(rule, code);
1332 PF_MD5_UPD(rule, flags);
1333 PF_MD5_UPD(rule, flagset);
1334 PF_MD5_UPD(rule, allow_opts);
1335 PF_MD5_UPD(rule, rt);
1336 PF_MD5_UPD(rule, tos);
1337 PF_MD5_UPD(rule, scrub_flags);
1338 PF_MD5_UPD(rule, min_ttl);
1339 PF_MD5_UPD(rule, set_tos);
1340 if (rule->anchor != NULL)
1341 PF_MD5_UPD_STR(rule, anchor->path);
1342 }
1343
1344 static void
pf_hash_rule(struct pf_krule * rule)1345 pf_hash_rule(struct pf_krule *rule)
1346 {
1347 MD5_CTX ctx;
1348
1349 MD5Init(&ctx);
1350 pf_hash_rule_rolling(&ctx, rule);
1351 MD5Final(rule->md5sum, &ctx);
1352 }
1353
1354 static int
pf_krule_compare(struct pf_krule * a,struct pf_krule * b)1355 pf_krule_compare(struct pf_krule *a, struct pf_krule *b)
1356 {
1357
1358 return (memcmp(a->md5sum, b->md5sum, PF_MD5_DIGEST_LENGTH));
1359 }
1360
1361 static int
pf_commit_rules(u_int32_t ticket,int rs_num,char * anchor)1362 pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
1363 {
1364 struct pf_kruleset *rs;
1365 struct pf_krule *rule, **old_array, *old_rule;
1366 struct pf_krulequeue *old_rules;
1367 struct pf_krule_global *old_tree;
1368 int error;
1369 u_int32_t old_rcount;
1370
1371 PF_RULES_WASSERT();
1372
1373 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1374 return (EINVAL);
1375 rs = pf_find_kruleset(anchor);
1376 if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1377 ticket != rs->rules[rs_num].inactive.ticket)
1378 return (EBUSY);
1379
1380 /* Calculate checksum for the main ruleset */
1381 if (rs == &pf_main_ruleset) {
1382 error = pf_setup_pfsync_matching(rs);
1383 if (error != 0)
1384 return (error);
1385 }
1386
1387 /* Swap rules, keep the old. */
1388 old_rules = rs->rules[rs_num].active.ptr;
1389 old_rcount = rs->rules[rs_num].active.rcount;
1390 old_array = rs->rules[rs_num].active.ptr_array;
1391 old_tree = rs->rules[rs_num].active.tree;
1392
1393 rs->rules[rs_num].active.ptr =
1394 rs->rules[rs_num].inactive.ptr;
1395 rs->rules[rs_num].active.ptr_array =
1396 rs->rules[rs_num].inactive.ptr_array;
1397 rs->rules[rs_num].active.tree =
1398 rs->rules[rs_num].inactive.tree;
1399 rs->rules[rs_num].active.rcount =
1400 rs->rules[rs_num].inactive.rcount;
1401
1402 /* Attempt to preserve counter information. */
1403 if (V_pf_status.keep_counters && old_tree != NULL) {
1404 TAILQ_FOREACH(rule, rs->rules[rs_num].active.ptr,
1405 entries) {
1406 old_rule = RB_FIND(pf_krule_global, old_tree, rule);
1407 if (old_rule == NULL) {
1408 continue;
1409 }
1410 pf_counter_u64_critical_enter();
1411 pf_counter_u64_add_protected(&rule->evaluations,
1412 pf_counter_u64_fetch(&old_rule->evaluations));
1413 pf_counter_u64_add_protected(&rule->packets[0],
1414 pf_counter_u64_fetch(&old_rule->packets[0]));
1415 pf_counter_u64_add_protected(&rule->packets[1],
1416 pf_counter_u64_fetch(&old_rule->packets[1]));
1417 pf_counter_u64_add_protected(&rule->bytes[0],
1418 pf_counter_u64_fetch(&old_rule->bytes[0]));
1419 pf_counter_u64_add_protected(&rule->bytes[1],
1420 pf_counter_u64_fetch(&old_rule->bytes[1]));
1421 pf_counter_u64_critical_exit();
1422 }
1423 }
1424
1425 rs->rules[rs_num].inactive.ptr = old_rules;
1426 rs->rules[rs_num].inactive.ptr_array = old_array;
1427 rs->rules[rs_num].inactive.tree = NULL; /* important for pf_ioctl_addrule */
1428 rs->rules[rs_num].inactive.rcount = old_rcount;
1429
1430 rs->rules[rs_num].active.ticket =
1431 rs->rules[rs_num].inactive.ticket;
1432 pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
1433
1434 /* Purge the old rule list. */
1435 PF_UNLNKDRULES_LOCK();
1436 while ((rule = TAILQ_FIRST(old_rules)) != NULL)
1437 pf_unlink_rule_locked(old_rules, rule);
1438 PF_UNLNKDRULES_UNLOCK();
1439 if (rs->rules[rs_num].inactive.ptr_array)
1440 free(rs->rules[rs_num].inactive.ptr_array, M_TEMP);
1441 rs->rules[rs_num].inactive.ptr_array = NULL;
1442 rs->rules[rs_num].inactive.rcount = 0;
1443 rs->rules[rs_num].inactive.open = 0;
1444 pf_remove_if_empty_kruleset(rs);
1445 free(old_tree, M_TEMP);
1446
1447 return (0);
1448 }
1449
1450 static int
pf_setup_pfsync_matching(struct pf_kruleset * rs)1451 pf_setup_pfsync_matching(struct pf_kruleset *rs)
1452 {
1453 MD5_CTX ctx;
1454 struct pf_krule *rule;
1455 int rs_cnt;
1456 u_int8_t digest[PF_MD5_DIGEST_LENGTH];
1457
1458 MD5Init(&ctx);
1459 for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
1460 /* XXX PF_RULESET_SCRUB as well? */
1461 if (rs_cnt == PF_RULESET_SCRUB)
1462 continue;
1463
1464 if (rs->rules[rs_cnt].inactive.ptr_array)
1465 free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
1466 rs->rules[rs_cnt].inactive.ptr_array = NULL;
1467
1468 if (rs->rules[rs_cnt].inactive.rcount) {
1469 rs->rules[rs_cnt].inactive.ptr_array =
1470 mallocarray(rs->rules[rs_cnt].inactive.rcount,
1471 sizeof(struct pf_rule **),
1472 M_TEMP, M_NOWAIT);
1473
1474 if (!rs->rules[rs_cnt].inactive.ptr_array)
1475 return (ENOMEM);
1476 }
1477
1478 TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
1479 entries) {
1480 pf_hash_rule_rolling(&ctx, rule);
1481 (rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule;
1482 }
1483 }
1484
1485 MD5Final(digest, &ctx);
1486 memcpy(V_pf_status.pf_chksum, digest, sizeof(V_pf_status.pf_chksum));
1487 return (0);
1488 }
1489
1490 static int
pf_eth_addr_setup(struct pf_keth_ruleset * ruleset,struct pf_addr_wrap * addr)1491 pf_eth_addr_setup(struct pf_keth_ruleset *ruleset, struct pf_addr_wrap *addr)
1492 {
1493 int error = 0;
1494
1495 switch (addr->type) {
1496 case PF_ADDR_TABLE:
1497 addr->p.tbl = pfr_eth_attach_table(ruleset, addr->v.tblname);
1498 if (addr->p.tbl == NULL)
1499 error = ENOMEM;
1500 break;
1501 default:
1502 error = EINVAL;
1503 }
1504
1505 return (error);
1506 }
1507
1508 static int
pf_addr_setup(struct pf_kruleset * ruleset,struct pf_addr_wrap * addr,sa_family_t af)1509 pf_addr_setup(struct pf_kruleset *ruleset, struct pf_addr_wrap *addr,
1510 sa_family_t af)
1511 {
1512 int error = 0;
1513
1514 switch (addr->type) {
1515 case PF_ADDR_TABLE:
1516 addr->p.tbl = pfr_attach_table(ruleset, addr->v.tblname);
1517 if (addr->p.tbl == NULL)
1518 error = ENOMEM;
1519 break;
1520 case PF_ADDR_DYNIFTL:
1521 error = pfi_dynaddr_setup(addr, af);
1522 break;
1523 }
1524
1525 return (error);
1526 }
1527
1528 static void
pf_addr_copyout(struct pf_addr_wrap * addr)1529 pf_addr_copyout(struct pf_addr_wrap *addr)
1530 {
1531
1532 switch (addr->type) {
1533 case PF_ADDR_DYNIFTL:
1534 pfi_dynaddr_copyout(addr);
1535 break;
1536 case PF_ADDR_TABLE:
1537 pf_tbladdr_copyout(addr);
1538 break;
1539 }
1540 }
1541
1542 static void
pf_src_node_copy(const struct pf_ksrc_node * in,struct pf_src_node * out)1543 pf_src_node_copy(const struct pf_ksrc_node *in, struct pf_src_node *out)
1544 {
1545 int secs = time_uptime, diff;
1546
1547 bzero(out, sizeof(struct pf_src_node));
1548
1549 bcopy(&in->addr, &out->addr, sizeof(struct pf_addr));
1550 bcopy(&in->raddr, &out->raddr, sizeof(struct pf_addr));
1551
1552 if (in->rule.ptr != NULL)
1553 out->rule.nr = in->rule.ptr->nr;
1554
1555 for (int i = 0; i < 2; i++) {
1556 out->bytes[i] = counter_u64_fetch(in->bytes[i]);
1557 out->packets[i] = counter_u64_fetch(in->packets[i]);
1558 }
1559
1560 out->states = in->states;
1561 out->conn = in->conn;
1562 out->af = in->af;
1563 out->ruletype = in->ruletype;
1564
1565 out->creation = secs - in->creation;
1566 if (out->expire > secs)
1567 out->expire -= secs;
1568 else
1569 out->expire = 0;
1570
1571 /* Adjust the connection rate estimate. */
1572 diff = secs - in->conn_rate.last;
1573 if (diff >= in->conn_rate.seconds)
1574 out->conn_rate.count = 0;
1575 else
1576 out->conn_rate.count -=
1577 in->conn_rate.count * diff /
1578 in->conn_rate.seconds;
1579 }
1580
1581 #ifdef ALTQ
1582 /*
1583 * Handle export of struct pf_kaltq to user binaries that may be using any
1584 * version of struct pf_altq.
1585 */
1586 static int
pf_export_kaltq(struct pf_altq * q,struct pfioc_altq_v1 * pa,size_t ioc_size)1587 pf_export_kaltq(struct pf_altq *q, struct pfioc_altq_v1 *pa, size_t ioc_size)
1588 {
1589 u_int32_t version;
1590
1591 if (ioc_size == sizeof(struct pfioc_altq_v0))
1592 version = 0;
1593 else
1594 version = pa->version;
1595
1596 if (version > PFIOC_ALTQ_VERSION)
1597 return (EINVAL);
1598
1599 #define ASSIGN(x) exported_q->x = q->x
1600 #define COPY(x) \
1601 bcopy(&q->x, &exported_q->x, min(sizeof(q->x), sizeof(exported_q->x)))
1602 #define SATU16(x) (u_int32_t)uqmin((x), USHRT_MAX)
1603 #define SATU32(x) (u_int32_t)uqmin((x), UINT_MAX)
1604
1605 switch (version) {
1606 case 0: {
1607 struct pf_altq_v0 *exported_q =
1608 &((struct pfioc_altq_v0 *)pa)->altq;
1609
1610 COPY(ifname);
1611
1612 ASSIGN(scheduler);
1613 ASSIGN(tbrsize);
1614 exported_q->tbrsize = SATU16(q->tbrsize);
1615 exported_q->ifbandwidth = SATU32(q->ifbandwidth);
1616
1617 COPY(qname);
1618 COPY(parent);
1619 ASSIGN(parent_qid);
1620 exported_q->bandwidth = SATU32(q->bandwidth);
1621 ASSIGN(priority);
1622 ASSIGN(local_flags);
1623
1624 ASSIGN(qlimit);
1625 ASSIGN(flags);
1626
1627 if (q->scheduler == ALTQT_HFSC) {
1628 #define ASSIGN_OPT(x) exported_q->pq_u.hfsc_opts.x = q->pq_u.hfsc_opts.x
1629 #define ASSIGN_OPT_SATU32(x) exported_q->pq_u.hfsc_opts.x = \
1630 SATU32(q->pq_u.hfsc_opts.x)
1631
1632 ASSIGN_OPT_SATU32(rtsc_m1);
1633 ASSIGN_OPT(rtsc_d);
1634 ASSIGN_OPT_SATU32(rtsc_m2);
1635
1636 ASSIGN_OPT_SATU32(lssc_m1);
1637 ASSIGN_OPT(lssc_d);
1638 ASSIGN_OPT_SATU32(lssc_m2);
1639
1640 ASSIGN_OPT_SATU32(ulsc_m1);
1641 ASSIGN_OPT(ulsc_d);
1642 ASSIGN_OPT_SATU32(ulsc_m2);
1643
1644 ASSIGN_OPT(flags);
1645
1646 #undef ASSIGN_OPT
1647 #undef ASSIGN_OPT_SATU32
1648 } else
1649 COPY(pq_u);
1650
1651 ASSIGN(qid);
1652 break;
1653 }
1654 case 1: {
1655 struct pf_altq_v1 *exported_q =
1656 &((struct pfioc_altq_v1 *)pa)->altq;
1657
1658 COPY(ifname);
1659
1660 ASSIGN(scheduler);
1661 ASSIGN(tbrsize);
1662 ASSIGN(ifbandwidth);
1663
1664 COPY(qname);
1665 COPY(parent);
1666 ASSIGN(parent_qid);
1667 ASSIGN(bandwidth);
1668 ASSIGN(priority);
1669 ASSIGN(local_flags);
1670
1671 ASSIGN(qlimit);
1672 ASSIGN(flags);
1673 COPY(pq_u);
1674
1675 ASSIGN(qid);
1676 break;
1677 }
1678 default:
1679 panic("%s: unhandled struct pfioc_altq version", __func__);
1680 break;
1681 }
1682
1683 #undef ASSIGN
1684 #undef COPY
1685 #undef SATU16
1686 #undef SATU32
1687
1688 return (0);
1689 }
1690
1691 /*
1692 * Handle import to struct pf_kaltq of struct pf_altq from user binaries
1693 * that may be using any version of it.
1694 */
1695 static int
pf_import_kaltq(struct pfioc_altq_v1 * pa,struct pf_altq * q,size_t ioc_size)1696 pf_import_kaltq(struct pfioc_altq_v1 *pa, struct pf_altq *q, size_t ioc_size)
1697 {
1698 u_int32_t version;
1699
1700 if (ioc_size == sizeof(struct pfioc_altq_v0))
1701 version = 0;
1702 else
1703 version = pa->version;
1704
1705 if (version > PFIOC_ALTQ_VERSION)
1706 return (EINVAL);
1707
1708 #define ASSIGN(x) q->x = imported_q->x
1709 #define COPY(x) \
1710 bcopy(&imported_q->x, &q->x, min(sizeof(imported_q->x), sizeof(q->x)))
1711
1712 switch (version) {
1713 case 0: {
1714 struct pf_altq_v0 *imported_q =
1715 &((struct pfioc_altq_v0 *)pa)->altq;
1716
1717 COPY(ifname);
1718
1719 ASSIGN(scheduler);
1720 ASSIGN(tbrsize); /* 16-bit -> 32-bit */
1721 ASSIGN(ifbandwidth); /* 32-bit -> 64-bit */
1722
1723 COPY(qname);
1724 COPY(parent);
1725 ASSIGN(parent_qid);
1726 ASSIGN(bandwidth); /* 32-bit -> 64-bit */
1727 ASSIGN(priority);
1728 ASSIGN(local_flags);
1729
1730 ASSIGN(qlimit);
1731 ASSIGN(flags);
1732
1733 if (imported_q->scheduler == ALTQT_HFSC) {
1734 #define ASSIGN_OPT(x) q->pq_u.hfsc_opts.x = imported_q->pq_u.hfsc_opts.x
1735
1736 /*
1737 * The m1 and m2 parameters are being copied from
1738 * 32-bit to 64-bit.
1739 */
1740 ASSIGN_OPT(rtsc_m1);
1741 ASSIGN_OPT(rtsc_d);
1742 ASSIGN_OPT(rtsc_m2);
1743
1744 ASSIGN_OPT(lssc_m1);
1745 ASSIGN_OPT(lssc_d);
1746 ASSIGN_OPT(lssc_m2);
1747
1748 ASSIGN_OPT(ulsc_m1);
1749 ASSIGN_OPT(ulsc_d);
1750 ASSIGN_OPT(ulsc_m2);
1751
1752 ASSIGN_OPT(flags);
1753
1754 #undef ASSIGN_OPT
1755 } else
1756 COPY(pq_u);
1757
1758 ASSIGN(qid);
1759 break;
1760 }
1761 case 1: {
1762 struct pf_altq_v1 *imported_q =
1763 &((struct pfioc_altq_v1 *)pa)->altq;
1764
1765 COPY(ifname);
1766
1767 ASSIGN(scheduler);
1768 ASSIGN(tbrsize);
1769 ASSIGN(ifbandwidth);
1770
1771 COPY(qname);
1772 COPY(parent);
1773 ASSIGN(parent_qid);
1774 ASSIGN(bandwidth);
1775 ASSIGN(priority);
1776 ASSIGN(local_flags);
1777
1778 ASSIGN(qlimit);
1779 ASSIGN(flags);
1780 COPY(pq_u);
1781
1782 ASSIGN(qid);
1783 break;
1784 }
1785 default:
1786 panic("%s: unhandled struct pfioc_altq version", __func__);
1787 break;
1788 }
1789
1790 #undef ASSIGN
1791 #undef COPY
1792
1793 return (0);
1794 }
1795
1796 static struct pf_altq *
pf_altq_get_nth_active(u_int32_t n)1797 pf_altq_get_nth_active(u_int32_t n)
1798 {
1799 struct pf_altq *altq;
1800 u_int32_t nr;
1801
1802 nr = 0;
1803 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
1804 if (nr == n)
1805 return (altq);
1806 nr++;
1807 }
1808
1809 TAILQ_FOREACH(altq, V_pf_altqs_active, entries) {
1810 if (nr == n)
1811 return (altq);
1812 nr++;
1813 }
1814
1815 return (NULL);
1816 }
1817 #endif /* ALTQ */
1818
1819 struct pf_krule *
pf_krule_alloc(void)1820 pf_krule_alloc(void)
1821 {
1822 struct pf_krule *rule;
1823
1824 rule = malloc(sizeof(struct pf_krule), M_PFRULE, M_WAITOK | M_ZERO);
1825 mtx_init(&rule->rpool.mtx, "pf_krule_pool", NULL, MTX_DEF);
1826 rule->timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
1827 M_WAITOK | M_ZERO);
1828 return (rule);
1829 }
1830
1831 void
pf_krule_free(struct pf_krule * rule)1832 pf_krule_free(struct pf_krule *rule)
1833 {
1834 #ifdef PF_WANT_32_TO_64_COUNTER
1835 bool wowned;
1836 #endif
1837
1838 if (rule == NULL)
1839 return;
1840
1841 #ifdef PF_WANT_32_TO_64_COUNTER
1842 if (rule->allrulelinked) {
1843 wowned = PF_RULES_WOWNED();
1844 if (!wowned)
1845 PF_RULES_WLOCK();
1846 LIST_REMOVE(rule, allrulelist);
1847 V_pf_allrulecount--;
1848 if (!wowned)
1849 PF_RULES_WUNLOCK();
1850 }
1851 #endif
1852
1853 pf_counter_u64_deinit(&rule->evaluations);
1854 for (int i = 0; i < 2; i++) {
1855 pf_counter_u64_deinit(&rule->packets[i]);
1856 pf_counter_u64_deinit(&rule->bytes[i]);
1857 }
1858 counter_u64_free(rule->states_cur);
1859 counter_u64_free(rule->states_tot);
1860 counter_u64_free(rule->src_nodes);
1861 uma_zfree_pcpu(pf_timestamp_pcpu_zone, rule->timestamp);
1862
1863 mtx_destroy(&rule->rpool.mtx);
1864 free(rule, M_PFRULE);
1865 }
1866
1867 void
pf_krule_clear_counters(struct pf_krule * rule)1868 pf_krule_clear_counters(struct pf_krule *rule)
1869 {
1870 pf_counter_u64_zero(&rule->evaluations);
1871 for (int i = 0; i < 2; i++) {
1872 pf_counter_u64_zero(&rule->packets[i]);
1873 pf_counter_u64_zero(&rule->bytes[i]);
1874 }
1875 counter_u64_zero(rule->states_tot);
1876 }
1877
1878 static void
pf_kpooladdr_to_pooladdr(const struct pf_kpooladdr * kpool,struct pf_pooladdr * pool)1879 pf_kpooladdr_to_pooladdr(const struct pf_kpooladdr *kpool,
1880 struct pf_pooladdr *pool)
1881 {
1882
1883 bzero(pool, sizeof(*pool));
1884 bcopy(&kpool->addr, &pool->addr, sizeof(pool->addr));
1885 strlcpy(pool->ifname, kpool->ifname, sizeof(pool->ifname));
1886 }
1887
1888 static int
pf_pooladdr_to_kpooladdr(const struct pf_pooladdr * pool,struct pf_kpooladdr * kpool)1889 pf_pooladdr_to_kpooladdr(const struct pf_pooladdr *pool,
1890 struct pf_kpooladdr *kpool)
1891 {
1892 int ret;
1893
1894 bzero(kpool, sizeof(*kpool));
1895 bcopy(&pool->addr, &kpool->addr, sizeof(kpool->addr));
1896 ret = pf_user_strcpy(kpool->ifname, pool->ifname,
1897 sizeof(kpool->ifname));
1898 return (ret);
1899 }
1900
1901 static void
pf_pool_to_kpool(const struct pf_pool * pool,struct pf_kpool * kpool)1902 pf_pool_to_kpool(const struct pf_pool *pool, struct pf_kpool *kpool)
1903 {
1904 _Static_assert(sizeof(pool->key) == sizeof(kpool->key), "");
1905 _Static_assert(sizeof(pool->counter) == sizeof(kpool->counter), "");
1906
1907 bcopy(&pool->key, &kpool->key, sizeof(kpool->key));
1908 bcopy(&pool->counter, &kpool->counter, sizeof(kpool->counter));
1909
1910 kpool->tblidx = pool->tblidx;
1911 kpool->proxy_port[0] = pool->proxy_port[0];
1912 kpool->proxy_port[1] = pool->proxy_port[1];
1913 kpool->opts = pool->opts;
1914 }
1915
1916 static int
pf_rule_to_krule(const struct pf_rule * rule,struct pf_krule * krule)1917 pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule)
1918 {
1919 int ret;
1920
1921 #ifndef INET
1922 if (rule->af == AF_INET) {
1923 return (EAFNOSUPPORT);
1924 }
1925 #endif /* INET */
1926 #ifndef INET6
1927 if (rule->af == AF_INET6) {
1928 return (EAFNOSUPPORT);
1929 }
1930 #endif /* INET6 */
1931
1932 ret = pf_check_rule_addr(&rule->src);
1933 if (ret != 0)
1934 return (ret);
1935 ret = pf_check_rule_addr(&rule->dst);
1936 if (ret != 0)
1937 return (ret);
1938
1939 bcopy(&rule->src, &krule->src, sizeof(rule->src));
1940 bcopy(&rule->dst, &krule->dst, sizeof(rule->dst));
1941
1942 ret = pf_user_strcpy(krule->label[0], rule->label, sizeof(rule->label));
1943 if (ret != 0)
1944 return (ret);
1945 ret = pf_user_strcpy(krule->ifname, rule->ifname, sizeof(rule->ifname));
1946 if (ret != 0)
1947 return (ret);
1948 ret = pf_user_strcpy(krule->qname, rule->qname, sizeof(rule->qname));
1949 if (ret != 0)
1950 return (ret);
1951 ret = pf_user_strcpy(krule->pqname, rule->pqname, sizeof(rule->pqname));
1952 if (ret != 0)
1953 return (ret);
1954 ret = pf_user_strcpy(krule->tagname, rule->tagname,
1955 sizeof(rule->tagname));
1956 if (ret != 0)
1957 return (ret);
1958 ret = pf_user_strcpy(krule->match_tagname, rule->match_tagname,
1959 sizeof(rule->match_tagname));
1960 if (ret != 0)
1961 return (ret);
1962 ret = pf_user_strcpy(krule->overload_tblname, rule->overload_tblname,
1963 sizeof(rule->overload_tblname));
1964 if (ret != 0)
1965 return (ret);
1966
1967 pf_pool_to_kpool(&rule->rpool, &krule->rpool);
1968
1969 /* Don't allow userspace to set evaluations, packets or bytes. */
1970 /* kif, anchor, overload_tbl are not copied over. */
1971
1972 krule->os_fingerprint = rule->os_fingerprint;
1973
1974 krule->rtableid = rule->rtableid;
1975 bcopy(rule->timeout, krule->timeout, sizeof(krule->timeout));
1976 krule->max_states = rule->max_states;
1977 krule->max_src_nodes = rule->max_src_nodes;
1978 krule->max_src_states = rule->max_src_states;
1979 krule->max_src_conn = rule->max_src_conn;
1980 krule->max_src_conn_rate.limit = rule->max_src_conn_rate.limit;
1981 krule->max_src_conn_rate.seconds = rule->max_src_conn_rate.seconds;
1982 krule->qid = rule->qid;
1983 krule->pqid = rule->pqid;
1984 krule->nr = rule->nr;
1985 krule->prob = rule->prob;
1986 krule->cuid = rule->cuid;
1987 krule->cpid = rule->cpid;
1988
1989 krule->return_icmp = rule->return_icmp;
1990 krule->return_icmp6 = rule->return_icmp6;
1991 krule->max_mss = rule->max_mss;
1992 krule->tag = rule->tag;
1993 krule->match_tag = rule->match_tag;
1994 krule->scrub_flags = rule->scrub_flags;
1995
1996 bcopy(&rule->uid, &krule->uid, sizeof(krule->uid));
1997 bcopy(&rule->gid, &krule->gid, sizeof(krule->gid));
1998
1999 krule->rule_flag = rule->rule_flag;
2000 krule->action = rule->action;
2001 krule->direction = rule->direction;
2002 krule->log = rule->log;
2003 krule->logif = rule->logif;
2004 krule->quick = rule->quick;
2005 krule->ifnot = rule->ifnot;
2006 krule->match_tag_not = rule->match_tag_not;
2007 krule->natpass = rule->natpass;
2008
2009 krule->keep_state = rule->keep_state;
2010 krule->af = rule->af;
2011 krule->proto = rule->proto;
2012 krule->type = rule->type;
2013 krule->code = rule->code;
2014 krule->flags = rule->flags;
2015 krule->flagset = rule->flagset;
2016 krule->min_ttl = rule->min_ttl;
2017 krule->allow_opts = rule->allow_opts;
2018 krule->rt = rule->rt;
2019 krule->return_ttl = rule->return_ttl;
2020 krule->tos = rule->tos;
2021 krule->set_tos = rule->set_tos;
2022
2023 krule->flush = rule->flush;
2024 krule->prio = rule->prio;
2025 krule->set_prio[0] = rule->set_prio[0];
2026 krule->set_prio[1] = rule->set_prio[1];
2027
2028 bcopy(&rule->divert, &krule->divert, sizeof(krule->divert));
2029
2030 return (0);
2031 }
2032
2033 int
pf_ioctl_getrules(struct pfioc_rule * pr)2034 pf_ioctl_getrules(struct pfioc_rule *pr)
2035 {
2036 struct pf_kruleset *ruleset;
2037 struct pf_krule *tail;
2038 int rs_num;
2039
2040 PF_RULES_WLOCK();
2041 ruleset = pf_find_kruleset(pr->anchor);
2042 if (ruleset == NULL) {
2043 PF_RULES_WUNLOCK();
2044 return (EINVAL);
2045 }
2046 rs_num = pf_get_ruleset_number(pr->rule.action);
2047 if (rs_num >= PF_RULESET_MAX) {
2048 PF_RULES_WUNLOCK();
2049 return (EINVAL);
2050 }
2051 tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
2052 pf_krulequeue);
2053 if (tail)
2054 pr->nr = tail->nr + 1;
2055 else
2056 pr->nr = 0;
2057 pr->ticket = ruleset->rules[rs_num].active.ticket;
2058 PF_RULES_WUNLOCK();
2059
2060 return (0);
2061 }
2062
2063 int
pf_ioctl_addrule(struct pf_krule * rule,uint32_t ticket,uint32_t pool_ticket,const char * anchor,const char * anchor_call,uid_t uid,pid_t pid)2064 pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
2065 uint32_t pool_ticket, const char *anchor, const char *anchor_call,
2066 uid_t uid, pid_t pid)
2067 {
2068 struct pf_kruleset *ruleset;
2069 struct pf_krule *tail;
2070 struct pf_kpooladdr *pa;
2071 struct pfi_kkif *kif = NULL;
2072 int rs_num;
2073 int error = 0;
2074
2075 if ((rule->return_icmp >> 8) > ICMP_MAXTYPE) {
2076 error = EINVAL;
2077 goto errout_unlocked;
2078 }
2079
2080 #define ERROUT(x) ERROUT_FUNCTION(errout, x)
2081
2082 if (rule->ifname[0])
2083 kif = pf_kkif_create(M_WAITOK);
2084 pf_counter_u64_init(&rule->evaluations, M_WAITOK);
2085 for (int i = 0; i < 2; i++) {
2086 pf_counter_u64_init(&rule->packets[i], M_WAITOK);
2087 pf_counter_u64_init(&rule->bytes[i], M_WAITOK);
2088 }
2089 rule->states_cur = counter_u64_alloc(M_WAITOK);
2090 rule->states_tot = counter_u64_alloc(M_WAITOK);
2091 rule->src_nodes = counter_u64_alloc(M_WAITOK);
2092 rule->cuid = uid;
2093 rule->cpid = pid;
2094 TAILQ_INIT(&rule->rpool.list);
2095
2096 PF_CONFIG_LOCK();
2097 PF_RULES_WLOCK();
2098 #ifdef PF_WANT_32_TO_64_COUNTER
2099 LIST_INSERT_HEAD(&V_pf_allrulelist, rule, allrulelist);
2100 MPASS(!rule->allrulelinked);
2101 rule->allrulelinked = true;
2102 V_pf_allrulecount++;
2103 #endif
2104 ruleset = pf_find_kruleset(anchor);
2105 if (ruleset == NULL)
2106 ERROUT(EINVAL);
2107 rs_num = pf_get_ruleset_number(rule->action);
2108 if (rs_num >= PF_RULESET_MAX)
2109 ERROUT(EINVAL);
2110 if (ticket != ruleset->rules[rs_num].inactive.ticket) {
2111 DPFPRINTF(PF_DEBUG_MISC,
2112 ("ticket: %d != [%d]%d\n", ticket, rs_num,
2113 ruleset->rules[rs_num].inactive.ticket));
2114 ERROUT(EBUSY);
2115 }
2116 if (pool_ticket != V_ticket_pabuf) {
2117 DPFPRINTF(PF_DEBUG_MISC,
2118 ("pool_ticket: %d != %d\n", pool_ticket,
2119 V_ticket_pabuf));
2120 ERROUT(EBUSY);
2121 }
2122 /*
2123 * XXXMJG hack: there is no mechanism to ensure they started the
2124 * transaction. Ticket checked above may happen to match by accident,
2125 * even if nobody called DIOCXBEGIN, let alone this process.
2126 * Partially work around it by checking if the RB tree got allocated,
2127 * see pf_begin_rules.
2128 */
2129 if (ruleset->rules[rs_num].inactive.tree == NULL) {
2130 ERROUT(EINVAL);
2131 }
2132
2133 tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
2134 pf_krulequeue);
2135 if (tail)
2136 rule->nr = tail->nr + 1;
2137 else
2138 rule->nr = 0;
2139 if (rule->ifname[0]) {
2140 rule->kif = pfi_kkif_attach(kif, rule->ifname);
2141 kif = NULL;
2142 pfi_kkif_ref(rule->kif);
2143 } else
2144 rule->kif = NULL;
2145
2146 if (rule->rtableid > 0 && rule->rtableid >= rt_numfibs)
2147 error = EBUSY;
2148
2149 #ifdef ALTQ
2150 /* set queue IDs */
2151 if (rule->qname[0] != 0) {
2152 if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
2153 error = EBUSY;
2154 else if (rule->pqname[0] != 0) {
2155 if ((rule->pqid =
2156 pf_qname2qid(rule->pqname)) == 0)
2157 error = EBUSY;
2158 } else
2159 rule->pqid = rule->qid;
2160 }
2161 #endif
2162 if (rule->tagname[0])
2163 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
2164 error = EBUSY;
2165 if (rule->match_tagname[0])
2166 if ((rule->match_tag =
2167 pf_tagname2tag(rule->match_tagname)) == 0)
2168 error = EBUSY;
2169 if (rule->rt && !rule->direction)
2170 error = EINVAL;
2171 if (!rule->log)
2172 rule->logif = 0;
2173 if (rule->logif >= PFLOGIFS_MAX)
2174 error = EINVAL;
2175 if (pf_addr_setup(ruleset, &rule->src.addr, rule->af))
2176 error = ENOMEM;
2177 if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
2178 error = ENOMEM;
2179 if (pf_kanchor_setup(rule, ruleset, anchor_call))
2180 error = EINVAL;
2181 if (rule->scrub_flags & PFSTATE_SETPRIO &&
2182 (rule->set_prio[0] > PF_PRIO_MAX ||
2183 rule->set_prio[1] > PF_PRIO_MAX))
2184 error = EINVAL;
2185 TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
2186 if (pa->addr.type == PF_ADDR_TABLE) {
2187 pa->addr.p.tbl = pfr_attach_table(ruleset,
2188 pa->addr.v.tblname);
2189 if (pa->addr.p.tbl == NULL)
2190 error = ENOMEM;
2191 }
2192
2193 rule->overload_tbl = NULL;
2194 if (rule->overload_tblname[0]) {
2195 if ((rule->overload_tbl = pfr_attach_table(ruleset,
2196 rule->overload_tblname)) == NULL)
2197 error = EINVAL;
2198 else
2199 rule->overload_tbl->pfrkt_flags |=
2200 PFR_TFLAG_ACTIVE;
2201 }
2202
2203 pf_mv_kpool(&V_pf_pabuf, &rule->rpool.list);
2204 if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
2205 (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
2206 (rule->rt > PF_NOPFROUTE)) &&
2207 (TAILQ_FIRST(&rule->rpool.list) == NULL))
2208 error = EINVAL;
2209
2210 if (error) {
2211 pf_free_rule(rule);
2212 rule = NULL;
2213 ERROUT(error);
2214 }
2215
2216 rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
2217 TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
2218 rule, entries);
2219 ruleset->rules[rs_num].inactive.rcount++;
2220
2221 PF_RULES_WUNLOCK();
2222 pf_hash_rule(rule);
2223 if (RB_INSERT(pf_krule_global, ruleset->rules[rs_num].inactive.tree, rule) != NULL) {
2224 PF_RULES_WLOCK();
2225 TAILQ_REMOVE(ruleset->rules[rs_num].inactive.ptr, rule, entries);
2226 ruleset->rules[rs_num].inactive.rcount--;
2227 pf_free_rule(rule);
2228 rule = NULL;
2229 ERROUT(EEXIST);
2230 }
2231 PF_CONFIG_UNLOCK();
2232
2233 return (0);
2234
2235 #undef ERROUT
2236 errout:
2237 PF_RULES_WUNLOCK();
2238 PF_CONFIG_UNLOCK();
2239 errout_unlocked:
2240 pf_kkif_free(kif);
2241 pf_krule_free(rule);
2242 return (error);
2243 }
2244
2245 static bool
pf_label_match(const struct pf_krule * rule,const char * label)2246 pf_label_match(const struct pf_krule *rule, const char *label)
2247 {
2248 int i = 0;
2249
2250 while (*rule->label[i]) {
2251 if (strcmp(rule->label[i], label) == 0)
2252 return (true);
2253 i++;
2254 }
2255
2256 return (false);
2257 }
2258
2259 static unsigned int
pf_kill_matching_state(struct pf_state_key_cmp * key,int dir)2260 pf_kill_matching_state(struct pf_state_key_cmp *key, int dir)
2261 {
2262 struct pf_kstate *s;
2263 int more = 0;
2264
2265 s = pf_find_state_all(key, dir, &more);
2266 if (s == NULL)
2267 return (0);
2268
2269 if (more) {
2270 PF_STATE_UNLOCK(s);
2271 return (0);
2272 }
2273
2274 pf_unlink_state(s);
2275 return (1);
2276 }
2277
2278 static int
pf_killstates_row(struct pf_kstate_kill * psk,struct pf_idhash * ih)2279 pf_killstates_row(struct pf_kstate_kill *psk, struct pf_idhash *ih)
2280 {
2281 struct pf_kstate *s;
2282 struct pf_state_key *sk;
2283 struct pf_addr *srcaddr, *dstaddr;
2284 struct pf_state_key_cmp match_key;
2285 int idx, killed = 0;
2286 unsigned int dir;
2287 u_int16_t srcport, dstport;
2288 struct pfi_kkif *kif;
2289
2290 relock_DIOCKILLSTATES:
2291 PF_HASHROW_LOCK(ih);
2292 LIST_FOREACH(s, &ih->states, entry) {
2293 /* For floating states look at the original kif. */
2294 kif = s->kif == V_pfi_all ? s->orig_kif : s->kif;
2295
2296 sk = s->key[psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE];
2297 if (s->direction == PF_OUT) {
2298 srcaddr = &sk->addr[1];
2299 dstaddr = &sk->addr[0];
2300 srcport = sk->port[1];
2301 dstport = sk->port[0];
2302 } else {
2303 srcaddr = &sk->addr[0];
2304 dstaddr = &sk->addr[1];
2305 srcport = sk->port[0];
2306 dstport = sk->port[1];
2307 }
2308
2309 if (psk->psk_af && sk->af != psk->psk_af)
2310 continue;
2311
2312 if (psk->psk_proto && psk->psk_proto != sk->proto)
2313 continue;
2314
2315 if (! PF_MATCHA(psk->psk_src.neg, &psk->psk_src.addr.v.a.addr,
2316 &psk->psk_src.addr.v.a.mask, srcaddr, sk->af))
2317 continue;
2318
2319 if (! PF_MATCHA(psk->psk_dst.neg, &psk->psk_dst.addr.v.a.addr,
2320 &psk->psk_dst.addr.v.a.mask, dstaddr, sk->af))
2321 continue;
2322
2323 if (! PF_MATCHA(psk->psk_rt_addr.neg,
2324 &psk->psk_rt_addr.addr.v.a.addr,
2325 &psk->psk_rt_addr.addr.v.a.mask,
2326 &s->rt_addr, sk->af))
2327 continue;
2328
2329 if (psk->psk_src.port_op != 0 &&
2330 ! pf_match_port(psk->psk_src.port_op,
2331 psk->psk_src.port[0], psk->psk_src.port[1], srcport))
2332 continue;
2333
2334 if (psk->psk_dst.port_op != 0 &&
2335 ! pf_match_port(psk->psk_dst.port_op,
2336 psk->psk_dst.port[0], psk->psk_dst.port[1], dstport))
2337 continue;
2338
2339 if (psk->psk_label[0] &&
2340 ! pf_label_match(s->rule.ptr, psk->psk_label))
2341 continue;
2342
2343 if (psk->psk_ifname[0] && strcmp(psk->psk_ifname,
2344 kif->pfik_name))
2345 continue;
2346
2347 if (psk->psk_kill_match) {
2348 /* Create the key to find matching states, with lock
2349 * held. */
2350
2351 bzero(&match_key, sizeof(match_key));
2352
2353 if (s->direction == PF_OUT) {
2354 dir = PF_IN;
2355 idx = psk->psk_nat ? PF_SK_WIRE : PF_SK_STACK;
2356 } else {
2357 dir = PF_OUT;
2358 idx = psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE;
2359 }
2360
2361 match_key.af = s->key[idx]->af;
2362 match_key.proto = s->key[idx]->proto;
2363 PF_ACPY(&match_key.addr[0],
2364 &s->key[idx]->addr[1], match_key.af);
2365 match_key.port[0] = s->key[idx]->port[1];
2366 PF_ACPY(&match_key.addr[1],
2367 &s->key[idx]->addr[0], match_key.af);
2368 match_key.port[1] = s->key[idx]->port[0];
2369 }
2370
2371 pf_unlink_state(s);
2372 killed++;
2373
2374 if (psk->psk_kill_match)
2375 killed += pf_kill_matching_state(&match_key, dir);
2376
2377 goto relock_DIOCKILLSTATES;
2378 }
2379 PF_HASHROW_UNLOCK(ih);
2380
2381 return (killed);
2382 }
2383
2384 int
pf_start(void)2385 pf_start(void)
2386 {
2387 int error = 0;
2388
2389 sx_xlock(&V_pf_ioctl_lock);
2390 if (V_pf_status.running)
2391 error = EEXIST;
2392 else {
2393 hook_pf();
2394 if (! TAILQ_EMPTY(V_pf_keth->active.rules))
2395 hook_pf_eth();
2396 V_pf_status.running = 1;
2397 V_pf_status.since = time_second;
2398 new_unrhdr64(&V_pf_stateid, time_second);
2399
2400 DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
2401 }
2402 sx_xunlock(&V_pf_ioctl_lock);
2403
2404 return (error);
2405 }
2406
2407 int
pf_stop(void)2408 pf_stop(void)
2409 {
2410 int error = 0;
2411
2412 sx_xlock(&V_pf_ioctl_lock);
2413 if (!V_pf_status.running)
2414 error = ENOENT;
2415 else {
2416 V_pf_status.running = 0;
2417 dehook_pf();
2418 dehook_pf_eth();
2419 V_pf_status.since = time_second;
2420 DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
2421 }
2422 sx_xunlock(&V_pf_ioctl_lock);
2423
2424 return (error);
2425 }
2426
2427 static int
pfioctl(struct cdev * dev,u_long cmd,caddr_t addr,int flags,struct thread * td)2428 pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
2429 {
2430 int error = 0;
2431 PF_RULES_RLOCK_TRACKER;
2432
2433 #define ERROUT_IOCTL(target, x) \
2434 do { \
2435 error = (x); \
2436 SDT_PROBE3(pf, ioctl, ioctl, error, cmd, error, __LINE__); \
2437 goto target; \
2438 } while (0)
2439
2440
2441 /* XXX keep in sync with switch() below */
2442 if (securelevel_gt(td->td_ucred, 2))
2443 switch (cmd) {
2444 case DIOCGETRULES:
2445 case DIOCGETRULENV:
2446 case DIOCGETADDRS:
2447 case DIOCGETADDR:
2448 case DIOCGETSTATE:
2449 case DIOCGETSTATENV:
2450 case DIOCSETSTATUSIF:
2451 case DIOCGETSTATUSNV:
2452 case DIOCCLRSTATUS:
2453 case DIOCNATLOOK:
2454 case DIOCSETDEBUG:
2455 #ifdef COMPAT_FREEBSD14
2456 case DIOCGETSTATES:
2457 case DIOCGETSTATESV2:
2458 #endif
2459 case DIOCGETTIMEOUT:
2460 case DIOCCLRRULECTRS:
2461 case DIOCGETLIMIT:
2462 case DIOCGETALTQSV0:
2463 case DIOCGETALTQSV1:
2464 case DIOCGETALTQV0:
2465 case DIOCGETALTQV1:
2466 case DIOCGETQSTATSV0:
2467 case DIOCGETQSTATSV1:
2468 case DIOCGETRULESETS:
2469 case DIOCGETRULESET:
2470 case DIOCRGETTABLES:
2471 case DIOCRGETTSTATS:
2472 case DIOCRCLRTSTATS:
2473 case DIOCRCLRADDRS:
2474 case DIOCRADDADDRS:
2475 case DIOCRDELADDRS:
2476 case DIOCRSETADDRS:
2477 case DIOCRGETADDRS:
2478 case DIOCRGETASTATS:
2479 case DIOCRCLRASTATS:
2480 case DIOCRTSTADDRS:
2481 case DIOCOSFPGET:
2482 case DIOCGETSRCNODES:
2483 case DIOCCLRSRCNODES:
2484 case DIOCGETSYNCOOKIES:
2485 case DIOCIGETIFACES:
2486 case DIOCGIFSPEEDV0:
2487 case DIOCGIFSPEEDV1:
2488 case DIOCSETIFFLAG:
2489 case DIOCCLRIFFLAG:
2490 case DIOCGETETHRULES:
2491 case DIOCGETETHRULE:
2492 case DIOCGETETHRULESETS:
2493 case DIOCGETETHRULESET:
2494 break;
2495 case DIOCRCLRTABLES:
2496 case DIOCRADDTABLES:
2497 case DIOCRDELTABLES:
2498 case DIOCRSETTFLAGS:
2499 if (((struct pfioc_table *)addr)->pfrio_flags &
2500 PFR_FLAG_DUMMY)
2501 break; /* dummy operation ok */
2502 return (EPERM);
2503 default:
2504 return (EPERM);
2505 }
2506
2507 if (!(flags & FWRITE))
2508 switch (cmd) {
2509 case DIOCGETRULES:
2510 case DIOCGETADDRS:
2511 case DIOCGETADDR:
2512 case DIOCGETSTATE:
2513 case DIOCGETSTATENV:
2514 case DIOCGETSTATUSNV:
2515 #ifdef COMPAT_FREEBSD14
2516 case DIOCGETSTATES:
2517 case DIOCGETSTATESV2:
2518 #endif
2519 case DIOCGETTIMEOUT:
2520 case DIOCGETLIMIT:
2521 case DIOCGETALTQSV0:
2522 case DIOCGETALTQSV1:
2523 case DIOCGETALTQV0:
2524 case DIOCGETALTQV1:
2525 case DIOCGETQSTATSV0:
2526 case DIOCGETQSTATSV1:
2527 case DIOCGETRULESETS:
2528 case DIOCGETRULESET:
2529 case DIOCNATLOOK:
2530 case DIOCRGETTABLES:
2531 case DIOCRGETTSTATS:
2532 case DIOCRGETADDRS:
2533 case DIOCRGETASTATS:
2534 case DIOCRTSTADDRS:
2535 case DIOCOSFPGET:
2536 case DIOCGETSRCNODES:
2537 case DIOCGETSYNCOOKIES:
2538 case DIOCIGETIFACES:
2539 case DIOCGIFSPEEDV1:
2540 case DIOCGIFSPEEDV0:
2541 case DIOCGETRULENV:
2542 case DIOCGETETHRULES:
2543 case DIOCGETETHRULE:
2544 case DIOCGETETHRULESETS:
2545 case DIOCGETETHRULESET:
2546 break;
2547 case DIOCRCLRTABLES:
2548 case DIOCRADDTABLES:
2549 case DIOCRDELTABLES:
2550 case DIOCRCLRTSTATS:
2551 case DIOCRCLRADDRS:
2552 case DIOCRADDADDRS:
2553 case DIOCRDELADDRS:
2554 case DIOCRSETADDRS:
2555 case DIOCRSETTFLAGS:
2556 if (((struct pfioc_table *)addr)->pfrio_flags &
2557 PFR_FLAG_DUMMY) {
2558 flags |= FWRITE; /* need write lock for dummy */
2559 break; /* dummy operation ok */
2560 }
2561 return (EACCES);
2562 default:
2563 return (EACCES);
2564 }
2565
2566 CURVNET_SET(TD_TO_VNET(td));
2567
2568 switch (cmd) {
2569 #ifdef COMPAT_FREEBSD14
2570 case DIOCSTART:
2571 error = pf_start();
2572 break;
2573
2574 case DIOCSTOP:
2575 error = pf_stop();
2576 break;
2577 #endif
2578
2579 case DIOCGETETHRULES: {
2580 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
2581 nvlist_t *nvl;
2582 void *packed;
2583 struct pf_keth_rule *tail;
2584 struct pf_keth_ruleset *rs;
2585 u_int32_t ticket, nr;
2586 const char *anchor = "";
2587
2588 nvl = NULL;
2589 packed = NULL;
2590
2591 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULES_error, x)
2592
2593 if (nv->len > pf_ioctl_maxcount)
2594 ERROUT(ENOMEM);
2595
2596 /* Copy the request in */
2597 packed = malloc(nv->len, M_NVLIST, M_WAITOK);
2598 if (packed == NULL)
2599 ERROUT(ENOMEM);
2600
2601 error = copyin(nv->data, packed, nv->len);
2602 if (error)
2603 ERROUT(error);
2604
2605 nvl = nvlist_unpack(packed, nv->len, 0);
2606 if (nvl == NULL)
2607 ERROUT(EBADMSG);
2608
2609 if (! nvlist_exists_string(nvl, "anchor"))
2610 ERROUT(EBADMSG);
2611
2612 anchor = nvlist_get_string(nvl, "anchor");
2613
2614 rs = pf_find_keth_ruleset(anchor);
2615
2616 nvlist_destroy(nvl);
2617 nvl = NULL;
2618 free(packed, M_NVLIST);
2619 packed = NULL;
2620
2621 if (rs == NULL)
2622 ERROUT(ENOENT);
2623
2624 /* Reply */
2625 nvl = nvlist_create(0);
2626 if (nvl == NULL)
2627 ERROUT(ENOMEM);
2628
2629 PF_RULES_RLOCK();
2630
2631 ticket = rs->active.ticket;
2632 tail = TAILQ_LAST(rs->active.rules, pf_keth_ruleq);
2633 if (tail)
2634 nr = tail->nr + 1;
2635 else
2636 nr = 0;
2637
2638 PF_RULES_RUNLOCK();
2639
2640 nvlist_add_number(nvl, "ticket", ticket);
2641 nvlist_add_number(nvl, "nr", nr);
2642
2643 packed = nvlist_pack(nvl, &nv->len);
2644 if (packed == NULL)
2645 ERROUT(ENOMEM);
2646
2647 if (nv->size == 0)
2648 ERROUT(0);
2649 else if (nv->size < nv->len)
2650 ERROUT(ENOSPC);
2651
2652 error = copyout(packed, nv->data, nv->len);
2653
2654 #undef ERROUT
2655 DIOCGETETHRULES_error:
2656 free(packed, M_NVLIST);
2657 nvlist_destroy(nvl);
2658 break;
2659 }
2660
2661 case DIOCGETETHRULE: {
2662 struct epoch_tracker et;
2663 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
2664 nvlist_t *nvl = NULL;
2665 void *nvlpacked = NULL;
2666 struct pf_keth_rule *rule = NULL;
2667 struct pf_keth_ruleset *rs;
2668 u_int32_t ticket, nr;
2669 bool clear = false;
2670 const char *anchor;
2671
2672 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULE_error, x)
2673
2674 if (nv->len > pf_ioctl_maxcount)
2675 ERROUT(ENOMEM);
2676
2677 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
2678 if (nvlpacked == NULL)
2679 ERROUT(ENOMEM);
2680
2681 error = copyin(nv->data, nvlpacked, nv->len);
2682 if (error)
2683 ERROUT(error);
2684
2685 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
2686 if (nvl == NULL)
2687 ERROUT(EBADMSG);
2688 if (! nvlist_exists_number(nvl, "ticket"))
2689 ERROUT(EBADMSG);
2690 ticket = nvlist_get_number(nvl, "ticket");
2691 if (! nvlist_exists_string(nvl, "anchor"))
2692 ERROUT(EBADMSG);
2693 anchor = nvlist_get_string(nvl, "anchor");
2694
2695 if (nvlist_exists_bool(nvl, "clear"))
2696 clear = nvlist_get_bool(nvl, "clear");
2697
2698 if (clear && !(flags & FWRITE))
2699 ERROUT(EACCES);
2700
2701 if (! nvlist_exists_number(nvl, "nr"))
2702 ERROUT(EBADMSG);
2703 nr = nvlist_get_number(nvl, "nr");
2704
2705 PF_RULES_RLOCK();
2706 rs = pf_find_keth_ruleset(anchor);
2707 if (rs == NULL) {
2708 PF_RULES_RUNLOCK();
2709 ERROUT(ENOENT);
2710 }
2711 if (ticket != rs->active.ticket) {
2712 PF_RULES_RUNLOCK();
2713 ERROUT(EBUSY);
2714 }
2715
2716 nvlist_destroy(nvl);
2717 nvl = NULL;
2718 free(nvlpacked, M_NVLIST);
2719 nvlpacked = NULL;
2720
2721 rule = TAILQ_FIRST(rs->active.rules);
2722 while ((rule != NULL) && (rule->nr != nr))
2723 rule = TAILQ_NEXT(rule, entries);
2724 if (rule == NULL) {
2725 PF_RULES_RUNLOCK();
2726 ERROUT(ENOENT);
2727 }
2728 /* Make sure rule can't go away. */
2729 NET_EPOCH_ENTER(et);
2730 PF_RULES_RUNLOCK();
2731 nvl = pf_keth_rule_to_nveth_rule(rule);
2732 if (pf_keth_anchor_nvcopyout(rs, rule, nvl))
2733 ERROUT(EBUSY);
2734 NET_EPOCH_EXIT(et);
2735 if (nvl == NULL)
2736 ERROUT(ENOMEM);
2737
2738 nvlpacked = nvlist_pack(nvl, &nv->len);
2739 if (nvlpacked == NULL)
2740 ERROUT(ENOMEM);
2741
2742 if (nv->size == 0)
2743 ERROUT(0);
2744 else if (nv->size < nv->len)
2745 ERROUT(ENOSPC);
2746
2747 error = copyout(nvlpacked, nv->data, nv->len);
2748 if (error == 0 && clear) {
2749 counter_u64_zero(rule->evaluations);
2750 for (int i = 0; i < 2; i++) {
2751 counter_u64_zero(rule->packets[i]);
2752 counter_u64_zero(rule->bytes[i]);
2753 }
2754 }
2755
2756 #undef ERROUT
2757 DIOCGETETHRULE_error:
2758 free(nvlpacked, M_NVLIST);
2759 nvlist_destroy(nvl);
2760 break;
2761 }
2762
2763 case DIOCADDETHRULE: {
2764 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
2765 nvlist_t *nvl = NULL;
2766 void *nvlpacked = NULL;
2767 struct pf_keth_rule *rule = NULL, *tail = NULL;
2768 struct pf_keth_ruleset *ruleset = NULL;
2769 struct pfi_kkif *kif = NULL, *bridge_to_kif = NULL;
2770 const char *anchor = "", *anchor_call = "";
2771
2772 #define ERROUT(x) ERROUT_IOCTL(DIOCADDETHRULE_error, x)
2773
2774 if (nv->len > pf_ioctl_maxcount)
2775 ERROUT(ENOMEM);
2776
2777 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
2778 if (nvlpacked == NULL)
2779 ERROUT(ENOMEM);
2780
2781 error = copyin(nv->data, nvlpacked, nv->len);
2782 if (error)
2783 ERROUT(error);
2784
2785 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
2786 if (nvl == NULL)
2787 ERROUT(EBADMSG);
2788
2789 if (! nvlist_exists_number(nvl, "ticket"))
2790 ERROUT(EBADMSG);
2791
2792 if (nvlist_exists_string(nvl, "anchor"))
2793 anchor = nvlist_get_string(nvl, "anchor");
2794 if (nvlist_exists_string(nvl, "anchor_call"))
2795 anchor_call = nvlist_get_string(nvl, "anchor_call");
2796
2797 ruleset = pf_find_keth_ruleset(anchor);
2798 if (ruleset == NULL)
2799 ERROUT(EINVAL);
2800
2801 if (nvlist_get_number(nvl, "ticket") !=
2802 ruleset->inactive.ticket) {
2803 DPFPRINTF(PF_DEBUG_MISC,
2804 ("ticket: %d != %d\n",
2805 (u_int32_t)nvlist_get_number(nvl, "ticket"),
2806 ruleset->inactive.ticket));
2807 ERROUT(EBUSY);
2808 }
2809
2810 rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK);
2811 if (rule == NULL)
2812 ERROUT(ENOMEM);
2813 rule->timestamp = NULL;
2814
2815 error = pf_nveth_rule_to_keth_rule(nvl, rule);
2816 if (error != 0)
2817 ERROUT(error);
2818
2819 if (rule->ifname[0])
2820 kif = pf_kkif_create(M_WAITOK);
2821 if (rule->bridge_to_name[0])
2822 bridge_to_kif = pf_kkif_create(M_WAITOK);
2823 rule->evaluations = counter_u64_alloc(M_WAITOK);
2824 for (int i = 0; i < 2; i++) {
2825 rule->packets[i] = counter_u64_alloc(M_WAITOK);
2826 rule->bytes[i] = counter_u64_alloc(M_WAITOK);
2827 }
2828 rule->timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
2829 M_WAITOK | M_ZERO);
2830
2831 PF_RULES_WLOCK();
2832
2833 if (rule->ifname[0]) {
2834 rule->kif = pfi_kkif_attach(kif, rule->ifname);
2835 pfi_kkif_ref(rule->kif);
2836 } else
2837 rule->kif = NULL;
2838 if (rule->bridge_to_name[0]) {
2839 rule->bridge_to = pfi_kkif_attach(bridge_to_kif,
2840 rule->bridge_to_name);
2841 pfi_kkif_ref(rule->bridge_to);
2842 } else
2843 rule->bridge_to = NULL;
2844
2845 #ifdef ALTQ
2846 /* set queue IDs */
2847 if (rule->qname[0] != 0) {
2848 if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
2849 error = EBUSY;
2850 else
2851 rule->qid = rule->qid;
2852 }
2853 #endif
2854 if (rule->tagname[0])
2855 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
2856 error = EBUSY;
2857 if (rule->match_tagname[0])
2858 if ((rule->match_tag = pf_tagname2tag(
2859 rule->match_tagname)) == 0)
2860 error = EBUSY;
2861
2862 if (error == 0 && rule->ipdst.addr.type == PF_ADDR_TABLE)
2863 error = pf_eth_addr_setup(ruleset, &rule->ipdst.addr);
2864 if (error == 0 && rule->ipsrc.addr.type == PF_ADDR_TABLE)
2865 error = pf_eth_addr_setup(ruleset, &rule->ipsrc.addr);
2866
2867 if (error) {
2868 pf_free_eth_rule(rule);
2869 PF_RULES_WUNLOCK();
2870 ERROUT(error);
2871 }
2872
2873 if (pf_keth_anchor_setup(rule, ruleset, anchor_call)) {
2874 pf_free_eth_rule(rule);
2875 PF_RULES_WUNLOCK();
2876 ERROUT(EINVAL);
2877 }
2878
2879 tail = TAILQ_LAST(ruleset->inactive.rules, pf_keth_ruleq);
2880 if (tail)
2881 rule->nr = tail->nr + 1;
2882 else
2883 rule->nr = 0;
2884
2885 TAILQ_INSERT_TAIL(ruleset->inactive.rules, rule, entries);
2886
2887 PF_RULES_WUNLOCK();
2888
2889 #undef ERROUT
2890 DIOCADDETHRULE_error:
2891 nvlist_destroy(nvl);
2892 free(nvlpacked, M_NVLIST);
2893 break;
2894 }
2895
2896 case DIOCGETETHRULESETS: {
2897 struct epoch_tracker et;
2898 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
2899 nvlist_t *nvl = NULL;
2900 void *nvlpacked = NULL;
2901 struct pf_keth_ruleset *ruleset;
2902 struct pf_keth_anchor *anchor;
2903 int nr = 0;
2904
2905 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULESETS_error, x)
2906
2907 if (nv->len > pf_ioctl_maxcount)
2908 ERROUT(ENOMEM);
2909
2910 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
2911 if (nvlpacked == NULL)
2912 ERROUT(ENOMEM);
2913
2914 error = copyin(nv->data, nvlpacked, nv->len);
2915 if (error)
2916 ERROUT(error);
2917
2918 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
2919 if (nvl == NULL)
2920 ERROUT(EBADMSG);
2921 if (! nvlist_exists_string(nvl, "path"))
2922 ERROUT(EBADMSG);
2923
2924 NET_EPOCH_ENTER(et);
2925
2926 if ((ruleset = pf_find_keth_ruleset(
2927 nvlist_get_string(nvl, "path"))) == NULL) {
2928 NET_EPOCH_EXIT(et);
2929 ERROUT(ENOENT);
2930 }
2931
2932 if (ruleset->anchor == NULL) {
2933 RB_FOREACH(anchor, pf_keth_anchor_global, &V_pf_keth_anchors)
2934 if (anchor->parent == NULL)
2935 nr++;
2936 } else {
2937 RB_FOREACH(anchor, pf_keth_anchor_node,
2938 &ruleset->anchor->children)
2939 nr++;
2940 }
2941
2942 NET_EPOCH_EXIT(et);
2943
2944 nvlist_destroy(nvl);
2945 nvl = NULL;
2946 free(nvlpacked, M_NVLIST);
2947 nvlpacked = NULL;
2948
2949 nvl = nvlist_create(0);
2950 if (nvl == NULL)
2951 ERROUT(ENOMEM);
2952
2953 nvlist_add_number(nvl, "nr", nr);
2954
2955 nvlpacked = nvlist_pack(nvl, &nv->len);
2956 if (nvlpacked == NULL)
2957 ERROUT(ENOMEM);
2958
2959 if (nv->size == 0)
2960 ERROUT(0);
2961 else if (nv->size < nv->len)
2962 ERROUT(ENOSPC);
2963
2964 error = copyout(nvlpacked, nv->data, nv->len);
2965
2966 #undef ERROUT
2967 DIOCGETETHRULESETS_error:
2968 free(nvlpacked, M_NVLIST);
2969 nvlist_destroy(nvl);
2970 break;
2971 }
2972
2973 case DIOCGETETHRULESET: {
2974 struct epoch_tracker et;
2975 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
2976 nvlist_t *nvl = NULL;
2977 void *nvlpacked = NULL;
2978 struct pf_keth_ruleset *ruleset;
2979 struct pf_keth_anchor *anchor;
2980 int nr = 0, req_nr = 0;
2981 bool found = false;
2982
2983 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULESET_error, x)
2984
2985 if (nv->len > pf_ioctl_maxcount)
2986 ERROUT(ENOMEM);
2987
2988 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
2989 if (nvlpacked == NULL)
2990 ERROUT(ENOMEM);
2991
2992 error = copyin(nv->data, nvlpacked, nv->len);
2993 if (error)
2994 ERROUT(error);
2995
2996 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
2997 if (nvl == NULL)
2998 ERROUT(EBADMSG);
2999 if (! nvlist_exists_string(nvl, "path"))
3000 ERROUT(EBADMSG);
3001 if (! nvlist_exists_number(nvl, "nr"))
3002 ERROUT(EBADMSG);
3003
3004 req_nr = nvlist_get_number(nvl, "nr");
3005
3006 NET_EPOCH_ENTER(et);
3007
3008 if ((ruleset = pf_find_keth_ruleset(
3009 nvlist_get_string(nvl, "path"))) == NULL) {
3010 NET_EPOCH_EXIT(et);
3011 ERROUT(ENOENT);
3012 }
3013
3014 nvlist_destroy(nvl);
3015 nvl = NULL;
3016 free(nvlpacked, M_NVLIST);
3017 nvlpacked = NULL;
3018
3019 nvl = nvlist_create(0);
3020 if (nvl == NULL) {
3021 NET_EPOCH_EXIT(et);
3022 ERROUT(ENOMEM);
3023 }
3024
3025 if (ruleset->anchor == NULL) {
3026 RB_FOREACH(anchor, pf_keth_anchor_global,
3027 &V_pf_keth_anchors) {
3028 if (anchor->parent == NULL && nr++ == req_nr) {
3029 found = true;
3030 break;
3031 }
3032 }
3033 } else {
3034 RB_FOREACH(anchor, pf_keth_anchor_node,
3035 &ruleset->anchor->children) {
3036 if (nr++ == req_nr) {
3037 found = true;
3038 break;
3039 }
3040 }
3041 }
3042
3043 NET_EPOCH_EXIT(et);
3044 if (found) {
3045 nvlist_add_number(nvl, "nr", nr);
3046 nvlist_add_string(nvl, "name", anchor->name);
3047 if (ruleset->anchor)
3048 nvlist_add_string(nvl, "path",
3049 ruleset->anchor->path);
3050 else
3051 nvlist_add_string(nvl, "path", "");
3052 } else {
3053 ERROUT(EBUSY);
3054 }
3055
3056 nvlpacked = nvlist_pack(nvl, &nv->len);
3057 if (nvlpacked == NULL)
3058 ERROUT(ENOMEM);
3059
3060 if (nv->size == 0)
3061 ERROUT(0);
3062 else if (nv->size < nv->len)
3063 ERROUT(ENOSPC);
3064
3065 error = copyout(nvlpacked, nv->data, nv->len);
3066
3067 #undef ERROUT
3068 DIOCGETETHRULESET_error:
3069 free(nvlpacked, M_NVLIST);
3070 nvlist_destroy(nvl);
3071 break;
3072 }
3073
3074 case DIOCADDRULENV: {
3075 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3076 nvlist_t *nvl = NULL;
3077 void *nvlpacked = NULL;
3078 struct pf_krule *rule = NULL;
3079 const char *anchor = "", *anchor_call = "";
3080 uint32_t ticket = 0, pool_ticket = 0;
3081
3082 #define ERROUT(x) ERROUT_IOCTL(DIOCADDRULENV_error, x)
3083
3084 if (nv->len > pf_ioctl_maxcount)
3085 ERROUT(ENOMEM);
3086
3087 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3088 error = copyin(nv->data, nvlpacked, nv->len);
3089 if (error)
3090 ERROUT(error);
3091
3092 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3093 if (nvl == NULL)
3094 ERROUT(EBADMSG);
3095
3096 if (! nvlist_exists_number(nvl, "ticket"))
3097 ERROUT(EINVAL);
3098 ticket = nvlist_get_number(nvl, "ticket");
3099
3100 if (! nvlist_exists_number(nvl, "pool_ticket"))
3101 ERROUT(EINVAL);
3102 pool_ticket = nvlist_get_number(nvl, "pool_ticket");
3103
3104 if (! nvlist_exists_nvlist(nvl, "rule"))
3105 ERROUT(EINVAL);
3106
3107 rule = pf_krule_alloc();
3108 error = pf_nvrule_to_krule(nvlist_get_nvlist(nvl, "rule"),
3109 rule);
3110 if (error)
3111 ERROUT(error);
3112
3113 if (nvlist_exists_string(nvl, "anchor"))
3114 anchor = nvlist_get_string(nvl, "anchor");
3115 if (nvlist_exists_string(nvl, "anchor_call"))
3116 anchor_call = nvlist_get_string(nvl, "anchor_call");
3117
3118 if ((error = nvlist_error(nvl)))
3119 ERROUT(error);
3120
3121 /* Frees rule on error */
3122 error = pf_ioctl_addrule(rule, ticket, pool_ticket, anchor,
3123 anchor_call, td->td_ucred->cr_ruid,
3124 td->td_proc ? td->td_proc->p_pid : 0);
3125
3126 nvlist_destroy(nvl);
3127 free(nvlpacked, M_NVLIST);
3128 break;
3129 #undef ERROUT
3130 DIOCADDRULENV_error:
3131 pf_krule_free(rule);
3132 nvlist_destroy(nvl);
3133 free(nvlpacked, M_NVLIST);
3134
3135 break;
3136 }
3137 case DIOCADDRULE: {
3138 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
3139 struct pf_krule *rule;
3140
3141 rule = pf_krule_alloc();
3142 error = pf_rule_to_krule(&pr->rule, rule);
3143 if (error != 0) {
3144 pf_krule_free(rule);
3145 break;
3146 }
3147
3148 pr->anchor[sizeof(pr->anchor) - 1] = 0;
3149
3150 /* Frees rule on error */
3151 error = pf_ioctl_addrule(rule, pr->ticket, pr->pool_ticket,
3152 pr->anchor, pr->anchor_call, td->td_ucred->cr_ruid,
3153 td->td_proc ? td->td_proc->p_pid : 0);
3154 break;
3155 }
3156
3157 case DIOCGETRULES: {
3158 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
3159
3160 pr->anchor[sizeof(pr->anchor) - 1] = 0;
3161
3162 error = pf_ioctl_getrules(pr);
3163
3164 break;
3165 }
3166
3167 case DIOCGETRULENV: {
3168 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3169 nvlist_t *nvrule = NULL;
3170 nvlist_t *nvl = NULL;
3171 struct pf_kruleset *ruleset;
3172 struct pf_krule *rule;
3173 void *nvlpacked = NULL;
3174 int rs_num, nr;
3175 bool clear_counter = false;
3176
3177 #define ERROUT(x) ERROUT_IOCTL(DIOCGETRULENV_error, x)
3178
3179 if (nv->len > pf_ioctl_maxcount)
3180 ERROUT(ENOMEM);
3181
3182 /* Copy the request in */
3183 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3184 if (nvlpacked == NULL)
3185 ERROUT(ENOMEM);
3186
3187 error = copyin(nv->data, nvlpacked, nv->len);
3188 if (error)
3189 ERROUT(error);
3190
3191 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3192 if (nvl == NULL)
3193 ERROUT(EBADMSG);
3194
3195 if (! nvlist_exists_string(nvl, "anchor"))
3196 ERROUT(EBADMSG);
3197 if (! nvlist_exists_number(nvl, "ruleset"))
3198 ERROUT(EBADMSG);
3199 if (! nvlist_exists_number(nvl, "ticket"))
3200 ERROUT(EBADMSG);
3201 if (! nvlist_exists_number(nvl, "nr"))
3202 ERROUT(EBADMSG);
3203
3204 if (nvlist_exists_bool(nvl, "clear_counter"))
3205 clear_counter = nvlist_get_bool(nvl, "clear_counter");
3206
3207 if (clear_counter && !(flags & FWRITE))
3208 ERROUT(EACCES);
3209
3210 nr = nvlist_get_number(nvl, "nr");
3211
3212 PF_RULES_WLOCK();
3213 ruleset = pf_find_kruleset(nvlist_get_string(nvl, "anchor"));
3214 if (ruleset == NULL) {
3215 PF_RULES_WUNLOCK();
3216 ERROUT(ENOENT);
3217 }
3218
3219 rs_num = pf_get_ruleset_number(nvlist_get_number(nvl, "ruleset"));
3220 if (rs_num >= PF_RULESET_MAX) {
3221 PF_RULES_WUNLOCK();
3222 ERROUT(EINVAL);
3223 }
3224
3225 if (nvlist_get_number(nvl, "ticket") !=
3226 ruleset->rules[rs_num].active.ticket) {
3227 PF_RULES_WUNLOCK();
3228 ERROUT(EBUSY);
3229 }
3230
3231 if ((error = nvlist_error(nvl))) {
3232 PF_RULES_WUNLOCK();
3233 ERROUT(error);
3234 }
3235
3236 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
3237 while ((rule != NULL) && (rule->nr != nr))
3238 rule = TAILQ_NEXT(rule, entries);
3239 if (rule == NULL) {
3240 PF_RULES_WUNLOCK();
3241 ERROUT(EBUSY);
3242 }
3243
3244 nvrule = pf_krule_to_nvrule(rule);
3245
3246 nvlist_destroy(nvl);
3247 nvl = nvlist_create(0);
3248 if (nvl == NULL) {
3249 PF_RULES_WUNLOCK();
3250 ERROUT(ENOMEM);
3251 }
3252 nvlist_add_number(nvl, "nr", nr);
3253 nvlist_add_nvlist(nvl, "rule", nvrule);
3254 nvlist_destroy(nvrule);
3255 nvrule = NULL;
3256 if (pf_kanchor_nvcopyout(ruleset, rule, nvl)) {
3257 PF_RULES_WUNLOCK();
3258 ERROUT(EBUSY);
3259 }
3260
3261 free(nvlpacked, M_NVLIST);
3262 nvlpacked = nvlist_pack(nvl, &nv->len);
3263 if (nvlpacked == NULL) {
3264 PF_RULES_WUNLOCK();
3265 ERROUT(ENOMEM);
3266 }
3267
3268 if (nv->size == 0) {
3269 PF_RULES_WUNLOCK();
3270 ERROUT(0);
3271 }
3272 else if (nv->size < nv->len) {
3273 PF_RULES_WUNLOCK();
3274 ERROUT(ENOSPC);
3275 }
3276
3277 if (clear_counter)
3278 pf_krule_clear_counters(rule);
3279
3280 PF_RULES_WUNLOCK();
3281
3282 error = copyout(nvlpacked, nv->data, nv->len);
3283
3284 #undef ERROUT
3285 DIOCGETRULENV_error:
3286 free(nvlpacked, M_NVLIST);
3287 nvlist_destroy(nvrule);
3288 nvlist_destroy(nvl);
3289
3290 break;
3291 }
3292
3293 case DIOCCHANGERULE: {
3294 struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
3295 struct pf_kruleset *ruleset;
3296 struct pf_krule *oldrule = NULL, *newrule = NULL;
3297 struct pfi_kkif *kif = NULL;
3298 struct pf_kpooladdr *pa;
3299 u_int32_t nr = 0;
3300 int rs_num;
3301
3302 pcr->anchor[sizeof(pcr->anchor) - 1] = 0;
3303
3304 if (pcr->action < PF_CHANGE_ADD_HEAD ||
3305 pcr->action > PF_CHANGE_GET_TICKET) {
3306 error = EINVAL;
3307 break;
3308 }
3309 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
3310 error = EINVAL;
3311 break;
3312 }
3313
3314 if (pcr->action != PF_CHANGE_REMOVE) {
3315 newrule = pf_krule_alloc();
3316 error = pf_rule_to_krule(&pcr->rule, newrule);
3317 if (error != 0) {
3318 pf_krule_free(newrule);
3319 break;
3320 }
3321
3322 if (newrule->ifname[0])
3323 kif = pf_kkif_create(M_WAITOK);
3324 pf_counter_u64_init(&newrule->evaluations, M_WAITOK);
3325 for (int i = 0; i < 2; i++) {
3326 pf_counter_u64_init(&newrule->packets[i], M_WAITOK);
3327 pf_counter_u64_init(&newrule->bytes[i], M_WAITOK);
3328 }
3329 newrule->states_cur = counter_u64_alloc(M_WAITOK);
3330 newrule->states_tot = counter_u64_alloc(M_WAITOK);
3331 newrule->src_nodes = counter_u64_alloc(M_WAITOK);
3332 newrule->cuid = td->td_ucred->cr_ruid;
3333 newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
3334 TAILQ_INIT(&newrule->rpool.list);
3335 }
3336 #define ERROUT(x) ERROUT_IOCTL(DIOCCHANGERULE_error, x)
3337
3338 PF_CONFIG_LOCK();
3339 PF_RULES_WLOCK();
3340 #ifdef PF_WANT_32_TO_64_COUNTER
3341 if (newrule != NULL) {
3342 LIST_INSERT_HEAD(&V_pf_allrulelist, newrule, allrulelist);
3343 newrule->allrulelinked = true;
3344 V_pf_allrulecount++;
3345 }
3346 #endif
3347
3348 if (!(pcr->action == PF_CHANGE_REMOVE ||
3349 pcr->action == PF_CHANGE_GET_TICKET) &&
3350 pcr->pool_ticket != V_ticket_pabuf)
3351 ERROUT(EBUSY);
3352
3353 ruleset = pf_find_kruleset(pcr->anchor);
3354 if (ruleset == NULL)
3355 ERROUT(EINVAL);
3356
3357 rs_num = pf_get_ruleset_number(pcr->rule.action);
3358 if (rs_num >= PF_RULESET_MAX)
3359 ERROUT(EINVAL);
3360
3361 /*
3362 * XXXMJG: there is no guarantee that the ruleset was
3363 * created by the usual route of calling DIOCXBEGIN.
3364 * As a result it is possible the rule tree will not
3365 * be allocated yet. Hack around it by doing it here.
3366 * Note it is fine to let the tree persist in case of
3367 * error as it will be freed down the road on future
3368 * updates (if need be).
3369 */
3370 if (ruleset->rules[rs_num].active.tree == NULL) {
3371 ruleset->rules[rs_num].active.tree = pf_rule_tree_alloc(M_NOWAIT);
3372 if (ruleset->rules[rs_num].active.tree == NULL) {
3373 ERROUT(ENOMEM);
3374 }
3375 }
3376
3377 if (pcr->action == PF_CHANGE_GET_TICKET) {
3378 pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
3379 ERROUT(0);
3380 } else if (pcr->ticket !=
3381 ruleset->rules[rs_num].active.ticket)
3382 ERROUT(EINVAL);
3383
3384 if (pcr->action != PF_CHANGE_REMOVE) {
3385 if (newrule->ifname[0]) {
3386 newrule->kif = pfi_kkif_attach(kif,
3387 newrule->ifname);
3388 kif = NULL;
3389 pfi_kkif_ref(newrule->kif);
3390 } else
3391 newrule->kif = NULL;
3392
3393 if (newrule->rtableid > 0 &&
3394 newrule->rtableid >= rt_numfibs)
3395 error = EBUSY;
3396
3397 #ifdef ALTQ
3398 /* set queue IDs */
3399 if (newrule->qname[0] != 0) {
3400 if ((newrule->qid =
3401 pf_qname2qid(newrule->qname)) == 0)
3402 error = EBUSY;
3403 else if (newrule->pqname[0] != 0) {
3404 if ((newrule->pqid =
3405 pf_qname2qid(newrule->pqname)) == 0)
3406 error = EBUSY;
3407 } else
3408 newrule->pqid = newrule->qid;
3409 }
3410 #endif /* ALTQ */
3411 if (newrule->tagname[0])
3412 if ((newrule->tag =
3413 pf_tagname2tag(newrule->tagname)) == 0)
3414 error = EBUSY;
3415 if (newrule->match_tagname[0])
3416 if ((newrule->match_tag = pf_tagname2tag(
3417 newrule->match_tagname)) == 0)
3418 error = EBUSY;
3419 if (newrule->rt && !newrule->direction)
3420 error = EINVAL;
3421 if (!newrule->log)
3422 newrule->logif = 0;
3423 if (newrule->logif >= PFLOGIFS_MAX)
3424 error = EINVAL;
3425 if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af))
3426 error = ENOMEM;
3427 if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
3428 error = ENOMEM;
3429 if (pf_kanchor_setup(newrule, ruleset, pcr->anchor_call))
3430 error = EINVAL;
3431 TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
3432 if (pa->addr.type == PF_ADDR_TABLE) {
3433 pa->addr.p.tbl =
3434 pfr_attach_table(ruleset,
3435 pa->addr.v.tblname);
3436 if (pa->addr.p.tbl == NULL)
3437 error = ENOMEM;
3438 }
3439
3440 newrule->overload_tbl = NULL;
3441 if (newrule->overload_tblname[0]) {
3442 if ((newrule->overload_tbl = pfr_attach_table(
3443 ruleset, newrule->overload_tblname)) ==
3444 NULL)
3445 error = EINVAL;
3446 else
3447 newrule->overload_tbl->pfrkt_flags |=
3448 PFR_TFLAG_ACTIVE;
3449 }
3450
3451 pf_mv_kpool(&V_pf_pabuf, &newrule->rpool.list);
3452 if (((((newrule->action == PF_NAT) ||
3453 (newrule->action == PF_RDR) ||
3454 (newrule->action == PF_BINAT) ||
3455 (newrule->rt > PF_NOPFROUTE)) &&
3456 !newrule->anchor)) &&
3457 (TAILQ_FIRST(&newrule->rpool.list) == NULL))
3458 error = EINVAL;
3459
3460 if (error) {
3461 pf_free_rule(newrule);
3462 PF_RULES_WUNLOCK();
3463 PF_CONFIG_UNLOCK();
3464 break;
3465 }
3466
3467 newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
3468 }
3469 pf_empty_kpool(&V_pf_pabuf);
3470
3471 if (pcr->action == PF_CHANGE_ADD_HEAD)
3472 oldrule = TAILQ_FIRST(
3473 ruleset->rules[rs_num].active.ptr);
3474 else if (pcr->action == PF_CHANGE_ADD_TAIL)
3475 oldrule = TAILQ_LAST(
3476 ruleset->rules[rs_num].active.ptr, pf_krulequeue);
3477 else {
3478 oldrule = TAILQ_FIRST(
3479 ruleset->rules[rs_num].active.ptr);
3480 while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
3481 oldrule = TAILQ_NEXT(oldrule, entries);
3482 if (oldrule == NULL) {
3483 if (newrule != NULL)
3484 pf_free_rule(newrule);
3485 PF_RULES_WUNLOCK();
3486 PF_CONFIG_UNLOCK();
3487 error = EINVAL;
3488 break;
3489 }
3490 }
3491
3492 if (pcr->action == PF_CHANGE_REMOVE) {
3493 pf_unlink_rule(ruleset->rules[rs_num].active.ptr,
3494 oldrule);
3495 RB_REMOVE(pf_krule_global,
3496 ruleset->rules[rs_num].active.tree, oldrule);
3497 ruleset->rules[rs_num].active.rcount--;
3498 } else {
3499 pf_hash_rule(newrule);
3500 if (RB_INSERT(pf_krule_global,
3501 ruleset->rules[rs_num].active.tree, newrule) != NULL) {
3502 pf_free_rule(newrule);
3503 PF_RULES_WUNLOCK();
3504 PF_CONFIG_UNLOCK();
3505 error = EEXIST;
3506 break;
3507 }
3508
3509 if (oldrule == NULL)
3510 TAILQ_INSERT_TAIL(
3511 ruleset->rules[rs_num].active.ptr,
3512 newrule, entries);
3513 else if (pcr->action == PF_CHANGE_ADD_HEAD ||
3514 pcr->action == PF_CHANGE_ADD_BEFORE)
3515 TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
3516 else
3517 TAILQ_INSERT_AFTER(
3518 ruleset->rules[rs_num].active.ptr,
3519 oldrule, newrule, entries);
3520 ruleset->rules[rs_num].active.rcount++;
3521 }
3522
3523 nr = 0;
3524 TAILQ_FOREACH(oldrule,
3525 ruleset->rules[rs_num].active.ptr, entries)
3526 oldrule->nr = nr++;
3527
3528 ruleset->rules[rs_num].active.ticket++;
3529
3530 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
3531 pf_remove_if_empty_kruleset(ruleset);
3532
3533 PF_RULES_WUNLOCK();
3534 PF_CONFIG_UNLOCK();
3535 break;
3536
3537 #undef ERROUT
3538 DIOCCHANGERULE_error:
3539 PF_RULES_WUNLOCK();
3540 PF_CONFIG_UNLOCK();
3541 pf_krule_free(newrule);
3542 pf_kkif_free(kif);
3543 break;
3544 }
3545
3546 case DIOCCLRSTATESNV: {
3547 error = pf_clearstates_nv((struct pfioc_nv *)addr);
3548 break;
3549 }
3550
3551 case DIOCKILLSTATESNV: {
3552 error = pf_killstates_nv((struct pfioc_nv *)addr);
3553 break;
3554 }
3555
3556 case DIOCADDSTATE: {
3557 struct pfioc_state *ps = (struct pfioc_state *)addr;
3558 struct pfsync_state_1301 *sp = &ps->state;
3559
3560 if (sp->timeout >= PFTM_MAX) {
3561 error = EINVAL;
3562 break;
3563 }
3564 if (V_pfsync_state_import_ptr != NULL) {
3565 PF_RULES_RLOCK();
3566 error = V_pfsync_state_import_ptr(
3567 (union pfsync_state_union *)sp, PFSYNC_SI_IOCTL,
3568 PFSYNC_MSG_VERSION_1301);
3569 PF_RULES_RUNLOCK();
3570 } else
3571 error = EOPNOTSUPP;
3572 break;
3573 }
3574
3575 case DIOCGETSTATE: {
3576 struct pfioc_state *ps = (struct pfioc_state *)addr;
3577 struct pf_kstate *s;
3578
3579 s = pf_find_state_byid(ps->state.id, ps->state.creatorid);
3580 if (s == NULL) {
3581 error = ENOENT;
3582 break;
3583 }
3584
3585 pfsync_state_export((union pfsync_state_union*)&ps->state,
3586 s, PFSYNC_MSG_VERSION_1301);
3587 PF_STATE_UNLOCK(s);
3588 break;
3589 }
3590
3591 case DIOCGETSTATENV: {
3592 error = pf_getstate((struct pfioc_nv *)addr);
3593 break;
3594 }
3595
3596 #ifdef COMPAT_FREEBSD14
3597 case DIOCGETSTATES: {
3598 struct pfioc_states *ps = (struct pfioc_states *)addr;
3599 struct pf_kstate *s;
3600 struct pfsync_state_1301 *pstore, *p;
3601 int i, nr;
3602 size_t slice_count = 16, count;
3603 void *out;
3604
3605 if (ps->ps_len <= 0) {
3606 nr = uma_zone_get_cur(V_pf_state_z);
3607 ps->ps_len = sizeof(struct pfsync_state_1301) * nr;
3608 break;
3609 }
3610
3611 out = ps->ps_states;
3612 pstore = mallocarray(slice_count,
3613 sizeof(struct pfsync_state_1301), M_TEMP, M_WAITOK | M_ZERO);
3614 nr = 0;
3615
3616 for (i = 0; i <= pf_hashmask; i++) {
3617 struct pf_idhash *ih = &V_pf_idhash[i];
3618
3619 DIOCGETSTATES_retry:
3620 p = pstore;
3621
3622 if (LIST_EMPTY(&ih->states))
3623 continue;
3624
3625 PF_HASHROW_LOCK(ih);
3626 count = 0;
3627 LIST_FOREACH(s, &ih->states, entry) {
3628 if (s->timeout == PFTM_UNLINKED)
3629 continue;
3630 count++;
3631 }
3632
3633 if (count > slice_count) {
3634 PF_HASHROW_UNLOCK(ih);
3635 free(pstore, M_TEMP);
3636 slice_count = count * 2;
3637 pstore = mallocarray(slice_count,
3638 sizeof(struct pfsync_state_1301), M_TEMP,
3639 M_WAITOK | M_ZERO);
3640 goto DIOCGETSTATES_retry;
3641 }
3642
3643 if ((nr+count) * sizeof(*p) > ps->ps_len) {
3644 PF_HASHROW_UNLOCK(ih);
3645 goto DIOCGETSTATES_full;
3646 }
3647
3648 LIST_FOREACH(s, &ih->states, entry) {
3649 if (s->timeout == PFTM_UNLINKED)
3650 continue;
3651
3652 pfsync_state_export((union pfsync_state_union*)p,
3653 s, PFSYNC_MSG_VERSION_1301);
3654 p++;
3655 nr++;
3656 }
3657 PF_HASHROW_UNLOCK(ih);
3658 error = copyout(pstore, out,
3659 sizeof(struct pfsync_state_1301) * count);
3660 if (error)
3661 break;
3662 out = ps->ps_states + nr;
3663 }
3664 DIOCGETSTATES_full:
3665 ps->ps_len = sizeof(struct pfsync_state_1301) * nr;
3666 free(pstore, M_TEMP);
3667
3668 break;
3669 }
3670
3671 case DIOCGETSTATESV2: {
3672 struct pfioc_states_v2 *ps = (struct pfioc_states_v2 *)addr;
3673 struct pf_kstate *s;
3674 struct pf_state_export *pstore, *p;
3675 int i, nr;
3676 size_t slice_count = 16, count;
3677 void *out;
3678
3679 if (ps->ps_req_version > PF_STATE_VERSION) {
3680 error = ENOTSUP;
3681 break;
3682 }
3683
3684 if (ps->ps_len <= 0) {
3685 nr = uma_zone_get_cur(V_pf_state_z);
3686 ps->ps_len = sizeof(struct pf_state_export) * nr;
3687 break;
3688 }
3689
3690 out = ps->ps_states;
3691 pstore = mallocarray(slice_count,
3692 sizeof(struct pf_state_export), M_TEMP, M_WAITOK | M_ZERO);
3693 nr = 0;
3694
3695 for (i = 0; i <= pf_hashmask; i++) {
3696 struct pf_idhash *ih = &V_pf_idhash[i];
3697
3698 DIOCGETSTATESV2_retry:
3699 p = pstore;
3700
3701 if (LIST_EMPTY(&ih->states))
3702 continue;
3703
3704 PF_HASHROW_LOCK(ih);
3705 count = 0;
3706 LIST_FOREACH(s, &ih->states, entry) {
3707 if (s->timeout == PFTM_UNLINKED)
3708 continue;
3709 count++;
3710 }
3711
3712 if (count > slice_count) {
3713 PF_HASHROW_UNLOCK(ih);
3714 free(pstore, M_TEMP);
3715 slice_count = count * 2;
3716 pstore = mallocarray(slice_count,
3717 sizeof(struct pf_state_export), M_TEMP,
3718 M_WAITOK | M_ZERO);
3719 goto DIOCGETSTATESV2_retry;
3720 }
3721
3722 if ((nr+count) * sizeof(*p) > ps->ps_len) {
3723 PF_HASHROW_UNLOCK(ih);
3724 goto DIOCGETSTATESV2_full;
3725 }
3726
3727 LIST_FOREACH(s, &ih->states, entry) {
3728 if (s->timeout == PFTM_UNLINKED)
3729 continue;
3730
3731 pf_state_export(p, s);
3732 p++;
3733 nr++;
3734 }
3735 PF_HASHROW_UNLOCK(ih);
3736 error = copyout(pstore, out,
3737 sizeof(struct pf_state_export) * count);
3738 if (error)
3739 break;
3740 out = ps->ps_states + nr;
3741 }
3742 DIOCGETSTATESV2_full:
3743 ps->ps_len = nr * sizeof(struct pf_state_export);
3744 free(pstore, M_TEMP);
3745
3746 break;
3747 }
3748 #endif
3749 case DIOCGETSTATUSNV: {
3750 error = pf_getstatus((struct pfioc_nv *)addr);
3751 break;
3752 }
3753
3754 case DIOCSETSTATUSIF: {
3755 struct pfioc_if *pi = (struct pfioc_if *)addr;
3756
3757 if (pi->ifname[0] == 0) {
3758 bzero(V_pf_status.ifname, IFNAMSIZ);
3759 break;
3760 }
3761 PF_RULES_WLOCK();
3762 error = pf_user_strcpy(V_pf_status.ifname, pi->ifname, IFNAMSIZ);
3763 PF_RULES_WUNLOCK();
3764 break;
3765 }
3766
3767 case DIOCCLRSTATUS: {
3768 PF_RULES_WLOCK();
3769 for (int i = 0; i < PFRES_MAX; i++)
3770 counter_u64_zero(V_pf_status.counters[i]);
3771 for (int i = 0; i < FCNT_MAX; i++)
3772 pf_counter_u64_zero(&V_pf_status.fcounters[i]);
3773 for (int i = 0; i < SCNT_MAX; i++)
3774 counter_u64_zero(V_pf_status.scounters[i]);
3775 for (int i = 0; i < KLCNT_MAX; i++)
3776 counter_u64_zero(V_pf_status.lcounters[i]);
3777 V_pf_status.since = time_second;
3778 if (*V_pf_status.ifname)
3779 pfi_update_status(V_pf_status.ifname, NULL);
3780 PF_RULES_WUNLOCK();
3781 break;
3782 }
3783
3784 case DIOCNATLOOK: {
3785 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
3786 struct pf_state_key *sk;
3787 struct pf_kstate *state;
3788 struct pf_state_key_cmp key;
3789 int m = 0, direction = pnl->direction;
3790 int sidx, didx;
3791
3792 /* NATLOOK src and dst are reversed, so reverse sidx/didx */
3793 sidx = (direction == PF_IN) ? 1 : 0;
3794 didx = (direction == PF_IN) ? 0 : 1;
3795
3796 if (!pnl->proto ||
3797 PF_AZERO(&pnl->saddr, pnl->af) ||
3798 PF_AZERO(&pnl->daddr, pnl->af) ||
3799 ((pnl->proto == IPPROTO_TCP ||
3800 pnl->proto == IPPROTO_UDP) &&
3801 (!pnl->dport || !pnl->sport)))
3802 error = EINVAL;
3803 else {
3804 bzero(&key, sizeof(key));
3805 key.af = pnl->af;
3806 key.proto = pnl->proto;
3807 PF_ACPY(&key.addr[sidx], &pnl->saddr, pnl->af);
3808 key.port[sidx] = pnl->sport;
3809 PF_ACPY(&key.addr[didx], &pnl->daddr, pnl->af);
3810 key.port[didx] = pnl->dport;
3811
3812 state = pf_find_state_all(&key, direction, &m);
3813 if (state == NULL) {
3814 error = ENOENT;
3815 } else {
3816 if (m > 1) {
3817 PF_STATE_UNLOCK(state);
3818 error = E2BIG; /* more than one state */
3819 } else {
3820 sk = state->key[sidx];
3821 PF_ACPY(&pnl->rsaddr, &sk->addr[sidx], sk->af);
3822 pnl->rsport = sk->port[sidx];
3823 PF_ACPY(&pnl->rdaddr, &sk->addr[didx], sk->af);
3824 pnl->rdport = sk->port[didx];
3825 PF_STATE_UNLOCK(state);
3826 }
3827 }
3828 }
3829 break;
3830 }
3831
3832 case DIOCSETTIMEOUT: {
3833 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
3834 int old;
3835
3836 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
3837 pt->seconds < 0) {
3838 error = EINVAL;
3839 break;
3840 }
3841 PF_RULES_WLOCK();
3842 old = V_pf_default_rule.timeout[pt->timeout];
3843 if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
3844 pt->seconds = 1;
3845 V_pf_default_rule.timeout[pt->timeout] = pt->seconds;
3846 if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
3847 wakeup(pf_purge_thread);
3848 pt->seconds = old;
3849 PF_RULES_WUNLOCK();
3850 break;
3851 }
3852
3853 case DIOCGETTIMEOUT: {
3854 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
3855
3856 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
3857 error = EINVAL;
3858 break;
3859 }
3860 PF_RULES_RLOCK();
3861 pt->seconds = V_pf_default_rule.timeout[pt->timeout];
3862 PF_RULES_RUNLOCK();
3863 break;
3864 }
3865
3866 case DIOCGETLIMIT: {
3867 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
3868
3869 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
3870 error = EINVAL;
3871 break;
3872 }
3873 PF_RULES_RLOCK();
3874 pl->limit = V_pf_limits[pl->index].limit;
3875 PF_RULES_RUNLOCK();
3876 break;
3877 }
3878
3879 case DIOCSETLIMIT: {
3880 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
3881 int old_limit;
3882
3883 PF_RULES_WLOCK();
3884 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
3885 V_pf_limits[pl->index].zone == NULL) {
3886 PF_RULES_WUNLOCK();
3887 error = EINVAL;
3888 break;
3889 }
3890 uma_zone_set_max(V_pf_limits[pl->index].zone, pl->limit);
3891 old_limit = V_pf_limits[pl->index].limit;
3892 V_pf_limits[pl->index].limit = pl->limit;
3893 pl->limit = old_limit;
3894 PF_RULES_WUNLOCK();
3895 break;
3896 }
3897
3898 case DIOCSETDEBUG: {
3899 u_int32_t *level = (u_int32_t *)addr;
3900
3901 PF_RULES_WLOCK();
3902 V_pf_status.debug = *level;
3903 PF_RULES_WUNLOCK();
3904 break;
3905 }
3906
3907 case DIOCCLRRULECTRS: {
3908 /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
3909 struct pf_kruleset *ruleset = &pf_main_ruleset;
3910 struct pf_krule *rule;
3911
3912 PF_RULES_WLOCK();
3913 TAILQ_FOREACH(rule,
3914 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
3915 pf_counter_u64_zero(&rule->evaluations);
3916 for (int i = 0; i < 2; i++) {
3917 pf_counter_u64_zero(&rule->packets[i]);
3918 pf_counter_u64_zero(&rule->bytes[i]);
3919 }
3920 }
3921 PF_RULES_WUNLOCK();
3922 break;
3923 }
3924
3925 case DIOCGIFSPEEDV0:
3926 case DIOCGIFSPEEDV1: {
3927 struct pf_ifspeed_v1 *psp = (struct pf_ifspeed_v1 *)addr;
3928 struct pf_ifspeed_v1 ps;
3929 struct ifnet *ifp;
3930
3931 if (psp->ifname[0] == '\0') {
3932 error = EINVAL;
3933 break;
3934 }
3935
3936 error = pf_user_strcpy(ps.ifname, psp->ifname, IFNAMSIZ);
3937 if (error != 0)
3938 break;
3939 ifp = ifunit(ps.ifname);
3940 if (ifp != NULL) {
3941 psp->baudrate32 =
3942 (u_int32_t)uqmin(ifp->if_baudrate, UINT_MAX);
3943 if (cmd == DIOCGIFSPEEDV1)
3944 psp->baudrate = ifp->if_baudrate;
3945 } else {
3946 error = EINVAL;
3947 }
3948 break;
3949 }
3950
3951 #ifdef ALTQ
3952 case DIOCSTARTALTQ: {
3953 struct pf_altq *altq;
3954
3955 PF_RULES_WLOCK();
3956 /* enable all altq interfaces on active list */
3957 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
3958 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
3959 error = pf_enable_altq(altq);
3960 if (error != 0)
3961 break;
3962 }
3963 }
3964 if (error == 0)
3965 V_pf_altq_running = 1;
3966 PF_RULES_WUNLOCK();
3967 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
3968 break;
3969 }
3970
3971 case DIOCSTOPALTQ: {
3972 struct pf_altq *altq;
3973
3974 PF_RULES_WLOCK();
3975 /* disable all altq interfaces on active list */
3976 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
3977 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
3978 error = pf_disable_altq(altq);
3979 if (error != 0)
3980 break;
3981 }
3982 }
3983 if (error == 0)
3984 V_pf_altq_running = 0;
3985 PF_RULES_WUNLOCK();
3986 DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
3987 break;
3988 }
3989
3990 case DIOCADDALTQV0:
3991 case DIOCADDALTQV1: {
3992 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
3993 struct pf_altq *altq, *a;
3994 struct ifnet *ifp;
3995
3996 altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK | M_ZERO);
3997 error = pf_import_kaltq(pa, altq, IOCPARM_LEN(cmd));
3998 if (error)
3999 break;
4000 altq->local_flags = 0;
4001
4002 PF_RULES_WLOCK();
4003 if (pa->ticket != V_ticket_altqs_inactive) {
4004 PF_RULES_WUNLOCK();
4005 free(altq, M_PFALTQ);
4006 error = EBUSY;
4007 break;
4008 }
4009
4010 /*
4011 * if this is for a queue, find the discipline and
4012 * copy the necessary fields
4013 */
4014 if (altq->qname[0] != 0) {
4015 if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
4016 PF_RULES_WUNLOCK();
4017 error = EBUSY;
4018 free(altq, M_PFALTQ);
4019 break;
4020 }
4021 altq->altq_disc = NULL;
4022 TAILQ_FOREACH(a, V_pf_altq_ifs_inactive, entries) {
4023 if (strncmp(a->ifname, altq->ifname,
4024 IFNAMSIZ) == 0) {
4025 altq->altq_disc = a->altq_disc;
4026 break;
4027 }
4028 }
4029 }
4030
4031 if ((ifp = ifunit(altq->ifname)) == NULL)
4032 altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
4033 else
4034 error = altq_add(ifp, altq);
4035
4036 if (error) {
4037 PF_RULES_WUNLOCK();
4038 free(altq, M_PFALTQ);
4039 break;
4040 }
4041
4042 if (altq->qname[0] != 0)
4043 TAILQ_INSERT_TAIL(V_pf_altqs_inactive, altq, entries);
4044 else
4045 TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, altq, entries);
4046 /* version error check done on import above */
4047 pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
4048 PF_RULES_WUNLOCK();
4049 break;
4050 }
4051
4052 case DIOCGETALTQSV0:
4053 case DIOCGETALTQSV1: {
4054 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4055 struct pf_altq *altq;
4056
4057 PF_RULES_RLOCK();
4058 pa->nr = 0;
4059 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries)
4060 pa->nr++;
4061 TAILQ_FOREACH(altq, V_pf_altqs_active, entries)
4062 pa->nr++;
4063 pa->ticket = V_ticket_altqs_active;
4064 PF_RULES_RUNLOCK();
4065 break;
4066 }
4067
4068 case DIOCGETALTQV0:
4069 case DIOCGETALTQV1: {
4070 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4071 struct pf_altq *altq;
4072
4073 PF_RULES_RLOCK();
4074 if (pa->ticket != V_ticket_altqs_active) {
4075 PF_RULES_RUNLOCK();
4076 error = EBUSY;
4077 break;
4078 }
4079 altq = pf_altq_get_nth_active(pa->nr);
4080 if (altq == NULL) {
4081 PF_RULES_RUNLOCK();
4082 error = EBUSY;
4083 break;
4084 }
4085 pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
4086 PF_RULES_RUNLOCK();
4087 break;
4088 }
4089
4090 case DIOCCHANGEALTQV0:
4091 case DIOCCHANGEALTQV1:
4092 /* CHANGEALTQ not supported yet! */
4093 error = ENODEV;
4094 break;
4095
4096 case DIOCGETQSTATSV0:
4097 case DIOCGETQSTATSV1: {
4098 struct pfioc_qstats_v1 *pq = (struct pfioc_qstats_v1 *)addr;
4099 struct pf_altq *altq;
4100 int nbytes;
4101 u_int32_t version;
4102
4103 PF_RULES_RLOCK();
4104 if (pq->ticket != V_ticket_altqs_active) {
4105 PF_RULES_RUNLOCK();
4106 error = EBUSY;
4107 break;
4108 }
4109 nbytes = pq->nbytes;
4110 altq = pf_altq_get_nth_active(pq->nr);
4111 if (altq == NULL) {
4112 PF_RULES_RUNLOCK();
4113 error = EBUSY;
4114 break;
4115 }
4116
4117 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
4118 PF_RULES_RUNLOCK();
4119 error = ENXIO;
4120 break;
4121 }
4122 PF_RULES_RUNLOCK();
4123 if (cmd == DIOCGETQSTATSV0)
4124 version = 0; /* DIOCGETQSTATSV0 means stats struct v0 */
4125 else
4126 version = pq->version;
4127 error = altq_getqstats(altq, pq->buf, &nbytes, version);
4128 if (error == 0) {
4129 pq->scheduler = altq->scheduler;
4130 pq->nbytes = nbytes;
4131 }
4132 break;
4133 }
4134 #endif /* ALTQ */
4135
4136 case DIOCBEGINADDRS: {
4137 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4138
4139 PF_RULES_WLOCK();
4140 pf_empty_kpool(&V_pf_pabuf);
4141 pp->ticket = ++V_ticket_pabuf;
4142 PF_RULES_WUNLOCK();
4143 break;
4144 }
4145
4146 case DIOCADDADDR: {
4147 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4148 struct pf_kpooladdr *pa;
4149 struct pfi_kkif *kif = NULL;
4150
4151 #ifndef INET
4152 if (pp->af == AF_INET) {
4153 error = EAFNOSUPPORT;
4154 break;
4155 }
4156 #endif /* INET */
4157 #ifndef INET6
4158 if (pp->af == AF_INET6) {
4159 error = EAFNOSUPPORT;
4160 break;
4161 }
4162 #endif /* INET6 */
4163 if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
4164 pp->addr.addr.type != PF_ADDR_DYNIFTL &&
4165 pp->addr.addr.type != PF_ADDR_TABLE) {
4166 error = EINVAL;
4167 break;
4168 }
4169 if (pp->addr.addr.p.dyn != NULL) {
4170 error = EINVAL;
4171 break;
4172 }
4173 pa = malloc(sizeof(*pa), M_PFRULE, M_WAITOK);
4174 error = pf_pooladdr_to_kpooladdr(&pp->addr, pa);
4175 if (error != 0)
4176 break;
4177 if (pa->ifname[0])
4178 kif = pf_kkif_create(M_WAITOK);
4179 PF_RULES_WLOCK();
4180 if (pp->ticket != V_ticket_pabuf) {
4181 PF_RULES_WUNLOCK();
4182 if (pa->ifname[0])
4183 pf_kkif_free(kif);
4184 free(pa, M_PFRULE);
4185 error = EBUSY;
4186 break;
4187 }
4188 if (pa->ifname[0]) {
4189 pa->kif = pfi_kkif_attach(kif, pa->ifname);
4190 kif = NULL;
4191 pfi_kkif_ref(pa->kif);
4192 } else
4193 pa->kif = NULL;
4194 if (pa->addr.type == PF_ADDR_DYNIFTL && ((error =
4195 pfi_dynaddr_setup(&pa->addr, pp->af)) != 0)) {
4196 if (pa->ifname[0])
4197 pfi_kkif_unref(pa->kif);
4198 PF_RULES_WUNLOCK();
4199 free(pa, M_PFRULE);
4200 break;
4201 }
4202 TAILQ_INSERT_TAIL(&V_pf_pabuf, pa, entries);
4203 PF_RULES_WUNLOCK();
4204 break;
4205 }
4206
4207 case DIOCGETADDRS: {
4208 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4209 struct pf_kpool *pool;
4210 struct pf_kpooladdr *pa;
4211
4212 pp->anchor[sizeof(pp->anchor) - 1] = 0;
4213 pp->nr = 0;
4214
4215 PF_RULES_RLOCK();
4216 pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
4217 pp->r_num, 0, 1, 0);
4218 if (pool == NULL) {
4219 PF_RULES_RUNLOCK();
4220 error = EBUSY;
4221 break;
4222 }
4223 TAILQ_FOREACH(pa, &pool->list, entries)
4224 pp->nr++;
4225 PF_RULES_RUNLOCK();
4226 break;
4227 }
4228
4229 case DIOCGETADDR: {
4230 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4231 struct pf_kpool *pool;
4232 struct pf_kpooladdr *pa;
4233 u_int32_t nr = 0;
4234
4235 pp->anchor[sizeof(pp->anchor) - 1] = 0;
4236
4237 PF_RULES_RLOCK();
4238 pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
4239 pp->r_num, 0, 1, 1);
4240 if (pool == NULL) {
4241 PF_RULES_RUNLOCK();
4242 error = EBUSY;
4243 break;
4244 }
4245 pa = TAILQ_FIRST(&pool->list);
4246 while ((pa != NULL) && (nr < pp->nr)) {
4247 pa = TAILQ_NEXT(pa, entries);
4248 nr++;
4249 }
4250 if (pa == NULL) {
4251 PF_RULES_RUNLOCK();
4252 error = EBUSY;
4253 break;
4254 }
4255 pf_kpooladdr_to_pooladdr(pa, &pp->addr);
4256 pf_addr_copyout(&pp->addr.addr);
4257 PF_RULES_RUNLOCK();
4258 break;
4259 }
4260
4261 case DIOCCHANGEADDR: {
4262 struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr;
4263 struct pf_kpool *pool;
4264 struct pf_kpooladdr *oldpa = NULL, *newpa = NULL;
4265 struct pf_kruleset *ruleset;
4266 struct pfi_kkif *kif = NULL;
4267
4268 pca->anchor[sizeof(pca->anchor) - 1] = 0;
4269
4270 if (pca->action < PF_CHANGE_ADD_HEAD ||
4271 pca->action > PF_CHANGE_REMOVE) {
4272 error = EINVAL;
4273 break;
4274 }
4275 if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
4276 pca->addr.addr.type != PF_ADDR_DYNIFTL &&
4277 pca->addr.addr.type != PF_ADDR_TABLE) {
4278 error = EINVAL;
4279 break;
4280 }
4281 if (pca->addr.addr.p.dyn != NULL) {
4282 error = EINVAL;
4283 break;
4284 }
4285
4286 if (pca->action != PF_CHANGE_REMOVE) {
4287 #ifndef INET
4288 if (pca->af == AF_INET) {
4289 error = EAFNOSUPPORT;
4290 break;
4291 }
4292 #endif /* INET */
4293 #ifndef INET6
4294 if (pca->af == AF_INET6) {
4295 error = EAFNOSUPPORT;
4296 break;
4297 }
4298 #endif /* INET6 */
4299 newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK);
4300 bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
4301 if (newpa->ifname[0])
4302 kif = pf_kkif_create(M_WAITOK);
4303 newpa->kif = NULL;
4304 }
4305 #define ERROUT(x) ERROUT_IOCTL(DIOCCHANGEADDR_error, x)
4306 PF_RULES_WLOCK();
4307 ruleset = pf_find_kruleset(pca->anchor);
4308 if (ruleset == NULL)
4309 ERROUT(EBUSY);
4310
4311 pool = pf_get_kpool(pca->anchor, pca->ticket, pca->r_action,
4312 pca->r_num, pca->r_last, 1, 1);
4313 if (pool == NULL)
4314 ERROUT(EBUSY);
4315
4316 if (pca->action != PF_CHANGE_REMOVE) {
4317 if (newpa->ifname[0]) {
4318 newpa->kif = pfi_kkif_attach(kif, newpa->ifname);
4319 pfi_kkif_ref(newpa->kif);
4320 kif = NULL;
4321 }
4322
4323 switch (newpa->addr.type) {
4324 case PF_ADDR_DYNIFTL:
4325 error = pfi_dynaddr_setup(&newpa->addr,
4326 pca->af);
4327 break;
4328 case PF_ADDR_TABLE:
4329 newpa->addr.p.tbl = pfr_attach_table(ruleset,
4330 newpa->addr.v.tblname);
4331 if (newpa->addr.p.tbl == NULL)
4332 error = ENOMEM;
4333 break;
4334 }
4335 if (error)
4336 goto DIOCCHANGEADDR_error;
4337 }
4338
4339 switch (pca->action) {
4340 case PF_CHANGE_ADD_HEAD:
4341 oldpa = TAILQ_FIRST(&pool->list);
4342 break;
4343 case PF_CHANGE_ADD_TAIL:
4344 oldpa = TAILQ_LAST(&pool->list, pf_kpalist);
4345 break;
4346 default:
4347 oldpa = TAILQ_FIRST(&pool->list);
4348 for (int i = 0; oldpa && i < pca->nr; i++)
4349 oldpa = TAILQ_NEXT(oldpa, entries);
4350
4351 if (oldpa == NULL)
4352 ERROUT(EINVAL);
4353 }
4354
4355 if (pca->action == PF_CHANGE_REMOVE) {
4356 TAILQ_REMOVE(&pool->list, oldpa, entries);
4357 switch (oldpa->addr.type) {
4358 case PF_ADDR_DYNIFTL:
4359 pfi_dynaddr_remove(oldpa->addr.p.dyn);
4360 break;
4361 case PF_ADDR_TABLE:
4362 pfr_detach_table(oldpa->addr.p.tbl);
4363 break;
4364 }
4365 if (oldpa->kif)
4366 pfi_kkif_unref(oldpa->kif);
4367 free(oldpa, M_PFRULE);
4368 } else {
4369 if (oldpa == NULL)
4370 TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
4371 else if (pca->action == PF_CHANGE_ADD_HEAD ||
4372 pca->action == PF_CHANGE_ADD_BEFORE)
4373 TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
4374 else
4375 TAILQ_INSERT_AFTER(&pool->list, oldpa,
4376 newpa, entries);
4377 }
4378
4379 pool->cur = TAILQ_FIRST(&pool->list);
4380 PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, pca->af);
4381 PF_RULES_WUNLOCK();
4382 break;
4383
4384 #undef ERROUT
4385 DIOCCHANGEADDR_error:
4386 if (newpa != NULL) {
4387 if (newpa->kif)
4388 pfi_kkif_unref(newpa->kif);
4389 free(newpa, M_PFRULE);
4390 }
4391 PF_RULES_WUNLOCK();
4392 pf_kkif_free(kif);
4393 break;
4394 }
4395
4396 case DIOCGETRULESETS: {
4397 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
4398 struct pf_kruleset *ruleset;
4399 struct pf_kanchor *anchor;
4400
4401 pr->path[sizeof(pr->path) - 1] = 0;
4402
4403 PF_RULES_RLOCK();
4404 if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
4405 PF_RULES_RUNLOCK();
4406 error = ENOENT;
4407 break;
4408 }
4409 pr->nr = 0;
4410 if (ruleset->anchor == NULL) {
4411 /* XXX kludge for pf_main_ruleset */
4412 RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
4413 if (anchor->parent == NULL)
4414 pr->nr++;
4415 } else {
4416 RB_FOREACH(anchor, pf_kanchor_node,
4417 &ruleset->anchor->children)
4418 pr->nr++;
4419 }
4420 PF_RULES_RUNLOCK();
4421 break;
4422 }
4423
4424 case DIOCGETRULESET: {
4425 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
4426 struct pf_kruleset *ruleset;
4427 struct pf_kanchor *anchor;
4428 u_int32_t nr = 0;
4429
4430 pr->path[sizeof(pr->path) - 1] = 0;
4431
4432 PF_RULES_RLOCK();
4433 if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
4434 PF_RULES_RUNLOCK();
4435 error = ENOENT;
4436 break;
4437 }
4438 pr->name[0] = 0;
4439 if (ruleset->anchor == NULL) {
4440 /* XXX kludge for pf_main_ruleset */
4441 RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
4442 if (anchor->parent == NULL && nr++ == pr->nr) {
4443 strlcpy(pr->name, anchor->name,
4444 sizeof(pr->name));
4445 break;
4446 }
4447 } else {
4448 RB_FOREACH(anchor, pf_kanchor_node,
4449 &ruleset->anchor->children)
4450 if (nr++ == pr->nr) {
4451 strlcpy(pr->name, anchor->name,
4452 sizeof(pr->name));
4453 break;
4454 }
4455 }
4456 if (!pr->name[0])
4457 error = EBUSY;
4458 PF_RULES_RUNLOCK();
4459 break;
4460 }
4461
4462 case DIOCRCLRTABLES: {
4463 struct pfioc_table *io = (struct pfioc_table *)addr;
4464
4465 if (io->pfrio_esize != 0) {
4466 error = ENODEV;
4467 break;
4468 }
4469 PF_RULES_WLOCK();
4470 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
4471 io->pfrio_flags | PFR_FLAG_USERIOCTL);
4472 PF_RULES_WUNLOCK();
4473 break;
4474 }
4475
4476 case DIOCRADDTABLES: {
4477 struct pfioc_table *io = (struct pfioc_table *)addr;
4478 struct pfr_table *pfrts;
4479 size_t totlen;
4480
4481 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4482 error = ENODEV;
4483 break;
4484 }
4485
4486 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4487 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4488 error = ENOMEM;
4489 break;
4490 }
4491
4492 totlen = io->pfrio_size * sizeof(struct pfr_table);
4493 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4494 M_TEMP, M_WAITOK);
4495 error = copyin(io->pfrio_buffer, pfrts, totlen);
4496 if (error) {
4497 free(pfrts, M_TEMP);
4498 break;
4499 }
4500 PF_RULES_WLOCK();
4501 error = pfr_add_tables(pfrts, io->pfrio_size,
4502 &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4503 PF_RULES_WUNLOCK();
4504 free(pfrts, M_TEMP);
4505 break;
4506 }
4507
4508 case DIOCRDELTABLES: {
4509 struct pfioc_table *io = (struct pfioc_table *)addr;
4510 struct pfr_table *pfrts;
4511 size_t totlen;
4512
4513 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4514 error = ENODEV;
4515 break;
4516 }
4517
4518 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4519 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4520 error = ENOMEM;
4521 break;
4522 }
4523
4524 totlen = io->pfrio_size * sizeof(struct pfr_table);
4525 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4526 M_TEMP, M_WAITOK);
4527 error = copyin(io->pfrio_buffer, pfrts, totlen);
4528 if (error) {
4529 free(pfrts, M_TEMP);
4530 break;
4531 }
4532 PF_RULES_WLOCK();
4533 error = pfr_del_tables(pfrts, io->pfrio_size,
4534 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4535 PF_RULES_WUNLOCK();
4536 free(pfrts, M_TEMP);
4537 break;
4538 }
4539
4540 case DIOCRGETTABLES: {
4541 struct pfioc_table *io = (struct pfioc_table *)addr;
4542 struct pfr_table *pfrts;
4543 size_t totlen;
4544 int n;
4545
4546 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4547 error = ENODEV;
4548 break;
4549 }
4550 PF_RULES_RLOCK();
4551 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4552 if (n < 0) {
4553 PF_RULES_RUNLOCK();
4554 error = EINVAL;
4555 break;
4556 }
4557 io->pfrio_size = min(io->pfrio_size, n);
4558
4559 totlen = io->pfrio_size * sizeof(struct pfr_table);
4560
4561 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4562 M_TEMP, M_NOWAIT | M_ZERO);
4563 if (pfrts == NULL) {
4564 error = ENOMEM;
4565 PF_RULES_RUNLOCK();
4566 break;
4567 }
4568 error = pfr_get_tables(&io->pfrio_table, pfrts,
4569 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4570 PF_RULES_RUNLOCK();
4571 if (error == 0)
4572 error = copyout(pfrts, io->pfrio_buffer, totlen);
4573 free(pfrts, M_TEMP);
4574 break;
4575 }
4576
4577 case DIOCRGETTSTATS: {
4578 struct pfioc_table *io = (struct pfioc_table *)addr;
4579 struct pfr_tstats *pfrtstats;
4580 size_t totlen;
4581 int n;
4582
4583 if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
4584 error = ENODEV;
4585 break;
4586 }
4587 PF_TABLE_STATS_LOCK();
4588 PF_RULES_RLOCK();
4589 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4590 if (n < 0) {
4591 PF_RULES_RUNLOCK();
4592 PF_TABLE_STATS_UNLOCK();
4593 error = EINVAL;
4594 break;
4595 }
4596 io->pfrio_size = min(io->pfrio_size, n);
4597
4598 totlen = io->pfrio_size * sizeof(struct pfr_tstats);
4599 pfrtstats = mallocarray(io->pfrio_size,
4600 sizeof(struct pfr_tstats), M_TEMP, M_NOWAIT | M_ZERO);
4601 if (pfrtstats == NULL) {
4602 error = ENOMEM;
4603 PF_RULES_RUNLOCK();
4604 PF_TABLE_STATS_UNLOCK();
4605 break;
4606 }
4607 error = pfr_get_tstats(&io->pfrio_table, pfrtstats,
4608 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4609 PF_RULES_RUNLOCK();
4610 PF_TABLE_STATS_UNLOCK();
4611 if (error == 0)
4612 error = copyout(pfrtstats, io->pfrio_buffer, totlen);
4613 free(pfrtstats, M_TEMP);
4614 break;
4615 }
4616
4617 case DIOCRCLRTSTATS: {
4618 struct pfioc_table *io = (struct pfioc_table *)addr;
4619 struct pfr_table *pfrts;
4620 size_t totlen;
4621
4622 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4623 error = ENODEV;
4624 break;
4625 }
4626
4627 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4628 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4629 /* We used to count tables and use the minimum required
4630 * size, so we didn't fail on overly large requests.
4631 * Keep doing so. */
4632 io->pfrio_size = pf_ioctl_maxcount;
4633 break;
4634 }
4635
4636 totlen = io->pfrio_size * sizeof(struct pfr_table);
4637 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4638 M_TEMP, M_WAITOK);
4639 error = copyin(io->pfrio_buffer, pfrts, totlen);
4640 if (error) {
4641 free(pfrts, M_TEMP);
4642 break;
4643 }
4644
4645 PF_TABLE_STATS_LOCK();
4646 PF_RULES_RLOCK();
4647 error = pfr_clr_tstats(pfrts, io->pfrio_size,
4648 &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4649 PF_RULES_RUNLOCK();
4650 PF_TABLE_STATS_UNLOCK();
4651 free(pfrts, M_TEMP);
4652 break;
4653 }
4654
4655 case DIOCRSETTFLAGS: {
4656 struct pfioc_table *io = (struct pfioc_table *)addr;
4657 struct pfr_table *pfrts;
4658 size_t totlen;
4659 int n;
4660
4661 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4662 error = ENODEV;
4663 break;
4664 }
4665
4666 PF_RULES_RLOCK();
4667 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4668 if (n < 0) {
4669 PF_RULES_RUNLOCK();
4670 error = EINVAL;
4671 break;
4672 }
4673
4674 io->pfrio_size = min(io->pfrio_size, n);
4675 PF_RULES_RUNLOCK();
4676
4677 totlen = io->pfrio_size * sizeof(struct pfr_table);
4678 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4679 M_TEMP, M_WAITOK);
4680 error = copyin(io->pfrio_buffer, pfrts, totlen);
4681 if (error) {
4682 free(pfrts, M_TEMP);
4683 break;
4684 }
4685 PF_RULES_WLOCK();
4686 error = pfr_set_tflags(pfrts, io->pfrio_size,
4687 io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
4688 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4689 PF_RULES_WUNLOCK();
4690 free(pfrts, M_TEMP);
4691 break;
4692 }
4693
4694 case DIOCRCLRADDRS: {
4695 struct pfioc_table *io = (struct pfioc_table *)addr;
4696
4697 if (io->pfrio_esize != 0) {
4698 error = ENODEV;
4699 break;
4700 }
4701 PF_RULES_WLOCK();
4702 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
4703 io->pfrio_flags | PFR_FLAG_USERIOCTL);
4704 PF_RULES_WUNLOCK();
4705 break;
4706 }
4707
4708 case DIOCRADDADDRS: {
4709 struct pfioc_table *io = (struct pfioc_table *)addr;
4710 struct pfr_addr *pfras;
4711 size_t totlen;
4712
4713 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
4714 error = ENODEV;
4715 break;
4716 }
4717 if (io->pfrio_size < 0 ||
4718 io->pfrio_size > pf_ioctl_maxcount ||
4719 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
4720 error = EINVAL;
4721 break;
4722 }
4723 totlen = io->pfrio_size * sizeof(struct pfr_addr);
4724 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
4725 M_TEMP, M_WAITOK);
4726 error = copyin(io->pfrio_buffer, pfras, totlen);
4727 if (error) {
4728 free(pfras, M_TEMP);
4729 break;
4730 }
4731 PF_RULES_WLOCK();
4732 error = pfr_add_addrs(&io->pfrio_table, pfras,
4733 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
4734 PFR_FLAG_USERIOCTL);
4735 PF_RULES_WUNLOCK();
4736 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
4737 error = copyout(pfras, io->pfrio_buffer, totlen);
4738 free(pfras, M_TEMP);
4739 break;
4740 }
4741
4742 case DIOCRDELADDRS: {
4743 struct pfioc_table *io = (struct pfioc_table *)addr;
4744 struct pfr_addr *pfras;
4745 size_t totlen;
4746
4747 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
4748 error = ENODEV;
4749 break;
4750 }
4751 if (io->pfrio_size < 0 ||
4752 io->pfrio_size > pf_ioctl_maxcount ||
4753 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
4754 error = EINVAL;
4755 break;
4756 }
4757 totlen = io->pfrio_size * sizeof(struct pfr_addr);
4758 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
4759 M_TEMP, M_WAITOK);
4760 error = copyin(io->pfrio_buffer, pfras, totlen);
4761 if (error) {
4762 free(pfras, M_TEMP);
4763 break;
4764 }
4765 PF_RULES_WLOCK();
4766 error = pfr_del_addrs(&io->pfrio_table, pfras,
4767 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
4768 PFR_FLAG_USERIOCTL);
4769 PF_RULES_WUNLOCK();
4770 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
4771 error = copyout(pfras, io->pfrio_buffer, totlen);
4772 free(pfras, M_TEMP);
4773 break;
4774 }
4775
4776 case DIOCRSETADDRS: {
4777 struct pfioc_table *io = (struct pfioc_table *)addr;
4778 struct pfr_addr *pfras;
4779 size_t totlen, count;
4780
4781 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
4782 error = ENODEV;
4783 break;
4784 }
4785 if (io->pfrio_size < 0 || io->pfrio_size2 < 0) {
4786 error = EINVAL;
4787 break;
4788 }
4789 count = max(io->pfrio_size, io->pfrio_size2);
4790 if (count > pf_ioctl_maxcount ||
4791 WOULD_OVERFLOW(count, sizeof(struct pfr_addr))) {
4792 error = EINVAL;
4793 break;
4794 }
4795 totlen = count * sizeof(struct pfr_addr);
4796 pfras = mallocarray(count, sizeof(struct pfr_addr), M_TEMP,
4797 M_WAITOK);
4798 error = copyin(io->pfrio_buffer, pfras, totlen);
4799 if (error) {
4800 free(pfras, M_TEMP);
4801 break;
4802 }
4803 PF_RULES_WLOCK();
4804 error = pfr_set_addrs(&io->pfrio_table, pfras,
4805 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
4806 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
4807 PFR_FLAG_USERIOCTL, 0);
4808 PF_RULES_WUNLOCK();
4809 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
4810 error = copyout(pfras, io->pfrio_buffer, totlen);
4811 free(pfras, M_TEMP);
4812 break;
4813 }
4814
4815 case DIOCRGETADDRS: {
4816 struct pfioc_table *io = (struct pfioc_table *)addr;
4817 struct pfr_addr *pfras;
4818 size_t totlen;
4819
4820 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
4821 error = ENODEV;
4822 break;
4823 }
4824 if (io->pfrio_size < 0 ||
4825 io->pfrio_size > pf_ioctl_maxcount ||
4826 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
4827 error = EINVAL;
4828 break;
4829 }
4830 totlen = io->pfrio_size * sizeof(struct pfr_addr);
4831 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
4832 M_TEMP, M_WAITOK | M_ZERO);
4833 PF_RULES_RLOCK();
4834 error = pfr_get_addrs(&io->pfrio_table, pfras,
4835 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4836 PF_RULES_RUNLOCK();
4837 if (error == 0)
4838 error = copyout(pfras, io->pfrio_buffer, totlen);
4839 free(pfras, M_TEMP);
4840 break;
4841 }
4842
4843 case DIOCRGETASTATS: {
4844 struct pfioc_table *io = (struct pfioc_table *)addr;
4845 struct pfr_astats *pfrastats;
4846 size_t totlen;
4847
4848 if (io->pfrio_esize != sizeof(struct pfr_astats)) {
4849 error = ENODEV;
4850 break;
4851 }
4852 if (io->pfrio_size < 0 ||
4853 io->pfrio_size > pf_ioctl_maxcount ||
4854 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_astats))) {
4855 error = EINVAL;
4856 break;
4857 }
4858 totlen = io->pfrio_size * sizeof(struct pfr_astats);
4859 pfrastats = mallocarray(io->pfrio_size,
4860 sizeof(struct pfr_astats), M_TEMP, M_WAITOK | M_ZERO);
4861 PF_RULES_RLOCK();
4862 error = pfr_get_astats(&io->pfrio_table, pfrastats,
4863 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4864 PF_RULES_RUNLOCK();
4865 if (error == 0)
4866 error = copyout(pfrastats, io->pfrio_buffer, totlen);
4867 free(pfrastats, M_TEMP);
4868 break;
4869 }
4870
4871 case DIOCRCLRASTATS: {
4872 struct pfioc_table *io = (struct pfioc_table *)addr;
4873 struct pfr_addr *pfras;
4874 size_t totlen;
4875
4876 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
4877 error = ENODEV;
4878 break;
4879 }
4880 if (io->pfrio_size < 0 ||
4881 io->pfrio_size > pf_ioctl_maxcount ||
4882 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
4883 error = EINVAL;
4884 break;
4885 }
4886 totlen = io->pfrio_size * sizeof(struct pfr_addr);
4887 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
4888 M_TEMP, M_WAITOK);
4889 error = copyin(io->pfrio_buffer, pfras, totlen);
4890 if (error) {
4891 free(pfras, M_TEMP);
4892 break;
4893 }
4894 PF_RULES_WLOCK();
4895 error = pfr_clr_astats(&io->pfrio_table, pfras,
4896 io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
4897 PFR_FLAG_USERIOCTL);
4898 PF_RULES_WUNLOCK();
4899 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
4900 error = copyout(pfras, io->pfrio_buffer, totlen);
4901 free(pfras, M_TEMP);
4902 break;
4903 }
4904
4905 case DIOCRTSTADDRS: {
4906 struct pfioc_table *io = (struct pfioc_table *)addr;
4907 struct pfr_addr *pfras;
4908 size_t totlen;
4909
4910 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
4911 error = ENODEV;
4912 break;
4913 }
4914 if (io->pfrio_size < 0 ||
4915 io->pfrio_size > pf_ioctl_maxcount ||
4916 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
4917 error = EINVAL;
4918 break;
4919 }
4920 totlen = io->pfrio_size * sizeof(struct pfr_addr);
4921 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
4922 M_TEMP, M_WAITOK);
4923 error = copyin(io->pfrio_buffer, pfras, totlen);
4924 if (error) {
4925 free(pfras, M_TEMP);
4926 break;
4927 }
4928 PF_RULES_RLOCK();
4929 error = pfr_tst_addrs(&io->pfrio_table, pfras,
4930 io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
4931 PFR_FLAG_USERIOCTL);
4932 PF_RULES_RUNLOCK();
4933 if (error == 0)
4934 error = copyout(pfras, io->pfrio_buffer, totlen);
4935 free(pfras, M_TEMP);
4936 break;
4937 }
4938
4939 case DIOCRINADEFINE: {
4940 struct pfioc_table *io = (struct pfioc_table *)addr;
4941 struct pfr_addr *pfras;
4942 size_t totlen;
4943
4944 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
4945 error = ENODEV;
4946 break;
4947 }
4948 if (io->pfrio_size < 0 ||
4949 io->pfrio_size > pf_ioctl_maxcount ||
4950 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
4951 error = EINVAL;
4952 break;
4953 }
4954 totlen = io->pfrio_size * sizeof(struct pfr_addr);
4955 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
4956 M_TEMP, M_WAITOK);
4957 error = copyin(io->pfrio_buffer, pfras, totlen);
4958 if (error) {
4959 free(pfras, M_TEMP);
4960 break;
4961 }
4962 PF_RULES_WLOCK();
4963 error = pfr_ina_define(&io->pfrio_table, pfras,
4964 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
4965 io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4966 PF_RULES_WUNLOCK();
4967 free(pfras, M_TEMP);
4968 break;
4969 }
4970
4971 case DIOCOSFPADD: {
4972 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
4973 PF_RULES_WLOCK();
4974 error = pf_osfp_add(io);
4975 PF_RULES_WUNLOCK();
4976 break;
4977 }
4978
4979 case DIOCOSFPGET: {
4980 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
4981 PF_RULES_RLOCK();
4982 error = pf_osfp_get(io);
4983 PF_RULES_RUNLOCK();
4984 break;
4985 }
4986
4987 case DIOCXBEGIN: {
4988 struct pfioc_trans *io = (struct pfioc_trans *)addr;
4989 struct pfioc_trans_e *ioes, *ioe;
4990 size_t totlen;
4991 int i;
4992
4993 if (io->esize != sizeof(*ioe)) {
4994 error = ENODEV;
4995 break;
4996 }
4997 if (io->size < 0 ||
4998 io->size > pf_ioctl_maxcount ||
4999 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5000 error = EINVAL;
5001 break;
5002 }
5003 totlen = sizeof(struct pfioc_trans_e) * io->size;
5004 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5005 M_TEMP, M_WAITOK);
5006 error = copyin(io->array, ioes, totlen);
5007 if (error) {
5008 free(ioes, M_TEMP);
5009 break;
5010 }
5011 /* Ensure there's no more ethernet rules to clean up. */
5012 NET_EPOCH_DRAIN_CALLBACKS();
5013 PF_RULES_WLOCK();
5014 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5015 ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5016 switch (ioe->rs_num) {
5017 case PF_RULESET_ETH:
5018 if ((error = pf_begin_eth(&ioe->ticket, ioe->anchor))) {
5019 PF_RULES_WUNLOCK();
5020 free(ioes, M_TEMP);
5021 goto fail;
5022 }
5023 break;
5024 #ifdef ALTQ
5025 case PF_RULESET_ALTQ:
5026 if (ioe->anchor[0]) {
5027 PF_RULES_WUNLOCK();
5028 free(ioes, M_TEMP);
5029 error = EINVAL;
5030 goto fail;
5031 }
5032 if ((error = pf_begin_altq(&ioe->ticket))) {
5033 PF_RULES_WUNLOCK();
5034 free(ioes, M_TEMP);
5035 goto fail;
5036 }
5037 break;
5038 #endif /* ALTQ */
5039 case PF_RULESET_TABLE:
5040 {
5041 struct pfr_table table;
5042
5043 bzero(&table, sizeof(table));
5044 strlcpy(table.pfrt_anchor, ioe->anchor,
5045 sizeof(table.pfrt_anchor));
5046 if ((error = pfr_ina_begin(&table,
5047 &ioe->ticket, NULL, 0))) {
5048 PF_RULES_WUNLOCK();
5049 free(ioes, M_TEMP);
5050 goto fail;
5051 }
5052 break;
5053 }
5054 default:
5055 if ((error = pf_begin_rules(&ioe->ticket,
5056 ioe->rs_num, ioe->anchor))) {
5057 PF_RULES_WUNLOCK();
5058 free(ioes, M_TEMP);
5059 goto fail;
5060 }
5061 break;
5062 }
5063 }
5064 PF_RULES_WUNLOCK();
5065 error = copyout(ioes, io->array, totlen);
5066 free(ioes, M_TEMP);
5067 break;
5068 }
5069
5070 case DIOCXROLLBACK: {
5071 struct pfioc_trans *io = (struct pfioc_trans *)addr;
5072 struct pfioc_trans_e *ioe, *ioes;
5073 size_t totlen;
5074 int i;
5075
5076 if (io->esize != sizeof(*ioe)) {
5077 error = ENODEV;
5078 break;
5079 }
5080 if (io->size < 0 ||
5081 io->size > pf_ioctl_maxcount ||
5082 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5083 error = EINVAL;
5084 break;
5085 }
5086 totlen = sizeof(struct pfioc_trans_e) * io->size;
5087 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5088 M_TEMP, M_WAITOK);
5089 error = copyin(io->array, ioes, totlen);
5090 if (error) {
5091 free(ioes, M_TEMP);
5092 break;
5093 }
5094 PF_RULES_WLOCK();
5095 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5096 ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5097 switch (ioe->rs_num) {
5098 case PF_RULESET_ETH:
5099 if ((error = pf_rollback_eth(ioe->ticket,
5100 ioe->anchor))) {
5101 PF_RULES_WUNLOCK();
5102 free(ioes, M_TEMP);
5103 goto fail; /* really bad */
5104 }
5105 break;
5106 #ifdef ALTQ
5107 case PF_RULESET_ALTQ:
5108 if (ioe->anchor[0]) {
5109 PF_RULES_WUNLOCK();
5110 free(ioes, M_TEMP);
5111 error = EINVAL;
5112 goto fail;
5113 }
5114 if ((error = pf_rollback_altq(ioe->ticket))) {
5115 PF_RULES_WUNLOCK();
5116 free(ioes, M_TEMP);
5117 goto fail; /* really bad */
5118 }
5119 break;
5120 #endif /* ALTQ */
5121 case PF_RULESET_TABLE:
5122 {
5123 struct pfr_table table;
5124
5125 bzero(&table, sizeof(table));
5126 strlcpy(table.pfrt_anchor, ioe->anchor,
5127 sizeof(table.pfrt_anchor));
5128 if ((error = pfr_ina_rollback(&table,
5129 ioe->ticket, NULL, 0))) {
5130 PF_RULES_WUNLOCK();
5131 free(ioes, M_TEMP);
5132 goto fail; /* really bad */
5133 }
5134 break;
5135 }
5136 default:
5137 if ((error = pf_rollback_rules(ioe->ticket,
5138 ioe->rs_num, ioe->anchor))) {
5139 PF_RULES_WUNLOCK();
5140 free(ioes, M_TEMP);
5141 goto fail; /* really bad */
5142 }
5143 break;
5144 }
5145 }
5146 PF_RULES_WUNLOCK();
5147 free(ioes, M_TEMP);
5148 break;
5149 }
5150
5151 case DIOCXCOMMIT: {
5152 struct pfioc_trans *io = (struct pfioc_trans *)addr;
5153 struct pfioc_trans_e *ioe, *ioes;
5154 struct pf_kruleset *rs;
5155 struct pf_keth_ruleset *ers;
5156 size_t totlen;
5157 int i;
5158
5159 if (io->esize != sizeof(*ioe)) {
5160 error = ENODEV;
5161 break;
5162 }
5163
5164 if (io->size < 0 ||
5165 io->size > pf_ioctl_maxcount ||
5166 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5167 error = EINVAL;
5168 break;
5169 }
5170
5171 totlen = sizeof(struct pfioc_trans_e) * io->size;
5172 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5173 M_TEMP, M_WAITOK);
5174 error = copyin(io->array, ioes, totlen);
5175 if (error) {
5176 free(ioes, M_TEMP);
5177 break;
5178 }
5179 PF_RULES_WLOCK();
5180 /* First makes sure everything will succeed. */
5181 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5182 ioe->anchor[sizeof(ioe->anchor) - 1] = 0;
5183 switch (ioe->rs_num) {
5184 case PF_RULESET_ETH:
5185 ers = pf_find_keth_ruleset(ioe->anchor);
5186 if (ers == NULL || ioe->ticket == 0 ||
5187 ioe->ticket != ers->inactive.ticket) {
5188 PF_RULES_WUNLOCK();
5189 free(ioes, M_TEMP);
5190 error = EINVAL;
5191 goto fail;
5192 }
5193 break;
5194 #ifdef ALTQ
5195 case PF_RULESET_ALTQ:
5196 if (ioe->anchor[0]) {
5197 PF_RULES_WUNLOCK();
5198 free(ioes, M_TEMP);
5199 error = EINVAL;
5200 goto fail;
5201 }
5202 if (!V_altqs_inactive_open || ioe->ticket !=
5203 V_ticket_altqs_inactive) {
5204 PF_RULES_WUNLOCK();
5205 free(ioes, M_TEMP);
5206 error = EBUSY;
5207 goto fail;
5208 }
5209 break;
5210 #endif /* ALTQ */
5211 case PF_RULESET_TABLE:
5212 rs = pf_find_kruleset(ioe->anchor);
5213 if (rs == NULL || !rs->topen || ioe->ticket !=
5214 rs->tticket) {
5215 PF_RULES_WUNLOCK();
5216 free(ioes, M_TEMP);
5217 error = EBUSY;
5218 goto fail;
5219 }
5220 break;
5221 default:
5222 if (ioe->rs_num < 0 || ioe->rs_num >=
5223 PF_RULESET_MAX) {
5224 PF_RULES_WUNLOCK();
5225 free(ioes, M_TEMP);
5226 error = EINVAL;
5227 goto fail;
5228 }
5229 rs = pf_find_kruleset(ioe->anchor);
5230 if (rs == NULL ||
5231 !rs->rules[ioe->rs_num].inactive.open ||
5232 rs->rules[ioe->rs_num].inactive.ticket !=
5233 ioe->ticket) {
5234 PF_RULES_WUNLOCK();
5235 free(ioes, M_TEMP);
5236 error = EBUSY;
5237 goto fail;
5238 }
5239 break;
5240 }
5241 }
5242 /* Now do the commit - no errors should happen here. */
5243 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5244 switch (ioe->rs_num) {
5245 case PF_RULESET_ETH:
5246 if ((error = pf_commit_eth(ioe->ticket, ioe->anchor))) {
5247 PF_RULES_WUNLOCK();
5248 free(ioes, M_TEMP);
5249 goto fail; /* really bad */
5250 }
5251 break;
5252 #ifdef ALTQ
5253 case PF_RULESET_ALTQ:
5254 if ((error = pf_commit_altq(ioe->ticket))) {
5255 PF_RULES_WUNLOCK();
5256 free(ioes, M_TEMP);
5257 goto fail; /* really bad */
5258 }
5259 break;
5260 #endif /* ALTQ */
5261 case PF_RULESET_TABLE:
5262 {
5263 struct pfr_table table;
5264
5265 bzero(&table, sizeof(table));
5266 (void)strlcpy(table.pfrt_anchor, ioe->anchor,
5267 sizeof(table.pfrt_anchor));
5268 if ((error = pfr_ina_commit(&table,
5269 ioe->ticket, NULL, NULL, 0))) {
5270 PF_RULES_WUNLOCK();
5271 free(ioes, M_TEMP);
5272 goto fail; /* really bad */
5273 }
5274 break;
5275 }
5276 default:
5277 if ((error = pf_commit_rules(ioe->ticket,
5278 ioe->rs_num, ioe->anchor))) {
5279 PF_RULES_WUNLOCK();
5280 free(ioes, M_TEMP);
5281 goto fail; /* really bad */
5282 }
5283 break;
5284 }
5285 }
5286 PF_RULES_WUNLOCK();
5287
5288 /* Only hook into EtherNet taffic if we've got rules for it. */
5289 if (! TAILQ_EMPTY(V_pf_keth->active.rules))
5290 hook_pf_eth();
5291 else
5292 dehook_pf_eth();
5293
5294 free(ioes, M_TEMP);
5295 break;
5296 }
5297
5298 case DIOCGETSRCNODES: {
5299 struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
5300 struct pf_srchash *sh;
5301 struct pf_ksrc_node *n;
5302 struct pf_src_node *p, *pstore;
5303 uint32_t i, nr = 0;
5304
5305 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask;
5306 i++, sh++) {
5307 PF_HASHROW_LOCK(sh);
5308 LIST_FOREACH(n, &sh->nodes, entry)
5309 nr++;
5310 PF_HASHROW_UNLOCK(sh);
5311 }
5312
5313 psn->psn_len = min(psn->psn_len,
5314 sizeof(struct pf_src_node) * nr);
5315
5316 if (psn->psn_len == 0) {
5317 psn->psn_len = sizeof(struct pf_src_node) * nr;
5318 break;
5319 }
5320
5321 nr = 0;
5322
5323 p = pstore = malloc(psn->psn_len, M_TEMP, M_WAITOK | M_ZERO);
5324 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask;
5325 i++, sh++) {
5326 PF_HASHROW_LOCK(sh);
5327 LIST_FOREACH(n, &sh->nodes, entry) {
5328
5329 if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
5330 break;
5331
5332 pf_src_node_copy(n, p);
5333
5334 p++;
5335 nr++;
5336 }
5337 PF_HASHROW_UNLOCK(sh);
5338 }
5339 error = copyout(pstore, psn->psn_src_nodes,
5340 sizeof(struct pf_src_node) * nr);
5341 if (error) {
5342 free(pstore, M_TEMP);
5343 break;
5344 }
5345 psn->psn_len = sizeof(struct pf_src_node) * nr;
5346 free(pstore, M_TEMP);
5347 break;
5348 }
5349
5350 case DIOCCLRSRCNODES: {
5351 pf_clear_srcnodes(NULL);
5352 pf_purge_expired_src_nodes();
5353 break;
5354 }
5355
5356 case DIOCKILLSRCNODES:
5357 pf_kill_srcnodes((struct pfioc_src_node_kill *)addr);
5358 break;
5359
5360 #ifdef COMPAT_FREEBSD13
5361 case DIOCKEEPCOUNTERS_FREEBSD13:
5362 #endif
5363 case DIOCKEEPCOUNTERS:
5364 error = pf_keepcounters((struct pfioc_nv *)addr);
5365 break;
5366
5367 case DIOCGETSYNCOOKIES:
5368 error = pf_get_syncookies((struct pfioc_nv *)addr);
5369 break;
5370
5371 case DIOCSETSYNCOOKIES:
5372 error = pf_set_syncookies((struct pfioc_nv *)addr);
5373 break;
5374
5375 case DIOCSETHOSTID: {
5376 u_int32_t *hostid = (u_int32_t *)addr;
5377
5378 PF_RULES_WLOCK();
5379 if (*hostid == 0)
5380 V_pf_status.hostid = arc4random();
5381 else
5382 V_pf_status.hostid = *hostid;
5383 PF_RULES_WUNLOCK();
5384 break;
5385 }
5386
5387 case DIOCOSFPFLUSH:
5388 PF_RULES_WLOCK();
5389 pf_osfp_flush();
5390 PF_RULES_WUNLOCK();
5391 break;
5392
5393 case DIOCIGETIFACES: {
5394 struct pfioc_iface *io = (struct pfioc_iface *)addr;
5395 struct pfi_kif *ifstore;
5396 size_t bufsiz;
5397
5398 if (io->pfiio_esize != sizeof(struct pfi_kif)) {
5399 error = ENODEV;
5400 break;
5401 }
5402
5403 if (io->pfiio_size < 0 ||
5404 io->pfiio_size > pf_ioctl_maxcount ||
5405 WOULD_OVERFLOW(io->pfiio_size, sizeof(struct pfi_kif))) {
5406 error = EINVAL;
5407 break;
5408 }
5409
5410 io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5411
5412 bufsiz = io->pfiio_size * sizeof(struct pfi_kif);
5413 ifstore = mallocarray(io->pfiio_size, sizeof(struct pfi_kif),
5414 M_TEMP, M_WAITOK | M_ZERO);
5415
5416 PF_RULES_RLOCK();
5417 pfi_get_ifaces(io->pfiio_name, ifstore, &io->pfiio_size);
5418 PF_RULES_RUNLOCK();
5419 error = copyout(ifstore, io->pfiio_buffer, bufsiz);
5420 free(ifstore, M_TEMP);
5421 break;
5422 }
5423
5424 case DIOCSETIFFLAG: {
5425 struct pfioc_iface *io = (struct pfioc_iface *)addr;
5426
5427 io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5428
5429 PF_RULES_WLOCK();
5430 error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
5431 PF_RULES_WUNLOCK();
5432 break;
5433 }
5434
5435 case DIOCCLRIFFLAG: {
5436 struct pfioc_iface *io = (struct pfioc_iface *)addr;
5437
5438 io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5439
5440 PF_RULES_WLOCK();
5441 error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
5442 PF_RULES_WUNLOCK();
5443 break;
5444 }
5445
5446 case DIOCSETREASS: {
5447 u_int32_t *reass = (u_int32_t *)addr;
5448
5449 V_pf_status.reass = *reass & (PF_REASS_ENABLED|PF_REASS_NODF);
5450 /* Removal of DF flag without reassembly enabled is not a
5451 * valid combination. Disable reassembly in such case. */
5452 if (!(V_pf_status.reass & PF_REASS_ENABLED))
5453 V_pf_status.reass = 0;
5454 break;
5455 }
5456
5457 default:
5458 error = ENODEV;
5459 break;
5460 }
5461 fail:
5462 CURVNET_RESTORE();
5463
5464 #undef ERROUT_IOCTL
5465
5466 return (error);
5467 }
5468
5469 void
pfsync_state_export(union pfsync_state_union * sp,struct pf_kstate * st,int msg_version)5470 pfsync_state_export(union pfsync_state_union *sp, struct pf_kstate *st, int msg_version)
5471 {
5472 bzero(sp, sizeof(union pfsync_state_union));
5473
5474 /* copy from state key */
5475 sp->pfs_1301.key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
5476 sp->pfs_1301.key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
5477 sp->pfs_1301.key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
5478 sp->pfs_1301.key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
5479 sp->pfs_1301.key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
5480 sp->pfs_1301.key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
5481 sp->pfs_1301.key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
5482 sp->pfs_1301.key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
5483 sp->pfs_1301.proto = st->key[PF_SK_WIRE]->proto;
5484 sp->pfs_1301.af = st->key[PF_SK_WIRE]->af;
5485
5486 /* copy from state */
5487 strlcpy(sp->pfs_1301.ifname, st->kif->pfik_name, sizeof(sp->pfs_1301.ifname));
5488 bcopy(&st->rt_addr, &sp->pfs_1301.rt_addr, sizeof(sp->pfs_1301.rt_addr));
5489 sp->pfs_1301.creation = htonl(time_uptime - (st->creation / 1000));
5490 sp->pfs_1301.expire = pf_state_expires(st);
5491 if (sp->pfs_1301.expire <= time_uptime)
5492 sp->pfs_1301.expire = htonl(0);
5493 else
5494 sp->pfs_1301.expire = htonl(sp->pfs_1301.expire - time_uptime);
5495
5496 sp->pfs_1301.direction = st->direction;
5497 sp->pfs_1301.log = st->act.log;
5498 sp->pfs_1301.timeout = st->timeout;
5499
5500 switch (msg_version) {
5501 case PFSYNC_MSG_VERSION_1301:
5502 sp->pfs_1301.state_flags = st->state_flags;
5503 break;
5504 case PFSYNC_MSG_VERSION_1400:
5505 sp->pfs_1400.state_flags = htons(st->state_flags);
5506 sp->pfs_1400.qid = htons(st->act.qid);
5507 sp->pfs_1400.pqid = htons(st->act.pqid);
5508 sp->pfs_1400.dnpipe = htons(st->act.dnpipe);
5509 sp->pfs_1400.dnrpipe = htons(st->act.dnrpipe);
5510 sp->pfs_1400.rtableid = htonl(st->act.rtableid);
5511 sp->pfs_1400.min_ttl = st->act.min_ttl;
5512 sp->pfs_1400.set_tos = st->act.set_tos;
5513 sp->pfs_1400.max_mss = htons(st->act.max_mss);
5514 sp->pfs_1400.set_prio[0] = st->act.set_prio[0];
5515 sp->pfs_1400.set_prio[1] = st->act.set_prio[1];
5516 sp->pfs_1400.rt = st->rt;
5517 if (st->rt_kif)
5518 strlcpy(sp->pfs_1400.rt_ifname,
5519 st->rt_kif->pfik_name,
5520 sizeof(sp->pfs_1400.rt_ifname));
5521 break;
5522 default:
5523 panic("%s: Unsupported pfsync_msg_version %d",
5524 __func__, msg_version);
5525 }
5526
5527 if (st->src_node)
5528 sp->pfs_1301.sync_flags |= PFSYNC_FLAG_SRCNODE;
5529 if (st->nat_src_node)
5530 sp->pfs_1301.sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5531
5532 sp->pfs_1301.id = st->id;
5533 sp->pfs_1301.creatorid = st->creatorid;
5534 pf_state_peer_hton(&st->src, &sp->pfs_1301.src);
5535 pf_state_peer_hton(&st->dst, &sp->pfs_1301.dst);
5536
5537 if (st->rule.ptr == NULL)
5538 sp->pfs_1301.rule = htonl(-1);
5539 else
5540 sp->pfs_1301.rule = htonl(st->rule.ptr->nr);
5541 if (st->anchor.ptr == NULL)
5542 sp->pfs_1301.anchor = htonl(-1);
5543 else
5544 sp->pfs_1301.anchor = htonl(st->anchor.ptr->nr);
5545 if (st->nat_rule.ptr == NULL)
5546 sp->pfs_1301.nat_rule = htonl(-1);
5547 else
5548 sp->pfs_1301.nat_rule = htonl(st->nat_rule.ptr->nr);
5549
5550 pf_state_counter_hton(st->packets[0], sp->pfs_1301.packets[0]);
5551 pf_state_counter_hton(st->packets[1], sp->pfs_1301.packets[1]);
5552 pf_state_counter_hton(st->bytes[0], sp->pfs_1301.bytes[0]);
5553 pf_state_counter_hton(st->bytes[1], sp->pfs_1301.bytes[1]);
5554 }
5555
5556 void
pf_state_export(struct pf_state_export * sp,struct pf_kstate * st)5557 pf_state_export(struct pf_state_export *sp, struct pf_kstate *st)
5558 {
5559 bzero(sp, sizeof(*sp));
5560
5561 sp->version = PF_STATE_VERSION;
5562
5563 /* copy from state key */
5564 sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
5565 sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
5566 sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
5567 sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
5568 sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
5569 sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
5570 sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
5571 sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
5572 sp->proto = st->key[PF_SK_WIRE]->proto;
5573 sp->af = st->key[PF_SK_WIRE]->af;
5574
5575 /* copy from state */
5576 strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
5577 strlcpy(sp->orig_ifname, st->orig_kif->pfik_name,
5578 sizeof(sp->orig_ifname));
5579 bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
5580 sp->creation = htonl(time_uptime - (st->creation / 1000));
5581 sp->expire = pf_state_expires(st);
5582 if (sp->expire <= time_uptime)
5583 sp->expire = htonl(0);
5584 else
5585 sp->expire = htonl(sp->expire - time_uptime);
5586
5587 sp->direction = st->direction;
5588 sp->log = st->act.log;
5589 sp->timeout = st->timeout;
5590 /* 8 bits for the old libpfctl, 16 bits for the new libpfctl */
5591 sp->state_flags_compat = st->state_flags;
5592 sp->state_flags = htons(st->state_flags);
5593 if (st->src_node)
5594 sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
5595 if (st->nat_src_node)
5596 sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5597
5598 sp->id = st->id;
5599 sp->creatorid = st->creatorid;
5600 pf_state_peer_hton(&st->src, &sp->src);
5601 pf_state_peer_hton(&st->dst, &sp->dst);
5602
5603 if (st->rule.ptr == NULL)
5604 sp->rule = htonl(-1);
5605 else
5606 sp->rule = htonl(st->rule.ptr->nr);
5607 if (st->anchor.ptr == NULL)
5608 sp->anchor = htonl(-1);
5609 else
5610 sp->anchor = htonl(st->anchor.ptr->nr);
5611 if (st->nat_rule.ptr == NULL)
5612 sp->nat_rule = htonl(-1);
5613 else
5614 sp->nat_rule = htonl(st->nat_rule.ptr->nr);
5615
5616 sp->packets[0] = st->packets[0];
5617 sp->packets[1] = st->packets[1];
5618 sp->bytes[0] = st->bytes[0];
5619 sp->bytes[1] = st->bytes[1];
5620
5621 sp->qid = htons(st->act.qid);
5622 sp->pqid = htons(st->act.pqid);
5623 sp->dnpipe = htons(st->act.dnpipe);
5624 sp->dnrpipe = htons(st->act.dnrpipe);
5625 sp->rtableid = htonl(st->act.rtableid);
5626 sp->min_ttl = st->act.min_ttl;
5627 sp->set_tos = st->act.set_tos;
5628 sp->max_mss = htons(st->act.max_mss);
5629 sp->rt = st->rt;
5630 if (st->rt_kif)
5631 strlcpy(sp->rt_ifname, st->rt_kif->pfik_name,
5632 sizeof(sp->rt_ifname));
5633 sp->set_prio[0] = st->act.set_prio[0];
5634 sp->set_prio[1] = st->act.set_prio[1];
5635
5636 }
5637
5638 static void
pf_tbladdr_copyout(struct pf_addr_wrap * aw)5639 pf_tbladdr_copyout(struct pf_addr_wrap *aw)
5640 {
5641 struct pfr_ktable *kt;
5642
5643 KASSERT(aw->type == PF_ADDR_TABLE, ("%s: type %u", __func__, aw->type));
5644
5645 kt = aw->p.tbl;
5646 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
5647 kt = kt->pfrkt_root;
5648 aw->p.tbl = NULL;
5649 aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
5650 kt->pfrkt_cnt : -1;
5651 }
5652
5653 static int
pf_add_status_counters(nvlist_t * nvl,const char * name,counter_u64_t * counters,size_t number,char ** names)5654 pf_add_status_counters(nvlist_t *nvl, const char *name, counter_u64_t *counters,
5655 size_t number, char **names)
5656 {
5657 nvlist_t *nvc;
5658
5659 nvc = nvlist_create(0);
5660 if (nvc == NULL)
5661 return (ENOMEM);
5662
5663 for (int i = 0; i < number; i++) {
5664 nvlist_append_number_array(nvc, "counters",
5665 counter_u64_fetch(counters[i]));
5666 nvlist_append_string_array(nvc, "names",
5667 names[i]);
5668 nvlist_append_number_array(nvc, "ids",
5669 i);
5670 }
5671 nvlist_add_nvlist(nvl, name, nvc);
5672 nvlist_destroy(nvc);
5673
5674 return (0);
5675 }
5676
5677 static int
pf_getstatus(struct pfioc_nv * nv)5678 pf_getstatus(struct pfioc_nv *nv)
5679 {
5680 nvlist_t *nvl = NULL, *nvc = NULL;
5681 void *nvlpacked = NULL;
5682 int error;
5683 struct pf_status s;
5684 char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
5685 char *pf_lcounter[KLCNT_MAX+1] = KLCNT_NAMES;
5686 char *pf_fcounter[FCNT_MAX+1] = FCNT_NAMES;
5687 PF_RULES_RLOCK_TRACKER;
5688
5689 #define ERROUT(x) ERROUT_FUNCTION(errout, x)
5690
5691 PF_RULES_RLOCK();
5692
5693 nvl = nvlist_create(0);
5694 if (nvl == NULL)
5695 ERROUT(ENOMEM);
5696
5697 nvlist_add_bool(nvl, "running", V_pf_status.running);
5698 nvlist_add_number(nvl, "since", V_pf_status.since);
5699 nvlist_add_number(nvl, "debug", V_pf_status.debug);
5700 nvlist_add_number(nvl, "hostid", V_pf_status.hostid);
5701 nvlist_add_number(nvl, "states", V_pf_status.states);
5702 nvlist_add_number(nvl, "src_nodes", V_pf_status.src_nodes);
5703 nvlist_add_number(nvl, "reass", V_pf_status.reass);
5704 nvlist_add_bool(nvl, "syncookies_active",
5705 V_pf_status.syncookies_active);
5706 nvlist_add_number(nvl, "halfopen_states", V_pf_status.states_halfopen);
5707
5708 /* counters */
5709 error = pf_add_status_counters(nvl, "counters", V_pf_status.counters,
5710 PFRES_MAX, pf_reasons);
5711 if (error != 0)
5712 ERROUT(error);
5713
5714 /* lcounters */
5715 error = pf_add_status_counters(nvl, "lcounters", V_pf_status.lcounters,
5716 KLCNT_MAX, pf_lcounter);
5717 if (error != 0)
5718 ERROUT(error);
5719
5720 /* fcounters */
5721 nvc = nvlist_create(0);
5722 if (nvc == NULL)
5723 ERROUT(ENOMEM);
5724
5725 for (int i = 0; i < FCNT_MAX; i++) {
5726 nvlist_append_number_array(nvc, "counters",
5727 pf_counter_u64_fetch(&V_pf_status.fcounters[i]));
5728 nvlist_append_string_array(nvc, "names",
5729 pf_fcounter[i]);
5730 nvlist_append_number_array(nvc, "ids",
5731 i);
5732 }
5733 nvlist_add_nvlist(nvl, "fcounters", nvc);
5734 nvlist_destroy(nvc);
5735 nvc = NULL;
5736
5737 /* scounters */
5738 error = pf_add_status_counters(nvl, "scounters", V_pf_status.scounters,
5739 SCNT_MAX, pf_fcounter);
5740 if (error != 0)
5741 ERROUT(error);
5742
5743 nvlist_add_string(nvl, "ifname", V_pf_status.ifname);
5744 nvlist_add_binary(nvl, "chksum", V_pf_status.pf_chksum,
5745 PF_MD5_DIGEST_LENGTH);
5746
5747 pfi_update_status(V_pf_status.ifname, &s);
5748
5749 /* pcounters / bcounters */
5750 for (int i = 0; i < 2; i++) {
5751 for (int j = 0; j < 2; j++) {
5752 for (int k = 0; k < 2; k++) {
5753 nvlist_append_number_array(nvl, "pcounters",
5754 s.pcounters[i][j][k]);
5755 }
5756 nvlist_append_number_array(nvl, "bcounters",
5757 s.bcounters[i][j]);
5758 }
5759 }
5760
5761 nvlpacked = nvlist_pack(nvl, &nv->len);
5762 if (nvlpacked == NULL)
5763 ERROUT(ENOMEM);
5764
5765 if (nv->size == 0)
5766 ERROUT(0);
5767 else if (nv->size < nv->len)
5768 ERROUT(ENOSPC);
5769
5770 PF_RULES_RUNLOCK();
5771 error = copyout(nvlpacked, nv->data, nv->len);
5772 goto done;
5773
5774 #undef ERROUT
5775 errout:
5776 PF_RULES_RUNLOCK();
5777 done:
5778 free(nvlpacked, M_NVLIST);
5779 nvlist_destroy(nvc);
5780 nvlist_destroy(nvl);
5781
5782 return (error);
5783 }
5784
5785 /*
5786 * XXX - Check for version mismatch!!!
5787 */
5788 static void
pf_clear_all_states(void)5789 pf_clear_all_states(void)
5790 {
5791 struct epoch_tracker et;
5792 struct pf_kstate *s;
5793 u_int i;
5794
5795 NET_EPOCH_ENTER(et);
5796 for (i = 0; i <= pf_hashmask; i++) {
5797 struct pf_idhash *ih = &V_pf_idhash[i];
5798 relock:
5799 PF_HASHROW_LOCK(ih);
5800 LIST_FOREACH(s, &ih->states, entry) {
5801 s->timeout = PFTM_PURGE;
5802 /* Don't send out individual delete messages. */
5803 s->state_flags |= PFSTATE_NOSYNC;
5804 pf_unlink_state(s);
5805 goto relock;
5806 }
5807 PF_HASHROW_UNLOCK(ih);
5808 }
5809 NET_EPOCH_EXIT(et);
5810 }
5811
5812 static int
pf_clear_tables(void)5813 pf_clear_tables(void)
5814 {
5815 struct pfioc_table io;
5816 int error;
5817
5818 bzero(&io, sizeof(io));
5819 io.pfrio_flags |= PFR_FLAG_ALLRSETS;
5820
5821 error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel,
5822 io.pfrio_flags);
5823
5824 return (error);
5825 }
5826
5827 static void
pf_clear_srcnodes(struct pf_ksrc_node * n)5828 pf_clear_srcnodes(struct pf_ksrc_node *n)
5829 {
5830 struct pf_kstate *s;
5831 int i;
5832
5833 for (i = 0; i <= pf_hashmask; i++) {
5834 struct pf_idhash *ih = &V_pf_idhash[i];
5835
5836 PF_HASHROW_LOCK(ih);
5837 LIST_FOREACH(s, &ih->states, entry) {
5838 if (n == NULL || n == s->src_node)
5839 s->src_node = NULL;
5840 if (n == NULL || n == s->nat_src_node)
5841 s->nat_src_node = NULL;
5842 }
5843 PF_HASHROW_UNLOCK(ih);
5844 }
5845
5846 if (n == NULL) {
5847 struct pf_srchash *sh;
5848
5849 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask;
5850 i++, sh++) {
5851 PF_HASHROW_LOCK(sh);
5852 LIST_FOREACH(n, &sh->nodes, entry) {
5853 n->expire = 1;
5854 n->states = 0;
5855 }
5856 PF_HASHROW_UNLOCK(sh);
5857 }
5858 } else {
5859 /* XXX: hash slot should already be locked here. */
5860 n->expire = 1;
5861 n->states = 0;
5862 }
5863 }
5864
5865 static void
pf_kill_srcnodes(struct pfioc_src_node_kill * psnk)5866 pf_kill_srcnodes(struct pfioc_src_node_kill *psnk)
5867 {
5868 struct pf_ksrc_node_list kill;
5869
5870 LIST_INIT(&kill);
5871 for (int i = 0; i <= pf_srchashmask; i++) {
5872 struct pf_srchash *sh = &V_pf_srchash[i];
5873 struct pf_ksrc_node *sn, *tmp;
5874
5875 PF_HASHROW_LOCK(sh);
5876 LIST_FOREACH_SAFE(sn, &sh->nodes, entry, tmp)
5877 if (PF_MATCHA(psnk->psnk_src.neg,
5878 &psnk->psnk_src.addr.v.a.addr,
5879 &psnk->psnk_src.addr.v.a.mask,
5880 &sn->addr, sn->af) &&
5881 PF_MATCHA(psnk->psnk_dst.neg,
5882 &psnk->psnk_dst.addr.v.a.addr,
5883 &psnk->psnk_dst.addr.v.a.mask,
5884 &sn->raddr, sn->af)) {
5885 pf_unlink_src_node(sn);
5886 LIST_INSERT_HEAD(&kill, sn, entry);
5887 sn->expire = 1;
5888 }
5889 PF_HASHROW_UNLOCK(sh);
5890 }
5891
5892 for (int i = 0; i <= pf_hashmask; i++) {
5893 struct pf_idhash *ih = &V_pf_idhash[i];
5894 struct pf_kstate *s;
5895
5896 PF_HASHROW_LOCK(ih);
5897 LIST_FOREACH(s, &ih->states, entry) {
5898 if (s->src_node && s->src_node->expire == 1)
5899 s->src_node = NULL;
5900 if (s->nat_src_node && s->nat_src_node->expire == 1)
5901 s->nat_src_node = NULL;
5902 }
5903 PF_HASHROW_UNLOCK(ih);
5904 }
5905
5906 psnk->psnk_killed = pf_free_src_nodes(&kill);
5907 }
5908
5909 static int
pf_keepcounters(struct pfioc_nv * nv)5910 pf_keepcounters(struct pfioc_nv *nv)
5911 {
5912 nvlist_t *nvl = NULL;
5913 void *nvlpacked = NULL;
5914 int error = 0;
5915
5916 #define ERROUT(x) ERROUT_FUNCTION(on_error, x)
5917
5918 if (nv->len > pf_ioctl_maxcount)
5919 ERROUT(ENOMEM);
5920
5921 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
5922 if (nvlpacked == NULL)
5923 ERROUT(ENOMEM);
5924
5925 error = copyin(nv->data, nvlpacked, nv->len);
5926 if (error)
5927 ERROUT(error);
5928
5929 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
5930 if (nvl == NULL)
5931 ERROUT(EBADMSG);
5932
5933 if (! nvlist_exists_bool(nvl, "keep_counters"))
5934 ERROUT(EBADMSG);
5935
5936 V_pf_status.keep_counters = nvlist_get_bool(nvl, "keep_counters");
5937
5938 on_error:
5939 nvlist_destroy(nvl);
5940 free(nvlpacked, M_NVLIST);
5941 return (error);
5942 }
5943
5944 unsigned int
pf_clear_states(const struct pf_kstate_kill * kill)5945 pf_clear_states(const struct pf_kstate_kill *kill)
5946 {
5947 struct pf_state_key_cmp match_key;
5948 struct pf_kstate *s;
5949 struct pfi_kkif *kif;
5950 int idx;
5951 unsigned int killed = 0, dir;
5952
5953 NET_EPOCH_ASSERT();
5954
5955 for (unsigned int i = 0; i <= pf_hashmask; i++) {
5956 struct pf_idhash *ih = &V_pf_idhash[i];
5957
5958 relock_DIOCCLRSTATES:
5959 PF_HASHROW_LOCK(ih);
5960 LIST_FOREACH(s, &ih->states, entry) {
5961 /* For floating states look at the original kif. */
5962 kif = s->kif == V_pfi_all ? s->orig_kif : s->kif;
5963
5964 if (kill->psk_ifname[0] &&
5965 strcmp(kill->psk_ifname,
5966 kif->pfik_name))
5967 continue;
5968
5969 if (kill->psk_kill_match) {
5970 bzero(&match_key, sizeof(match_key));
5971
5972 if (s->direction == PF_OUT) {
5973 dir = PF_IN;
5974 idx = PF_SK_STACK;
5975 } else {
5976 dir = PF_OUT;
5977 idx = PF_SK_WIRE;
5978 }
5979
5980 match_key.af = s->key[idx]->af;
5981 match_key.proto = s->key[idx]->proto;
5982 PF_ACPY(&match_key.addr[0],
5983 &s->key[idx]->addr[1], match_key.af);
5984 match_key.port[0] = s->key[idx]->port[1];
5985 PF_ACPY(&match_key.addr[1],
5986 &s->key[idx]->addr[0], match_key.af);
5987 match_key.port[1] = s->key[idx]->port[0];
5988 }
5989
5990 /*
5991 * Don't send out individual
5992 * delete messages.
5993 */
5994 s->state_flags |= PFSTATE_NOSYNC;
5995 pf_unlink_state(s);
5996 killed++;
5997
5998 if (kill->psk_kill_match)
5999 killed += pf_kill_matching_state(&match_key,
6000 dir);
6001
6002 goto relock_DIOCCLRSTATES;
6003 }
6004 PF_HASHROW_UNLOCK(ih);
6005 }
6006
6007 if (V_pfsync_clear_states_ptr != NULL)
6008 V_pfsync_clear_states_ptr(V_pf_status.hostid, kill->psk_ifname);
6009
6010 return (killed);
6011 }
6012
6013 void
pf_killstates(struct pf_kstate_kill * kill,unsigned int * killed)6014 pf_killstates(struct pf_kstate_kill *kill, unsigned int *killed)
6015 {
6016 struct pf_kstate *s;
6017
6018 NET_EPOCH_ASSERT();
6019 if (kill->psk_pfcmp.id) {
6020 if (kill->psk_pfcmp.creatorid == 0)
6021 kill->psk_pfcmp.creatorid = V_pf_status.hostid;
6022 if ((s = pf_find_state_byid(kill->psk_pfcmp.id,
6023 kill->psk_pfcmp.creatorid))) {
6024 pf_unlink_state(s);
6025 *killed = 1;
6026 }
6027 return;
6028 }
6029
6030 for (unsigned int i = 0; i <= pf_hashmask; i++)
6031 *killed += pf_killstates_row(kill, &V_pf_idhash[i]);
6032 }
6033
6034 static int
pf_killstates_nv(struct pfioc_nv * nv)6035 pf_killstates_nv(struct pfioc_nv *nv)
6036 {
6037 struct pf_kstate_kill kill;
6038 struct epoch_tracker et;
6039 nvlist_t *nvl = NULL;
6040 void *nvlpacked = NULL;
6041 int error = 0;
6042 unsigned int killed = 0;
6043
6044 #define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6045
6046 if (nv->len > pf_ioctl_maxcount)
6047 ERROUT(ENOMEM);
6048
6049 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6050 if (nvlpacked == NULL)
6051 ERROUT(ENOMEM);
6052
6053 error = copyin(nv->data, nvlpacked, nv->len);
6054 if (error)
6055 ERROUT(error);
6056
6057 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6058 if (nvl == NULL)
6059 ERROUT(EBADMSG);
6060
6061 error = pf_nvstate_kill_to_kstate_kill(nvl, &kill);
6062 if (error)
6063 ERROUT(error);
6064
6065 NET_EPOCH_ENTER(et);
6066 pf_killstates(&kill, &killed);
6067 NET_EPOCH_EXIT(et);
6068
6069 free(nvlpacked, M_NVLIST);
6070 nvlpacked = NULL;
6071 nvlist_destroy(nvl);
6072 nvl = nvlist_create(0);
6073 if (nvl == NULL)
6074 ERROUT(ENOMEM);
6075
6076 nvlist_add_number(nvl, "killed", killed);
6077
6078 nvlpacked = nvlist_pack(nvl, &nv->len);
6079 if (nvlpacked == NULL)
6080 ERROUT(ENOMEM);
6081
6082 if (nv->size == 0)
6083 ERROUT(0);
6084 else if (nv->size < nv->len)
6085 ERROUT(ENOSPC);
6086
6087 error = copyout(nvlpacked, nv->data, nv->len);
6088
6089 on_error:
6090 nvlist_destroy(nvl);
6091 free(nvlpacked, M_NVLIST);
6092 return (error);
6093 }
6094
6095 static int
pf_clearstates_nv(struct pfioc_nv * nv)6096 pf_clearstates_nv(struct pfioc_nv *nv)
6097 {
6098 struct pf_kstate_kill kill;
6099 struct epoch_tracker et;
6100 nvlist_t *nvl = NULL;
6101 void *nvlpacked = NULL;
6102 int error = 0;
6103 unsigned int killed;
6104
6105 #define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6106
6107 if (nv->len > pf_ioctl_maxcount)
6108 ERROUT(ENOMEM);
6109
6110 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6111 if (nvlpacked == NULL)
6112 ERROUT(ENOMEM);
6113
6114 error = copyin(nv->data, nvlpacked, nv->len);
6115 if (error)
6116 ERROUT(error);
6117
6118 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6119 if (nvl == NULL)
6120 ERROUT(EBADMSG);
6121
6122 error = pf_nvstate_kill_to_kstate_kill(nvl, &kill);
6123 if (error)
6124 ERROUT(error);
6125
6126 NET_EPOCH_ENTER(et);
6127 killed = pf_clear_states(&kill);
6128 NET_EPOCH_EXIT(et);
6129
6130 free(nvlpacked, M_NVLIST);
6131 nvlpacked = NULL;
6132 nvlist_destroy(nvl);
6133 nvl = nvlist_create(0);
6134 if (nvl == NULL)
6135 ERROUT(ENOMEM);
6136
6137 nvlist_add_number(nvl, "killed", killed);
6138
6139 nvlpacked = nvlist_pack(nvl, &nv->len);
6140 if (nvlpacked == NULL)
6141 ERROUT(ENOMEM);
6142
6143 if (nv->size == 0)
6144 ERROUT(0);
6145 else if (nv->size < nv->len)
6146 ERROUT(ENOSPC);
6147
6148 error = copyout(nvlpacked, nv->data, nv->len);
6149
6150 #undef ERROUT
6151 on_error:
6152 nvlist_destroy(nvl);
6153 free(nvlpacked, M_NVLIST);
6154 return (error);
6155 }
6156
6157 static int
pf_getstate(struct pfioc_nv * nv)6158 pf_getstate(struct pfioc_nv *nv)
6159 {
6160 nvlist_t *nvl = NULL, *nvls;
6161 void *nvlpacked = NULL;
6162 struct pf_kstate *s = NULL;
6163 int error = 0;
6164 uint64_t id, creatorid;
6165
6166 #define ERROUT(x) ERROUT_FUNCTION(errout, x)
6167
6168 if (nv->len > pf_ioctl_maxcount)
6169 ERROUT(ENOMEM);
6170
6171 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6172 if (nvlpacked == NULL)
6173 ERROUT(ENOMEM);
6174
6175 error = copyin(nv->data, nvlpacked, nv->len);
6176 if (error)
6177 ERROUT(error);
6178
6179 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6180 if (nvl == NULL)
6181 ERROUT(EBADMSG);
6182
6183 PFNV_CHK(pf_nvuint64(nvl, "id", &id));
6184 PFNV_CHK(pf_nvuint64(nvl, "creatorid", &creatorid));
6185
6186 s = pf_find_state_byid(id, creatorid);
6187 if (s == NULL)
6188 ERROUT(ENOENT);
6189
6190 free(nvlpacked, M_NVLIST);
6191 nvlpacked = NULL;
6192 nvlist_destroy(nvl);
6193 nvl = nvlist_create(0);
6194 if (nvl == NULL)
6195 ERROUT(ENOMEM);
6196
6197 nvls = pf_state_to_nvstate(s);
6198 if (nvls == NULL)
6199 ERROUT(ENOMEM);
6200
6201 nvlist_add_nvlist(nvl, "state", nvls);
6202 nvlist_destroy(nvls);
6203
6204 nvlpacked = nvlist_pack(nvl, &nv->len);
6205 if (nvlpacked == NULL)
6206 ERROUT(ENOMEM);
6207
6208 if (nv->size == 0)
6209 ERROUT(0);
6210 else if (nv->size < nv->len)
6211 ERROUT(ENOSPC);
6212
6213 error = copyout(nvlpacked, nv->data, nv->len);
6214
6215 #undef ERROUT
6216 errout:
6217 if (s != NULL)
6218 PF_STATE_UNLOCK(s);
6219 free(nvlpacked, M_NVLIST);
6220 nvlist_destroy(nvl);
6221 return (error);
6222 }
6223
6224 /*
6225 * XXX - Check for version mismatch!!!
6226 */
6227
6228 /*
6229 * Duplicate pfctl -Fa operation to get rid of as much as we can.
6230 */
6231 static int
shutdown_pf(void)6232 shutdown_pf(void)
6233 {
6234 int error = 0;
6235 u_int32_t t[5];
6236 char nn = '\0';
6237 struct pf_kanchor *anchor;
6238 struct pf_keth_anchor *eth_anchor;
6239 int rs_num;
6240
6241 do {
6242 /* Unlink rules of all user defined anchors */
6243 RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors) {
6244 /* Wildcard based anchors may not have a respective
6245 * explicit anchor rule or they may be left empty
6246 * without rules. It leads to anchor.refcnt=0, and the
6247 * rest of the logic does not expect it. */
6248 if (anchor->refcnt == 0)
6249 anchor->refcnt = 1;
6250 for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
6251 if ((error = pf_begin_rules(&t[rs_num], rs_num,
6252 anchor->path)) != 0) {
6253 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: "
6254 "anchor.path=%s rs_num=%d\n",
6255 anchor->path, rs_num));
6256 goto error; /* XXX: rollback? */
6257 }
6258 }
6259 for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
6260 error = pf_commit_rules(t[rs_num], rs_num,
6261 anchor->path);
6262 MPASS(error == 0);
6263 }
6264 }
6265
6266 /* Unlink rules of all user defined ether anchors */
6267 RB_FOREACH(eth_anchor, pf_keth_anchor_global,
6268 &V_pf_keth_anchors) {
6269 /* Wildcard based anchors may not have a respective
6270 * explicit anchor rule or they may be left empty
6271 * without rules. It leads to anchor.refcnt=0, and the
6272 * rest of the logic does not expect it. */
6273 if (eth_anchor->refcnt == 0)
6274 eth_anchor->refcnt = 1;
6275 if ((error = pf_begin_eth(&t[0], eth_anchor->path))
6276 != 0) {
6277 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: eth "
6278 "anchor.path=%s\n", eth_anchor->path));
6279 goto error;
6280 }
6281 error = pf_commit_eth(t[0], eth_anchor->path);
6282 MPASS(error == 0);
6283 }
6284
6285 if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
6286 != 0) {
6287 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: SCRUB\n"));
6288 break;
6289 }
6290 if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn))
6291 != 0) {
6292 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: FILTER\n"));
6293 break; /* XXX: rollback? */
6294 }
6295 if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn))
6296 != 0) {
6297 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: NAT\n"));
6298 break; /* XXX: rollback? */
6299 }
6300 if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn))
6301 != 0) {
6302 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: BINAT\n"));
6303 break; /* XXX: rollback? */
6304 }
6305 if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn))
6306 != 0) {
6307 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: RDR\n"));
6308 break; /* XXX: rollback? */
6309 }
6310
6311 error = pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn);
6312 MPASS(error == 0);
6313 error = pf_commit_rules(t[1], PF_RULESET_FILTER, &nn);
6314 MPASS(error == 0);
6315 error = pf_commit_rules(t[2], PF_RULESET_NAT, &nn);
6316 MPASS(error == 0);
6317 error = pf_commit_rules(t[3], PF_RULESET_BINAT, &nn);
6318 MPASS(error == 0);
6319 error = pf_commit_rules(t[4], PF_RULESET_RDR, &nn);
6320 MPASS(error == 0);
6321
6322 if ((error = pf_clear_tables()) != 0)
6323 break;
6324
6325 if ((error = pf_begin_eth(&t[0], &nn)) != 0) {
6326 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: eth\n"));
6327 break;
6328 }
6329 error = pf_commit_eth(t[0], &nn);
6330 MPASS(error == 0);
6331
6332 #ifdef ALTQ
6333 if ((error = pf_begin_altq(&t[0])) != 0) {
6334 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: ALTQ\n"));
6335 break;
6336 }
6337 pf_commit_altq(t[0]);
6338 #endif
6339
6340 pf_clear_all_states();
6341
6342 pf_clear_srcnodes(NULL);
6343
6344 /* status does not use malloced mem so no need to cleanup */
6345 /* fingerprints and interfaces have their own cleanup code */
6346 } while(0);
6347
6348 error:
6349 return (error);
6350 }
6351
6352 static pfil_return_t
pf_check_return(int chk,struct mbuf ** m)6353 pf_check_return(int chk, struct mbuf **m)
6354 {
6355
6356 switch (chk) {
6357 case PF_PASS:
6358 if (*m == NULL)
6359 return (PFIL_CONSUMED);
6360 else
6361 return (PFIL_PASS);
6362 break;
6363 default:
6364 if (*m != NULL) {
6365 m_freem(*m);
6366 *m = NULL;
6367 }
6368 return (PFIL_DROPPED);
6369 }
6370 }
6371
6372 static pfil_return_t
pf_eth_check_in(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6373 pf_eth_check_in(struct mbuf **m, struct ifnet *ifp, int flags,
6374 void *ruleset __unused, struct inpcb *inp)
6375 {
6376 int chk;
6377
6378 chk = pf_test_eth(PF_IN, flags, ifp, m, inp);
6379
6380 return (pf_check_return(chk, m));
6381 }
6382
6383 static pfil_return_t
pf_eth_check_out(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6384 pf_eth_check_out(struct mbuf **m, struct ifnet *ifp, int flags,
6385 void *ruleset __unused, struct inpcb *inp)
6386 {
6387 int chk;
6388
6389 chk = pf_test_eth(PF_OUT, flags, ifp, m, inp);
6390
6391 return (pf_check_return(chk, m));
6392 }
6393
6394 #ifdef INET
6395 static pfil_return_t
pf_check_in(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6396 pf_check_in(struct mbuf **m, struct ifnet *ifp, int flags,
6397 void *ruleset __unused, struct inpcb *inp)
6398 {
6399 int chk;
6400
6401 chk = pf_test(PF_IN, flags, ifp, m, inp, NULL);
6402
6403 return (pf_check_return(chk, m));
6404 }
6405
6406 static pfil_return_t
pf_check_out(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6407 pf_check_out(struct mbuf **m, struct ifnet *ifp, int flags,
6408 void *ruleset __unused, struct inpcb *inp)
6409 {
6410 int chk;
6411
6412 chk = pf_test(PF_OUT, flags, ifp, m, inp, NULL);
6413
6414 return (pf_check_return(chk, m));
6415 }
6416 #endif
6417
6418 #ifdef INET6
6419 static pfil_return_t
pf_check6_in(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6420 pf_check6_in(struct mbuf **m, struct ifnet *ifp, int flags,
6421 void *ruleset __unused, struct inpcb *inp)
6422 {
6423 int chk;
6424
6425 /*
6426 * In case of loopback traffic IPv6 uses the real interface in
6427 * order to support scoped addresses. In order to support stateful
6428 * filtering we have change this to lo0 as it is the case in IPv4.
6429 */
6430 CURVNET_SET(ifp->if_vnet);
6431 chk = pf_test6(PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp,
6432 m, inp, NULL);
6433 CURVNET_RESTORE();
6434
6435 return (pf_check_return(chk, m));
6436 }
6437
6438 static pfil_return_t
pf_check6_out(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6439 pf_check6_out(struct mbuf **m, struct ifnet *ifp, int flags,
6440 void *ruleset __unused, struct inpcb *inp)
6441 {
6442 int chk;
6443
6444 CURVNET_SET(ifp->if_vnet);
6445 chk = pf_test6(PF_OUT, flags, ifp, m, inp, NULL);
6446 CURVNET_RESTORE();
6447
6448 return (pf_check_return(chk, m));
6449 }
6450 #endif /* INET6 */
6451
6452 VNET_DEFINE_STATIC(pfil_hook_t, pf_eth_in_hook);
6453 VNET_DEFINE_STATIC(pfil_hook_t, pf_eth_out_hook);
6454 #define V_pf_eth_in_hook VNET(pf_eth_in_hook)
6455 #define V_pf_eth_out_hook VNET(pf_eth_out_hook)
6456
6457 #ifdef INET
6458 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_in_hook);
6459 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_out_hook);
6460 #define V_pf_ip4_in_hook VNET(pf_ip4_in_hook)
6461 #define V_pf_ip4_out_hook VNET(pf_ip4_out_hook)
6462 #endif
6463 #ifdef INET6
6464 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_in_hook);
6465 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_out_hook);
6466 #define V_pf_ip6_in_hook VNET(pf_ip6_in_hook)
6467 #define V_pf_ip6_out_hook VNET(pf_ip6_out_hook)
6468 #endif
6469
6470 static void
hook_pf_eth(void)6471 hook_pf_eth(void)
6472 {
6473 struct pfil_hook_args pha = {
6474 .pa_version = PFIL_VERSION,
6475 .pa_modname = "pf",
6476 .pa_type = PFIL_TYPE_ETHERNET,
6477 };
6478 struct pfil_link_args pla = {
6479 .pa_version = PFIL_VERSION,
6480 };
6481 int ret __diagused;
6482
6483 if (atomic_load_bool(&V_pf_pfil_eth_hooked))
6484 return;
6485
6486 pha.pa_mbuf_chk = pf_eth_check_in;
6487 pha.pa_flags = PFIL_IN;
6488 pha.pa_rulname = "eth-in";
6489 V_pf_eth_in_hook = pfil_add_hook(&pha);
6490 pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6491 pla.pa_head = V_link_pfil_head;
6492 pla.pa_hook = V_pf_eth_in_hook;
6493 ret = pfil_link(&pla);
6494 MPASS(ret == 0);
6495 pha.pa_mbuf_chk = pf_eth_check_out;
6496 pha.pa_flags = PFIL_OUT;
6497 pha.pa_rulname = "eth-out";
6498 V_pf_eth_out_hook = pfil_add_hook(&pha);
6499 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6500 pla.pa_head = V_link_pfil_head;
6501 pla.pa_hook = V_pf_eth_out_hook;
6502 ret = pfil_link(&pla);
6503 MPASS(ret == 0);
6504
6505 atomic_store_bool(&V_pf_pfil_eth_hooked, true);
6506 }
6507
6508 static void
hook_pf(void)6509 hook_pf(void)
6510 {
6511 struct pfil_hook_args pha = {
6512 .pa_version = PFIL_VERSION,
6513 .pa_modname = "pf",
6514 };
6515 struct pfil_link_args pla = {
6516 .pa_version = PFIL_VERSION,
6517 };
6518 int ret __diagused;
6519
6520 if (atomic_load_bool(&V_pf_pfil_hooked))
6521 return;
6522
6523 #ifdef INET
6524 pha.pa_type = PFIL_TYPE_IP4;
6525 pha.pa_mbuf_chk = pf_check_in;
6526 pha.pa_flags = PFIL_IN;
6527 pha.pa_rulname = "default-in";
6528 V_pf_ip4_in_hook = pfil_add_hook(&pha);
6529 pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6530 pla.pa_head = V_inet_pfil_head;
6531 pla.pa_hook = V_pf_ip4_in_hook;
6532 ret = pfil_link(&pla);
6533 MPASS(ret == 0);
6534 pha.pa_mbuf_chk = pf_check_out;
6535 pha.pa_flags = PFIL_OUT;
6536 pha.pa_rulname = "default-out";
6537 V_pf_ip4_out_hook = pfil_add_hook(&pha);
6538 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6539 pla.pa_head = V_inet_pfil_head;
6540 pla.pa_hook = V_pf_ip4_out_hook;
6541 ret = pfil_link(&pla);
6542 MPASS(ret == 0);
6543 if (V_pf_filter_local) {
6544 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6545 pla.pa_head = V_inet_local_pfil_head;
6546 pla.pa_hook = V_pf_ip4_out_hook;
6547 ret = pfil_link(&pla);
6548 MPASS(ret == 0);
6549 }
6550 #endif
6551 #ifdef INET6
6552 pha.pa_type = PFIL_TYPE_IP6;
6553 pha.pa_mbuf_chk = pf_check6_in;
6554 pha.pa_flags = PFIL_IN;
6555 pha.pa_rulname = "default-in6";
6556 V_pf_ip6_in_hook = pfil_add_hook(&pha);
6557 pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6558 pla.pa_head = V_inet6_pfil_head;
6559 pla.pa_hook = V_pf_ip6_in_hook;
6560 ret = pfil_link(&pla);
6561 MPASS(ret == 0);
6562 pha.pa_mbuf_chk = pf_check6_out;
6563 pha.pa_rulname = "default-out6";
6564 pha.pa_flags = PFIL_OUT;
6565 V_pf_ip6_out_hook = pfil_add_hook(&pha);
6566 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6567 pla.pa_head = V_inet6_pfil_head;
6568 pla.pa_hook = V_pf_ip6_out_hook;
6569 ret = pfil_link(&pla);
6570 MPASS(ret == 0);
6571 if (V_pf_filter_local) {
6572 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6573 pla.pa_head = V_inet6_local_pfil_head;
6574 pla.pa_hook = V_pf_ip6_out_hook;
6575 ret = pfil_link(&pla);
6576 MPASS(ret == 0);
6577 }
6578 #endif
6579
6580 atomic_store_bool(&V_pf_pfil_hooked, true);
6581 }
6582
6583 static void
dehook_pf_eth(void)6584 dehook_pf_eth(void)
6585 {
6586
6587 if (!atomic_load_bool(&V_pf_pfil_eth_hooked))
6588 return;
6589
6590 pfil_remove_hook(V_pf_eth_in_hook);
6591 pfil_remove_hook(V_pf_eth_out_hook);
6592
6593 atomic_store_bool(&V_pf_pfil_eth_hooked, false);
6594 }
6595
6596 static void
dehook_pf(void)6597 dehook_pf(void)
6598 {
6599
6600 if (!atomic_load_bool(&V_pf_pfil_hooked))
6601 return;
6602
6603 #ifdef INET
6604 pfil_remove_hook(V_pf_ip4_in_hook);
6605 pfil_remove_hook(V_pf_ip4_out_hook);
6606 #endif
6607 #ifdef INET6
6608 pfil_remove_hook(V_pf_ip6_in_hook);
6609 pfil_remove_hook(V_pf_ip6_out_hook);
6610 #endif
6611
6612 atomic_store_bool(&V_pf_pfil_hooked, false);
6613 }
6614
6615 static void
pf_load_vnet(void)6616 pf_load_vnet(void)
6617 {
6618 V_pf_tag_z = uma_zcreate("pf tags", sizeof(struct pf_tagname),
6619 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
6620
6621 rm_init_flags(&V_pf_rules_lock, "pf rulesets", RM_RECURSE);
6622 sx_init(&V_pf_ioctl_lock, "pf ioctl");
6623
6624 pf_init_tagset(&V_pf_tags, &pf_rule_tag_hashsize,
6625 PF_RULE_TAG_HASH_SIZE_DEFAULT);
6626 #ifdef ALTQ
6627 pf_init_tagset(&V_pf_qids, &pf_queue_tag_hashsize,
6628 PF_QUEUE_TAG_HASH_SIZE_DEFAULT);
6629 #endif
6630
6631 V_pf_keth = &V_pf_main_keth_anchor.ruleset;
6632
6633 pfattach_vnet();
6634 V_pf_vnet_active = 1;
6635 }
6636
6637 static int
pf_load(void)6638 pf_load(void)
6639 {
6640 int error;
6641
6642 sx_init(&pf_end_lock, "pf end thread");
6643
6644 pf_mtag_initialize();
6645
6646 pf_dev = make_dev(&pf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, PF_NAME);
6647 if (pf_dev == NULL)
6648 return (ENOMEM);
6649
6650 pf_end_threads = 0;
6651 error = kproc_create(pf_purge_thread, NULL, &pf_purge_proc, 0, 0, "pf purge");
6652 if (error != 0)
6653 return (error);
6654
6655 pfi_initialize();
6656
6657 return (0);
6658 }
6659
6660 static void
pf_unload_vnet(void)6661 pf_unload_vnet(void)
6662 {
6663 int ret __diagused;
6664
6665 V_pf_vnet_active = 0;
6666 V_pf_status.running = 0;
6667 dehook_pf();
6668 dehook_pf_eth();
6669
6670 PF_RULES_WLOCK();
6671 pf_syncookies_cleanup();
6672 shutdown_pf();
6673 PF_RULES_WUNLOCK();
6674
6675 /* Make sure we've cleaned up ethernet rules before we continue. */
6676 NET_EPOCH_DRAIN_CALLBACKS();
6677
6678 ret = swi_remove(V_pf_swi_cookie);
6679 MPASS(ret == 0);
6680 ret = intr_event_destroy(V_pf_swi_ie);
6681 MPASS(ret == 0);
6682
6683 pf_unload_vnet_purge();
6684
6685 pf_normalize_cleanup();
6686 PF_RULES_WLOCK();
6687 pfi_cleanup_vnet();
6688 PF_RULES_WUNLOCK();
6689 pfr_cleanup();
6690 pf_osfp_flush();
6691 pf_cleanup();
6692 if (IS_DEFAULT_VNET(curvnet))
6693 pf_mtag_cleanup();
6694
6695 pf_cleanup_tagset(&V_pf_tags);
6696 #ifdef ALTQ
6697 pf_cleanup_tagset(&V_pf_qids);
6698 #endif
6699 uma_zdestroy(V_pf_tag_z);
6700
6701 #ifdef PF_WANT_32_TO_64_COUNTER
6702 PF_RULES_WLOCK();
6703 LIST_REMOVE(V_pf_kifmarker, pfik_allkiflist);
6704
6705 MPASS(LIST_EMPTY(&V_pf_allkiflist));
6706 MPASS(V_pf_allkifcount == 0);
6707
6708 LIST_REMOVE(&V_pf_default_rule, allrulelist);
6709 V_pf_allrulecount--;
6710 LIST_REMOVE(V_pf_rulemarker, allrulelist);
6711
6712 MPASS(LIST_EMPTY(&V_pf_allrulelist));
6713 MPASS(V_pf_allrulecount == 0);
6714
6715 PF_RULES_WUNLOCK();
6716
6717 free(V_pf_kifmarker, PFI_MTYPE);
6718 free(V_pf_rulemarker, M_PFRULE);
6719 #endif
6720
6721 /* Free counters last as we updated them during shutdown. */
6722 pf_counter_u64_deinit(&V_pf_default_rule.evaluations);
6723 for (int i = 0; i < 2; i++) {
6724 pf_counter_u64_deinit(&V_pf_default_rule.packets[i]);
6725 pf_counter_u64_deinit(&V_pf_default_rule.bytes[i]);
6726 }
6727 counter_u64_free(V_pf_default_rule.states_cur);
6728 counter_u64_free(V_pf_default_rule.states_tot);
6729 counter_u64_free(V_pf_default_rule.src_nodes);
6730 uma_zfree_pcpu(pf_timestamp_pcpu_zone, V_pf_default_rule.timestamp);
6731
6732 for (int i = 0; i < PFRES_MAX; i++)
6733 counter_u64_free(V_pf_status.counters[i]);
6734 for (int i = 0; i < KLCNT_MAX; i++)
6735 counter_u64_free(V_pf_status.lcounters[i]);
6736 for (int i = 0; i < FCNT_MAX; i++)
6737 pf_counter_u64_deinit(&V_pf_status.fcounters[i]);
6738 for (int i = 0; i < SCNT_MAX; i++)
6739 counter_u64_free(V_pf_status.scounters[i]);
6740
6741 rm_destroy(&V_pf_rules_lock);
6742 sx_destroy(&V_pf_ioctl_lock);
6743 }
6744
6745 static void
pf_unload(void)6746 pf_unload(void)
6747 {
6748
6749 sx_xlock(&pf_end_lock);
6750 pf_end_threads = 1;
6751 while (pf_end_threads < 2) {
6752 wakeup_one(pf_purge_thread);
6753 sx_sleep(pf_purge_proc, &pf_end_lock, 0, "pftmo", 0);
6754 }
6755 sx_xunlock(&pf_end_lock);
6756
6757 pf_nl_unregister();
6758
6759 if (pf_dev != NULL)
6760 destroy_dev(pf_dev);
6761
6762 pfi_cleanup();
6763
6764 sx_destroy(&pf_end_lock);
6765 }
6766
6767 static void
vnet_pf_init(void * unused __unused)6768 vnet_pf_init(void *unused __unused)
6769 {
6770
6771 pf_load_vnet();
6772 }
6773 VNET_SYSINIT(vnet_pf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
6774 vnet_pf_init, NULL);
6775
6776 static void
vnet_pf_uninit(const void * unused __unused)6777 vnet_pf_uninit(const void *unused __unused)
6778 {
6779
6780 pf_unload_vnet();
6781 }
6782 SYSUNINIT(pf_unload, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND, pf_unload, NULL);
6783 VNET_SYSUNINIT(vnet_pf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
6784 vnet_pf_uninit, NULL);
6785
6786 static int
pf_modevent(module_t mod,int type,void * data)6787 pf_modevent(module_t mod, int type, void *data)
6788 {
6789 int error = 0;
6790
6791 switch(type) {
6792 case MOD_LOAD:
6793 error = pf_load();
6794 pf_nl_register();
6795 break;
6796 case MOD_UNLOAD:
6797 /* Handled in SYSUNINIT(pf_unload) to ensure it's done after
6798 * the vnet_pf_uninit()s */
6799 break;
6800 default:
6801 error = EINVAL;
6802 break;
6803 }
6804
6805 return (error);
6806 }
6807
6808 static moduledata_t pf_mod = {
6809 "pf",
6810 pf_modevent,
6811 0
6812 };
6813
6814 DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
6815 MODULE_DEPEND(pf, netlink, 1, 1, 1);
6816 MODULE_VERSION(pf, PF_MODVER);
6817