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 int
pf_start(void)2525 pf_start(void)
2526 {
2527 int error = 0;
2528
2529 sx_xlock(&V_pf_ioctl_lock);
2530 if (V_pf_status.running)
2531 error = EEXIST;
2532 else {
2533 hook_pf();
2534 if (! TAILQ_EMPTY(V_pf_keth->active.rules))
2535 hook_pf_eth();
2536 V_pf_status.running = 1;
2537 V_pf_status.since = time_uptime;
2538 new_unrhdr64(&V_pf_stateid, time_second);
2539
2540 DPFPRINTF(PF_DEBUG_MISC, "pf: started");
2541 }
2542 sx_xunlock(&V_pf_ioctl_lock);
2543
2544 return (error);
2545 }
2546
2547 int
pf_stop(void)2548 pf_stop(void)
2549 {
2550 int error = 0;
2551
2552 sx_xlock(&V_pf_ioctl_lock);
2553 if (!V_pf_status.running)
2554 error = ENOENT;
2555 else {
2556 V_pf_status.running = 0;
2557 dehook_pf();
2558 dehook_pf_eth();
2559 V_pf_status.since = time_uptime;
2560 DPFPRINTF(PF_DEBUG_MISC, "pf: stopped");
2561 }
2562 sx_xunlock(&V_pf_ioctl_lock);
2563
2564 return (error);
2565 }
2566
2567 void
pf_ioctl_clear_status(void)2568 pf_ioctl_clear_status(void)
2569 {
2570 PF_RULES_WLOCK();
2571 for (int i = 0; i < PFRES_MAX; i++)
2572 counter_u64_zero(V_pf_status.counters[i]);
2573 for (int i = 0; i < FCNT_MAX; i++)
2574 pf_counter_u64_zero(&V_pf_status.fcounters[i]);
2575 for (int i = 0; i < SCNT_MAX; i++)
2576 counter_u64_zero(V_pf_status.scounters[i]);
2577 for (int i = 0; i < NCNT_MAX; i++)
2578 counter_u64_zero(V_pf_status.ncounters[i]);
2579 for (int i = 0; i < KLCNT_MAX; i++)
2580 counter_u64_zero(V_pf_status.lcounters[i]);
2581 V_pf_status.since = time_uptime;
2582 if (*V_pf_status.ifname)
2583 pfi_update_status(V_pf_status.ifname, NULL);
2584 PF_RULES_WUNLOCK();
2585 }
2586
2587 int
pf_ioctl_set_timeout(int timeout,int seconds,int * prev_seconds)2588 pf_ioctl_set_timeout(int timeout, int seconds, int *prev_seconds)
2589 {
2590 uint32_t old;
2591
2592 if (timeout < 0 || timeout >= PFTM_MAX ||
2593 seconds < 0)
2594 return (EINVAL);
2595
2596 PF_RULES_WLOCK();
2597 old = V_pf_default_rule.timeout[timeout];
2598 if (timeout == PFTM_INTERVAL && seconds == 0)
2599 seconds = 1;
2600 V_pf_default_rule.timeout[timeout] = seconds;
2601 if (timeout == PFTM_INTERVAL && seconds < old)
2602 wakeup(pf_purge_thread);
2603
2604 if (prev_seconds != NULL)
2605 *prev_seconds = old;
2606
2607 PF_RULES_WUNLOCK();
2608
2609 return (0);
2610 }
2611
2612 int
pf_ioctl_get_timeout(int timeout,int * seconds)2613 pf_ioctl_get_timeout(int timeout, int *seconds)
2614 {
2615 PF_RULES_RLOCK_TRACKER;
2616
2617 if (timeout < 0 || timeout >= PFTM_MAX)
2618 return (EINVAL);
2619
2620 PF_RULES_RLOCK();
2621 *seconds = V_pf_default_rule.timeout[timeout];
2622 PF_RULES_RUNLOCK();
2623
2624 return (0);
2625 }
2626
2627 int
pf_ioctl_set_limit(int index,unsigned int limit,unsigned int * old_limit)2628 pf_ioctl_set_limit(int index, unsigned int limit, unsigned int *old_limit)
2629 {
2630
2631 PF_RULES_WLOCK();
2632 if (index < 0 || index >= PF_LIMIT_MAX ||
2633 V_pf_limits[index].zone == NULL) {
2634 PF_RULES_WUNLOCK();
2635 return (EINVAL);
2636 }
2637 uma_zone_set_max(V_pf_limits[index].zone,
2638 limit == 0 ? INT_MAX : limit);
2639 if (old_limit != NULL)
2640 *old_limit = V_pf_limits[index].limit;
2641 V_pf_limits[index].limit = limit;
2642 PF_RULES_WUNLOCK();
2643
2644 return (0);
2645 }
2646
2647 int
pf_ioctl_get_limit(int index,unsigned int * limit)2648 pf_ioctl_get_limit(int index, unsigned int *limit)
2649 {
2650 PF_RULES_RLOCK_TRACKER;
2651
2652 if (index < 0 || index >= PF_LIMIT_MAX)
2653 return (EINVAL);
2654
2655 PF_RULES_RLOCK();
2656 *limit = V_pf_limits[index].limit;
2657 PF_RULES_RUNLOCK();
2658
2659 return (0);
2660 }
2661
2662 int
pf_ioctl_begin_addrs(uint32_t * ticket)2663 pf_ioctl_begin_addrs(uint32_t *ticket)
2664 {
2665 PF_RULES_WLOCK();
2666 pf_empty_kpool(&V_pf_pabuf[0]);
2667 pf_empty_kpool(&V_pf_pabuf[1]);
2668 pf_empty_kpool(&V_pf_pabuf[2]);
2669 *ticket = ++V_ticket_pabuf;
2670 PF_RULES_WUNLOCK();
2671
2672 return (0);
2673 }
2674
2675 int
pf_ioctl_add_addr(struct pf_nl_pooladdr * pp)2676 pf_ioctl_add_addr(struct pf_nl_pooladdr *pp)
2677 {
2678 struct pf_kpooladdr *pa = NULL;
2679 struct pfi_kkif *kif = NULL;
2680 int error;
2681
2682 if (pp->which != PF_RDR && pp->which != PF_NAT &&
2683 pp->which != PF_RT)
2684 return (EINVAL);
2685
2686 switch (pp->af) {
2687 #ifdef INET
2688 case AF_INET:
2689 /* FALLTHROUGH */
2690 #endif /* INET */
2691 #ifdef INET6
2692 case AF_INET6:
2693 /* FALLTHROUGH */
2694 #endif /* INET6 */
2695 case AF_UNSPEC:
2696 break;
2697 default:
2698 return (EAFNOSUPPORT);
2699 }
2700
2701 if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
2702 pp->addr.addr.type != PF_ADDR_DYNIFTL &&
2703 pp->addr.addr.type != PF_ADDR_TABLE)
2704 return (EINVAL);
2705
2706 if (pp->addr.addr.p.dyn != NULL)
2707 return (EINVAL);
2708
2709 pa = malloc(sizeof(*pa), M_PFRULE, M_WAITOK);
2710 error = pf_pooladdr_to_kpooladdr(&pp->addr, pa);
2711 if (error != 0)
2712 goto out;
2713 if (pa->ifname[0])
2714 kif = pf_kkif_create(M_WAITOK);
2715 PF_RULES_WLOCK();
2716 if (pp->ticket != V_ticket_pabuf) {
2717 PF_RULES_WUNLOCK();
2718 if (pa->ifname[0])
2719 pf_kkif_free(kif);
2720 error = EBUSY;
2721 goto out;
2722 }
2723 if (pa->ifname[0]) {
2724 pa->kif = pfi_kkif_attach(kif, pa->ifname);
2725 kif = NULL;
2726 pfi_kkif_ref(pa->kif);
2727 } else
2728 pa->kif = NULL;
2729 if (pa->addr.type == PF_ADDR_DYNIFTL && ((error =
2730 pfi_dynaddr_setup(&pa->addr, pp->af)) != 0)) {
2731 if (pa->ifname[0])
2732 pfi_kkif_unref(pa->kif);
2733 PF_RULES_WUNLOCK();
2734 goto out;
2735 }
2736 pa->af = pp->af;
2737 switch (pp->which) {
2738 case PF_NAT:
2739 TAILQ_INSERT_TAIL(&V_pf_pabuf[0], pa, entries);
2740 break;
2741 case PF_RDR:
2742 TAILQ_INSERT_TAIL(&V_pf_pabuf[1], pa, entries);
2743 break;
2744 case PF_RT:
2745 TAILQ_INSERT_TAIL(&V_pf_pabuf[2], pa, entries);
2746 break;
2747 }
2748 PF_RULES_WUNLOCK();
2749
2750 return (0);
2751
2752 out:
2753 free(pa, M_PFRULE);
2754 return (error);
2755 }
2756
2757 int
pf_ioctl_get_addrs(struct pf_nl_pooladdr * pp)2758 pf_ioctl_get_addrs(struct pf_nl_pooladdr *pp)
2759 {
2760 struct pf_kpool *pool;
2761 struct pf_kpooladdr *pa;
2762
2763 PF_RULES_RLOCK_TRACKER;
2764
2765 if (pp->which != PF_RDR && pp->which != PF_NAT &&
2766 pp->which != PF_RT)
2767 return (EINVAL);
2768
2769 pp->anchor[sizeof(pp->anchor) - 1] = 0;
2770 pp->nr = 0;
2771
2772 PF_RULES_RLOCK();
2773 pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
2774 pp->r_num, 0, 1, 0, pp->which);
2775 if (pool == NULL) {
2776 PF_RULES_RUNLOCK();
2777 return (EBUSY);
2778 }
2779 TAILQ_FOREACH(pa, &pool->list, entries)
2780 pp->nr++;
2781 PF_RULES_RUNLOCK();
2782
2783 return (0);
2784 }
2785
2786 int
pf_ioctl_get_addr(struct pf_nl_pooladdr * pp)2787 pf_ioctl_get_addr(struct pf_nl_pooladdr *pp)
2788 {
2789 struct pf_kpool *pool;
2790 struct pf_kpooladdr *pa;
2791 u_int32_t nr = 0;
2792
2793 if (pp->which != PF_RDR && pp->which != PF_NAT &&
2794 pp->which != PF_RT)
2795 return (EINVAL);
2796
2797 PF_RULES_RLOCK_TRACKER;
2798
2799 pp->anchor[sizeof(pp->anchor) - 1] = '\0';
2800
2801 PF_RULES_RLOCK();
2802 pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
2803 pp->r_num, 0, 1, 1, pp->which);
2804 if (pool == NULL) {
2805 PF_RULES_RUNLOCK();
2806 return (EBUSY);
2807 }
2808 pa = TAILQ_FIRST(&pool->list);
2809 while ((pa != NULL) && (nr < pp->nr)) {
2810 pa = TAILQ_NEXT(pa, entries);
2811 nr++;
2812 }
2813 if (pa == NULL) {
2814 PF_RULES_RUNLOCK();
2815 return (EBUSY);
2816 }
2817 pf_kpooladdr_to_pooladdr(pa, &pp->addr);
2818 pp->af = pa->af;
2819 pf_addr_copyout(&pp->addr.addr);
2820 PF_RULES_RUNLOCK();
2821
2822 return (0);
2823 }
2824
2825 int
pf_ioctl_get_rulesets(struct pfioc_ruleset * pr)2826 pf_ioctl_get_rulesets(struct pfioc_ruleset *pr)
2827 {
2828 struct pf_kruleset *ruleset;
2829 struct pf_kanchor *anchor;
2830
2831 PF_RULES_RLOCK_TRACKER;
2832
2833 pr->path[sizeof(pr->path) - 1] = '\0';
2834
2835 PF_RULES_RLOCK();
2836 if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
2837 PF_RULES_RUNLOCK();
2838 return (ENOENT);
2839 }
2840 pr->nr = 0;
2841 if (ruleset == &pf_main_ruleset) {
2842 /* XXX kludge for pf_main_ruleset */
2843 RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
2844 if (anchor->parent == NULL)
2845 pr->nr++;
2846 } else {
2847 RB_FOREACH(anchor, pf_kanchor_node,
2848 &ruleset->anchor->children)
2849 pr->nr++;
2850 }
2851 PF_RULES_RUNLOCK();
2852
2853 return (0);
2854 }
2855
2856 int
pf_ioctl_get_ruleset(struct pfioc_ruleset * pr)2857 pf_ioctl_get_ruleset(struct pfioc_ruleset *pr)
2858 {
2859 struct pf_kruleset *ruleset;
2860 struct pf_kanchor *anchor;
2861 u_int32_t nr = 0;
2862 int error = 0;
2863
2864 PF_RULES_RLOCK_TRACKER;
2865
2866 PF_RULES_RLOCK();
2867 if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
2868 PF_RULES_RUNLOCK();
2869 return (ENOENT);
2870 }
2871
2872 pr->name[0] = '\0';
2873 if (ruleset == &pf_main_ruleset) {
2874 /* XXX kludge for pf_main_ruleset */
2875 RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
2876 if (anchor->parent == NULL && nr++ == pr->nr) {
2877 strlcpy(pr->name, anchor->name,
2878 sizeof(pr->name));
2879 break;
2880 }
2881 } else {
2882 RB_FOREACH(anchor, pf_kanchor_node,
2883 &ruleset->anchor->children)
2884 if (nr++ == pr->nr) {
2885 strlcpy(pr->name, anchor->name,
2886 sizeof(pr->name));
2887 break;
2888 }
2889 }
2890 if (!pr->name[0])
2891 error = EBUSY;
2892 PF_RULES_RUNLOCK();
2893
2894 return (error);
2895 }
2896
2897 int
pf_ioctl_natlook(struct pfioc_natlook * pnl)2898 pf_ioctl_natlook(struct pfioc_natlook *pnl)
2899 {
2900 struct pf_state_key *sk;
2901 struct pf_kstate *state;
2902 struct pf_state_key_cmp key;
2903 int m = 0, direction = pnl->direction;
2904 int sidx, didx;
2905
2906 /* NATLOOK src and dst are reversed, so reverse sidx/didx */
2907 sidx = (direction == PF_IN) ? 1 : 0;
2908 didx = (direction == PF_IN) ? 0 : 1;
2909
2910 if (!pnl->proto ||
2911 PF_AZERO(&pnl->saddr, pnl->af) ||
2912 PF_AZERO(&pnl->daddr, pnl->af) ||
2913 ((pnl->proto == IPPROTO_TCP ||
2914 pnl->proto == IPPROTO_UDP) &&
2915 (!pnl->dport || !pnl->sport)))
2916 return (EINVAL);
2917
2918 switch (pnl->direction) {
2919 case PF_IN:
2920 case PF_OUT:
2921 case PF_INOUT:
2922 break;
2923 default:
2924 return (EINVAL);
2925 }
2926
2927 switch (pnl->af) {
2928 #ifdef INET
2929 case AF_INET:
2930 break;
2931 #endif /* INET */
2932 #ifdef INET6
2933 case AF_INET6:
2934 break;
2935 #endif /* INET6 */
2936 default:
2937 return (EAFNOSUPPORT);
2938 }
2939
2940 bzero(&key, sizeof(key));
2941 key.af = pnl->af;
2942 key.proto = pnl->proto;
2943 pf_addrcpy(&key.addr[sidx], &pnl->saddr, pnl->af);
2944 key.port[sidx] = pnl->sport;
2945 pf_addrcpy(&key.addr[didx], &pnl->daddr, pnl->af);
2946 key.port[didx] = pnl->dport;
2947
2948 state = pf_find_state_all(&key, direction, &m);
2949 if (state == NULL)
2950 return (ENOENT);
2951
2952 if (m > 1) {
2953 PF_STATE_UNLOCK(state);
2954 return (E2BIG); /* more than one state */
2955 }
2956
2957 sk = state->key[sidx];
2958 pf_addrcpy(&pnl->rsaddr,
2959 &sk->addr[sidx], sk->af);
2960 pnl->rsport = sk->port[sidx];
2961 pf_addrcpy(&pnl->rdaddr,
2962 &sk->addr[didx], sk->af);
2963 pnl->rdport = sk->port[didx];
2964 PF_STATE_UNLOCK(state);
2965
2966 return (0);
2967 }
2968
2969 static int
pfioctl(struct cdev * dev,u_long cmd,caddr_t addr,int flags,struct thread * td)2970 pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
2971 {
2972 int error = 0;
2973 PF_RULES_RLOCK_TRACKER;
2974
2975 #define ERROUT_IOCTL(target, x) \
2976 do { \
2977 error = (x); \
2978 SDT_PROBE3(pf, ioctl, ioctl, error, cmd, error, __LINE__); \
2979 goto target; \
2980 } while (0)
2981
2982
2983 /* XXX keep in sync with switch() below */
2984 if (securelevel_gt(td->td_ucred, 2))
2985 switch (cmd) {
2986 case DIOCGETRULES:
2987 case DIOCGETRULENV:
2988 case DIOCGETADDRS:
2989 case DIOCGETADDR:
2990 case DIOCGETSTATE:
2991 case DIOCGETSTATENV:
2992 case DIOCSETSTATUSIF:
2993 case DIOCGETSTATUSNV:
2994 case DIOCCLRSTATUS:
2995 case DIOCNATLOOK:
2996 case DIOCSETDEBUG:
2997 #ifdef COMPAT_FREEBSD14
2998 case DIOCGETSTATES:
2999 case DIOCGETSTATESV2:
3000 #endif
3001 case DIOCGETTIMEOUT:
3002 case DIOCCLRRULECTRS:
3003 case DIOCGETLIMIT:
3004 case DIOCGETALTQSV0:
3005 case DIOCGETALTQSV1:
3006 case DIOCGETALTQV0:
3007 case DIOCGETALTQV1:
3008 case DIOCGETQSTATSV0:
3009 case DIOCGETQSTATSV1:
3010 case DIOCGETRULESETS:
3011 case DIOCGETRULESET:
3012 case DIOCRGETTABLES:
3013 case DIOCRGETTSTATS:
3014 case DIOCRCLRTSTATS:
3015 case DIOCRCLRADDRS:
3016 case DIOCRADDADDRS:
3017 case DIOCRDELADDRS:
3018 case DIOCRSETADDRS:
3019 case DIOCRGETADDRS:
3020 case DIOCRGETASTATS:
3021 case DIOCRCLRASTATS:
3022 case DIOCRTSTADDRS:
3023 case DIOCOSFPGET:
3024 case DIOCGETSRCNODES:
3025 case DIOCCLRSRCNODES:
3026 case DIOCGETSYNCOOKIES:
3027 case DIOCIGETIFACES:
3028 case DIOCGIFSPEEDV0:
3029 case DIOCGIFSPEEDV1:
3030 case DIOCSETIFFLAG:
3031 case DIOCCLRIFFLAG:
3032 case DIOCGETETHRULES:
3033 case DIOCGETETHRULE:
3034 case DIOCGETETHRULESETS:
3035 case DIOCGETETHRULESET:
3036 break;
3037 case DIOCRCLRTABLES:
3038 case DIOCRADDTABLES:
3039 case DIOCRDELTABLES:
3040 case DIOCRSETTFLAGS:
3041 if (((struct pfioc_table *)addr)->pfrio_flags &
3042 PFR_FLAG_DUMMY)
3043 break; /* dummy operation ok */
3044 return (EPERM);
3045 default:
3046 return (EPERM);
3047 }
3048
3049 if (!(flags & FWRITE))
3050 switch (cmd) {
3051 case DIOCGETRULES:
3052 case DIOCGETADDRS:
3053 case DIOCGETADDR:
3054 case DIOCGETSTATE:
3055 case DIOCGETSTATENV:
3056 case DIOCGETSTATUSNV:
3057 #ifdef COMPAT_FREEBSD14
3058 case DIOCGETSTATES:
3059 case DIOCGETSTATESV2:
3060 #endif
3061 case DIOCGETTIMEOUT:
3062 case DIOCGETLIMIT:
3063 case DIOCGETALTQSV0:
3064 case DIOCGETALTQSV1:
3065 case DIOCGETALTQV0:
3066 case DIOCGETALTQV1:
3067 case DIOCGETQSTATSV0:
3068 case DIOCGETQSTATSV1:
3069 case DIOCGETRULESETS:
3070 case DIOCGETRULESET:
3071 case DIOCNATLOOK:
3072 case DIOCRGETTABLES:
3073 case DIOCRGETTSTATS:
3074 case DIOCRGETADDRS:
3075 case DIOCRGETASTATS:
3076 case DIOCRTSTADDRS:
3077 case DIOCOSFPGET:
3078 case DIOCGETSRCNODES:
3079 case DIOCGETSYNCOOKIES:
3080 case DIOCIGETIFACES:
3081 case DIOCGIFSPEEDV1:
3082 case DIOCGIFSPEEDV0:
3083 case DIOCGETRULENV:
3084 case DIOCGETETHRULES:
3085 case DIOCGETETHRULE:
3086 case DIOCGETETHRULESETS:
3087 case DIOCGETETHRULESET:
3088 break;
3089 case DIOCRCLRTABLES:
3090 case DIOCRADDTABLES:
3091 case DIOCRDELTABLES:
3092 case DIOCRCLRTSTATS:
3093 case DIOCRCLRADDRS:
3094 case DIOCRADDADDRS:
3095 case DIOCRDELADDRS:
3096 case DIOCRSETADDRS:
3097 case DIOCRSETTFLAGS:
3098 if (((struct pfioc_table *)addr)->pfrio_flags &
3099 PFR_FLAG_DUMMY) {
3100 flags |= FWRITE; /* need write lock for dummy */
3101 break; /* dummy operation ok */
3102 }
3103 return (EACCES);
3104 default:
3105 return (EACCES);
3106 }
3107
3108 CURVNET_SET(TD_TO_VNET(td));
3109
3110 switch (cmd) {
3111 #ifdef COMPAT_FREEBSD14
3112 case DIOCSTART:
3113 error = pf_start();
3114 break;
3115
3116 case DIOCSTOP:
3117 error = pf_stop();
3118 break;
3119 #endif
3120
3121 case DIOCGETETHRULES: {
3122 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3123 nvlist_t *nvl;
3124 void *packed;
3125 struct pf_keth_rule *tail;
3126 struct pf_keth_ruleset *rs;
3127 u_int32_t ticket, nr;
3128 const char *anchor = "";
3129
3130 nvl = NULL;
3131 packed = NULL;
3132
3133 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULES_error, x)
3134
3135 if (nv->len > pf_ioctl_maxcount)
3136 ERROUT(ENOMEM);
3137
3138 /* Copy the request in */
3139 packed = malloc(nv->len, M_NVLIST, M_WAITOK);
3140 error = copyin(nv->data, packed, nv->len);
3141 if (error)
3142 ERROUT(error);
3143
3144 nvl = nvlist_unpack(packed, nv->len, 0);
3145 if (nvl == NULL)
3146 ERROUT(EBADMSG);
3147
3148 if (! nvlist_exists_string(nvl, "anchor"))
3149 ERROUT(EBADMSG);
3150
3151 anchor = nvlist_get_string(nvl, "anchor");
3152
3153 rs = pf_find_keth_ruleset(anchor);
3154
3155 nvlist_destroy(nvl);
3156 nvl = NULL;
3157 free(packed, M_NVLIST);
3158 packed = NULL;
3159
3160 if (rs == NULL)
3161 ERROUT(ENOENT);
3162
3163 /* Reply */
3164 nvl = nvlist_create(0);
3165 if (nvl == NULL)
3166 ERROUT(ENOMEM);
3167
3168 PF_RULES_RLOCK();
3169
3170 ticket = rs->active.ticket;
3171 tail = TAILQ_LAST(rs->active.rules, pf_keth_ruleq);
3172 if (tail)
3173 nr = tail->nr + 1;
3174 else
3175 nr = 0;
3176
3177 PF_RULES_RUNLOCK();
3178
3179 nvlist_add_number(nvl, "ticket", ticket);
3180 nvlist_add_number(nvl, "nr", nr);
3181
3182 packed = nvlist_pack(nvl, &nv->len);
3183 if (packed == NULL)
3184 ERROUT(ENOMEM);
3185
3186 if (nv->size == 0)
3187 ERROUT(0);
3188 else if (nv->size < nv->len)
3189 ERROUT(ENOSPC);
3190
3191 error = copyout(packed, nv->data, nv->len);
3192
3193 #undef ERROUT
3194 DIOCGETETHRULES_error:
3195 free(packed, M_NVLIST);
3196 nvlist_destroy(nvl);
3197 break;
3198 }
3199
3200 case DIOCGETETHRULE: {
3201 struct epoch_tracker et;
3202 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3203 nvlist_t *nvl = NULL;
3204 void *nvlpacked = NULL;
3205 struct pf_keth_rule *rule = NULL;
3206 struct pf_keth_ruleset *rs;
3207 u_int32_t ticket, nr;
3208 bool clear = false;
3209 const char *anchor;
3210
3211 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULE_error, x)
3212
3213 if (nv->len > pf_ioctl_maxcount)
3214 ERROUT(ENOMEM);
3215
3216 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3217 error = copyin(nv->data, nvlpacked, nv->len);
3218 if (error)
3219 ERROUT(error);
3220
3221 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3222 if (nvl == NULL)
3223 ERROUT(EBADMSG);
3224 if (! nvlist_exists_number(nvl, "ticket"))
3225 ERROUT(EBADMSG);
3226 ticket = nvlist_get_number(nvl, "ticket");
3227 if (! nvlist_exists_string(nvl, "anchor"))
3228 ERROUT(EBADMSG);
3229 anchor = nvlist_get_string(nvl, "anchor");
3230
3231 if (nvlist_exists_bool(nvl, "clear"))
3232 clear = nvlist_get_bool(nvl, "clear");
3233
3234 if (clear && !(flags & FWRITE))
3235 ERROUT(EACCES);
3236
3237 if (! nvlist_exists_number(nvl, "nr"))
3238 ERROUT(EBADMSG);
3239 nr = nvlist_get_number(nvl, "nr");
3240
3241 PF_RULES_RLOCK();
3242 rs = pf_find_keth_ruleset(anchor);
3243 if (rs == NULL) {
3244 PF_RULES_RUNLOCK();
3245 ERROUT(ENOENT);
3246 }
3247 if (ticket != rs->active.ticket) {
3248 PF_RULES_RUNLOCK();
3249 ERROUT(EBUSY);
3250 }
3251
3252 nvlist_destroy(nvl);
3253 nvl = NULL;
3254 free(nvlpacked, M_NVLIST);
3255 nvlpacked = NULL;
3256
3257 rule = TAILQ_FIRST(rs->active.rules);
3258 while ((rule != NULL) && (rule->nr != nr))
3259 rule = TAILQ_NEXT(rule, entries);
3260 if (rule == NULL) {
3261 PF_RULES_RUNLOCK();
3262 ERROUT(ENOENT);
3263 }
3264 /* Make sure rule can't go away. */
3265 NET_EPOCH_ENTER(et);
3266 PF_RULES_RUNLOCK();
3267 nvl = pf_keth_rule_to_nveth_rule(rule);
3268 if (pf_keth_anchor_nvcopyout(rs, rule, nvl)) {
3269 NET_EPOCH_EXIT(et);
3270 ERROUT(EBUSY);
3271 }
3272 NET_EPOCH_EXIT(et);
3273 if (nvl == NULL)
3274 ERROUT(ENOMEM);
3275
3276 nvlpacked = nvlist_pack(nvl, &nv->len);
3277 if (nvlpacked == NULL)
3278 ERROUT(ENOMEM);
3279
3280 if (nv->size == 0)
3281 ERROUT(0);
3282 else if (nv->size < nv->len)
3283 ERROUT(ENOSPC);
3284
3285 error = copyout(nvlpacked, nv->data, nv->len);
3286 if (error == 0 && clear) {
3287 counter_u64_zero(rule->evaluations);
3288 for (int i = 0; i < 2; i++) {
3289 counter_u64_zero(rule->packets[i]);
3290 counter_u64_zero(rule->bytes[i]);
3291 }
3292 }
3293
3294 #undef ERROUT
3295 DIOCGETETHRULE_error:
3296 free(nvlpacked, M_NVLIST);
3297 nvlist_destroy(nvl);
3298 break;
3299 }
3300
3301 case DIOCADDETHRULE: {
3302 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3303 nvlist_t *nvl = NULL;
3304 void *nvlpacked = NULL;
3305 struct pf_keth_rule *rule = NULL, *tail = NULL;
3306 struct pf_keth_ruleset *ruleset = NULL;
3307 struct pfi_kkif *kif = NULL, *bridge_to_kif = NULL;
3308 const char *anchor = "", *anchor_call = "";
3309
3310 #define ERROUT(x) ERROUT_IOCTL(DIOCADDETHRULE_error, x)
3311
3312 if (nv->len > pf_ioctl_maxcount)
3313 ERROUT(ENOMEM);
3314
3315 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3316 error = copyin(nv->data, nvlpacked, nv->len);
3317 if (error)
3318 ERROUT(error);
3319
3320 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3321 if (nvl == NULL)
3322 ERROUT(EBADMSG);
3323
3324 if (! nvlist_exists_number(nvl, "ticket"))
3325 ERROUT(EBADMSG);
3326
3327 if (nvlist_exists_string(nvl, "anchor"))
3328 anchor = nvlist_get_string(nvl, "anchor");
3329 if (nvlist_exists_string(nvl, "anchor_call"))
3330 anchor_call = nvlist_get_string(nvl, "anchor_call");
3331
3332 ruleset = pf_find_keth_ruleset(anchor);
3333 if (ruleset == NULL)
3334 ERROUT(EINVAL);
3335
3336 if (nvlist_get_number(nvl, "ticket") !=
3337 ruleset->inactive.ticket) {
3338 DPFPRINTF(PF_DEBUG_MISC,
3339 "ticket: %d != %d",
3340 (u_int32_t)nvlist_get_number(nvl, "ticket"),
3341 ruleset->inactive.ticket);
3342 ERROUT(EBUSY);
3343 }
3344
3345 rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK);
3346 rule->timestamp = NULL;
3347
3348 error = pf_nveth_rule_to_keth_rule(nvl, rule);
3349 if (error != 0)
3350 ERROUT(error);
3351
3352 if (rule->ifname[0])
3353 kif = pf_kkif_create(M_WAITOK);
3354 if (rule->bridge_to_name[0])
3355 bridge_to_kif = pf_kkif_create(M_WAITOK);
3356 rule->evaluations = counter_u64_alloc(M_WAITOK);
3357 for (int i = 0; i < 2; i++) {
3358 rule->packets[i] = counter_u64_alloc(M_WAITOK);
3359 rule->bytes[i] = counter_u64_alloc(M_WAITOK);
3360 }
3361 rule->timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
3362 M_WAITOK | M_ZERO);
3363
3364 PF_RULES_WLOCK();
3365
3366 if (rule->ifname[0]) {
3367 rule->kif = pfi_kkif_attach(kif, rule->ifname);
3368 pfi_kkif_ref(rule->kif);
3369 } else
3370 rule->kif = NULL;
3371 if (rule->bridge_to_name[0]) {
3372 rule->bridge_to = pfi_kkif_attach(bridge_to_kif,
3373 rule->bridge_to_name);
3374 pfi_kkif_ref(rule->bridge_to);
3375 } else
3376 rule->bridge_to = NULL;
3377
3378 #ifdef ALTQ
3379 /* set queue IDs */
3380 if (rule->qname[0] != 0) {
3381 if ((rule->qid = pf_qname2qid(rule->qname, true)) == 0)
3382 error = EBUSY;
3383 else
3384 rule->qid = rule->qid;
3385 }
3386 #endif
3387 if (rule->tagname[0])
3388 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
3389 error = EBUSY;
3390 if (rule->match_tagname[0])
3391 if ((rule->match_tag = pf_tagname2tag(
3392 rule->match_tagname)) == 0)
3393 error = EBUSY;
3394
3395 if (error == 0 && rule->ipdst.addr.type == PF_ADDR_TABLE)
3396 error = pf_eth_addr_setup(ruleset, &rule->ipdst.addr);
3397 if (error == 0 && rule->ipsrc.addr.type == PF_ADDR_TABLE)
3398 error = pf_eth_addr_setup(ruleset, &rule->ipsrc.addr);
3399
3400 if (error) {
3401 pf_free_eth_rule(rule);
3402 PF_RULES_WUNLOCK();
3403 ERROUT(error);
3404 }
3405
3406 if (pf_keth_anchor_setup(rule, ruleset, anchor_call)) {
3407 pf_free_eth_rule(rule);
3408 PF_RULES_WUNLOCK();
3409 ERROUT(EINVAL);
3410 }
3411
3412 tail = TAILQ_LAST(ruleset->inactive.rules, pf_keth_ruleq);
3413 if (tail)
3414 rule->nr = tail->nr + 1;
3415 else
3416 rule->nr = 0;
3417
3418 TAILQ_INSERT_TAIL(ruleset->inactive.rules, rule, entries);
3419
3420 PF_RULES_WUNLOCK();
3421
3422 #undef ERROUT
3423 DIOCADDETHRULE_error:
3424 nvlist_destroy(nvl);
3425 free(nvlpacked, M_NVLIST);
3426 break;
3427 }
3428
3429 case DIOCGETETHRULESETS: {
3430 struct epoch_tracker et;
3431 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3432 nvlist_t *nvl = NULL;
3433 void *nvlpacked = NULL;
3434 struct pf_keth_ruleset *ruleset;
3435 struct pf_keth_anchor *anchor;
3436 int nr = 0;
3437
3438 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULESETS_error, x)
3439
3440 if (nv->len > pf_ioctl_maxcount)
3441 ERROUT(ENOMEM);
3442
3443 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3444 error = copyin(nv->data, nvlpacked, nv->len);
3445 if (error)
3446 ERROUT(error);
3447
3448 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3449 if (nvl == NULL)
3450 ERROUT(EBADMSG);
3451 if (! nvlist_exists_string(nvl, "path"))
3452 ERROUT(EBADMSG);
3453
3454 NET_EPOCH_ENTER(et);
3455
3456 if ((ruleset = pf_find_keth_ruleset(
3457 nvlist_get_string(nvl, "path"))) == NULL) {
3458 NET_EPOCH_EXIT(et);
3459 ERROUT(ENOENT);
3460 }
3461
3462 if (ruleset->anchor == NULL) {
3463 RB_FOREACH(anchor, pf_keth_anchor_global, &V_pf_keth_anchors)
3464 if (anchor->parent == NULL)
3465 nr++;
3466 } else {
3467 RB_FOREACH(anchor, pf_keth_anchor_node,
3468 &ruleset->anchor->children)
3469 nr++;
3470 }
3471
3472 NET_EPOCH_EXIT(et);
3473
3474 nvlist_destroy(nvl);
3475 nvl = NULL;
3476 free(nvlpacked, M_NVLIST);
3477 nvlpacked = NULL;
3478
3479 nvl = nvlist_create(0);
3480 if (nvl == NULL)
3481 ERROUT(ENOMEM);
3482
3483 nvlist_add_number(nvl, "nr", nr);
3484
3485 nvlpacked = nvlist_pack(nvl, &nv->len);
3486 if (nvlpacked == NULL)
3487 ERROUT(ENOMEM);
3488
3489 if (nv->size == 0)
3490 ERROUT(0);
3491 else if (nv->size < nv->len)
3492 ERROUT(ENOSPC);
3493
3494 error = copyout(nvlpacked, nv->data, nv->len);
3495
3496 #undef ERROUT
3497 DIOCGETETHRULESETS_error:
3498 free(nvlpacked, M_NVLIST);
3499 nvlist_destroy(nvl);
3500 break;
3501 }
3502
3503 case DIOCGETETHRULESET: {
3504 struct epoch_tracker et;
3505 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3506 nvlist_t *nvl = NULL;
3507 void *nvlpacked = NULL;
3508 struct pf_keth_ruleset *ruleset;
3509 struct pf_keth_anchor *anchor;
3510 int nr = 0, req_nr = 0;
3511 bool found = false;
3512
3513 #define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULESET_error, x)
3514
3515 if (nv->len > pf_ioctl_maxcount)
3516 ERROUT(ENOMEM);
3517
3518 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3519 error = copyin(nv->data, nvlpacked, nv->len);
3520 if (error)
3521 ERROUT(error);
3522
3523 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3524 if (nvl == NULL)
3525 ERROUT(EBADMSG);
3526 if (! nvlist_exists_string(nvl, "path"))
3527 ERROUT(EBADMSG);
3528 if (! nvlist_exists_number(nvl, "nr"))
3529 ERROUT(EBADMSG);
3530
3531 req_nr = nvlist_get_number(nvl, "nr");
3532
3533 NET_EPOCH_ENTER(et);
3534
3535 if ((ruleset = pf_find_keth_ruleset(
3536 nvlist_get_string(nvl, "path"))) == NULL) {
3537 NET_EPOCH_EXIT(et);
3538 ERROUT(ENOENT);
3539 }
3540
3541 nvlist_destroy(nvl);
3542 nvl = NULL;
3543 free(nvlpacked, M_NVLIST);
3544 nvlpacked = NULL;
3545
3546 nvl = nvlist_create(0);
3547 if (nvl == NULL) {
3548 NET_EPOCH_EXIT(et);
3549 ERROUT(ENOMEM);
3550 }
3551
3552 if (ruleset->anchor == NULL) {
3553 RB_FOREACH(anchor, pf_keth_anchor_global,
3554 &V_pf_keth_anchors) {
3555 if (anchor->parent == NULL && nr++ == req_nr) {
3556 found = true;
3557 break;
3558 }
3559 }
3560 } else {
3561 RB_FOREACH(anchor, pf_keth_anchor_node,
3562 &ruleset->anchor->children) {
3563 if (nr++ == req_nr) {
3564 found = true;
3565 break;
3566 }
3567 }
3568 }
3569
3570 NET_EPOCH_EXIT(et);
3571 if (found) {
3572 nvlist_add_number(nvl, "nr", nr);
3573 nvlist_add_string(nvl, "name", anchor->name);
3574 if (ruleset->anchor)
3575 nvlist_add_string(nvl, "path",
3576 ruleset->anchor->path);
3577 else
3578 nvlist_add_string(nvl, "path", "");
3579 } else {
3580 ERROUT(EBUSY);
3581 }
3582
3583 nvlpacked = nvlist_pack(nvl, &nv->len);
3584 if (nvlpacked == NULL)
3585 ERROUT(ENOMEM);
3586
3587 if (nv->size == 0)
3588 ERROUT(0);
3589 else if (nv->size < nv->len)
3590 ERROUT(ENOSPC);
3591
3592 error = copyout(nvlpacked, nv->data, nv->len);
3593
3594 #undef ERROUT
3595 DIOCGETETHRULESET_error:
3596 free(nvlpacked, M_NVLIST);
3597 nvlist_destroy(nvl);
3598 break;
3599 }
3600
3601 case DIOCADDRULENV: {
3602 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3603 nvlist_t *nvl = NULL;
3604 void *nvlpacked = NULL;
3605 struct pf_krule *rule = NULL;
3606 const char *anchor = "", *anchor_call = "";
3607 uint32_t ticket = 0, pool_ticket = 0;
3608
3609 #define ERROUT(x) ERROUT_IOCTL(DIOCADDRULENV_error, x)
3610
3611 if (nv->len > pf_ioctl_maxcount)
3612 ERROUT(ENOMEM);
3613
3614 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3615 error = copyin(nv->data, nvlpacked, nv->len);
3616 if (error)
3617 ERROUT(error);
3618
3619 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3620 if (nvl == NULL)
3621 ERROUT(EBADMSG);
3622
3623 if (! nvlist_exists_number(nvl, "ticket"))
3624 ERROUT(EINVAL);
3625 ticket = nvlist_get_number(nvl, "ticket");
3626
3627 if (! nvlist_exists_number(nvl, "pool_ticket"))
3628 ERROUT(EINVAL);
3629 pool_ticket = nvlist_get_number(nvl, "pool_ticket");
3630
3631 if (! nvlist_exists_nvlist(nvl, "rule"))
3632 ERROUT(EINVAL);
3633
3634 rule = pf_krule_alloc();
3635 error = pf_nvrule_to_krule(nvlist_get_nvlist(nvl, "rule"),
3636 rule);
3637 if (error)
3638 ERROUT(error);
3639
3640 if (nvlist_exists_string(nvl, "anchor"))
3641 anchor = nvlist_get_string(nvl, "anchor");
3642 if (nvlist_exists_string(nvl, "anchor_call"))
3643 anchor_call = nvlist_get_string(nvl, "anchor_call");
3644
3645 if ((error = nvlist_error(nvl)))
3646 ERROUT(error);
3647
3648 /* Frees rule on error */
3649 error = pf_ioctl_addrule(rule, ticket, pool_ticket, anchor,
3650 anchor_call, td->td_ucred->cr_ruid,
3651 td->td_proc ? td->td_proc->p_pid : 0);
3652
3653 nvlist_destroy(nvl);
3654 free(nvlpacked, M_NVLIST);
3655 break;
3656 #undef ERROUT
3657 DIOCADDRULENV_error:
3658 pf_krule_free(rule);
3659 nvlist_destroy(nvl);
3660 free(nvlpacked, M_NVLIST);
3661
3662 break;
3663 }
3664 case DIOCADDRULE: {
3665 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
3666 struct pf_krule *rule;
3667
3668 rule = pf_krule_alloc();
3669 error = pf_rule_to_krule(&pr->rule, rule);
3670 if (error != 0) {
3671 pf_krule_free(rule);
3672 goto fail;
3673 }
3674
3675 pr->anchor[sizeof(pr->anchor) - 1] = '\0';
3676
3677 /* Frees rule on error */
3678 error = pf_ioctl_addrule(rule, pr->ticket, pr->pool_ticket,
3679 pr->anchor, pr->anchor_call, td->td_ucred->cr_ruid,
3680 td->td_proc ? td->td_proc->p_pid : 0);
3681 break;
3682 }
3683
3684 case DIOCGETRULES: {
3685 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
3686
3687 pr->anchor[sizeof(pr->anchor) - 1] = '\0';
3688
3689 error = pf_ioctl_getrules(pr);
3690
3691 break;
3692 }
3693
3694 case DIOCGETRULENV: {
3695 struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3696 nvlist_t *nvrule = NULL;
3697 nvlist_t *nvl = NULL;
3698 struct pf_kruleset *ruleset;
3699 struct pf_krule *rule;
3700 void *nvlpacked = NULL;
3701 int rs_num, nr;
3702 bool clear_counter = false;
3703
3704 #define ERROUT(x) ERROUT_IOCTL(DIOCGETRULENV_error, x)
3705
3706 if (nv->len > pf_ioctl_maxcount)
3707 ERROUT(ENOMEM);
3708
3709 /* Copy the request in */
3710 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3711 error = copyin(nv->data, nvlpacked, nv->len);
3712 if (error)
3713 ERROUT(error);
3714
3715 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3716 if (nvl == NULL)
3717 ERROUT(EBADMSG);
3718
3719 if (! nvlist_exists_string(nvl, "anchor"))
3720 ERROUT(EBADMSG);
3721 if (! nvlist_exists_number(nvl, "ruleset"))
3722 ERROUT(EBADMSG);
3723 if (! nvlist_exists_number(nvl, "ticket"))
3724 ERROUT(EBADMSG);
3725 if (! nvlist_exists_number(nvl, "nr"))
3726 ERROUT(EBADMSG);
3727
3728 if (nvlist_exists_bool(nvl, "clear_counter"))
3729 clear_counter = nvlist_get_bool(nvl, "clear_counter");
3730
3731 if (clear_counter && !(flags & FWRITE))
3732 ERROUT(EACCES);
3733
3734 nr = nvlist_get_number(nvl, "nr");
3735
3736 PF_RULES_WLOCK();
3737 ruleset = pf_find_kruleset(nvlist_get_string(nvl, "anchor"));
3738 if (ruleset == NULL) {
3739 PF_RULES_WUNLOCK();
3740 ERROUT(ENOENT);
3741 }
3742
3743 rs_num = pf_get_ruleset_number(nvlist_get_number(nvl, "ruleset"));
3744 if (rs_num >= PF_RULESET_MAX) {
3745 PF_RULES_WUNLOCK();
3746 ERROUT(EINVAL);
3747 }
3748
3749 if (nvlist_get_number(nvl, "ticket") !=
3750 ruleset->rules[rs_num].active.ticket) {
3751 PF_RULES_WUNLOCK();
3752 ERROUT(EBUSY);
3753 }
3754
3755 if ((error = nvlist_error(nvl))) {
3756 PF_RULES_WUNLOCK();
3757 ERROUT(error);
3758 }
3759
3760 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
3761 while ((rule != NULL) && (rule->nr != nr))
3762 rule = TAILQ_NEXT(rule, entries);
3763 if (rule == NULL) {
3764 PF_RULES_WUNLOCK();
3765 ERROUT(EBUSY);
3766 }
3767
3768 nvrule = pf_krule_to_nvrule(rule);
3769
3770 nvlist_destroy(nvl);
3771 nvl = nvlist_create(0);
3772 if (nvl == NULL) {
3773 PF_RULES_WUNLOCK();
3774 ERROUT(ENOMEM);
3775 }
3776 nvlist_add_number(nvl, "nr", nr);
3777 nvlist_add_nvlist(nvl, "rule", nvrule);
3778 nvlist_destroy(nvrule);
3779 nvrule = NULL;
3780 if (pf_kanchor_nvcopyout(ruleset, rule, nvl)) {
3781 PF_RULES_WUNLOCK();
3782 ERROUT(EBUSY);
3783 }
3784
3785 free(nvlpacked, M_NVLIST);
3786 nvlpacked = nvlist_pack(nvl, &nv->len);
3787 if (nvlpacked == NULL) {
3788 PF_RULES_WUNLOCK();
3789 ERROUT(ENOMEM);
3790 }
3791
3792 if (nv->size == 0) {
3793 PF_RULES_WUNLOCK();
3794 ERROUT(0);
3795 }
3796 else if (nv->size < nv->len) {
3797 PF_RULES_WUNLOCK();
3798 ERROUT(ENOSPC);
3799 }
3800
3801 if (clear_counter)
3802 pf_krule_clear_counters(rule);
3803
3804 PF_RULES_WUNLOCK();
3805
3806 error = copyout(nvlpacked, nv->data, nv->len);
3807
3808 #undef ERROUT
3809 DIOCGETRULENV_error:
3810 free(nvlpacked, M_NVLIST);
3811 nvlist_destroy(nvrule);
3812 nvlist_destroy(nvl);
3813
3814 break;
3815 }
3816
3817 case DIOCCHANGERULE: {
3818 struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
3819 struct pf_kruleset *ruleset;
3820 struct pf_krule *oldrule = NULL, *newrule = NULL;
3821 struct pfi_kkif *kif = NULL;
3822 struct pf_kpooladdr *pa;
3823 u_int32_t nr = 0;
3824 int rs_num;
3825
3826 pcr->anchor[sizeof(pcr->anchor) - 1] = '\0';
3827
3828 if (pcr->action < PF_CHANGE_ADD_HEAD ||
3829 pcr->action > PF_CHANGE_GET_TICKET) {
3830 error = EINVAL;
3831 goto fail;
3832 }
3833 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
3834 error = EINVAL;
3835 goto fail;
3836 }
3837
3838 if (pcr->action != PF_CHANGE_REMOVE) {
3839 newrule = pf_krule_alloc();
3840 error = pf_rule_to_krule(&pcr->rule, newrule);
3841 if (error != 0) {
3842 pf_krule_free(newrule);
3843 goto fail;
3844 }
3845
3846 if ((error = pf_rule_checkaf(newrule))) {
3847 pf_krule_free(newrule);
3848 goto fail;
3849 }
3850 if (newrule->ifname[0])
3851 kif = pf_kkif_create(M_WAITOK);
3852 pf_counter_u64_init(&newrule->evaluations, M_WAITOK);
3853 for (int i = 0; i < 2; i++) {
3854 pf_counter_u64_init(&newrule->packets[i], M_WAITOK);
3855 pf_counter_u64_init(&newrule->bytes[i], M_WAITOK);
3856 }
3857 newrule->states_cur = counter_u64_alloc(M_WAITOK);
3858 newrule->states_tot = counter_u64_alloc(M_WAITOK);
3859 for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
3860 newrule->src_nodes[sn_type] = counter_u64_alloc(M_WAITOK);
3861 newrule->cuid = td->td_ucred->cr_ruid;
3862 newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
3863 TAILQ_INIT(&newrule->nat.list);
3864 TAILQ_INIT(&newrule->rdr.list);
3865 TAILQ_INIT(&newrule->route.list);
3866 }
3867 #define ERROUT(x) ERROUT_IOCTL(DIOCCHANGERULE_error, x)
3868
3869 PF_CONFIG_LOCK();
3870 PF_RULES_WLOCK();
3871 #ifdef PF_WANT_32_TO_64_COUNTER
3872 if (newrule != NULL) {
3873 LIST_INSERT_HEAD(&V_pf_allrulelist, newrule, allrulelist);
3874 newrule->allrulelinked = true;
3875 V_pf_allrulecount++;
3876 }
3877 #endif
3878
3879 if (!(pcr->action == PF_CHANGE_REMOVE ||
3880 pcr->action == PF_CHANGE_GET_TICKET) &&
3881 pcr->pool_ticket != V_ticket_pabuf)
3882 ERROUT(EBUSY);
3883
3884 ruleset = pf_find_kruleset(pcr->anchor);
3885 if (ruleset == NULL)
3886 ERROUT(EINVAL);
3887
3888 rs_num = pf_get_ruleset_number(pcr->rule.action);
3889 if (rs_num >= PF_RULESET_MAX)
3890 ERROUT(EINVAL);
3891
3892 /*
3893 * XXXMJG: there is no guarantee that the ruleset was
3894 * created by the usual route of calling DIOCXBEGIN.
3895 * As a result it is possible the rule tree will not
3896 * be allocated yet. Hack around it by doing it here.
3897 * Note it is fine to let the tree persist in case of
3898 * error as it will be freed down the road on future
3899 * updates (if need be).
3900 */
3901 if (ruleset->rules[rs_num].active.tree == NULL) {
3902 ruleset->rules[rs_num].active.tree = pf_rule_tree_alloc(M_NOWAIT);
3903 if (ruleset->rules[rs_num].active.tree == NULL) {
3904 ERROUT(ENOMEM);
3905 }
3906 }
3907
3908 if (pcr->action == PF_CHANGE_GET_TICKET) {
3909 pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
3910 ERROUT(0);
3911 } else if (pcr->ticket !=
3912 ruleset->rules[rs_num].active.ticket)
3913 ERROUT(EINVAL);
3914
3915 if (pcr->action != PF_CHANGE_REMOVE) {
3916 if (newrule->ifname[0]) {
3917 newrule->kif = pfi_kkif_attach(kif,
3918 newrule->ifname);
3919 kif = NULL;
3920 pfi_kkif_ref(newrule->kif);
3921 } else
3922 newrule->kif = NULL;
3923
3924 if (newrule->rtableid > 0 &&
3925 newrule->rtableid >= rt_numfibs)
3926 error = EBUSY;
3927
3928 #ifdef ALTQ
3929 /* set queue IDs */
3930 if (newrule->qname[0] != 0) {
3931 if ((newrule->qid =
3932 pf_qname2qid(newrule->qname, true)) == 0)
3933 error = EBUSY;
3934 else if (newrule->pqname[0] != 0) {
3935 if ((newrule->pqid =
3936 pf_qname2qid(newrule->pqname, true)) == 0)
3937 error = EBUSY;
3938 } else
3939 newrule->pqid = newrule->qid;
3940 }
3941 #endif /* ALTQ */
3942 if (newrule->tagname[0])
3943 if ((newrule->tag =
3944 pf_tagname2tag(newrule->tagname)) == 0)
3945 error = EBUSY;
3946 if (newrule->match_tagname[0])
3947 if ((newrule->match_tag = pf_tagname2tag(
3948 newrule->match_tagname)) == 0)
3949 error = EBUSY;
3950 if (newrule->rt && !newrule->direction)
3951 error = EINVAL;
3952 if (!newrule->log)
3953 newrule->logif = 0;
3954 if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af))
3955 error = ENOMEM;
3956 if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
3957 error = ENOMEM;
3958 if (pf_kanchor_setup(newrule, ruleset, pcr->anchor_call))
3959 error = EINVAL;
3960 for (int i = 0; i < 3; i++) {
3961 TAILQ_FOREACH(pa, &V_pf_pabuf[i], entries)
3962 if (pa->addr.type == PF_ADDR_TABLE) {
3963 pa->addr.p.tbl =
3964 pfr_attach_table(ruleset,
3965 pa->addr.v.tblname);
3966 if (pa->addr.p.tbl == NULL)
3967 error = ENOMEM;
3968 }
3969 }
3970
3971 newrule->overload_tbl = NULL;
3972 if (newrule->overload_tblname[0]) {
3973 if ((newrule->overload_tbl = pfr_attach_table(
3974 ruleset, newrule->overload_tblname)) ==
3975 NULL)
3976 error = EINVAL;
3977 else
3978 newrule->overload_tbl->pfrkt_flags |=
3979 PFR_TFLAG_ACTIVE;
3980 }
3981
3982 pf_mv_kpool(&V_pf_pabuf[0], &newrule->nat.list);
3983 pf_mv_kpool(&V_pf_pabuf[1], &newrule->rdr.list);
3984 pf_mv_kpool(&V_pf_pabuf[2], &newrule->route.list);
3985 if (((((newrule->action == PF_NAT) ||
3986 (newrule->action == PF_RDR) ||
3987 (newrule->action == PF_BINAT) ||
3988 (newrule->rt > PF_NOPFROUTE)) &&
3989 !newrule->anchor)) &&
3990 (TAILQ_FIRST(&newrule->rdr.list) == NULL))
3991 error = EINVAL;
3992
3993 if (error) {
3994 pf_free_rule(newrule);
3995 PF_RULES_WUNLOCK();
3996 PF_CONFIG_UNLOCK();
3997 goto fail;
3998 }
3999
4000 newrule->nat.cur = TAILQ_FIRST(&newrule->nat.list);
4001 newrule->rdr.cur = TAILQ_FIRST(&newrule->rdr.list);
4002 }
4003 pf_empty_kpool(&V_pf_pabuf[0]);
4004 pf_empty_kpool(&V_pf_pabuf[1]);
4005 pf_empty_kpool(&V_pf_pabuf[2]);
4006
4007 if (pcr->action == PF_CHANGE_ADD_HEAD)
4008 oldrule = TAILQ_FIRST(
4009 ruleset->rules[rs_num].active.ptr);
4010 else if (pcr->action == PF_CHANGE_ADD_TAIL)
4011 oldrule = TAILQ_LAST(
4012 ruleset->rules[rs_num].active.ptr, pf_krulequeue);
4013 else {
4014 oldrule = TAILQ_FIRST(
4015 ruleset->rules[rs_num].active.ptr);
4016 while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
4017 oldrule = TAILQ_NEXT(oldrule, entries);
4018 if (oldrule == NULL) {
4019 if (newrule != NULL)
4020 pf_free_rule(newrule);
4021 PF_RULES_WUNLOCK();
4022 PF_CONFIG_UNLOCK();
4023 error = EINVAL;
4024 goto fail;
4025 }
4026 }
4027
4028 if (pcr->action == PF_CHANGE_REMOVE) {
4029 pf_unlink_rule(ruleset->rules[rs_num].active.ptr,
4030 oldrule);
4031 RB_REMOVE(pf_krule_global,
4032 ruleset->rules[rs_num].active.tree, oldrule);
4033 ruleset->rules[rs_num].active.rcount--;
4034 } else {
4035 pf_hash_rule(newrule);
4036 if (RB_INSERT(pf_krule_global,
4037 ruleset->rules[rs_num].active.tree, newrule) != NULL) {
4038 pf_free_rule(newrule);
4039 PF_RULES_WUNLOCK();
4040 PF_CONFIG_UNLOCK();
4041 error = EEXIST;
4042 goto fail;
4043 }
4044
4045 if (oldrule == NULL)
4046 TAILQ_INSERT_TAIL(
4047 ruleset->rules[rs_num].active.ptr,
4048 newrule, entries);
4049 else if (pcr->action == PF_CHANGE_ADD_HEAD ||
4050 pcr->action == PF_CHANGE_ADD_BEFORE)
4051 TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
4052 else
4053 TAILQ_INSERT_AFTER(
4054 ruleset->rules[rs_num].active.ptr,
4055 oldrule, newrule, entries);
4056 ruleset->rules[rs_num].active.rcount++;
4057 }
4058
4059 nr = 0;
4060 TAILQ_FOREACH(oldrule,
4061 ruleset->rules[rs_num].active.ptr, entries)
4062 oldrule->nr = nr++;
4063
4064 ruleset->rules[rs_num].active.ticket++;
4065
4066 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
4067 pf_remove_if_empty_kruleset(ruleset);
4068
4069 PF_RULES_WUNLOCK();
4070 PF_CONFIG_UNLOCK();
4071 break;
4072
4073 #undef ERROUT
4074 DIOCCHANGERULE_error:
4075 PF_RULES_WUNLOCK();
4076 PF_CONFIG_UNLOCK();
4077 pf_krule_free(newrule);
4078 pf_kkif_free(kif);
4079 break;
4080 }
4081
4082 case DIOCCLRSTATESNV: {
4083 error = pf_clearstates_nv((struct pfioc_nv *)addr);
4084 break;
4085 }
4086
4087 case DIOCKILLSTATESNV: {
4088 error = pf_killstates_nv((struct pfioc_nv *)addr);
4089 break;
4090 }
4091
4092 case DIOCADDSTATE: {
4093 struct pfioc_state *ps = (struct pfioc_state *)addr;
4094 struct pfsync_state_1301 *sp = &ps->state;
4095
4096 if (sp->timeout >= PFTM_MAX) {
4097 error = EINVAL;
4098 goto fail;
4099 }
4100 if (V_pfsync_state_import_ptr != NULL) {
4101 PF_RULES_RLOCK();
4102 error = V_pfsync_state_import_ptr(
4103 (union pfsync_state_union *)sp, PFSYNC_SI_IOCTL,
4104 PFSYNC_MSG_VERSION_1301);
4105 PF_RULES_RUNLOCK();
4106 } else
4107 error = EOPNOTSUPP;
4108 break;
4109 }
4110
4111 case DIOCGETSTATE: {
4112 struct pfioc_state *ps = (struct pfioc_state *)addr;
4113 struct pf_kstate *s;
4114
4115 s = pf_find_state_byid(ps->state.id, ps->state.creatorid);
4116 if (s == NULL) {
4117 error = ENOENT;
4118 goto fail;
4119 }
4120
4121 pfsync_state_export((union pfsync_state_union*)&ps->state,
4122 s, PFSYNC_MSG_VERSION_1301);
4123 PF_STATE_UNLOCK(s);
4124 break;
4125 }
4126
4127 case DIOCGETSTATENV: {
4128 error = pf_getstate((struct pfioc_nv *)addr);
4129 break;
4130 }
4131
4132 #ifdef COMPAT_FREEBSD14
4133 case DIOCGETSTATES: {
4134 struct pfioc_states *ps = (struct pfioc_states *)addr;
4135 struct pf_kstate *s;
4136 struct pfsync_state_1301 *pstore, *p;
4137 int i, nr;
4138 size_t slice_count = 16, count;
4139 void *out;
4140
4141 if (ps->ps_len <= 0) {
4142 nr = uma_zone_get_cur(V_pf_state_z);
4143 ps->ps_len = sizeof(struct pfsync_state_1301) * nr;
4144 break;
4145 }
4146
4147 out = ps->ps_states;
4148 pstore = mallocarray(slice_count,
4149 sizeof(struct pfsync_state_1301), M_PF, M_WAITOK | M_ZERO);
4150 nr = 0;
4151
4152 for (i = 0; i <= V_pf_hashmask; i++) {
4153 struct pf_idhash *ih = &V_pf_idhash[i];
4154
4155 DIOCGETSTATES_retry:
4156 p = pstore;
4157
4158 if (LIST_EMPTY(&ih->states))
4159 continue;
4160
4161 PF_HASHROW_LOCK(ih);
4162 count = 0;
4163 LIST_FOREACH(s, &ih->states, entry) {
4164 if (s->timeout == PFTM_UNLINKED)
4165 continue;
4166 count++;
4167 }
4168
4169 if (count > slice_count) {
4170 PF_HASHROW_UNLOCK(ih);
4171 free(pstore, M_PF);
4172 slice_count = count * 2;
4173 pstore = mallocarray(slice_count,
4174 sizeof(struct pfsync_state_1301), M_PF,
4175 M_WAITOK | M_ZERO);
4176 goto DIOCGETSTATES_retry;
4177 }
4178
4179 if ((nr+count) * sizeof(*p) > ps->ps_len) {
4180 PF_HASHROW_UNLOCK(ih);
4181 goto DIOCGETSTATES_full;
4182 }
4183
4184 LIST_FOREACH(s, &ih->states, entry) {
4185 if (s->timeout == PFTM_UNLINKED)
4186 continue;
4187
4188 pfsync_state_export((union pfsync_state_union*)p,
4189 s, PFSYNC_MSG_VERSION_1301);
4190 p++;
4191 nr++;
4192 }
4193 PF_HASHROW_UNLOCK(ih);
4194 error = copyout(pstore, out,
4195 sizeof(struct pfsync_state_1301) * count);
4196 if (error) {
4197 free(pstore, M_PF);
4198 goto fail;
4199 }
4200 out = ps->ps_states + nr;
4201 }
4202 DIOCGETSTATES_full:
4203 ps->ps_len = sizeof(struct pfsync_state_1301) * nr;
4204 free(pstore, M_PF);
4205
4206 break;
4207 }
4208
4209 case DIOCGETSTATESV2: {
4210 struct pfioc_states_v2 *ps = (struct pfioc_states_v2 *)addr;
4211 struct pf_kstate *s;
4212 struct pf_state_export *pstore, *p;
4213 int i, nr;
4214 size_t slice_count = 16, count;
4215 void *out;
4216
4217 if (ps->ps_req_version > PF_STATE_VERSION) {
4218 error = ENOTSUP;
4219 goto fail;
4220 }
4221
4222 if (ps->ps_len <= 0) {
4223 nr = uma_zone_get_cur(V_pf_state_z);
4224 ps->ps_len = sizeof(struct pf_state_export) * nr;
4225 break;
4226 }
4227
4228 out = ps->ps_states;
4229 pstore = mallocarray(slice_count,
4230 sizeof(struct pf_state_export), M_PF, M_WAITOK | M_ZERO);
4231 nr = 0;
4232
4233 for (i = 0; i <= V_pf_hashmask; i++) {
4234 struct pf_idhash *ih = &V_pf_idhash[i];
4235
4236 DIOCGETSTATESV2_retry:
4237 p = pstore;
4238
4239 if (LIST_EMPTY(&ih->states))
4240 continue;
4241
4242 PF_HASHROW_LOCK(ih);
4243 count = 0;
4244 LIST_FOREACH(s, &ih->states, entry) {
4245 if (s->timeout == PFTM_UNLINKED)
4246 continue;
4247 count++;
4248 }
4249
4250 if (count > slice_count) {
4251 PF_HASHROW_UNLOCK(ih);
4252 free(pstore, M_PF);
4253 slice_count = count * 2;
4254 pstore = mallocarray(slice_count,
4255 sizeof(struct pf_state_export), M_PF,
4256 M_WAITOK | M_ZERO);
4257 goto DIOCGETSTATESV2_retry;
4258 }
4259
4260 if ((nr+count) * sizeof(*p) > ps->ps_len) {
4261 PF_HASHROW_UNLOCK(ih);
4262 goto DIOCGETSTATESV2_full;
4263 }
4264
4265 LIST_FOREACH(s, &ih->states, entry) {
4266 if (s->timeout == PFTM_UNLINKED)
4267 continue;
4268
4269 pf_state_export(p, s);
4270 p++;
4271 nr++;
4272 }
4273 PF_HASHROW_UNLOCK(ih);
4274 error = copyout(pstore, out,
4275 sizeof(struct pf_state_export) * count);
4276 if (error) {
4277 free(pstore, M_PF);
4278 goto fail;
4279 }
4280 out = ps->ps_states + nr;
4281 }
4282 DIOCGETSTATESV2_full:
4283 ps->ps_len = nr * sizeof(struct pf_state_export);
4284 free(pstore, M_PF);
4285
4286 break;
4287 }
4288 #endif
4289 case DIOCGETSTATUSNV: {
4290 error = pf_getstatus((struct pfioc_nv *)addr);
4291 break;
4292 }
4293
4294 case DIOCSETSTATUSIF: {
4295 struct pfioc_if *pi = (struct pfioc_if *)addr;
4296
4297 if (pi->ifname[0] == 0) {
4298 bzero(V_pf_status.ifname, IFNAMSIZ);
4299 break;
4300 }
4301 PF_RULES_WLOCK();
4302 error = pf_user_strcpy(V_pf_status.ifname, pi->ifname, IFNAMSIZ);
4303 PF_RULES_WUNLOCK();
4304 break;
4305 }
4306
4307 case DIOCCLRSTATUS: {
4308 pf_ioctl_clear_status();
4309 break;
4310 }
4311
4312 case DIOCNATLOOK: {
4313 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
4314
4315 error = pf_ioctl_natlook(pnl);
4316 break;
4317 }
4318
4319 case DIOCSETTIMEOUT: {
4320 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
4321
4322 error = pf_ioctl_set_timeout(pt->timeout, pt->seconds,
4323 &pt->seconds);
4324 break;
4325 }
4326
4327 case DIOCGETTIMEOUT: {
4328 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
4329
4330 error = pf_ioctl_get_timeout(pt->timeout, &pt->seconds);
4331 break;
4332 }
4333
4334 case DIOCGETLIMIT: {
4335 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
4336
4337 error = pf_ioctl_get_limit(pl->index, &pl->limit);
4338 break;
4339 }
4340
4341 case DIOCSETLIMIT: {
4342 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
4343 unsigned int old_limit;
4344
4345 error = pf_ioctl_set_limit(pl->index, pl->limit, &old_limit);
4346 pl->limit = old_limit;
4347 break;
4348 }
4349
4350 case DIOCSETDEBUG: {
4351 u_int32_t *level = (u_int32_t *)addr;
4352
4353 PF_RULES_WLOCK();
4354 V_pf_status.debug = *level;
4355 PF_RULES_WUNLOCK();
4356 break;
4357 }
4358
4359 case DIOCCLRRULECTRS: {
4360 /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
4361 struct pf_kruleset *ruleset = &pf_main_ruleset;
4362 struct pf_krule *rule;
4363
4364 PF_RULES_WLOCK();
4365 TAILQ_FOREACH(rule,
4366 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
4367 pf_counter_u64_zero(&rule->evaluations);
4368 for (int i = 0; i < 2; i++) {
4369 pf_counter_u64_zero(&rule->packets[i]);
4370 pf_counter_u64_zero(&rule->bytes[i]);
4371 }
4372 }
4373 PF_RULES_WUNLOCK();
4374 break;
4375 }
4376
4377 case DIOCGIFSPEEDV0:
4378 case DIOCGIFSPEEDV1: {
4379 struct pf_ifspeed_v1 *psp = (struct pf_ifspeed_v1 *)addr;
4380 struct pf_ifspeed_v1 ps;
4381 struct ifnet *ifp;
4382
4383 if (psp->ifname[0] == '\0') {
4384 error = EINVAL;
4385 goto fail;
4386 }
4387
4388 error = pf_user_strcpy(ps.ifname, psp->ifname, IFNAMSIZ);
4389 if (error != 0)
4390 goto fail;
4391 ifp = ifunit(ps.ifname);
4392 if (ifp != NULL) {
4393 psp->baudrate32 =
4394 (u_int32_t)uqmin(ifp->if_baudrate, UINT_MAX);
4395 if (cmd == DIOCGIFSPEEDV1)
4396 psp->baudrate = ifp->if_baudrate;
4397 } else {
4398 error = EINVAL;
4399 }
4400 break;
4401 }
4402
4403 #ifdef ALTQ
4404 case DIOCSTARTALTQ: {
4405 struct pf_altq *altq;
4406
4407 PF_RULES_WLOCK();
4408 /* enable all altq interfaces on active list */
4409 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
4410 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
4411 error = pf_enable_altq(altq);
4412 if (error != 0)
4413 break;
4414 }
4415 }
4416 if (error == 0)
4417 V_pf_altq_running = 1;
4418 PF_RULES_WUNLOCK();
4419 DPFPRINTF(PF_DEBUG_MISC, "altq: started");
4420 break;
4421 }
4422
4423 case DIOCSTOPALTQ: {
4424 struct pf_altq *altq;
4425
4426 PF_RULES_WLOCK();
4427 /* disable all altq interfaces on active list */
4428 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
4429 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
4430 error = pf_disable_altq(altq);
4431 if (error != 0)
4432 break;
4433 }
4434 }
4435 if (error == 0)
4436 V_pf_altq_running = 0;
4437 PF_RULES_WUNLOCK();
4438 DPFPRINTF(PF_DEBUG_MISC, "altq: stopped");
4439 break;
4440 }
4441
4442 case DIOCADDALTQV0:
4443 case DIOCADDALTQV1: {
4444 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4445 struct pf_altq *altq, *a;
4446 struct ifnet *ifp;
4447
4448 altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK | M_ZERO);
4449 error = pf_import_kaltq(pa, altq, IOCPARM_LEN(cmd));
4450 if (error)
4451 goto fail;
4452 altq->local_flags = 0;
4453
4454 PF_RULES_WLOCK();
4455 if (pa->ticket != V_ticket_altqs_inactive) {
4456 PF_RULES_WUNLOCK();
4457 free(altq, M_PFALTQ);
4458 error = EBUSY;
4459 goto fail;
4460 }
4461
4462 /*
4463 * if this is for a queue, find the discipline and
4464 * copy the necessary fields
4465 */
4466 if (altq->qname[0] != 0) {
4467 if ((altq->qid = pf_qname2qid(altq->qname, true)) == 0) {
4468 PF_RULES_WUNLOCK();
4469 error = EBUSY;
4470 free(altq, M_PFALTQ);
4471 goto fail;
4472 }
4473 altq->altq_disc = NULL;
4474 TAILQ_FOREACH(a, V_pf_altq_ifs_inactive, entries) {
4475 if (strncmp(a->ifname, altq->ifname,
4476 IFNAMSIZ) == 0) {
4477 altq->altq_disc = a->altq_disc;
4478 break;
4479 }
4480 }
4481 }
4482
4483 if ((ifp = ifunit(altq->ifname)) == NULL)
4484 altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
4485 else
4486 error = altq_add(ifp, altq);
4487
4488 if (error) {
4489 PF_RULES_WUNLOCK();
4490 free(altq, M_PFALTQ);
4491 goto fail;
4492 }
4493
4494 if (altq->qname[0] != 0)
4495 TAILQ_INSERT_TAIL(V_pf_altqs_inactive, altq, entries);
4496 else
4497 TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, altq, entries);
4498 /* version error check done on import above */
4499 pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
4500 PF_RULES_WUNLOCK();
4501 break;
4502 }
4503
4504 case DIOCGETALTQSV0:
4505 case DIOCGETALTQSV1: {
4506 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4507 struct pf_altq *altq;
4508
4509 PF_RULES_RLOCK();
4510 pa->nr = 0;
4511 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries)
4512 pa->nr++;
4513 TAILQ_FOREACH(altq, V_pf_altqs_active, entries)
4514 pa->nr++;
4515 pa->ticket = V_ticket_altqs_active;
4516 PF_RULES_RUNLOCK();
4517 break;
4518 }
4519
4520 case DIOCGETALTQV0:
4521 case DIOCGETALTQV1: {
4522 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4523 struct pf_altq *altq;
4524
4525 PF_RULES_RLOCK();
4526 if (pa->ticket != V_ticket_altqs_active) {
4527 PF_RULES_RUNLOCK();
4528 error = EBUSY;
4529 goto fail;
4530 }
4531 altq = pf_altq_get_nth_active(pa->nr);
4532 if (altq == NULL) {
4533 PF_RULES_RUNLOCK();
4534 error = EBUSY;
4535 goto fail;
4536 }
4537 pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
4538 PF_RULES_RUNLOCK();
4539 break;
4540 }
4541
4542 case DIOCCHANGEALTQV0:
4543 case DIOCCHANGEALTQV1:
4544 /* CHANGEALTQ not supported yet! */
4545 error = ENODEV;
4546 break;
4547
4548 case DIOCGETQSTATSV0:
4549 case DIOCGETQSTATSV1: {
4550 struct pfioc_qstats_v1 *pq = (struct pfioc_qstats_v1 *)addr;
4551 struct pf_altq *altq;
4552 int nbytes;
4553 u_int32_t version;
4554
4555 PF_RULES_RLOCK();
4556 if (pq->ticket != V_ticket_altqs_active) {
4557 PF_RULES_RUNLOCK();
4558 error = EBUSY;
4559 goto fail;
4560 }
4561 nbytes = pq->nbytes;
4562 altq = pf_altq_get_nth_active(pq->nr);
4563 if (altq == NULL) {
4564 PF_RULES_RUNLOCK();
4565 error = EBUSY;
4566 goto fail;
4567 }
4568
4569 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
4570 PF_RULES_RUNLOCK();
4571 error = ENXIO;
4572 goto fail;
4573 }
4574 PF_RULES_RUNLOCK();
4575 if (cmd == DIOCGETQSTATSV0)
4576 version = 0; /* DIOCGETQSTATSV0 means stats struct v0 */
4577 else
4578 version = pq->version;
4579 error = altq_getqstats(altq, pq->buf, &nbytes, version);
4580 if (error == 0) {
4581 pq->scheduler = altq->scheduler;
4582 pq->nbytes = nbytes;
4583 }
4584 break;
4585 }
4586 #endif /* ALTQ */
4587
4588 case DIOCBEGINADDRS: {
4589 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4590
4591 error = pf_ioctl_begin_addrs(&pp->ticket);
4592 break;
4593 }
4594
4595 case DIOCADDADDR: {
4596 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4597 struct pf_nl_pooladdr npp = {};
4598
4599 npp.which = PF_RDR;
4600 memcpy(&npp, pp, sizeof(*pp));
4601 error = pf_ioctl_add_addr(&npp);
4602 break;
4603 }
4604
4605 case DIOCGETADDRS: {
4606 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4607 struct pf_nl_pooladdr npp = {};
4608
4609 npp.which = PF_RDR;
4610 memcpy(&npp, pp, sizeof(*pp));
4611 error = pf_ioctl_get_addrs(&npp);
4612 memcpy(pp, &npp, sizeof(*pp));
4613
4614 break;
4615 }
4616
4617 case DIOCGETADDR: {
4618 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4619 struct pf_nl_pooladdr npp = {};
4620
4621 npp.which = PF_RDR;
4622 memcpy(&npp, pp, sizeof(*pp));
4623 error = pf_ioctl_get_addr(&npp);
4624 memcpy(pp, &npp, sizeof(*pp));
4625
4626 break;
4627 }
4628
4629 case DIOCCHANGEADDR: {
4630 struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr;
4631 struct pf_kpool *pool;
4632 struct pf_kpooladdr *oldpa = NULL, *newpa = NULL;
4633 struct pf_kruleset *ruleset;
4634 struct pfi_kkif *kif = NULL;
4635
4636 pca->anchor[sizeof(pca->anchor) - 1] = '\0';
4637
4638 if (pca->action < PF_CHANGE_ADD_HEAD ||
4639 pca->action > PF_CHANGE_REMOVE) {
4640 error = EINVAL;
4641 goto fail;
4642 }
4643 if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
4644 pca->addr.addr.type != PF_ADDR_DYNIFTL &&
4645 pca->addr.addr.type != PF_ADDR_TABLE) {
4646 error = EINVAL;
4647 goto fail;
4648 }
4649 if (pca->addr.addr.p.dyn != NULL) {
4650 error = EINVAL;
4651 goto fail;
4652 }
4653
4654 if (pca->action != PF_CHANGE_REMOVE) {
4655 #ifndef INET
4656 if (pca->af == AF_INET) {
4657 error = EAFNOSUPPORT;
4658 goto fail;
4659 }
4660 #endif /* INET */
4661 #ifndef INET6
4662 if (pca->af == AF_INET6) {
4663 error = EAFNOSUPPORT;
4664 goto fail;
4665 }
4666 #endif /* INET6 */
4667 newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK);
4668 bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
4669 if (newpa->ifname[0])
4670 kif = pf_kkif_create(M_WAITOK);
4671 newpa->kif = NULL;
4672 }
4673 #define ERROUT(x) ERROUT_IOCTL(DIOCCHANGEADDR_error, x)
4674 PF_RULES_WLOCK();
4675 ruleset = pf_find_kruleset(pca->anchor);
4676 if (ruleset == NULL)
4677 ERROUT(EBUSY);
4678
4679 pool = pf_get_kpool(pca->anchor, pca->ticket, pca->r_action,
4680 pca->r_num, pca->r_last, 1, 1, PF_RDR);
4681 if (pool == NULL)
4682 ERROUT(EBUSY);
4683
4684 if (pca->action != PF_CHANGE_REMOVE) {
4685 if (newpa->ifname[0]) {
4686 newpa->kif = pfi_kkif_attach(kif, newpa->ifname);
4687 pfi_kkif_ref(newpa->kif);
4688 kif = NULL;
4689 }
4690
4691 switch (newpa->addr.type) {
4692 case PF_ADDR_DYNIFTL:
4693 error = pfi_dynaddr_setup(&newpa->addr,
4694 pca->af);
4695 break;
4696 case PF_ADDR_TABLE:
4697 newpa->addr.p.tbl = pfr_attach_table(ruleset,
4698 newpa->addr.v.tblname);
4699 if (newpa->addr.p.tbl == NULL)
4700 error = ENOMEM;
4701 break;
4702 }
4703 if (error)
4704 goto DIOCCHANGEADDR_error;
4705 }
4706
4707 switch (pca->action) {
4708 case PF_CHANGE_ADD_HEAD:
4709 oldpa = TAILQ_FIRST(&pool->list);
4710 break;
4711 case PF_CHANGE_ADD_TAIL:
4712 oldpa = TAILQ_LAST(&pool->list, pf_kpalist);
4713 break;
4714 default:
4715 oldpa = TAILQ_FIRST(&pool->list);
4716 for (int i = 0; oldpa && i < pca->nr; i++)
4717 oldpa = TAILQ_NEXT(oldpa, entries);
4718
4719 if (oldpa == NULL)
4720 ERROUT(EINVAL);
4721 }
4722
4723 if (pca->action == PF_CHANGE_REMOVE) {
4724 TAILQ_REMOVE(&pool->list, oldpa, entries);
4725 switch (oldpa->addr.type) {
4726 case PF_ADDR_DYNIFTL:
4727 pfi_dynaddr_remove(oldpa->addr.p.dyn);
4728 break;
4729 case PF_ADDR_TABLE:
4730 pfr_detach_table(oldpa->addr.p.tbl);
4731 break;
4732 }
4733 if (oldpa->kif)
4734 pfi_kkif_unref(oldpa->kif);
4735 free(oldpa, M_PFRULE);
4736 } else {
4737 if (oldpa == NULL)
4738 TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
4739 else if (pca->action == PF_CHANGE_ADD_HEAD ||
4740 pca->action == PF_CHANGE_ADD_BEFORE)
4741 TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
4742 else
4743 TAILQ_INSERT_AFTER(&pool->list, oldpa,
4744 newpa, entries);
4745 }
4746
4747 pool->cur = TAILQ_FIRST(&pool->list);
4748 pf_addrcpy(&pool->counter, &pool->cur->addr.v.a.addr, pca->af);
4749 PF_RULES_WUNLOCK();
4750 break;
4751
4752 #undef ERROUT
4753 DIOCCHANGEADDR_error:
4754 if (newpa != NULL) {
4755 if (newpa->kif)
4756 pfi_kkif_unref(newpa->kif);
4757 free(newpa, M_PFRULE);
4758 }
4759 PF_RULES_WUNLOCK();
4760 pf_kkif_free(kif);
4761 break;
4762 }
4763
4764 case DIOCGETRULESETS: {
4765 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
4766
4767 pr->path[sizeof(pr->path) - 1] = '\0';
4768
4769 error = pf_ioctl_get_rulesets(pr);
4770 break;
4771 }
4772
4773 case DIOCGETRULESET: {
4774 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
4775
4776 pr->path[sizeof(pr->path) - 1] = '\0';
4777
4778 error = pf_ioctl_get_ruleset(pr);
4779 break;
4780 }
4781
4782 case DIOCRCLRTABLES: {
4783 struct pfioc_table *io = (struct pfioc_table *)addr;
4784
4785 if (io->pfrio_esize != 0) {
4786 error = ENODEV;
4787 goto fail;
4788 }
4789 if (strnlen(io->pfrio_table.pfrt_anchor, MAXPATHLEN)
4790 == MAXPATHLEN) {
4791 error = EINVAL;
4792 goto fail;
4793 }
4794 if (strnlen(io->pfrio_table.pfrt_name, PF_TABLE_NAME_SIZE)
4795 == PF_TABLE_NAME_SIZE) {
4796 error = EINVAL;
4797 goto fail;
4798 }
4799
4800 PF_RULES_WLOCK();
4801 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
4802 io->pfrio_flags | PFR_FLAG_USERIOCTL);
4803 PF_RULES_WUNLOCK();
4804 break;
4805 }
4806
4807 case DIOCRADDTABLES: {
4808 struct pfioc_table *io = (struct pfioc_table *)addr;
4809 struct pfr_table *pfrts;
4810 size_t totlen;
4811
4812 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4813 error = ENODEV;
4814 goto fail;
4815 }
4816
4817 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4818 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4819 error = ENOMEM;
4820 goto fail;
4821 }
4822
4823 totlen = io->pfrio_size * sizeof(struct pfr_table);
4824 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4825 M_PF, M_WAITOK);
4826 error = copyin(io->pfrio_buffer, pfrts, totlen);
4827 if (error) {
4828 free(pfrts, M_PF);
4829 goto fail;
4830 }
4831 PF_RULES_WLOCK();
4832 error = pfr_add_tables(pfrts, io->pfrio_size,
4833 &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4834 PF_RULES_WUNLOCK();
4835 free(pfrts, M_PF);
4836 break;
4837 }
4838
4839 case DIOCRDELTABLES: {
4840 struct pfioc_table *io = (struct pfioc_table *)addr;
4841 struct pfr_table *pfrts;
4842 size_t totlen;
4843
4844 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4845 error = ENODEV;
4846 goto fail;
4847 }
4848
4849 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4850 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4851 error = ENOMEM;
4852 goto fail;
4853 }
4854
4855 totlen = io->pfrio_size * sizeof(struct pfr_table);
4856 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4857 M_PF, M_WAITOK);
4858 error = copyin(io->pfrio_buffer, pfrts, totlen);
4859 if (error) {
4860 free(pfrts, M_PF);
4861 goto fail;
4862 }
4863 PF_RULES_WLOCK();
4864 error = pfr_del_tables(pfrts, io->pfrio_size,
4865 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4866 PF_RULES_WUNLOCK();
4867 free(pfrts, M_PF);
4868 break;
4869 }
4870
4871 case DIOCRGETTABLES: {
4872 struct pfioc_table *io = (struct pfioc_table *)addr;
4873 struct pfr_table *pfrts;
4874 size_t totlen;
4875 int n;
4876
4877 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4878 error = ENODEV;
4879 goto fail;
4880 }
4881 PF_RULES_RLOCK();
4882 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4883 if (n < 0) {
4884 PF_RULES_RUNLOCK();
4885 error = EINVAL;
4886 goto fail;
4887 }
4888 io->pfrio_size = min(io->pfrio_size, n);
4889
4890 totlen = io->pfrio_size * sizeof(struct pfr_table);
4891
4892 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4893 M_PF, M_NOWAIT | M_ZERO);
4894 if (pfrts == NULL) {
4895 error = ENOMEM;
4896 PF_RULES_RUNLOCK();
4897 goto fail;
4898 }
4899 error = pfr_get_tables(&io->pfrio_table, pfrts,
4900 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4901 PF_RULES_RUNLOCK();
4902 if (error == 0)
4903 error = copyout(pfrts, io->pfrio_buffer, totlen);
4904 free(pfrts, M_PF);
4905 break;
4906 }
4907
4908 case DIOCRGETTSTATS: {
4909 struct pfioc_table *io = (struct pfioc_table *)addr;
4910 struct pfr_tstats *pfrtstats;
4911 size_t totlen;
4912 int n;
4913
4914 if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
4915 error = ENODEV;
4916 goto fail;
4917 }
4918 PF_TABLE_STATS_LOCK();
4919 PF_RULES_RLOCK();
4920 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4921 if (n < 0) {
4922 PF_RULES_RUNLOCK();
4923 PF_TABLE_STATS_UNLOCK();
4924 error = EINVAL;
4925 goto fail;
4926 }
4927 io->pfrio_size = min(io->pfrio_size, n);
4928
4929 totlen = io->pfrio_size * sizeof(struct pfr_tstats);
4930 pfrtstats = mallocarray(io->pfrio_size,
4931 sizeof(struct pfr_tstats), M_PF, M_NOWAIT | M_ZERO);
4932 if (pfrtstats == NULL) {
4933 error = ENOMEM;
4934 PF_RULES_RUNLOCK();
4935 PF_TABLE_STATS_UNLOCK();
4936 goto fail;
4937 }
4938 error = pfr_get_tstats(&io->pfrio_table, pfrtstats,
4939 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4940 PF_RULES_RUNLOCK();
4941 PF_TABLE_STATS_UNLOCK();
4942 if (error == 0)
4943 error = copyout(pfrtstats, io->pfrio_buffer, totlen);
4944 free(pfrtstats, M_PF);
4945 break;
4946 }
4947
4948 case DIOCRCLRTSTATS: {
4949 struct pfioc_table *io = (struct pfioc_table *)addr;
4950 struct pfr_table *pfrts;
4951 size_t totlen;
4952
4953 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4954 error = ENODEV;
4955 goto fail;
4956 }
4957
4958 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4959 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4960 /* We used to count tables and use the minimum required
4961 * size, so we didn't fail on overly large requests.
4962 * Keep doing so. */
4963 io->pfrio_size = pf_ioctl_maxcount;
4964 goto fail;
4965 }
4966
4967 totlen = io->pfrio_size * sizeof(struct pfr_table);
4968 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4969 M_PF, M_WAITOK);
4970 error = copyin(io->pfrio_buffer, pfrts, totlen);
4971 if (error) {
4972 free(pfrts, M_PF);
4973 goto fail;
4974 }
4975
4976 PF_TABLE_STATS_LOCK();
4977 PF_RULES_RLOCK();
4978 error = pfr_clr_tstats(pfrts, io->pfrio_size,
4979 &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4980 PF_RULES_RUNLOCK();
4981 PF_TABLE_STATS_UNLOCK();
4982 free(pfrts, M_PF);
4983 break;
4984 }
4985
4986 case DIOCRSETTFLAGS: {
4987 struct pfioc_table *io = (struct pfioc_table *)addr;
4988 struct pfr_table *pfrts;
4989 size_t totlen;
4990 int n;
4991
4992 if (io->pfrio_esize != sizeof(struct pfr_table)) {
4993 error = ENODEV;
4994 goto fail;
4995 }
4996
4997 PF_RULES_RLOCK();
4998 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4999 if (n < 0) {
5000 PF_RULES_RUNLOCK();
5001 error = EINVAL;
5002 goto fail;
5003 }
5004
5005 io->pfrio_size = min(io->pfrio_size, n);
5006 PF_RULES_RUNLOCK();
5007
5008 totlen = io->pfrio_size * sizeof(struct pfr_table);
5009 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
5010 M_PF, M_WAITOK);
5011 error = copyin(io->pfrio_buffer, pfrts, totlen);
5012 if (error) {
5013 free(pfrts, M_PF);
5014 goto fail;
5015 }
5016 PF_RULES_WLOCK();
5017 error = pfr_set_tflags(pfrts, io->pfrio_size,
5018 io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
5019 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5020 PF_RULES_WUNLOCK();
5021 free(pfrts, M_PF);
5022 break;
5023 }
5024
5025 case DIOCRCLRADDRS: {
5026 struct pfioc_table *io = (struct pfioc_table *)addr;
5027
5028 if (io->pfrio_esize != 0) {
5029 error = ENODEV;
5030 goto fail;
5031 }
5032 PF_RULES_WLOCK();
5033 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
5034 io->pfrio_flags | PFR_FLAG_USERIOCTL);
5035 PF_RULES_WUNLOCK();
5036 break;
5037 }
5038
5039 case DIOCRADDADDRS: {
5040 struct pfioc_table *io = (struct pfioc_table *)addr;
5041 struct pfr_addr *pfras;
5042 size_t totlen;
5043
5044 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5045 error = ENODEV;
5046 goto fail;
5047 }
5048 if (io->pfrio_size < 0 ||
5049 io->pfrio_size > pf_ioctl_maxcount ||
5050 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5051 error = EINVAL;
5052 goto fail;
5053 }
5054 totlen = io->pfrio_size * sizeof(struct pfr_addr);
5055 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5056 M_PF, M_WAITOK);
5057 error = copyin(io->pfrio_buffer, pfras, totlen);
5058 if (error) {
5059 free(pfras, M_PF);
5060 goto fail;
5061 }
5062 PF_RULES_WLOCK();
5063 io->pfrio_nadd = 0;
5064 error = pfr_add_addrs(&io->pfrio_table, pfras,
5065 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
5066 PFR_FLAG_USERIOCTL);
5067 PF_RULES_WUNLOCK();
5068 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5069 error = copyout(pfras, io->pfrio_buffer, totlen);
5070 free(pfras, M_PF);
5071 break;
5072 }
5073
5074 case DIOCRDELADDRS: {
5075 struct pfioc_table *io = (struct pfioc_table *)addr;
5076 struct pfr_addr *pfras;
5077 size_t totlen;
5078
5079 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5080 error = ENODEV;
5081 goto fail;
5082 }
5083 if (io->pfrio_size < 0 ||
5084 io->pfrio_size > pf_ioctl_maxcount ||
5085 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5086 error = EINVAL;
5087 goto fail;
5088 }
5089 totlen = io->pfrio_size * sizeof(struct pfr_addr);
5090 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5091 M_PF, M_WAITOK);
5092 error = copyin(io->pfrio_buffer, pfras, totlen);
5093 if (error) {
5094 free(pfras, M_PF);
5095 goto fail;
5096 }
5097 PF_RULES_WLOCK();
5098 error = pfr_del_addrs(&io->pfrio_table, pfras,
5099 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
5100 PFR_FLAG_USERIOCTL);
5101 PF_RULES_WUNLOCK();
5102 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5103 error = copyout(pfras, io->pfrio_buffer, totlen);
5104 free(pfras, M_PF);
5105 break;
5106 }
5107
5108 case DIOCRSETADDRS: {
5109 struct pfioc_table *io = (struct pfioc_table *)addr;
5110 struct pfr_addr *pfras;
5111 size_t totlen, count;
5112
5113 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5114 error = ENODEV;
5115 goto fail;
5116 }
5117 if (io->pfrio_size < 0 || io->pfrio_size2 < 0) {
5118 error = EINVAL;
5119 goto fail;
5120 }
5121 count = max(io->pfrio_size, io->pfrio_size2);
5122 if (count > pf_ioctl_maxcount ||
5123 WOULD_OVERFLOW(count, sizeof(struct pfr_addr))) {
5124 error = EINVAL;
5125 goto fail;
5126 }
5127 totlen = count * sizeof(struct pfr_addr);
5128 pfras = mallocarray(count, sizeof(struct pfr_addr), M_PF,
5129 M_WAITOK);
5130 error = copyin(io->pfrio_buffer, pfras, totlen);
5131 if (error) {
5132 free(pfras, M_PF);
5133 goto fail;
5134 }
5135 PF_RULES_WLOCK();
5136 error = pfr_set_addrs(&io->pfrio_table, pfras,
5137 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
5138 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
5139 PFR_FLAG_START | PFR_FLAG_DONE | PFR_FLAG_USERIOCTL, 0);
5140 PF_RULES_WUNLOCK();
5141 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5142 error = copyout(pfras, io->pfrio_buffer, totlen);
5143 free(pfras, M_PF);
5144 break;
5145 }
5146
5147 case DIOCRGETADDRS: {
5148 struct pfioc_table *io = (struct pfioc_table *)addr;
5149 struct pfr_addr *pfras;
5150 size_t totlen;
5151
5152 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5153 error = ENODEV;
5154 goto fail;
5155 }
5156 if (io->pfrio_size < 0 ||
5157 io->pfrio_size > pf_ioctl_maxcount ||
5158 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5159 error = EINVAL;
5160 goto fail;
5161 }
5162 totlen = io->pfrio_size * sizeof(struct pfr_addr);
5163 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5164 M_PF, M_WAITOK | M_ZERO);
5165 PF_RULES_RLOCK();
5166 error = pfr_get_addrs(&io->pfrio_table, pfras,
5167 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5168 PF_RULES_RUNLOCK();
5169 if (error == 0)
5170 error = copyout(pfras, io->pfrio_buffer, totlen);
5171 free(pfras, M_PF);
5172 break;
5173 }
5174
5175 case DIOCRGETASTATS: {
5176 struct pfioc_table *io = (struct pfioc_table *)addr;
5177 struct pfr_astats *pfrastats;
5178 size_t totlen;
5179
5180 if (io->pfrio_esize != sizeof(struct pfr_astats)) {
5181 error = ENODEV;
5182 goto fail;
5183 }
5184 if (io->pfrio_size < 0 ||
5185 io->pfrio_size > pf_ioctl_maxcount ||
5186 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_astats))) {
5187 error = EINVAL;
5188 goto fail;
5189 }
5190 totlen = io->pfrio_size * sizeof(struct pfr_astats);
5191 pfrastats = mallocarray(io->pfrio_size,
5192 sizeof(struct pfr_astats), M_PF, M_WAITOK | M_ZERO);
5193 PF_RULES_RLOCK();
5194 error = pfr_get_astats(&io->pfrio_table, pfrastats,
5195 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5196 PF_RULES_RUNLOCK();
5197 if (error == 0)
5198 error = copyout(pfrastats, io->pfrio_buffer, totlen);
5199 free(pfrastats, M_PF);
5200 break;
5201 }
5202
5203 case DIOCRCLRASTATS: {
5204 struct pfioc_table *io = (struct pfioc_table *)addr;
5205 struct pfr_addr *pfras;
5206 size_t totlen;
5207
5208 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5209 error = ENODEV;
5210 goto fail;
5211 }
5212 if (io->pfrio_size < 0 ||
5213 io->pfrio_size > pf_ioctl_maxcount ||
5214 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5215 error = EINVAL;
5216 goto fail;
5217 }
5218 totlen = io->pfrio_size * sizeof(struct pfr_addr);
5219 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5220 M_PF, M_WAITOK);
5221 error = copyin(io->pfrio_buffer, pfras, totlen);
5222 if (error) {
5223 free(pfras, M_PF);
5224 goto fail;
5225 }
5226 PF_RULES_WLOCK();
5227 error = pfr_clr_astats(&io->pfrio_table, pfras,
5228 io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
5229 PFR_FLAG_USERIOCTL);
5230 PF_RULES_WUNLOCK();
5231 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5232 error = copyout(pfras, io->pfrio_buffer, totlen);
5233 free(pfras, M_PF);
5234 break;
5235 }
5236
5237 case DIOCRTSTADDRS: {
5238 struct pfioc_table *io = (struct pfioc_table *)addr;
5239 struct pfr_addr *pfras;
5240 size_t totlen;
5241
5242 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5243 error = ENODEV;
5244 goto fail;
5245 }
5246 if (io->pfrio_size < 0 ||
5247 io->pfrio_size > pf_ioctl_maxcount ||
5248 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5249 error = EINVAL;
5250 goto fail;
5251 }
5252 totlen = io->pfrio_size * sizeof(struct pfr_addr);
5253 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5254 M_PF, M_WAITOK);
5255 error = copyin(io->pfrio_buffer, pfras, totlen);
5256 if (error) {
5257 free(pfras, M_PF);
5258 goto fail;
5259 }
5260 PF_RULES_RLOCK();
5261 error = pfr_tst_addrs(&io->pfrio_table, pfras,
5262 io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
5263 PFR_FLAG_USERIOCTL);
5264 PF_RULES_RUNLOCK();
5265 if (error == 0)
5266 error = copyout(pfras, io->pfrio_buffer, totlen);
5267 free(pfras, M_PF);
5268 break;
5269 }
5270
5271 case DIOCRINADEFINE: {
5272 struct pfioc_table *io = (struct pfioc_table *)addr;
5273 struct pfr_addr *pfras;
5274 size_t totlen;
5275
5276 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5277 error = ENODEV;
5278 goto fail;
5279 }
5280 if (io->pfrio_size < 0 ||
5281 io->pfrio_size > pf_ioctl_maxcount ||
5282 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5283 error = EINVAL;
5284 goto fail;
5285 }
5286 totlen = io->pfrio_size * sizeof(struct pfr_addr);
5287 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5288 M_PF, M_WAITOK);
5289 error = copyin(io->pfrio_buffer, pfras, totlen);
5290 if (error) {
5291 free(pfras, M_PF);
5292 goto fail;
5293 }
5294 PF_RULES_WLOCK();
5295 error = pfr_ina_define(&io->pfrio_table, pfras,
5296 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
5297 io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5298 PF_RULES_WUNLOCK();
5299 free(pfras, M_PF);
5300 break;
5301 }
5302
5303 case DIOCOSFPADD: {
5304 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
5305 PF_RULES_WLOCK();
5306 error = pf_osfp_add(io);
5307 PF_RULES_WUNLOCK();
5308 break;
5309 }
5310
5311 case DIOCOSFPGET: {
5312 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
5313 PF_RULES_RLOCK();
5314 error = pf_osfp_get(io);
5315 PF_RULES_RUNLOCK();
5316 break;
5317 }
5318
5319 case DIOCXBEGIN: {
5320 struct pfioc_trans *io = (struct pfioc_trans *)addr;
5321 struct pfioc_trans_e *ioes, *ioe;
5322 size_t totlen;
5323 int i;
5324
5325 if (io->esize != sizeof(*ioe)) {
5326 error = ENODEV;
5327 goto fail;
5328 }
5329 if (io->size < 0 ||
5330 io->size > pf_ioctl_maxcount ||
5331 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5332 error = EINVAL;
5333 goto fail;
5334 }
5335 totlen = sizeof(struct pfioc_trans_e) * io->size;
5336 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5337 M_PF, M_WAITOK);
5338 error = copyin(io->array, ioes, totlen);
5339 if (error) {
5340 free(ioes, M_PF);
5341 goto fail;
5342 }
5343 PF_RULES_WLOCK();
5344 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5345 ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5346 switch (ioe->rs_num) {
5347 case PF_RULESET_ETH:
5348 if ((error = pf_begin_eth(&ioe->ticket, ioe->anchor))) {
5349 PF_RULES_WUNLOCK();
5350 free(ioes, M_PF);
5351 goto fail;
5352 }
5353 break;
5354 #ifdef ALTQ
5355 case PF_RULESET_ALTQ:
5356 if (ioe->anchor[0]) {
5357 PF_RULES_WUNLOCK();
5358 free(ioes, M_PF);
5359 error = EINVAL;
5360 goto fail;
5361 }
5362 if ((error = pf_begin_altq(&ioe->ticket))) {
5363 PF_RULES_WUNLOCK();
5364 free(ioes, M_PF);
5365 goto fail;
5366 }
5367 break;
5368 #endif /* ALTQ */
5369 case PF_RULESET_TABLE:
5370 {
5371 struct pfr_table table;
5372
5373 bzero(&table, sizeof(table));
5374 strlcpy(table.pfrt_anchor, ioe->anchor,
5375 sizeof(table.pfrt_anchor));
5376 if ((error = pfr_ina_begin(&table,
5377 &ioe->ticket, NULL, 0))) {
5378 PF_RULES_WUNLOCK();
5379 free(ioes, M_PF);
5380 goto fail;
5381 }
5382 break;
5383 }
5384 default:
5385 if ((error = pf_begin_rules(&ioe->ticket,
5386 ioe->rs_num, ioe->anchor))) {
5387 PF_RULES_WUNLOCK();
5388 free(ioes, M_PF);
5389 goto fail;
5390 }
5391 break;
5392 }
5393 }
5394 PF_RULES_WUNLOCK();
5395 error = copyout(ioes, io->array, totlen);
5396 free(ioes, M_PF);
5397 break;
5398 }
5399
5400 case DIOCXROLLBACK: {
5401 struct pfioc_trans *io = (struct pfioc_trans *)addr;
5402 struct pfioc_trans_e *ioe, *ioes;
5403 size_t totlen;
5404 int i;
5405
5406 if (io->esize != sizeof(*ioe)) {
5407 error = ENODEV;
5408 goto fail;
5409 }
5410 if (io->size < 0 ||
5411 io->size > pf_ioctl_maxcount ||
5412 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5413 error = EINVAL;
5414 goto fail;
5415 }
5416 totlen = sizeof(struct pfioc_trans_e) * io->size;
5417 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5418 M_PF, M_WAITOK);
5419 error = copyin(io->array, ioes, totlen);
5420 if (error) {
5421 free(ioes, M_PF);
5422 goto fail;
5423 }
5424 PF_RULES_WLOCK();
5425 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5426 ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5427 switch (ioe->rs_num) {
5428 case PF_RULESET_ETH:
5429 if ((error = pf_rollback_eth(ioe->ticket,
5430 ioe->anchor))) {
5431 PF_RULES_WUNLOCK();
5432 free(ioes, M_PF);
5433 goto fail; /* really bad */
5434 }
5435 break;
5436 #ifdef ALTQ
5437 case PF_RULESET_ALTQ:
5438 if (ioe->anchor[0]) {
5439 PF_RULES_WUNLOCK();
5440 free(ioes, M_PF);
5441 error = EINVAL;
5442 goto fail;
5443 }
5444 if ((error = pf_rollback_altq(ioe->ticket))) {
5445 PF_RULES_WUNLOCK();
5446 free(ioes, M_PF);
5447 goto fail; /* really bad */
5448 }
5449 break;
5450 #endif /* ALTQ */
5451 case PF_RULESET_TABLE:
5452 {
5453 struct pfr_table table;
5454
5455 bzero(&table, sizeof(table));
5456 strlcpy(table.pfrt_anchor, ioe->anchor,
5457 sizeof(table.pfrt_anchor));
5458 if ((error = pfr_ina_rollback(&table,
5459 ioe->ticket, NULL, 0))) {
5460 PF_RULES_WUNLOCK();
5461 free(ioes, M_PF);
5462 goto fail; /* really bad */
5463 }
5464 break;
5465 }
5466 default:
5467 if ((error = pf_rollback_rules(ioe->ticket,
5468 ioe->rs_num, ioe->anchor))) {
5469 PF_RULES_WUNLOCK();
5470 free(ioes, M_PF);
5471 goto fail; /* really bad */
5472 }
5473 break;
5474 }
5475 }
5476 PF_RULES_WUNLOCK();
5477 free(ioes, M_PF);
5478 break;
5479 }
5480
5481 case DIOCXCOMMIT: {
5482 struct pfioc_trans *io = (struct pfioc_trans *)addr;
5483 struct pfioc_trans_e *ioe, *ioes;
5484 struct pf_kruleset *rs;
5485 struct pf_keth_ruleset *ers;
5486 size_t totlen;
5487 int i;
5488
5489 if (io->esize != sizeof(*ioe)) {
5490 error = ENODEV;
5491 goto fail;
5492 }
5493
5494 if (io->size < 0 ||
5495 io->size > pf_ioctl_maxcount ||
5496 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5497 error = EINVAL;
5498 goto fail;
5499 }
5500
5501 totlen = sizeof(struct pfioc_trans_e) * io->size;
5502 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5503 M_PF, M_WAITOK);
5504 error = copyin(io->array, ioes, totlen);
5505 if (error) {
5506 free(ioes, M_PF);
5507 goto fail;
5508 }
5509 PF_RULES_WLOCK();
5510 /* First makes sure everything will succeed. */
5511 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5512 ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5513 switch (ioe->rs_num) {
5514 case PF_RULESET_ETH:
5515 ers = pf_find_keth_ruleset(ioe->anchor);
5516 if (ers == NULL || ioe->ticket == 0 ||
5517 ioe->ticket != ers->inactive.ticket) {
5518 PF_RULES_WUNLOCK();
5519 free(ioes, M_PF);
5520 error = EINVAL;
5521 goto fail;
5522 }
5523 break;
5524 #ifdef ALTQ
5525 case PF_RULESET_ALTQ:
5526 if (ioe->anchor[0]) {
5527 PF_RULES_WUNLOCK();
5528 free(ioes, M_PF);
5529 error = EINVAL;
5530 goto fail;
5531 }
5532 if (!V_altqs_inactive_open || ioe->ticket !=
5533 V_ticket_altqs_inactive) {
5534 PF_RULES_WUNLOCK();
5535 free(ioes, M_PF);
5536 error = EBUSY;
5537 goto fail;
5538 }
5539 break;
5540 #endif /* ALTQ */
5541 case PF_RULESET_TABLE:
5542 rs = pf_find_kruleset(ioe->anchor);
5543 if (rs == NULL || !rs->topen || ioe->ticket !=
5544 rs->tticket) {
5545 PF_RULES_WUNLOCK();
5546 free(ioes, M_PF);
5547 error = EBUSY;
5548 goto fail;
5549 }
5550 break;
5551 default:
5552 if (ioe->rs_num < 0 || ioe->rs_num >=
5553 PF_RULESET_MAX) {
5554 PF_RULES_WUNLOCK();
5555 free(ioes, M_PF);
5556 error = EINVAL;
5557 goto fail;
5558 }
5559 rs = pf_find_kruleset(ioe->anchor);
5560 if (rs == NULL ||
5561 !rs->rules[ioe->rs_num].inactive.open ||
5562 rs->rules[ioe->rs_num].inactive.ticket !=
5563 ioe->ticket) {
5564 PF_RULES_WUNLOCK();
5565 free(ioes, M_PF);
5566 error = EBUSY;
5567 goto fail;
5568 }
5569 break;
5570 }
5571 }
5572 /* Now do the commit - no errors should happen here. */
5573 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5574 switch (ioe->rs_num) {
5575 case PF_RULESET_ETH:
5576 if ((error = pf_commit_eth(ioe->ticket, ioe->anchor))) {
5577 PF_RULES_WUNLOCK();
5578 free(ioes, M_PF);
5579 goto fail; /* really bad */
5580 }
5581 break;
5582 #ifdef ALTQ
5583 case PF_RULESET_ALTQ:
5584 if ((error = pf_commit_altq(ioe->ticket))) {
5585 PF_RULES_WUNLOCK();
5586 free(ioes, M_PF);
5587 goto fail; /* really bad */
5588 }
5589 break;
5590 #endif /* ALTQ */
5591 case PF_RULESET_TABLE:
5592 {
5593 struct pfr_table table;
5594
5595 bzero(&table, sizeof(table));
5596 (void)strlcpy(table.pfrt_anchor, ioe->anchor,
5597 sizeof(table.pfrt_anchor));
5598 if ((error = pfr_ina_commit(&table,
5599 ioe->ticket, NULL, NULL, 0))) {
5600 PF_RULES_WUNLOCK();
5601 free(ioes, M_PF);
5602 goto fail; /* really bad */
5603 }
5604 break;
5605 }
5606 default:
5607 if ((error = pf_commit_rules(ioe->ticket,
5608 ioe->rs_num, ioe->anchor))) {
5609 PF_RULES_WUNLOCK();
5610 free(ioes, M_PF);
5611 goto fail; /* really bad */
5612 }
5613 break;
5614 }
5615 }
5616 PF_RULES_WUNLOCK();
5617
5618 /* Only hook into EtherNet taffic if we've got rules for it. */
5619 if (! TAILQ_EMPTY(V_pf_keth->active.rules))
5620 hook_pf_eth();
5621 else
5622 dehook_pf_eth();
5623
5624 free(ioes, M_PF);
5625 break;
5626 }
5627
5628 case DIOCGETSRCNODES: {
5629 struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
5630 struct pf_srchash *sh;
5631 struct pf_ksrc_node *n;
5632 struct pf_src_node *p, *pstore;
5633 uint32_t i, nr = 0;
5634
5635 for (i = 0, sh = V_pf_srchash; i <= V_pf_srchashmask;
5636 i++, sh++) {
5637 PF_HASHROW_LOCK(sh);
5638 LIST_FOREACH(n, &sh->nodes, entry)
5639 nr++;
5640 PF_HASHROW_UNLOCK(sh);
5641 }
5642
5643 psn->psn_len = min(psn->psn_len,
5644 sizeof(struct pf_src_node) * nr);
5645
5646 if (psn->psn_len == 0) {
5647 psn->psn_len = sizeof(struct pf_src_node) * nr;
5648 goto fail;
5649 }
5650
5651 nr = 0;
5652
5653 p = pstore = malloc(psn->psn_len, M_PF, M_WAITOK | M_ZERO);
5654 for (i = 0, sh = V_pf_srchash; i <= V_pf_srchashmask;
5655 i++, sh++) {
5656 PF_HASHROW_LOCK(sh);
5657 LIST_FOREACH(n, &sh->nodes, entry) {
5658
5659 if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
5660 break;
5661
5662 pf_src_node_copy(n, p);
5663
5664 p++;
5665 nr++;
5666 }
5667 PF_HASHROW_UNLOCK(sh);
5668 }
5669 error = copyout(pstore, psn->psn_src_nodes,
5670 sizeof(struct pf_src_node) * nr);
5671 if (error) {
5672 free(pstore, M_PF);
5673 goto fail;
5674 }
5675 psn->psn_len = sizeof(struct pf_src_node) * nr;
5676 free(pstore, M_PF);
5677 break;
5678 }
5679
5680 case DIOCCLRSRCNODES: {
5681 pf_kill_srcnodes(NULL);
5682 break;
5683 }
5684
5685 case DIOCKILLSRCNODES:
5686 pf_kill_srcnodes((struct pfioc_src_node_kill *)addr);
5687 break;
5688
5689 #ifdef COMPAT_FREEBSD13
5690 case DIOCKEEPCOUNTERS_FREEBSD13:
5691 #endif
5692 case DIOCKEEPCOUNTERS:
5693 error = pf_keepcounters((struct pfioc_nv *)addr);
5694 break;
5695
5696 case DIOCGETSYNCOOKIES:
5697 error = pf_get_syncookies((struct pfioc_nv *)addr);
5698 break;
5699
5700 case DIOCSETSYNCOOKIES:
5701 error = pf_set_syncookies((struct pfioc_nv *)addr);
5702 break;
5703
5704 case DIOCSETHOSTID: {
5705 u_int32_t *hostid = (u_int32_t *)addr;
5706
5707 PF_RULES_WLOCK();
5708 if (*hostid == 0)
5709 V_pf_status.hostid = arc4random();
5710 else
5711 V_pf_status.hostid = *hostid;
5712 PF_RULES_WUNLOCK();
5713 break;
5714 }
5715
5716 case DIOCOSFPFLUSH:
5717 PF_RULES_WLOCK();
5718 pf_osfp_flush();
5719 PF_RULES_WUNLOCK();
5720 break;
5721
5722 case DIOCIGETIFACES: {
5723 struct pfioc_iface *io = (struct pfioc_iface *)addr;
5724 struct pfi_kif *ifstore;
5725 size_t bufsiz;
5726
5727 if (io->pfiio_esize != sizeof(struct pfi_kif)) {
5728 error = ENODEV;
5729 goto fail;
5730 }
5731
5732 if (io->pfiio_size < 0 ||
5733 io->pfiio_size > pf_ioctl_maxcount ||
5734 WOULD_OVERFLOW(io->pfiio_size, sizeof(struct pfi_kif))) {
5735 error = EINVAL;
5736 goto fail;
5737 }
5738
5739 io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5740
5741 bufsiz = io->pfiio_size * sizeof(struct pfi_kif);
5742 ifstore = mallocarray(io->pfiio_size, sizeof(struct pfi_kif),
5743 M_PF, M_WAITOK | M_ZERO);
5744
5745 PF_RULES_RLOCK();
5746 pfi_get_ifaces(io->pfiio_name, ifstore, &io->pfiio_size);
5747 PF_RULES_RUNLOCK();
5748 error = copyout(ifstore, io->pfiio_buffer, bufsiz);
5749 free(ifstore, M_PF);
5750 break;
5751 }
5752
5753 case DIOCSETIFFLAG: {
5754 struct pfioc_iface *io = (struct pfioc_iface *)addr;
5755
5756 io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5757
5758 PF_RULES_WLOCK();
5759 error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
5760 PF_RULES_WUNLOCK();
5761 break;
5762 }
5763
5764 case DIOCCLRIFFLAG: {
5765 struct pfioc_iface *io = (struct pfioc_iface *)addr;
5766
5767 io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5768
5769 PF_RULES_WLOCK();
5770 error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
5771 PF_RULES_WUNLOCK();
5772 break;
5773 }
5774
5775 case DIOCSETREASS: {
5776 u_int32_t *reass = (u_int32_t *)addr;
5777
5778 V_pf_status.reass = *reass & (PF_REASS_ENABLED|PF_REASS_NODF);
5779 /* Removal of DF flag without reassembly enabled is not a
5780 * valid combination. Disable reassembly in such case. */
5781 if (!(V_pf_status.reass & PF_REASS_ENABLED))
5782 V_pf_status.reass = 0;
5783 break;
5784 }
5785
5786 default:
5787 error = ENODEV;
5788 break;
5789 }
5790 fail:
5791 CURVNET_RESTORE();
5792
5793 #undef ERROUT_IOCTL
5794
5795 return (error);
5796 }
5797
5798 void
pfsync_state_export(union pfsync_state_union * sp,struct pf_kstate * st,int msg_version)5799 pfsync_state_export(union pfsync_state_union *sp, struct pf_kstate *st, int msg_version)
5800 {
5801 const char *tagname;
5802 bzero(sp, sizeof(union pfsync_state_union));
5803
5804 /* copy from state key */
5805 sp->pfs_1301.key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
5806 sp->pfs_1301.key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
5807 sp->pfs_1301.key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
5808 sp->pfs_1301.key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
5809 sp->pfs_1301.key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
5810 sp->pfs_1301.key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
5811 sp->pfs_1301.key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
5812 sp->pfs_1301.key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
5813
5814 /* copy from state */
5815 strlcpy(sp->pfs_1301.ifname, st->kif->pfik_name, sizeof(sp->pfs_1301.ifname));
5816 bcopy(&st->act.rt_addr, &sp->pfs_1301.rt_addr, sizeof(sp->pfs_1301.rt_addr));
5817 sp->pfs_1301.creation = htonl(time_uptime - (st->creation / 1000));
5818 sp->pfs_1301.expire = pf_state_expires(st);
5819 if (sp->pfs_1301.expire <= time_uptime)
5820 sp->pfs_1301.expire = htonl(0);
5821 else
5822 sp->pfs_1301.expire = htonl(sp->pfs_1301.expire - time_uptime);
5823
5824 switch (msg_version) {
5825 case PFSYNC_MSG_VERSION_1301:
5826 sp->pfs_1301.state_flags = st->state_flags;
5827 sp->pfs_1301.direction = st->direction;
5828 sp->pfs_1301.log = st->act.log;
5829 sp->pfs_1301.timeout = st->timeout;
5830 sp->pfs_1301.proto = st->key[PF_SK_WIRE]->proto;
5831 sp->pfs_1301.af = st->key[PF_SK_WIRE]->af;
5832 /*
5833 * XXX Why do we bother pfsyncing source node information if source
5834 * nodes are not synced? Showing users that there is source tracking
5835 * when there is none seems useless.
5836 */
5837 if (st->sns[PF_SN_LIMIT] != NULL)
5838 sp->pfs_1301.sync_flags |= PFSYNC_FLAG_SRCNODE;
5839 if (st->sns[PF_SN_NAT] != NULL || st->sns[PF_SN_ROUTE])
5840 sp->pfs_1301.sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5841 break;
5842 case PFSYNC_MSG_VERSION_1400:
5843 sp->pfs_1400.state_flags = htons(st->state_flags);
5844 sp->pfs_1400.direction = st->direction;
5845 sp->pfs_1400.log = st->act.log;
5846 sp->pfs_1400.timeout = st->timeout;
5847 sp->pfs_1400.proto = st->key[PF_SK_WIRE]->proto;
5848 sp->pfs_1400.af = st->key[PF_SK_WIRE]->af;
5849 sp->pfs_1400.qid = htons(st->act.qid);
5850 sp->pfs_1400.pqid = htons(st->act.pqid);
5851 sp->pfs_1400.dnpipe = htons(st->act.dnpipe);
5852 sp->pfs_1400.dnrpipe = htons(st->act.dnrpipe);
5853 sp->pfs_1400.rtableid = htonl(st->act.rtableid);
5854 sp->pfs_1400.min_ttl = st->act.min_ttl;
5855 sp->pfs_1400.set_tos = st->act.set_tos;
5856 sp->pfs_1400.max_mss = htons(st->act.max_mss);
5857 sp->pfs_1400.set_prio[0] = st->act.set_prio[0];
5858 sp->pfs_1400.set_prio[1] = st->act.set_prio[1];
5859 sp->pfs_1400.rt = st->act.rt;
5860 if (st->act.rt_kif)
5861 strlcpy(sp->pfs_1400.rt_ifname,
5862 st->act.rt_kif->pfik_name,
5863 sizeof(sp->pfs_1400.rt_ifname));
5864 /*
5865 * XXX Why do we bother pfsyncing source node information if source
5866 * nodes are not synced? Showing users that there is source tracking
5867 * when there is none seems useless.
5868 */
5869 if (st->sns[PF_SN_LIMIT] != NULL)
5870 sp->pfs_1400.sync_flags |= PFSYNC_FLAG_SRCNODE;
5871 if (st->sns[PF_SN_NAT] != NULL || st->sns[PF_SN_ROUTE])
5872 sp->pfs_1400.sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5873 break;
5874 case PFSYNC_MSG_VERSION_1500:
5875 sp->pfs_1500.state_flags = htons(st->state_flags);
5876 sp->pfs_1500.direction = st->direction;
5877 sp->pfs_1500.log = st->act.log;
5878 sp->pfs_1500.timeout = st->timeout;
5879 sp->pfs_1500.wire_proto = st->key[PF_SK_WIRE]->proto;
5880 sp->pfs_1500.wire_af = st->key[PF_SK_WIRE]->af;
5881 sp->pfs_1500.stack_proto = st->key[PF_SK_STACK]->proto;
5882 sp->pfs_1500.stack_af = st->key[PF_SK_STACK]->af;
5883 sp->pfs_1500.qid = htons(st->act.qid);
5884 sp->pfs_1500.pqid = htons(st->act.pqid);
5885 sp->pfs_1500.dnpipe = htons(st->act.dnpipe);
5886 sp->pfs_1500.dnrpipe = htons(st->act.dnrpipe);
5887 sp->pfs_1500.rtableid = htonl(st->act.rtableid);
5888 sp->pfs_1500.min_ttl = st->act.min_ttl;
5889 sp->pfs_1500.set_tos = st->act.set_tos;
5890 sp->pfs_1500.max_mss = htons(st->act.max_mss);
5891 sp->pfs_1500.set_prio[0] = st->act.set_prio[0];
5892 sp->pfs_1500.set_prio[1] = st->act.set_prio[1];
5893 sp->pfs_1500.rt = st->act.rt;
5894 sp->pfs_1500.rt_af = st->act.rt_af;
5895 if (st->act.rt_kif)
5896 strlcpy(sp->pfs_1500.rt_ifname,
5897 st->act.rt_kif->pfik_name,
5898 sizeof(sp->pfs_1500.rt_ifname));
5899 strlcpy(sp->pfs_1500.orig_ifname,
5900 st->orig_kif->pfik_name,
5901 sizeof(sp->pfs_1500.orig_ifname));
5902 if ((tagname = pf_tag2tagname(st->tag)) != NULL)
5903 strlcpy(sp->pfs_1500.tagname, tagname,
5904 sizeof(sp->pfs_1500.tagname));
5905 break;
5906 default:
5907 panic("%s: Unsupported pfsync_msg_version %d",
5908 __func__, msg_version);
5909 }
5910
5911 sp->pfs_1301.id = st->id;
5912 sp->pfs_1301.creatorid = st->creatorid;
5913 pf_state_peer_hton(&st->src, &sp->pfs_1301.src);
5914 pf_state_peer_hton(&st->dst, &sp->pfs_1301.dst);
5915
5916 if (st->rule == NULL)
5917 sp->pfs_1301.rule = htonl(-1);
5918 else
5919 sp->pfs_1301.rule = htonl(st->rule->nr);
5920 if (st->anchor == NULL)
5921 sp->pfs_1301.anchor = htonl(-1);
5922 else
5923 sp->pfs_1301.anchor = htonl(st->anchor->nr);
5924 if (st->nat_rule == NULL)
5925 sp->pfs_1301.nat_rule = htonl(-1);
5926 else
5927 sp->pfs_1301.nat_rule = htonl(st->nat_rule->nr);
5928
5929 pf_state_counter_hton(st->packets[0], sp->pfs_1301.packets[0]);
5930 pf_state_counter_hton(st->packets[1], sp->pfs_1301.packets[1]);
5931 pf_state_counter_hton(st->bytes[0], sp->pfs_1301.bytes[0]);
5932 pf_state_counter_hton(st->bytes[1], sp->pfs_1301.bytes[1]);
5933 }
5934
5935 void
pf_state_export(struct pf_state_export * sp,struct pf_kstate * st)5936 pf_state_export(struct pf_state_export *sp, struct pf_kstate *st)
5937 {
5938 bzero(sp, sizeof(*sp));
5939
5940 sp->version = PF_STATE_VERSION;
5941
5942 /* copy from state key */
5943 sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
5944 sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
5945 sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
5946 sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
5947 sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
5948 sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
5949 sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
5950 sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
5951 sp->proto = st->key[PF_SK_WIRE]->proto;
5952 sp->af = st->key[PF_SK_WIRE]->af;
5953
5954 /* copy from state */
5955 strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
5956 strlcpy(sp->orig_ifname, st->orig_kif->pfik_name,
5957 sizeof(sp->orig_ifname));
5958 memcpy(&sp->rt_addr, &st->act.rt_addr, sizeof(sp->rt_addr));
5959 sp->creation = htonl(time_uptime - (st->creation / 1000));
5960 sp->expire = pf_state_expires(st);
5961 if (sp->expire <= time_uptime)
5962 sp->expire = htonl(0);
5963 else
5964 sp->expire = htonl(sp->expire - time_uptime);
5965
5966 sp->direction = st->direction;
5967 sp->log = st->act.log;
5968 sp->timeout = st->timeout;
5969 /* 8 bits for the old libpfctl, 16 bits for the new libpfctl */
5970 sp->state_flags_compat = st->state_flags;
5971 sp->state_flags = htons(st->state_flags);
5972 if (st->sns[PF_SN_LIMIT] != NULL)
5973 sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
5974 if (st->sns[PF_SN_NAT] != NULL || st->sns[PF_SN_ROUTE] != NULL)
5975 sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5976 sp->id = st->id;
5977 sp->creatorid = st->creatorid;
5978 pf_state_peer_hton(&st->src, &sp->src);
5979 pf_state_peer_hton(&st->dst, &sp->dst);
5980
5981 if (st->rule == NULL)
5982 sp->rule = htonl(-1);
5983 else
5984 sp->rule = htonl(st->rule->nr);
5985 if (st->anchor == NULL)
5986 sp->anchor = htonl(-1);
5987 else
5988 sp->anchor = htonl(st->anchor->nr);
5989 if (st->nat_rule == NULL)
5990 sp->nat_rule = htonl(-1);
5991 else
5992 sp->nat_rule = htonl(st->nat_rule->nr);
5993
5994 sp->packets[0] = st->packets[0];
5995 sp->packets[1] = st->packets[1];
5996 sp->bytes[0] = st->bytes[0];
5997 sp->bytes[1] = st->bytes[1];
5998
5999 sp->qid = htons(st->act.qid);
6000 sp->pqid = htons(st->act.pqid);
6001 sp->dnpipe = htons(st->act.dnpipe);
6002 sp->dnrpipe = htons(st->act.dnrpipe);
6003 sp->rtableid = htonl(st->act.rtableid);
6004 sp->min_ttl = st->act.min_ttl;
6005 sp->set_tos = st->act.set_tos;
6006 sp->max_mss = htons(st->act.max_mss);
6007 sp->rt = st->act.rt;
6008 if (st->act.rt_kif)
6009 strlcpy(sp->rt_ifname, st->act.rt_kif->pfik_name,
6010 sizeof(sp->rt_ifname));
6011 sp->set_prio[0] = st->act.set_prio[0];
6012 sp->set_prio[1] = st->act.set_prio[1];
6013
6014 }
6015
6016 static void
pf_tbladdr_copyout(struct pf_addr_wrap * aw)6017 pf_tbladdr_copyout(struct pf_addr_wrap *aw)
6018 {
6019 struct pfr_ktable *kt;
6020
6021 KASSERT(aw->type == PF_ADDR_TABLE, ("%s: type %u", __func__, aw->type));
6022
6023 kt = aw->p.tbl;
6024 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
6025 kt = kt->pfrkt_root;
6026 aw->p.tbl = NULL;
6027 aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
6028 kt->pfrkt_cnt : -1;
6029 }
6030
6031 static int
pf_add_status_counters(nvlist_t * nvl,const char * name,counter_u64_t * counters,size_t number,char ** names)6032 pf_add_status_counters(nvlist_t *nvl, const char *name, counter_u64_t *counters,
6033 size_t number, char **names)
6034 {
6035 nvlist_t *nvc;
6036
6037 nvc = nvlist_create(0);
6038 if (nvc == NULL)
6039 return (ENOMEM);
6040
6041 for (int i = 0; i < number; i++) {
6042 nvlist_append_number_array(nvc, "counters",
6043 counter_u64_fetch(counters[i]));
6044 nvlist_append_string_array(nvc, "names",
6045 names[i]);
6046 nvlist_append_number_array(nvc, "ids",
6047 i);
6048 }
6049 nvlist_add_nvlist(nvl, name, nvc);
6050 nvlist_destroy(nvc);
6051
6052 return (0);
6053 }
6054
6055 static int
pf_getstatus(struct pfioc_nv * nv)6056 pf_getstatus(struct pfioc_nv *nv)
6057 {
6058 nvlist_t *nvl = NULL, *nvc = NULL;
6059 void *nvlpacked = NULL;
6060 int error;
6061 struct pf_status s;
6062 char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
6063 char *pf_lcounter[KLCNT_MAX+1] = KLCNT_NAMES;
6064 char *pf_fcounter[FCNT_MAX+1] = FCNT_NAMES;
6065 time_t since;
6066
6067 PF_RULES_RLOCK_TRACKER;
6068
6069 #define ERROUT(x) ERROUT_FUNCTION(errout, x)
6070
6071 PF_RULES_RLOCK();
6072
6073 nvl = nvlist_create(0);
6074 if (nvl == NULL)
6075 ERROUT(ENOMEM);
6076
6077 since = time_second - (time_uptime - V_pf_status.since);
6078
6079 nvlist_add_bool(nvl, "running", V_pf_status.running);
6080 nvlist_add_number(nvl, "since", since);
6081 nvlist_add_number(nvl, "debug", V_pf_status.debug);
6082 nvlist_add_number(nvl, "hostid", V_pf_status.hostid);
6083 nvlist_add_number(nvl, "states", V_pf_status.states);
6084 nvlist_add_number(nvl, "src_nodes", V_pf_status.src_nodes);
6085 nvlist_add_number(nvl, "reass", V_pf_status.reass);
6086 nvlist_add_bool(nvl, "syncookies_active",
6087 V_pf_status.syncookies_active);
6088 nvlist_add_number(nvl, "halfopen_states", V_pf_status.states_halfopen);
6089
6090 /* counters */
6091 error = pf_add_status_counters(nvl, "counters", V_pf_status.counters,
6092 PFRES_MAX, pf_reasons);
6093 if (error != 0)
6094 ERROUT(error);
6095
6096 /* lcounters */
6097 error = pf_add_status_counters(nvl, "lcounters", V_pf_status.lcounters,
6098 KLCNT_MAX, pf_lcounter);
6099 if (error != 0)
6100 ERROUT(error);
6101
6102 /* fcounters */
6103 nvc = nvlist_create(0);
6104 if (nvc == NULL)
6105 ERROUT(ENOMEM);
6106
6107 for (int i = 0; i < FCNT_MAX; i++) {
6108 nvlist_append_number_array(nvc, "counters",
6109 pf_counter_u64_fetch(&V_pf_status.fcounters[i]));
6110 nvlist_append_string_array(nvc, "names",
6111 pf_fcounter[i]);
6112 nvlist_append_number_array(nvc, "ids",
6113 i);
6114 }
6115 nvlist_add_nvlist(nvl, "fcounters", nvc);
6116 nvlist_destroy(nvc);
6117 nvc = NULL;
6118
6119 /* scounters */
6120 error = pf_add_status_counters(nvl, "scounters", V_pf_status.scounters,
6121 SCNT_MAX, pf_fcounter);
6122 if (error != 0)
6123 ERROUT(error);
6124
6125 nvlist_add_string(nvl, "ifname", V_pf_status.ifname);
6126 nvlist_add_binary(nvl, "chksum", V_pf_status.pf_chksum,
6127 PF_MD5_DIGEST_LENGTH);
6128
6129 pfi_update_status(V_pf_status.ifname, &s);
6130
6131 /* pcounters / bcounters */
6132 for (int i = 0; i < 2; i++) {
6133 for (int j = 0; j < 2; j++) {
6134 for (int k = 0; k < 2; k++) {
6135 nvlist_append_number_array(nvl, "pcounters",
6136 s.pcounters[i][j][k]);
6137 }
6138 nvlist_append_number_array(nvl, "bcounters",
6139 s.bcounters[i][j]);
6140 }
6141 }
6142
6143 nvlpacked = nvlist_pack(nvl, &nv->len);
6144 if (nvlpacked == NULL)
6145 ERROUT(ENOMEM);
6146
6147 if (nv->size == 0)
6148 ERROUT(0);
6149 else if (nv->size < nv->len)
6150 ERROUT(ENOSPC);
6151
6152 PF_RULES_RUNLOCK();
6153 error = copyout(nvlpacked, nv->data, nv->len);
6154 goto done;
6155
6156 #undef ERROUT
6157 errout:
6158 PF_RULES_RUNLOCK();
6159 done:
6160 free(nvlpacked, M_NVLIST);
6161 nvlist_destroy(nvc);
6162 nvlist_destroy(nvl);
6163
6164 return (error);
6165 }
6166
6167 /*
6168 * XXX - Check for version mismatch!!!
6169 */
6170 static void
pf_clear_all_states(void)6171 pf_clear_all_states(void)
6172 {
6173 struct epoch_tracker et;
6174 struct pf_kstate *s;
6175 u_int i;
6176
6177 NET_EPOCH_ENTER(et);
6178 for (i = 0; i <= V_pf_hashmask; i++) {
6179 struct pf_idhash *ih = &V_pf_idhash[i];
6180 relock:
6181 PF_HASHROW_LOCK(ih);
6182 LIST_FOREACH(s, &ih->states, entry) {
6183 s->timeout = PFTM_PURGE;
6184 /* Don't send out individual delete messages. */
6185 s->state_flags |= PFSTATE_NOSYNC;
6186 pf_remove_state(s);
6187 goto relock;
6188 }
6189 PF_HASHROW_UNLOCK(ih);
6190 }
6191 NET_EPOCH_EXIT(et);
6192 }
6193
6194 static int
pf_clear_tables(void)6195 pf_clear_tables(void)
6196 {
6197 struct pfioc_table io;
6198 int error;
6199
6200 bzero(&io, sizeof(io));
6201 io.pfrio_flags |= PFR_FLAG_ALLRSETS;
6202
6203 error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel,
6204 io.pfrio_flags);
6205
6206 return (error);
6207 }
6208
6209 static void
pf_kill_srcnodes(struct pfioc_src_node_kill * psnk)6210 pf_kill_srcnodes(struct pfioc_src_node_kill *psnk)
6211 {
6212 struct pf_ksrc_node_list kill;
6213 u_int killed;
6214
6215 LIST_INIT(&kill);
6216 for (int i = 0; i <= V_pf_srchashmask; i++) {
6217 struct pf_srchash *sh = &V_pf_srchash[i];
6218 struct pf_ksrc_node *sn, *tmp;
6219
6220 PF_HASHROW_LOCK(sh);
6221 LIST_FOREACH_SAFE(sn, &sh->nodes, entry, tmp)
6222 if (psnk == NULL ||
6223 (pf_match_addr(psnk->psnk_src.neg,
6224 &psnk->psnk_src.addr.v.a.addr,
6225 &psnk->psnk_src.addr.v.a.mask,
6226 &sn->addr, sn->af) &&
6227 pf_match_addr(psnk->psnk_dst.neg,
6228 &psnk->psnk_dst.addr.v.a.addr,
6229 &psnk->psnk_dst.addr.v.a.mask,
6230 &sn->raddr, sn->af))) {
6231 pf_unlink_src_node(sn);
6232 LIST_INSERT_HEAD(&kill, sn, entry);
6233 sn->expire = 1;
6234 }
6235 PF_HASHROW_UNLOCK(sh);
6236 }
6237
6238 for (int i = 0; i <= V_pf_hashmask; i++) {
6239 struct pf_idhash *ih = &V_pf_idhash[i];
6240 struct pf_kstate *s;
6241
6242 PF_HASHROW_LOCK(ih);
6243 LIST_FOREACH(s, &ih->states, entry) {
6244 for(pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX;
6245 sn_type++) {
6246 if (s->sns[sn_type] &&
6247 s->sns[sn_type]->expire == 1) {
6248 s->sns[sn_type] = NULL;
6249 }
6250 }
6251 }
6252 PF_HASHROW_UNLOCK(ih);
6253 }
6254
6255 killed = pf_free_src_nodes(&kill);
6256
6257 if (psnk != NULL)
6258 psnk->psnk_killed = killed;
6259 }
6260
6261 static int
pf_keepcounters(struct pfioc_nv * nv)6262 pf_keepcounters(struct pfioc_nv *nv)
6263 {
6264 nvlist_t *nvl = NULL;
6265 void *nvlpacked = NULL;
6266 int error = 0;
6267
6268 #define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6269
6270 if (nv->len > pf_ioctl_maxcount)
6271 ERROUT(ENOMEM);
6272
6273 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6274 error = copyin(nv->data, nvlpacked, nv->len);
6275 if (error)
6276 ERROUT(error);
6277
6278 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6279 if (nvl == NULL)
6280 ERROUT(EBADMSG);
6281
6282 if (! nvlist_exists_bool(nvl, "keep_counters"))
6283 ERROUT(EBADMSG);
6284
6285 V_pf_status.keep_counters = nvlist_get_bool(nvl, "keep_counters");
6286
6287 on_error:
6288 nvlist_destroy(nvl);
6289 free(nvlpacked, M_NVLIST);
6290 return (error);
6291 }
6292
6293 unsigned int
pf_clear_states(const struct pf_kstate_kill * kill)6294 pf_clear_states(const struct pf_kstate_kill *kill)
6295 {
6296 struct pf_state_key_cmp match_key;
6297 struct pf_kstate *s;
6298 struct pfi_kkif *kif;
6299 int idx;
6300 unsigned int killed = 0, dir;
6301
6302 NET_EPOCH_ASSERT();
6303
6304 for (unsigned int i = 0; i <= V_pf_hashmask; i++) {
6305 struct pf_idhash *ih = &V_pf_idhash[i];
6306
6307 relock_DIOCCLRSTATES:
6308 PF_HASHROW_LOCK(ih);
6309 LIST_FOREACH(s, &ih->states, entry) {
6310 /* For floating states look at the original kif. */
6311 kif = s->kif == V_pfi_all ? s->orig_kif : s->kif;
6312
6313 if (kill->psk_ifname[0] &&
6314 strcmp(kill->psk_ifname,
6315 kif->pfik_name))
6316 continue;
6317
6318 if (kill->psk_kill_match) {
6319 bzero(&match_key, sizeof(match_key));
6320
6321 if (s->direction == PF_OUT) {
6322 dir = PF_IN;
6323 idx = PF_SK_STACK;
6324 } else {
6325 dir = PF_OUT;
6326 idx = PF_SK_WIRE;
6327 }
6328
6329 match_key.af = s->key[idx]->af;
6330 match_key.proto = s->key[idx]->proto;
6331 pf_addrcpy(&match_key.addr[0],
6332 &s->key[idx]->addr[1], match_key.af);
6333 match_key.port[0] = s->key[idx]->port[1];
6334 pf_addrcpy(&match_key.addr[1],
6335 &s->key[idx]->addr[0], match_key.af);
6336 match_key.port[1] = s->key[idx]->port[0];
6337 }
6338
6339 /*
6340 * Don't send out individual
6341 * delete messages.
6342 */
6343 s->state_flags |= PFSTATE_NOSYNC;
6344 pf_remove_state(s);
6345 killed++;
6346
6347 if (kill->psk_kill_match)
6348 killed += pf_kill_matching_state(&match_key,
6349 dir);
6350
6351 goto relock_DIOCCLRSTATES;
6352 }
6353 PF_HASHROW_UNLOCK(ih);
6354 }
6355
6356 if (V_pfsync_clear_states_ptr != NULL)
6357 V_pfsync_clear_states_ptr(V_pf_status.hostid, kill->psk_ifname);
6358
6359 return (killed);
6360 }
6361
6362 void
pf_killstates(struct pf_kstate_kill * kill,unsigned int * killed)6363 pf_killstates(struct pf_kstate_kill *kill, unsigned int *killed)
6364 {
6365 struct pf_kstate *s;
6366
6367 NET_EPOCH_ASSERT();
6368 if (kill->psk_pfcmp.id) {
6369 if (kill->psk_pfcmp.creatorid == 0)
6370 kill->psk_pfcmp.creatorid = V_pf_status.hostid;
6371 if ((s = pf_find_state_byid(kill->psk_pfcmp.id,
6372 kill->psk_pfcmp.creatorid))) {
6373 pf_remove_state(s);
6374 *killed = 1;
6375 }
6376 return;
6377 }
6378
6379 for (unsigned int i = 0; i <= V_pf_hashmask; i++)
6380 *killed += pf_killstates_row(kill, &V_pf_idhash[i]);
6381 }
6382
6383 static int
pf_killstates_nv(struct pfioc_nv * nv)6384 pf_killstates_nv(struct pfioc_nv *nv)
6385 {
6386 struct pf_kstate_kill kill;
6387 struct epoch_tracker et;
6388 nvlist_t *nvl = NULL;
6389 void *nvlpacked = NULL;
6390 int error = 0;
6391 unsigned int killed = 0;
6392
6393 #define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6394
6395 if (nv->len > pf_ioctl_maxcount)
6396 ERROUT(ENOMEM);
6397
6398 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6399 error = copyin(nv->data, nvlpacked, nv->len);
6400 if (error)
6401 ERROUT(error);
6402
6403 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6404 if (nvl == NULL)
6405 ERROUT(EBADMSG);
6406
6407 error = pf_nvstate_kill_to_kstate_kill(nvl, &kill);
6408 if (error)
6409 ERROUT(error);
6410
6411 NET_EPOCH_ENTER(et);
6412 pf_killstates(&kill, &killed);
6413 NET_EPOCH_EXIT(et);
6414
6415 free(nvlpacked, M_NVLIST);
6416 nvlpacked = NULL;
6417 nvlist_destroy(nvl);
6418 nvl = nvlist_create(0);
6419 if (nvl == NULL)
6420 ERROUT(ENOMEM);
6421
6422 nvlist_add_number(nvl, "killed", killed);
6423
6424 nvlpacked = nvlist_pack(nvl, &nv->len);
6425 if (nvlpacked == NULL)
6426 ERROUT(ENOMEM);
6427
6428 if (nv->size == 0)
6429 ERROUT(0);
6430 else if (nv->size < nv->len)
6431 ERROUT(ENOSPC);
6432
6433 error = copyout(nvlpacked, nv->data, nv->len);
6434
6435 on_error:
6436 nvlist_destroy(nvl);
6437 free(nvlpacked, M_NVLIST);
6438 return (error);
6439 }
6440
6441 static int
pf_clearstates_nv(struct pfioc_nv * nv)6442 pf_clearstates_nv(struct pfioc_nv *nv)
6443 {
6444 struct pf_kstate_kill kill;
6445 struct epoch_tracker et;
6446 nvlist_t *nvl = NULL;
6447 void *nvlpacked = NULL;
6448 int error = 0;
6449 unsigned int killed;
6450
6451 #define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6452
6453 if (nv->len > pf_ioctl_maxcount)
6454 ERROUT(ENOMEM);
6455
6456 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6457 error = copyin(nv->data, nvlpacked, nv->len);
6458 if (error)
6459 ERROUT(error);
6460
6461 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6462 if (nvl == NULL)
6463 ERROUT(EBADMSG);
6464
6465 error = pf_nvstate_kill_to_kstate_kill(nvl, &kill);
6466 if (error)
6467 ERROUT(error);
6468
6469 NET_EPOCH_ENTER(et);
6470 killed = pf_clear_states(&kill);
6471 NET_EPOCH_EXIT(et);
6472
6473 free(nvlpacked, M_NVLIST);
6474 nvlpacked = NULL;
6475 nvlist_destroy(nvl);
6476 nvl = nvlist_create(0);
6477 if (nvl == NULL)
6478 ERROUT(ENOMEM);
6479
6480 nvlist_add_number(nvl, "killed", killed);
6481
6482 nvlpacked = nvlist_pack(nvl, &nv->len);
6483 if (nvlpacked == NULL)
6484 ERROUT(ENOMEM);
6485
6486 if (nv->size == 0)
6487 ERROUT(0);
6488 else if (nv->size < nv->len)
6489 ERROUT(ENOSPC);
6490
6491 error = copyout(nvlpacked, nv->data, nv->len);
6492
6493 #undef ERROUT
6494 on_error:
6495 nvlist_destroy(nvl);
6496 free(nvlpacked, M_NVLIST);
6497 return (error);
6498 }
6499
6500 static int
pf_getstate(struct pfioc_nv * nv)6501 pf_getstate(struct pfioc_nv *nv)
6502 {
6503 nvlist_t *nvl = NULL, *nvls;
6504 void *nvlpacked = NULL;
6505 struct pf_kstate *s = NULL;
6506 int error = 0;
6507 uint64_t id, creatorid;
6508
6509 #define ERROUT(x) ERROUT_FUNCTION(errout, x)
6510
6511 if (nv->len > pf_ioctl_maxcount)
6512 ERROUT(ENOMEM);
6513
6514 nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6515 error = copyin(nv->data, nvlpacked, nv->len);
6516 if (error)
6517 ERROUT(error);
6518
6519 nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6520 if (nvl == NULL)
6521 ERROUT(EBADMSG);
6522
6523 PFNV_CHK(pf_nvuint64(nvl, "id", &id));
6524 PFNV_CHK(pf_nvuint64(nvl, "creatorid", &creatorid));
6525
6526 s = pf_find_state_byid(id, creatorid);
6527 if (s == NULL)
6528 ERROUT(ENOENT);
6529
6530 free(nvlpacked, M_NVLIST);
6531 nvlpacked = NULL;
6532 nvlist_destroy(nvl);
6533 nvl = nvlist_create(0);
6534 if (nvl == NULL)
6535 ERROUT(ENOMEM);
6536
6537 nvls = pf_state_to_nvstate(s);
6538 if (nvls == NULL)
6539 ERROUT(ENOMEM);
6540
6541 nvlist_add_nvlist(nvl, "state", nvls);
6542 nvlist_destroy(nvls);
6543
6544 nvlpacked = nvlist_pack(nvl, &nv->len);
6545 if (nvlpacked == NULL)
6546 ERROUT(ENOMEM);
6547
6548 if (nv->size == 0)
6549 ERROUT(0);
6550 else if (nv->size < nv->len)
6551 ERROUT(ENOSPC);
6552
6553 error = copyout(nvlpacked, nv->data, nv->len);
6554
6555 #undef ERROUT
6556 errout:
6557 if (s != NULL)
6558 PF_STATE_UNLOCK(s);
6559 free(nvlpacked, M_NVLIST);
6560 nvlist_destroy(nvl);
6561 return (error);
6562 }
6563
6564 /*
6565 * XXX - Check for version mismatch!!!
6566 */
6567
6568 /*
6569 * Duplicate pfctl -Fa operation to get rid of as much as we can.
6570 */
6571 static int
shutdown_pf(void)6572 shutdown_pf(void)
6573 {
6574 int error = 0;
6575 u_int32_t t[5];
6576 char nn = '\0';
6577 struct pf_kanchor *anchor, *tmp_anchor;
6578 struct pf_keth_anchor *eth_anchor, *tmp_eth_anchor;
6579 int rs_num;
6580
6581 do {
6582 /* Unlink rules of all user defined anchors */
6583 RB_FOREACH_SAFE(anchor, pf_kanchor_global, &V_pf_anchors,
6584 tmp_anchor) {
6585 for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
6586 if ((error = pf_begin_rules(&t[rs_num], rs_num,
6587 anchor->path)) != 0) {
6588 DPFPRINTF(PF_DEBUG_MISC, "%s: "
6589 "anchor.path=%s rs_num=%d",
6590 __func__, anchor->path, rs_num);
6591 goto error; /* XXX: rollback? */
6592 }
6593 }
6594 for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
6595 error = pf_commit_rules(t[rs_num], rs_num,
6596 anchor->path);
6597 MPASS(error == 0);
6598 }
6599 }
6600
6601 /* Unlink rules of all user defined ether anchors */
6602 RB_FOREACH_SAFE(eth_anchor, pf_keth_anchor_global,
6603 &V_pf_keth_anchors, tmp_eth_anchor) {
6604 if ((error = pf_begin_eth(&t[0], eth_anchor->path))
6605 != 0) {
6606 DPFPRINTF(PF_DEBUG_MISC, "%s: eth "
6607 "anchor.path=%s", __func__,
6608 eth_anchor->path);
6609 goto error;
6610 }
6611 error = pf_commit_eth(t[0], eth_anchor->path);
6612 MPASS(error == 0);
6613 }
6614
6615 if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
6616 != 0) {
6617 DPFPRINTF(PF_DEBUG_MISC, "%s: SCRUB", __func__);
6618 break;
6619 }
6620 if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn))
6621 != 0) {
6622 DPFPRINTF(PF_DEBUG_MISC, "%s: FILTER", __func__);
6623 break; /* XXX: rollback? */
6624 }
6625 if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn))
6626 != 0) {
6627 DPFPRINTF(PF_DEBUG_MISC, "%s: NAT", __func__);
6628 break; /* XXX: rollback? */
6629 }
6630 if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn))
6631 != 0) {
6632 DPFPRINTF(PF_DEBUG_MISC, "%s: BINAT", __func__);
6633 break; /* XXX: rollback? */
6634 }
6635 if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn))
6636 != 0) {
6637 DPFPRINTF(PF_DEBUG_MISC, "%s: RDR", __func__);
6638 break; /* XXX: rollback? */
6639 }
6640
6641 error = pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn);
6642 MPASS(error == 0);
6643 error = pf_commit_rules(t[1], PF_RULESET_FILTER, &nn);
6644 MPASS(error == 0);
6645 error = pf_commit_rules(t[2], PF_RULESET_NAT, &nn);
6646 MPASS(error == 0);
6647 error = pf_commit_rules(t[3], PF_RULESET_BINAT, &nn);
6648 MPASS(error == 0);
6649 error = pf_commit_rules(t[4], PF_RULESET_RDR, &nn);
6650 MPASS(error == 0);
6651
6652 if ((error = pf_clear_tables()) != 0)
6653 break;
6654
6655 if ((error = pf_begin_eth(&t[0], &nn)) != 0) {
6656 DPFPRINTF(PF_DEBUG_MISC, "%s: eth", __func__);
6657 break;
6658 }
6659 error = pf_commit_eth(t[0], &nn);
6660 MPASS(error == 0);
6661
6662 #ifdef ALTQ
6663 if ((error = pf_begin_altq(&t[0])) != 0) {
6664 DPFPRINTF(PF_DEBUG_MISC, "%s: ALTQ", __func__);
6665 break;
6666 }
6667 pf_commit_altq(t[0]);
6668 #endif
6669
6670 pf_clear_all_states();
6671
6672 pf_kill_srcnodes(NULL);
6673
6674 for (int i = 0; i < PF_RULESET_MAX; i++) {
6675 pf_rule_tree_free(pf_main_ruleset.rules[i].active.tree);
6676 pf_rule_tree_free(pf_main_ruleset.rules[i].inactive.tree);
6677 }
6678
6679 /* status does not use malloced mem so no need to cleanup */
6680 /* fingerprints and interfaces have their own cleanup code */
6681 } while(0);
6682
6683 error:
6684 return (error);
6685 }
6686
6687 static pfil_return_t
pf_check_return(int chk,struct mbuf ** m)6688 pf_check_return(int chk, struct mbuf **m)
6689 {
6690
6691 switch (chk) {
6692 case PF_PASS:
6693 if (*m == NULL)
6694 return (PFIL_CONSUMED);
6695 else
6696 return (PFIL_PASS);
6697 break;
6698 default:
6699 if (*m != NULL) {
6700 m_freem(*m);
6701 *m = NULL;
6702 }
6703 return (PFIL_DROPPED);
6704 }
6705 }
6706
6707 static pfil_return_t
pf_eth_check_in(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6708 pf_eth_check_in(struct mbuf **m, struct ifnet *ifp, int flags,
6709 void *ruleset __unused, struct inpcb *inp)
6710 {
6711 int chk;
6712
6713 CURVNET_ASSERT_SET();
6714
6715 chk = pf_test_eth(PF_IN, flags, ifp, m, inp);
6716
6717 return (pf_check_return(chk, m));
6718 }
6719
6720 static pfil_return_t
pf_eth_check_out(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6721 pf_eth_check_out(struct mbuf **m, struct ifnet *ifp, int flags,
6722 void *ruleset __unused, struct inpcb *inp)
6723 {
6724 int chk;
6725
6726 CURVNET_ASSERT_SET();
6727
6728 chk = pf_test_eth(PF_OUT, flags, ifp, m, inp);
6729
6730 return (pf_check_return(chk, m));
6731 }
6732
6733 #ifdef INET
6734 static pfil_return_t
pf_check_in(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6735 pf_check_in(struct mbuf **m, struct ifnet *ifp, int flags,
6736 void *ruleset __unused, struct inpcb *inp)
6737 {
6738 int chk;
6739
6740 CURVNET_ASSERT_SET();
6741
6742 chk = pf_test(AF_INET, PF_IN, flags, ifp, m, inp, NULL);
6743
6744 return (pf_check_return(chk, m));
6745 }
6746
6747 static pfil_return_t
pf_check_out(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6748 pf_check_out(struct mbuf **m, struct ifnet *ifp, int flags,
6749 void *ruleset __unused, struct inpcb *inp)
6750 {
6751 int chk;
6752
6753 CURVNET_ASSERT_SET();
6754
6755 chk = pf_test(AF_INET, PF_OUT, flags, ifp, m, inp, NULL);
6756
6757 return (pf_check_return(chk, m));
6758 }
6759 #endif
6760
6761 #ifdef INET6
6762 static pfil_return_t
pf_check6_in(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6763 pf_check6_in(struct mbuf **m, struct ifnet *ifp, int flags,
6764 void *ruleset __unused, struct inpcb *inp)
6765 {
6766 int chk;
6767
6768 CURVNET_ASSERT_SET();
6769
6770 /*
6771 * In case of loopback traffic IPv6 uses the real interface in
6772 * order to support scoped addresses. In order to support stateful
6773 * filtering we have change this to lo0 as it is the case in IPv4.
6774 */
6775 chk = pf_test(AF_INET6, PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp,
6776 m, inp, NULL);
6777
6778 return (pf_check_return(chk, m));
6779 }
6780
6781 static pfil_return_t
pf_check6_out(struct mbuf ** m,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)6782 pf_check6_out(struct mbuf **m, struct ifnet *ifp, int flags,
6783 void *ruleset __unused, struct inpcb *inp)
6784 {
6785 int chk;
6786
6787 CURVNET_ASSERT_SET();
6788
6789 chk = pf_test(AF_INET6, PF_OUT, flags, ifp, m, inp, NULL);
6790
6791 return (pf_check_return(chk, m));
6792 }
6793 #endif /* INET6 */
6794
6795 VNET_DEFINE_STATIC(pfil_hook_t, pf_eth_in_hook);
6796 VNET_DEFINE_STATIC(pfil_hook_t, pf_eth_out_hook);
6797 #define V_pf_eth_in_hook VNET(pf_eth_in_hook)
6798 #define V_pf_eth_out_hook VNET(pf_eth_out_hook)
6799
6800 #ifdef INET
6801 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_in_hook);
6802 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_out_hook);
6803 #define V_pf_ip4_in_hook VNET(pf_ip4_in_hook)
6804 #define V_pf_ip4_out_hook VNET(pf_ip4_out_hook)
6805 #endif
6806 #ifdef INET6
6807 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_in_hook);
6808 VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_out_hook);
6809 #define V_pf_ip6_in_hook VNET(pf_ip6_in_hook)
6810 #define V_pf_ip6_out_hook VNET(pf_ip6_out_hook)
6811 #endif
6812
6813 static void
hook_pf_eth(void)6814 hook_pf_eth(void)
6815 {
6816 struct pfil_hook_args pha = {
6817 .pa_version = PFIL_VERSION,
6818 .pa_modname = "pf",
6819 .pa_type = PFIL_TYPE_ETHERNET,
6820 };
6821 struct pfil_link_args pla = {
6822 .pa_version = PFIL_VERSION,
6823 };
6824 int ret __diagused;
6825
6826 if (atomic_load_bool(&V_pf_pfil_eth_hooked))
6827 return;
6828
6829 pha.pa_mbuf_chk = pf_eth_check_in;
6830 pha.pa_flags = PFIL_IN;
6831 pha.pa_rulname = "eth-in";
6832 V_pf_eth_in_hook = pfil_add_hook(&pha);
6833 pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6834 pla.pa_head = V_link_pfil_head;
6835 pla.pa_hook = V_pf_eth_in_hook;
6836 ret = pfil_link(&pla);
6837 MPASS(ret == 0);
6838 pha.pa_mbuf_chk = pf_eth_check_out;
6839 pha.pa_flags = PFIL_OUT;
6840 pha.pa_rulname = "eth-out";
6841 V_pf_eth_out_hook = pfil_add_hook(&pha);
6842 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6843 pla.pa_head = V_link_pfil_head;
6844 pla.pa_hook = V_pf_eth_out_hook;
6845 ret = pfil_link(&pla);
6846 MPASS(ret == 0);
6847
6848 atomic_store_bool(&V_pf_pfil_eth_hooked, true);
6849 }
6850
6851 static void
hook_pf(void)6852 hook_pf(void)
6853 {
6854 struct pfil_hook_args pha = {
6855 .pa_version = PFIL_VERSION,
6856 .pa_modname = "pf",
6857 };
6858 struct pfil_link_args pla = {
6859 .pa_version = PFIL_VERSION,
6860 };
6861 int ret __diagused;
6862
6863 if (atomic_load_bool(&V_pf_pfil_hooked))
6864 return;
6865
6866 #ifdef INET
6867 pha.pa_type = PFIL_TYPE_IP4;
6868 pha.pa_mbuf_chk = pf_check_in;
6869 pha.pa_flags = PFIL_IN;
6870 pha.pa_rulname = "default-in";
6871 V_pf_ip4_in_hook = pfil_add_hook(&pha);
6872 pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6873 pla.pa_head = V_inet_pfil_head;
6874 pla.pa_hook = V_pf_ip4_in_hook;
6875 ret = pfil_link(&pla);
6876 MPASS(ret == 0);
6877 pha.pa_mbuf_chk = pf_check_out;
6878 pha.pa_flags = PFIL_OUT;
6879 pha.pa_rulname = "default-out";
6880 V_pf_ip4_out_hook = pfil_add_hook(&pha);
6881 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6882 pla.pa_head = V_inet_pfil_head;
6883 pla.pa_hook = V_pf_ip4_out_hook;
6884 ret = pfil_link(&pla);
6885 MPASS(ret == 0);
6886 if (V_pf_filter_local) {
6887 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6888 pla.pa_head = V_inet_local_pfil_head;
6889 pla.pa_hook = V_pf_ip4_out_hook;
6890 ret = pfil_link(&pla);
6891 MPASS(ret == 0);
6892 }
6893 #endif
6894 #ifdef INET6
6895 pha.pa_type = PFIL_TYPE_IP6;
6896 pha.pa_mbuf_chk = pf_check6_in;
6897 pha.pa_flags = PFIL_IN;
6898 pha.pa_rulname = "default-in6";
6899 V_pf_ip6_in_hook = pfil_add_hook(&pha);
6900 pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6901 pla.pa_head = V_inet6_pfil_head;
6902 pla.pa_hook = V_pf_ip6_in_hook;
6903 ret = pfil_link(&pla);
6904 MPASS(ret == 0);
6905 pha.pa_mbuf_chk = pf_check6_out;
6906 pha.pa_rulname = "default-out6";
6907 pha.pa_flags = PFIL_OUT;
6908 V_pf_ip6_out_hook = pfil_add_hook(&pha);
6909 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6910 pla.pa_head = V_inet6_pfil_head;
6911 pla.pa_hook = V_pf_ip6_out_hook;
6912 ret = pfil_link(&pla);
6913 MPASS(ret == 0);
6914 if (V_pf_filter_local) {
6915 pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6916 pla.pa_head = V_inet6_local_pfil_head;
6917 pla.pa_hook = V_pf_ip6_out_hook;
6918 ret = pfil_link(&pla);
6919 MPASS(ret == 0);
6920 }
6921 #endif
6922
6923 atomic_store_bool(&V_pf_pfil_hooked, true);
6924 }
6925
6926 static void
dehook_pf_eth(void)6927 dehook_pf_eth(void)
6928 {
6929
6930 if (!atomic_load_bool(&V_pf_pfil_eth_hooked))
6931 return;
6932
6933 pfil_remove_hook(V_pf_eth_in_hook);
6934 pfil_remove_hook(V_pf_eth_out_hook);
6935
6936 atomic_store_bool(&V_pf_pfil_eth_hooked, false);
6937 }
6938
6939 static void
dehook_pf(void)6940 dehook_pf(void)
6941 {
6942
6943 if (!atomic_load_bool(&V_pf_pfil_hooked))
6944 return;
6945
6946 #ifdef INET
6947 pfil_remove_hook(V_pf_ip4_in_hook);
6948 pfil_remove_hook(V_pf_ip4_out_hook);
6949 #endif
6950 #ifdef INET6
6951 pfil_remove_hook(V_pf_ip6_in_hook);
6952 pfil_remove_hook(V_pf_ip6_out_hook);
6953 #endif
6954
6955 atomic_store_bool(&V_pf_pfil_hooked, false);
6956 }
6957
6958 static void
pf_load_vnet(void)6959 pf_load_vnet(void)
6960 {
6961 V_pf_tag_z = uma_zcreate("pf tags", sizeof(struct pf_tagname),
6962 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
6963
6964 rm_init_flags(&V_pf_rules_lock, "pf rulesets", RM_RECURSE);
6965 rm_init_flags(&V_pf_tags_lock, "pf tags and queues", RM_RECURSE);
6966 sx_init(&V_pf_ioctl_lock, "pf ioctl");
6967
6968 pf_init_tagset(&V_pf_tags, &pf_rule_tag_hashsize,
6969 PF_RULE_TAG_HASH_SIZE_DEFAULT);
6970 #ifdef ALTQ
6971 pf_init_tagset(&V_pf_qids, &pf_queue_tag_hashsize,
6972 PF_QUEUE_TAG_HASH_SIZE_DEFAULT);
6973 #endif
6974
6975 V_pf_keth = &V_pf_main_keth_anchor.ruleset;
6976
6977 pfattach_vnet();
6978 V_pf_vnet_active = 1;
6979 }
6980
6981 static int
pf_load(void)6982 pf_load(void)
6983 {
6984 int error;
6985
6986 sx_init(&pf_end_lock, "pf end thread");
6987
6988 pf_mtag_initialize();
6989
6990 pf_dev = make_dev(&pf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, PF_NAME);
6991 if (pf_dev == NULL)
6992 return (ENOMEM);
6993
6994 pf_end_threads = 0;
6995 error = kproc_create(pf_purge_thread, NULL, &pf_purge_proc, 0, 0, "pf purge");
6996 if (error != 0)
6997 return (error);
6998
6999 pfi_initialize();
7000
7001 return (0);
7002 }
7003
7004 static void
pf_unload_vnet(void)7005 pf_unload_vnet(void)
7006 {
7007 int ret __diagused;
7008
7009 V_pf_vnet_active = 0;
7010 V_pf_status.running = 0;
7011 dehook_pf();
7012 dehook_pf_eth();
7013
7014 PF_RULES_WLOCK();
7015 pf_syncookies_cleanup();
7016 shutdown_pf();
7017 PF_RULES_WUNLOCK();
7018
7019 ret = swi_remove(V_pf_swi_cookie);
7020 MPASS(ret == 0);
7021 ret = intr_event_destroy(V_pf_swi_ie);
7022 MPASS(ret == 0);
7023
7024 pf_unload_vnet_purge();
7025
7026 pf_normalize_cleanup();
7027 PF_RULES_WLOCK();
7028 pfi_cleanup_vnet();
7029 PF_RULES_WUNLOCK();
7030 pfr_cleanup();
7031 pf_osfp_flush();
7032 pf_cleanup();
7033 if (IS_DEFAULT_VNET(curvnet))
7034 pf_mtag_cleanup();
7035
7036 pf_cleanup_tagset(&V_pf_tags);
7037 #ifdef ALTQ
7038 pf_cleanup_tagset(&V_pf_qids);
7039 #endif
7040 uma_zdestroy(V_pf_tag_z);
7041
7042 #ifdef PF_WANT_32_TO_64_COUNTER
7043 PF_RULES_WLOCK();
7044 LIST_REMOVE(V_pf_kifmarker, pfik_allkiflist);
7045
7046 MPASS(LIST_EMPTY(&V_pf_allkiflist));
7047 MPASS(V_pf_allkifcount == 0);
7048
7049 LIST_REMOVE(&V_pf_default_rule, allrulelist);
7050 V_pf_allrulecount--;
7051 LIST_REMOVE(V_pf_rulemarker, allrulelist);
7052
7053 MPASS(LIST_EMPTY(&V_pf_allrulelist));
7054 MPASS(V_pf_allrulecount == 0);
7055
7056 PF_RULES_WUNLOCK();
7057
7058 free(V_pf_kifmarker, PFI_MTYPE);
7059 free(V_pf_rulemarker, M_PFRULE);
7060 #endif
7061
7062 /* Free counters last as we updated them during shutdown. */
7063 pf_counter_u64_deinit(&V_pf_default_rule.evaluations);
7064 for (int i = 0; i < 2; i++) {
7065 pf_counter_u64_deinit(&V_pf_default_rule.packets[i]);
7066 pf_counter_u64_deinit(&V_pf_default_rule.bytes[i]);
7067 }
7068 counter_u64_free(V_pf_default_rule.states_cur);
7069 counter_u64_free(V_pf_default_rule.states_tot);
7070 for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
7071 counter_u64_free(V_pf_default_rule.src_nodes[sn_type]);
7072 uma_zfree_pcpu(pf_timestamp_pcpu_zone, V_pf_default_rule.timestamp);
7073
7074 for (int i = 0; i < PFRES_MAX; i++)
7075 counter_u64_free(V_pf_status.counters[i]);
7076 for (int i = 0; i < KLCNT_MAX; i++)
7077 counter_u64_free(V_pf_status.lcounters[i]);
7078 for (int i = 0; i < FCNT_MAX; i++)
7079 pf_counter_u64_deinit(&V_pf_status.fcounters[i]);
7080 for (int i = 0; i < SCNT_MAX; i++)
7081 counter_u64_free(V_pf_status.scounters[i]);
7082 for (int i = 0; i < NCNT_MAX; i++)
7083 counter_u64_free(V_pf_status.ncounters[i]);
7084
7085 rm_destroy(&V_pf_rules_lock);
7086 sx_destroy(&V_pf_ioctl_lock);
7087 }
7088
7089 static void
pf_unload(void * dummy __unused)7090 pf_unload(void *dummy __unused)
7091 {
7092
7093 sx_xlock(&pf_end_lock);
7094 pf_end_threads = 1;
7095 while (pf_end_threads < 2) {
7096 wakeup_one(pf_purge_thread);
7097 sx_sleep(pf_purge_proc, &pf_end_lock, 0, "pftmo", 0);
7098 }
7099 sx_xunlock(&pf_end_lock);
7100
7101 pf_nl_unregister();
7102
7103 if (pf_dev != NULL)
7104 destroy_dev(pf_dev);
7105
7106 pfi_cleanup();
7107
7108 sx_destroy(&pf_end_lock);
7109 }
7110
7111 static void
vnet_pf_init(void * unused __unused)7112 vnet_pf_init(void *unused __unused)
7113 {
7114
7115 pf_load_vnet();
7116 }
7117 VNET_SYSINIT(vnet_pf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
7118 vnet_pf_init, NULL);
7119
7120 static void
vnet_pf_uninit(const void * unused __unused)7121 vnet_pf_uninit(const void *unused __unused)
7122 {
7123
7124 pf_unload_vnet();
7125 }
7126 SYSUNINIT(pf_unload, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND, pf_unload, NULL);
7127 VNET_SYSUNINIT(vnet_pf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
7128 vnet_pf_uninit, NULL);
7129
7130 static int
pf_modevent(module_t mod,int type,void * data)7131 pf_modevent(module_t mod, int type, void *data)
7132 {
7133 int error = 0;
7134
7135 switch(type) {
7136 case MOD_LOAD:
7137 error = pf_load();
7138 pf_nl_register();
7139 break;
7140 case MOD_UNLOAD:
7141 /* Handled in SYSUNINIT(pf_unload) to ensure it's done after
7142 * the vnet_pf_uninit()s */
7143 break;
7144 default:
7145 error = EINVAL;
7146 break;
7147 }
7148
7149 return (error);
7150 }
7151
7152 static moduledata_t pf_mod = {
7153 "pf",
7154 pf_modevent,
7155 0
7156 };
7157
7158 DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
7159 MODULE_DEPEND(pf, netlink, 1, 1, 1);
7160 MODULE_DEPEND(pf, crypto, 1, 1, 1);
7161 MODULE_VERSION(pf, PF_MODVER);
7162