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