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 <[email protected]>
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 __FBSDID("$FreeBSD$");
42
43 #include "opt_inet.h"
44 #include "opt_inet6.h"
45 #include "opt_bpf.h"
46 #include "opt_pf.h"
47
48 #include <sys/param.h>
49 #include <sys/_bitset.h>
50 #include <sys/bitset.h>
51 #include <sys/bus.h>
52 #include <sys/conf.h>
53 #include <sys/endian.h>
54 #include <sys/fcntl.h>
55 #include <sys/filio.h>
56 #include <sys/hash.h>
57 #include <sys/interrupt.h>
58 #include <sys/jail.h>
59 #include <sys/kernel.h>
60 #include <sys/kthread.h>
61 #include <sys/lock.h>
62 #include <sys/mbuf.h>
63 #include <sys/module.h>
64 #include <sys/proc.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/vnet.h>
74 #include <net/route.h>
75 #include <net/pfil.h>
76 #include <net/pfvar.h>
77 #include <net/if_pfsync.h>
78 #include <net/if_pflog.h>
79
80 #include <netinet/in.h>
81 #include <netinet/ip.h>
82 #include <netinet/ip_var.h>
83 #include <netinet6/ip6_var.h>
84 #include <netinet/ip_icmp.h>
85
86 #ifdef INET6
87 #include <netinet/ip6.h>
88 #endif /* INET6 */
89
90 #ifdef ALTQ
91 #include <net/altq/altq.h>
92 #endif
93
94 static struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
95 u_int8_t, u_int8_t, u_int8_t);
96
97 static void pf_mv_pool(struct pf_palist *, struct pf_palist *);
98 static void pf_empty_pool(struct pf_palist *);
99 static int pfioctl(struct cdev *, u_long, caddr_t, int,
100 struct thread *);
101 #ifdef ALTQ
102 static int pf_begin_altq(u_int32_t *);
103 static int pf_rollback_altq(u_int32_t);
104 static int pf_commit_altq(u_int32_t);
105 static int pf_enable_altq(struct pf_altq *);
106 static int pf_disable_altq(struct pf_altq *);
107 static u_int32_t pf_qname2qid(char *);
108 static void pf_qid_unref(u_int32_t);
109 #endif /* ALTQ */
110 static int pf_begin_rules(u_int32_t *, int, const char *);
111 static int pf_rollback_rules(u_int32_t, int, char *);
112 static int pf_setup_pfsync_matching(struct pf_ruleset *);
113 static void pf_hash_rule(MD5_CTX *, struct pf_rule *);
114 static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
115 static int pf_commit_rules(u_int32_t, int, char *);
116 static int pf_addr_setup(struct pf_ruleset *,
117 struct pf_addr_wrap *, sa_family_t);
118 static void pf_addr_copyout(struct pf_addr_wrap *);
119 #ifdef ALTQ
120 static int pf_export_kaltq(struct pf_altq *,
121 struct pfioc_altq_v1 *, size_t);
122 static int pf_import_kaltq(struct pfioc_altq_v1 *,
123 struct pf_altq *, size_t);
124 #endif /* ALTQ */
125
126 VNET_DEFINE(struct pf_rule, pf_default_rule);
127
128 #ifdef ALTQ
129 VNET_DEFINE_STATIC(int, pf_altq_running);
130 #define V_pf_altq_running VNET(pf_altq_running)
131 #endif
132
133 #define TAGID_MAX 50000
134 struct pf_tagname {
135 TAILQ_ENTRY(pf_tagname) namehash_entries;
136 TAILQ_ENTRY(pf_tagname) taghash_entries;
137 char name[PF_TAG_NAME_SIZE];
138 uint16_t tag;
139 int ref;
140 };
141
142 struct pf_tagset {
143 TAILQ_HEAD(, pf_tagname) *namehash;
144 TAILQ_HEAD(, pf_tagname) *taghash;
145 unsigned int mask;
146 uint32_t seed;
147 BITSET_DEFINE(, TAGID_MAX) avail;
148 };
149
150 VNET_DEFINE(struct pf_tagset, pf_tags);
151 #define V_pf_tags VNET(pf_tags)
152 static unsigned int pf_rule_tag_hashsize;
153 #define PF_RULE_TAG_HASH_SIZE_DEFAULT 128
154 SYSCTL_UINT(_net_pf, OID_AUTO, rule_tag_hashsize, CTLFLAG_RDTUN,
155 &pf_rule_tag_hashsize, PF_RULE_TAG_HASH_SIZE_DEFAULT,
156 "Size of pf(4) rule tag hashtable");
157
158 #ifdef ALTQ
159 VNET_DEFINE(struct pf_tagset, pf_qids);
160 #define V_pf_qids VNET(pf_qids)
161 static unsigned int pf_queue_tag_hashsize;
162 #define PF_QUEUE_TAG_HASH_SIZE_DEFAULT 128
163 SYSCTL_UINT(_net_pf, OID_AUTO, queue_tag_hashsize, CTLFLAG_RDTUN,
164 &pf_queue_tag_hashsize, PF_QUEUE_TAG_HASH_SIZE_DEFAULT,
165 "Size of pf(4) queue tag hashtable");
166 #endif
167 VNET_DEFINE(uma_zone_t, pf_tag_z);
168 #define V_pf_tag_z VNET(pf_tag_z)
169 static MALLOC_DEFINE(M_PFALTQ, "pf_altq", "pf(4) altq configuration db");
170 static MALLOC_DEFINE(M_PFRULE, "pf_rule", "pf(4) rules");
171
172 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
173 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
174 #endif
175
176 static void pf_init_tagset(struct pf_tagset *, unsigned int *,
177 unsigned int);
178 static void pf_cleanup_tagset(struct pf_tagset *);
179 static uint16_t tagname2hashindex(const struct pf_tagset *, const char *);
180 static uint16_t tag2hashindex(const struct pf_tagset *, uint16_t);
181 static u_int16_t tagname2tag(struct pf_tagset *, char *);
182 static u_int16_t pf_tagname2tag(char *);
183 static void tag_unref(struct pf_tagset *, u_int16_t);
184
185 #define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
186
187 struct cdev *pf_dev;
188
189 /*
190 * XXX - These are new and need to be checked when moveing to a new version
191 */
192 static void pf_clear_states(void);
193 static int pf_clear_tables(void);
194 static void pf_clear_srcnodes(struct pf_src_node *);
195 static void pf_kill_srcnodes(struct pfioc_src_node_kill *);
196 static void pf_tbladdr_copyout(struct pf_addr_wrap *);
197
198 /*
199 * Wrapper functions for pfil(9) hooks
200 */
201 #ifdef INET
202 static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
203 int dir, int flags, struct inpcb *inp);
204 static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
205 int dir, int flags, struct inpcb *inp);
206 #endif
207 #ifdef INET6
208 static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
209 int dir, int flags, struct inpcb *inp);
210 static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
211 int dir, int flags, struct inpcb *inp);
212 #endif
213
214 static int hook_pf(void);
215 static int dehook_pf(void);
216 static int shutdown_pf(void);
217 static int pf_load(void);
218 static void pf_unload(void);
219
220 static struct cdevsw pf_cdevsw = {
221 .d_ioctl = pfioctl,
222 .d_name = PF_NAME,
223 .d_version = D_VERSION,
224 };
225
226 volatile VNET_DEFINE_STATIC(int, pf_pfil_hooked);
227 #define V_pf_pfil_hooked VNET(pf_pfil_hooked)
228
229 /*
230 * We need a flag that is neither hooked nor running to know when
231 * the VNET is "valid". We primarily need this to control (global)
232 * external event, e.g., eventhandlers.
233 */
234 VNET_DEFINE(int, pf_vnet_active);
235 #define V_pf_vnet_active VNET(pf_vnet_active)
236
237 int pf_end_threads;
238 struct proc *pf_purge_proc;
239
240 struct rmlock pf_rules_lock;
241 struct sx pf_ioctl_lock;
242 struct sx pf_end_lock;
243
244 /* pfsync */
245 VNET_DEFINE(pfsync_state_import_t *, pfsync_state_import_ptr);
246 VNET_DEFINE(pfsync_insert_state_t *, pfsync_insert_state_ptr);
247 VNET_DEFINE(pfsync_update_state_t *, pfsync_update_state_ptr);
248 VNET_DEFINE(pfsync_delete_state_t *, pfsync_delete_state_ptr);
249 VNET_DEFINE(pfsync_clear_states_t *, pfsync_clear_states_ptr);
250 VNET_DEFINE(pfsync_defer_t *, pfsync_defer_ptr);
251 pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr;
252
253 /* pflog */
254 pflog_packet_t *pflog_packet_ptr = NULL;
255
256 extern u_long pf_ioctl_maxcount;
257
258 static void
pfattach_vnet(void)259 pfattach_vnet(void)
260 {
261 u_int32_t *my_timeout = V_pf_default_rule.timeout;
262
263 pf_initialize();
264 pfr_initialize();
265 pfi_initialize_vnet();
266 pf_normalize_init();
267
268 V_pf_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
269 V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
270
271 RB_INIT(&V_pf_anchors);
272 pf_init_ruleset(&pf_main_ruleset);
273
274 /* default rule should never be garbage collected */
275 V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next;
276 #ifdef PF_DEFAULT_TO_DROP
277 V_pf_default_rule.action = PF_DROP;
278 #else
279 V_pf_default_rule.action = PF_PASS;
280 #endif
281 V_pf_default_rule.nr = -1;
282 V_pf_default_rule.rtableid = -1;
283
284 V_pf_default_rule.states_cur = counter_u64_alloc(M_WAITOK);
285 V_pf_default_rule.states_tot = counter_u64_alloc(M_WAITOK);
286 V_pf_default_rule.src_nodes = counter_u64_alloc(M_WAITOK);
287
288 /* initialize default timeouts */
289 my_timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
290 my_timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
291 my_timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
292 my_timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
293 my_timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
294 my_timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
295 my_timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
296 my_timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
297 my_timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
298 my_timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
299 my_timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
300 my_timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
301 my_timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
302 my_timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
303 my_timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
304 my_timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
305 my_timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
306 my_timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
307 my_timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
308 my_timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
309
310 bzero(&V_pf_status, sizeof(V_pf_status));
311 V_pf_status.debug = PF_DEBUG_URGENT;
312
313 V_pf_pfil_hooked = 0;
314
315 /* XXX do our best to avoid a conflict */
316 V_pf_status.hostid = arc4random();
317
318 for (int i = 0; i < PFRES_MAX; i++)
319 V_pf_status.counters[i] = counter_u64_alloc(M_WAITOK);
320 for (int i = 0; i < LCNT_MAX; i++)
321 V_pf_status.lcounters[i] = counter_u64_alloc(M_WAITOK);
322 for (int i = 0; i < FCNT_MAX; i++)
323 V_pf_status.fcounters[i] = counter_u64_alloc(M_WAITOK);
324 for (int i = 0; i < SCNT_MAX; i++)
325 V_pf_status.scounters[i] = counter_u64_alloc(M_WAITOK);
326
327 if (swi_add(NULL, "pf send", pf_intr, curvnet, SWI_NET,
328 INTR_MPSAFE, &V_pf_swi_cookie) != 0)
329 /* XXXGL: leaked all above. */
330 return;
331 }
332
333
334 static struct pf_pool *
pf_get_pool(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)335 pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
336 u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
337 u_int8_t check_ticket)
338 {
339 struct pf_ruleset *ruleset;
340 struct pf_rule *rule;
341 int rs_num;
342
343 ruleset = pf_find_ruleset(anchor);
344 if (ruleset == NULL)
345 return (NULL);
346 rs_num = pf_get_ruleset_number(rule_action);
347 if (rs_num >= PF_RULESET_MAX)
348 return (NULL);
349 if (active) {
350 if (check_ticket && ticket !=
351 ruleset->rules[rs_num].active.ticket)
352 return (NULL);
353 if (r_last)
354 rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
355 pf_rulequeue);
356 else
357 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
358 } else {
359 if (check_ticket && ticket !=
360 ruleset->rules[rs_num].inactive.ticket)
361 return (NULL);
362 if (r_last)
363 rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
364 pf_rulequeue);
365 else
366 rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
367 }
368 if (!r_last) {
369 while ((rule != NULL) && (rule->nr != rule_number))
370 rule = TAILQ_NEXT(rule, entries);
371 }
372 if (rule == NULL)
373 return (NULL);
374
375 return (&rule->rpool);
376 }
377
378 static void
pf_mv_pool(struct pf_palist * poola,struct pf_palist * poolb)379 pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
380 {
381 struct pf_pooladdr *mv_pool_pa;
382
383 while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
384 TAILQ_REMOVE(poola, mv_pool_pa, entries);
385 TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
386 }
387 }
388
389 static void
pf_empty_pool(struct pf_palist * poola)390 pf_empty_pool(struct pf_palist *poola)
391 {
392 struct pf_pooladdr *pa;
393
394 while ((pa = TAILQ_FIRST(poola)) != NULL) {
395 switch (pa->addr.type) {
396 case PF_ADDR_DYNIFTL:
397 pfi_dynaddr_remove(pa->addr.p.dyn);
398 break;
399 case PF_ADDR_TABLE:
400 /* XXX: this could be unfinished pooladdr on pabuf */
401 if (pa->addr.p.tbl != NULL)
402 pfr_detach_table(pa->addr.p.tbl);
403 break;
404 }
405 if (pa->kif)
406 pfi_kif_unref(pa->kif);
407 TAILQ_REMOVE(poola, pa, entries);
408 free(pa, M_PFRULE);
409 }
410 }
411
412 static void
pf_unlink_rule(struct pf_rulequeue * rulequeue,struct pf_rule * rule)413 pf_unlink_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
414 {
415
416 PF_RULES_WASSERT();
417
418 TAILQ_REMOVE(rulequeue, rule, entries);
419
420 PF_UNLNKDRULES_LOCK();
421 rule->rule_flag |= PFRULE_REFS;
422 TAILQ_INSERT_TAIL(&V_pf_unlinked_rules, rule, entries);
423 PF_UNLNKDRULES_UNLOCK();
424 }
425
426 void
pf_free_rule(struct pf_rule * rule)427 pf_free_rule(struct pf_rule *rule)
428 {
429
430 PF_RULES_WASSERT();
431
432 if (rule->tag)
433 tag_unref(&V_pf_tags, rule->tag);
434 if (rule->match_tag)
435 tag_unref(&V_pf_tags, rule->match_tag);
436 #ifdef ALTQ
437 if (rule->pqid != rule->qid)
438 pf_qid_unref(rule->pqid);
439 pf_qid_unref(rule->qid);
440 #endif
441 switch (rule->src.addr.type) {
442 case PF_ADDR_DYNIFTL:
443 pfi_dynaddr_remove(rule->src.addr.p.dyn);
444 break;
445 case PF_ADDR_TABLE:
446 pfr_detach_table(rule->src.addr.p.tbl);
447 break;
448 }
449 switch (rule->dst.addr.type) {
450 case PF_ADDR_DYNIFTL:
451 pfi_dynaddr_remove(rule->dst.addr.p.dyn);
452 break;
453 case PF_ADDR_TABLE:
454 pfr_detach_table(rule->dst.addr.p.tbl);
455 break;
456 }
457 if (rule->overload_tbl)
458 pfr_detach_table(rule->overload_tbl);
459 if (rule->kif)
460 pfi_kif_unref(rule->kif);
461 pf_anchor_remove(rule);
462 pf_empty_pool(&rule->rpool.list);
463 counter_u64_free(rule->states_cur);
464 counter_u64_free(rule->states_tot);
465 counter_u64_free(rule->src_nodes);
466 free(rule, M_PFRULE);
467 }
468
469 static void
pf_init_tagset(struct pf_tagset * ts,unsigned int * tunable_size,unsigned int default_size)470 pf_init_tagset(struct pf_tagset *ts, unsigned int *tunable_size,
471 unsigned int default_size)
472 {
473 unsigned int i;
474 unsigned int hashsize;
475
476 if (*tunable_size == 0 || !powerof2(*tunable_size))
477 *tunable_size = default_size;
478
479 hashsize = *tunable_size;
480 ts->namehash = mallocarray(hashsize, sizeof(*ts->namehash), M_PFHASH,
481 M_WAITOK);
482 ts->taghash = mallocarray(hashsize, sizeof(*ts->taghash), M_PFHASH,
483 M_WAITOK);
484 ts->mask = hashsize - 1;
485 ts->seed = arc4random();
486 for (i = 0; i < hashsize; i++) {
487 TAILQ_INIT(&ts->namehash[i]);
488 TAILQ_INIT(&ts->taghash[i]);
489 }
490 BIT_FILL(TAGID_MAX, &ts->avail);
491 }
492
493 static void
pf_cleanup_tagset(struct pf_tagset * ts)494 pf_cleanup_tagset(struct pf_tagset *ts)
495 {
496 unsigned int i;
497 unsigned int hashsize;
498 struct pf_tagname *t, *tmp;
499
500 /*
501 * Only need to clean up one of the hashes as each tag is hashed
502 * into each table.
503 */
504 hashsize = ts->mask + 1;
505 for (i = 0; i < hashsize; i++)
506 TAILQ_FOREACH_SAFE(t, &ts->namehash[i], namehash_entries, tmp)
507 uma_zfree(V_pf_tag_z, t);
508
509 free(ts->namehash, M_PFHASH);
510 free(ts->taghash, M_PFHASH);
511 }
512
513 static uint16_t
tagname2hashindex(const struct pf_tagset * ts,const char * tagname)514 tagname2hashindex(const struct pf_tagset *ts, const char *tagname)
515 {
516
517 return (murmur3_32_hash(tagname, strlen(tagname), ts->seed) & ts->mask);
518 }
519
520 static uint16_t
tag2hashindex(const struct pf_tagset * ts,uint16_t tag)521 tag2hashindex(const struct pf_tagset *ts, uint16_t tag)
522 {
523
524 return (tag & ts->mask);
525 }
526
527 static u_int16_t
tagname2tag(struct pf_tagset * ts,char * tagname)528 tagname2tag(struct pf_tagset *ts, char *tagname)
529 {
530 struct pf_tagname *tag;
531 u_int32_t index;
532 u_int16_t new_tagid;
533
534 PF_RULES_WASSERT();
535
536 index = tagname2hashindex(ts, tagname);
537 TAILQ_FOREACH(tag, &ts->namehash[index], namehash_entries)
538 if (strcmp(tagname, tag->name) == 0) {
539 tag->ref++;
540 return (tag->tag);
541 }
542
543 /*
544 * new entry
545 *
546 * to avoid fragmentation, we do a linear search from the beginning
547 * and take the first free slot we find.
548 */
549 new_tagid = BIT_FFS(TAGID_MAX, &ts->avail);
550 /*
551 * Tags are 1-based, with valid tags in the range [1..TAGID_MAX].
552 * BIT_FFS() returns a 1-based bit number, with 0 indicating no bits
553 * set. It may also return a bit number greater than TAGID_MAX due
554 * to rounding of the number of bits in the vector up to a multiple
555 * of the vector word size at declaration/allocation time.
556 */
557 if ((new_tagid == 0) || (new_tagid > TAGID_MAX))
558 return (0);
559
560 /* Mark the tag as in use. Bits are 0-based for BIT_CLR() */
561 BIT_CLR(TAGID_MAX, new_tagid - 1, &ts->avail);
562
563 /* allocate and fill new struct pf_tagname */
564 tag = uma_zalloc(V_pf_tag_z, M_NOWAIT);
565 if (tag == NULL)
566 return (0);
567 strlcpy(tag->name, tagname, sizeof(tag->name));
568 tag->tag = new_tagid;
569 tag->ref = 1;
570
571 /* Insert into namehash */
572 TAILQ_INSERT_TAIL(&ts->namehash[index], tag, namehash_entries);
573
574 /* Insert into taghash */
575 index = tag2hashindex(ts, new_tagid);
576 TAILQ_INSERT_TAIL(&ts->taghash[index], tag, taghash_entries);
577
578 return (tag->tag);
579 }
580
581 static void
tag_unref(struct pf_tagset * ts,u_int16_t tag)582 tag_unref(struct pf_tagset *ts, u_int16_t tag)
583 {
584 struct pf_tagname *t;
585 uint16_t index;
586
587 PF_RULES_WASSERT();
588
589 index = tag2hashindex(ts, tag);
590 TAILQ_FOREACH(t, &ts->taghash[index], taghash_entries)
591 if (tag == t->tag) {
592 if (--t->ref == 0) {
593 TAILQ_REMOVE(&ts->taghash[index], t,
594 taghash_entries);
595 index = tagname2hashindex(ts, t->name);
596 TAILQ_REMOVE(&ts->namehash[index], t,
597 namehash_entries);
598 /* Bits are 0-based for BIT_SET() */
599 BIT_SET(TAGID_MAX, tag - 1, &ts->avail);
600 uma_zfree(V_pf_tag_z, t);
601 }
602 break;
603 }
604 }
605
606 static u_int16_t
pf_tagname2tag(char * tagname)607 pf_tagname2tag(char *tagname)
608 {
609 return (tagname2tag(&V_pf_tags, tagname));
610 }
611
612 #ifdef ALTQ
613 static u_int32_t
pf_qname2qid(char * qname)614 pf_qname2qid(char *qname)
615 {
616 return ((u_int32_t)tagname2tag(&V_pf_qids, qname));
617 }
618
619 static void
pf_qid_unref(u_int32_t qid)620 pf_qid_unref(u_int32_t qid)
621 {
622 tag_unref(&V_pf_qids, (u_int16_t)qid);
623 }
624
625 static int
pf_begin_altq(u_int32_t * ticket)626 pf_begin_altq(u_int32_t *ticket)
627 {
628 struct pf_altq *altq, *tmp;
629 int error = 0;
630
631 PF_RULES_WASSERT();
632
633 /* Purge the old altq lists */
634 TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
635 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
636 /* detach and destroy the discipline */
637 error = altq_remove(altq);
638 }
639 free(altq, M_PFALTQ);
640 }
641 TAILQ_INIT(V_pf_altq_ifs_inactive);
642 TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
643 pf_qid_unref(altq->qid);
644 free(altq, M_PFALTQ);
645 }
646 TAILQ_INIT(V_pf_altqs_inactive);
647 if (error)
648 return (error);
649 *ticket = ++V_ticket_altqs_inactive;
650 V_altqs_inactive_open = 1;
651 return (0);
652 }
653
654 static int
pf_rollback_altq(u_int32_t ticket)655 pf_rollback_altq(u_int32_t ticket)
656 {
657 struct pf_altq *altq, *tmp;
658 int error = 0;
659
660 PF_RULES_WASSERT();
661
662 if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
663 return (0);
664 /* Purge the old altq lists */
665 TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
666 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
667 /* detach and destroy the discipline */
668 error = altq_remove(altq);
669 }
670 free(altq, M_PFALTQ);
671 }
672 TAILQ_INIT(V_pf_altq_ifs_inactive);
673 TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
674 pf_qid_unref(altq->qid);
675 free(altq, M_PFALTQ);
676 }
677 TAILQ_INIT(V_pf_altqs_inactive);
678 V_altqs_inactive_open = 0;
679 return (error);
680 }
681
682 static int
pf_commit_altq(u_int32_t ticket)683 pf_commit_altq(u_int32_t ticket)
684 {
685 struct pf_altqqueue *old_altqs, *old_altq_ifs;
686 struct pf_altq *altq, *tmp;
687 int err, error = 0;
688
689 PF_RULES_WASSERT();
690
691 if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
692 return (EBUSY);
693
694 /* swap altqs, keep the old. */
695 old_altqs = V_pf_altqs_active;
696 old_altq_ifs = V_pf_altq_ifs_active;
697 V_pf_altqs_active = V_pf_altqs_inactive;
698 V_pf_altq_ifs_active = V_pf_altq_ifs_inactive;
699 V_pf_altqs_inactive = old_altqs;
700 V_pf_altq_ifs_inactive = old_altq_ifs;
701 V_ticket_altqs_active = V_ticket_altqs_inactive;
702
703 /* Attach new disciplines */
704 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
705 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
706 /* attach the discipline */
707 error = altq_pfattach(altq);
708 if (error == 0 && V_pf_altq_running)
709 error = pf_enable_altq(altq);
710 if (error != 0)
711 return (error);
712 }
713 }
714
715 /* Purge the old altq lists */
716 TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
717 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
718 /* detach and destroy the discipline */
719 if (V_pf_altq_running)
720 error = pf_disable_altq(altq);
721 err = altq_pfdetach(altq);
722 if (err != 0 && error == 0)
723 error = err;
724 err = altq_remove(altq);
725 if (err != 0 && error == 0)
726 error = err;
727 }
728 free(altq, M_PFALTQ);
729 }
730 TAILQ_INIT(V_pf_altq_ifs_inactive);
731 TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
732 pf_qid_unref(altq->qid);
733 free(altq, M_PFALTQ);
734 }
735 TAILQ_INIT(V_pf_altqs_inactive);
736
737 V_altqs_inactive_open = 0;
738 return (error);
739 }
740
741 static int
pf_enable_altq(struct pf_altq * altq)742 pf_enable_altq(struct pf_altq *altq)
743 {
744 struct ifnet *ifp;
745 struct tb_profile tb;
746 int error = 0;
747
748 if ((ifp = ifunit(altq->ifname)) == NULL)
749 return (EINVAL);
750
751 if (ifp->if_snd.altq_type != ALTQT_NONE)
752 error = altq_enable(&ifp->if_snd);
753
754 /* set tokenbucket regulator */
755 if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
756 tb.rate = altq->ifbandwidth;
757 tb.depth = altq->tbrsize;
758 error = tbr_set(&ifp->if_snd, &tb);
759 }
760
761 return (error);
762 }
763
764 static int
pf_disable_altq(struct pf_altq * altq)765 pf_disable_altq(struct pf_altq *altq)
766 {
767 struct ifnet *ifp;
768 struct tb_profile tb;
769 int error;
770
771 if ((ifp = ifunit(altq->ifname)) == NULL)
772 return (EINVAL);
773
774 /*
775 * when the discipline is no longer referenced, it was overridden
776 * by a new one. if so, just return.
777 */
778 if (altq->altq_disc != ifp->if_snd.altq_disc)
779 return (0);
780
781 error = altq_disable(&ifp->if_snd);
782
783 if (error == 0) {
784 /* clear tokenbucket regulator */
785 tb.rate = 0;
786 error = tbr_set(&ifp->if_snd, &tb);
787 }
788
789 return (error);
790 }
791
792 static int
pf_altq_ifnet_event_add(struct ifnet * ifp,int remove,u_int32_t ticket,struct pf_altq * altq)793 pf_altq_ifnet_event_add(struct ifnet *ifp, int remove, u_int32_t ticket,
794 struct pf_altq *altq)
795 {
796 struct ifnet *ifp1;
797 int error = 0;
798
799 /* Deactivate the interface in question */
800 altq->local_flags &= ~PFALTQ_FLAG_IF_REMOVED;
801 if ((ifp1 = ifunit(altq->ifname)) == NULL ||
802 (remove && ifp1 == ifp)) {
803 altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
804 } else {
805 error = altq_add(ifp1, altq);
806
807 if (ticket != V_ticket_altqs_inactive)
808 error = EBUSY;
809
810 if (error)
811 free(altq, M_PFALTQ);
812 }
813
814 return (error);
815 }
816
817 void
pf_altq_ifnet_event(struct ifnet * ifp,int remove)818 pf_altq_ifnet_event(struct ifnet *ifp, int remove)
819 {
820 struct pf_altq *a1, *a2, *a3;
821 u_int32_t ticket;
822 int error = 0;
823
824 /*
825 * No need to re-evaluate the configuration for events on interfaces
826 * that do not support ALTQ, as it's not possible for such
827 * interfaces to be part of the configuration.
828 */
829 if (!ALTQ_IS_READY(&ifp->if_snd))
830 return;
831
832 /* Interrupt userland queue modifications */
833 if (V_altqs_inactive_open)
834 pf_rollback_altq(V_ticket_altqs_inactive);
835
836 /* Start new altq ruleset */
837 if (pf_begin_altq(&ticket))
838 return;
839
840 /* Copy the current active set */
841 TAILQ_FOREACH(a1, V_pf_altq_ifs_active, entries) {
842 a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT);
843 if (a2 == NULL) {
844 error = ENOMEM;
845 break;
846 }
847 bcopy(a1, a2, sizeof(struct pf_altq));
848
849 error = pf_altq_ifnet_event_add(ifp, remove, ticket, a2);
850 if (error)
851 break;
852
853 TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, a2, entries);
854 }
855 if (error)
856 goto out;
857 TAILQ_FOREACH(a1, V_pf_altqs_active, entries) {
858 a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT);
859 if (a2 == NULL) {
860 error = ENOMEM;
861 break;
862 }
863 bcopy(a1, a2, sizeof(struct pf_altq));
864
865 if ((a2->qid = pf_qname2qid(a2->qname)) == 0) {
866 error = EBUSY;
867 free(a2, M_PFALTQ);
868 break;
869 }
870 a2->altq_disc = NULL;
871 TAILQ_FOREACH(a3, V_pf_altq_ifs_inactive, entries) {
872 if (strncmp(a3->ifname, a2->ifname,
873 IFNAMSIZ) == 0) {
874 a2->altq_disc = a3->altq_disc;
875 break;
876 }
877 }
878 error = pf_altq_ifnet_event_add(ifp, remove, ticket, a2);
879 if (error)
880 break;
881
882 TAILQ_INSERT_TAIL(V_pf_altqs_inactive, a2, entries);
883 }
884
885 out:
886 if (error != 0)
887 pf_rollback_altq(ticket);
888 else
889 pf_commit_altq(ticket);
890 }
891 #endif /* ALTQ */
892
893 static int
pf_begin_rules(u_int32_t * ticket,int rs_num,const char * anchor)894 pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
895 {
896 struct pf_ruleset *rs;
897 struct pf_rule *rule;
898
899 PF_RULES_WASSERT();
900
901 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
902 return (EINVAL);
903 rs = pf_find_or_create_ruleset(anchor);
904 if (rs == NULL)
905 return (EINVAL);
906 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
907 pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule);
908 rs->rules[rs_num].inactive.rcount--;
909 }
910 *ticket = ++rs->rules[rs_num].inactive.ticket;
911 rs->rules[rs_num].inactive.open = 1;
912 return (0);
913 }
914
915 static int
pf_rollback_rules(u_int32_t ticket,int rs_num,char * anchor)916 pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
917 {
918 struct pf_ruleset *rs;
919 struct pf_rule *rule;
920
921 PF_RULES_WASSERT();
922
923 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
924 return (EINVAL);
925 rs = pf_find_ruleset(anchor);
926 if (rs == NULL || !rs->rules[rs_num].inactive.open ||
927 rs->rules[rs_num].inactive.ticket != ticket)
928 return (0);
929 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
930 pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule);
931 rs->rules[rs_num].inactive.rcount--;
932 }
933 rs->rules[rs_num].inactive.open = 0;
934 return (0);
935 }
936
937 #define PF_MD5_UPD(st, elm) \
938 MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
939
940 #define PF_MD5_UPD_STR(st, elm) \
941 MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
942
943 #define PF_MD5_UPD_HTONL(st, elm, stor) do { \
944 (stor) = htonl((st)->elm); \
945 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
946 } while (0)
947
948 #define PF_MD5_UPD_HTONS(st, elm, stor) do { \
949 (stor) = htons((st)->elm); \
950 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
951 } while (0)
952
953 static void
pf_hash_rule_addr(MD5_CTX * ctx,struct pf_rule_addr * pfr)954 pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
955 {
956 PF_MD5_UPD(pfr, addr.type);
957 switch (pfr->addr.type) {
958 case PF_ADDR_DYNIFTL:
959 PF_MD5_UPD(pfr, addr.v.ifname);
960 PF_MD5_UPD(pfr, addr.iflags);
961 break;
962 case PF_ADDR_TABLE:
963 PF_MD5_UPD(pfr, addr.v.tblname);
964 break;
965 case PF_ADDR_ADDRMASK:
966 /* XXX ignore af? */
967 PF_MD5_UPD(pfr, addr.v.a.addr.addr32);
968 PF_MD5_UPD(pfr, addr.v.a.mask.addr32);
969 break;
970 }
971
972 PF_MD5_UPD(pfr, port[0]);
973 PF_MD5_UPD(pfr, port[1]);
974 PF_MD5_UPD(pfr, neg);
975 PF_MD5_UPD(pfr, port_op);
976 }
977
978 static void
pf_hash_rule(MD5_CTX * ctx,struct pf_rule * rule)979 pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule)
980 {
981 u_int16_t x;
982 u_int32_t y;
983
984 pf_hash_rule_addr(ctx, &rule->src);
985 pf_hash_rule_addr(ctx, &rule->dst);
986 PF_MD5_UPD_STR(rule, label);
987 PF_MD5_UPD_STR(rule, ifname);
988 PF_MD5_UPD_STR(rule, match_tagname);
989 PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */
990 PF_MD5_UPD_HTONL(rule, os_fingerprint, y);
991 PF_MD5_UPD_HTONL(rule, prob, y);
992 PF_MD5_UPD_HTONL(rule, uid.uid[0], y);
993 PF_MD5_UPD_HTONL(rule, uid.uid[1], y);
994 PF_MD5_UPD(rule, uid.op);
995 PF_MD5_UPD_HTONL(rule, gid.gid[0], y);
996 PF_MD5_UPD_HTONL(rule, gid.gid[1], y);
997 PF_MD5_UPD(rule, gid.op);
998 PF_MD5_UPD_HTONL(rule, rule_flag, y);
999 PF_MD5_UPD(rule, action);
1000 PF_MD5_UPD(rule, direction);
1001 PF_MD5_UPD(rule, af);
1002 PF_MD5_UPD(rule, quick);
1003 PF_MD5_UPD(rule, ifnot);
1004 PF_MD5_UPD(rule, match_tag_not);
1005 PF_MD5_UPD(rule, natpass);
1006 PF_MD5_UPD(rule, keep_state);
1007 PF_MD5_UPD(rule, proto);
1008 PF_MD5_UPD(rule, type);
1009 PF_MD5_UPD(rule, code);
1010 PF_MD5_UPD(rule, flags);
1011 PF_MD5_UPD(rule, flagset);
1012 PF_MD5_UPD(rule, allow_opts);
1013 PF_MD5_UPD(rule, rt);
1014 PF_MD5_UPD(rule, tos);
1015 }
1016
1017 static int
pf_commit_rules(u_int32_t ticket,int rs_num,char * anchor)1018 pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
1019 {
1020 struct pf_ruleset *rs;
1021 struct pf_rule *rule, **old_array;
1022 struct pf_rulequeue *old_rules;
1023 int error;
1024 u_int32_t old_rcount;
1025
1026 PF_RULES_WASSERT();
1027
1028 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1029 return (EINVAL);
1030 rs = pf_find_ruleset(anchor);
1031 if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1032 ticket != rs->rules[rs_num].inactive.ticket)
1033 return (EBUSY);
1034
1035 /* Calculate checksum for the main ruleset */
1036 if (rs == &pf_main_ruleset) {
1037 error = pf_setup_pfsync_matching(rs);
1038 if (error != 0)
1039 return (error);
1040 }
1041
1042 /* Swap rules, keep the old. */
1043 old_rules = rs->rules[rs_num].active.ptr;
1044 old_rcount = rs->rules[rs_num].active.rcount;
1045 old_array = rs->rules[rs_num].active.ptr_array;
1046
1047 rs->rules[rs_num].active.ptr =
1048 rs->rules[rs_num].inactive.ptr;
1049 rs->rules[rs_num].active.ptr_array =
1050 rs->rules[rs_num].inactive.ptr_array;
1051 rs->rules[rs_num].active.rcount =
1052 rs->rules[rs_num].inactive.rcount;
1053 rs->rules[rs_num].inactive.ptr = old_rules;
1054 rs->rules[rs_num].inactive.ptr_array = old_array;
1055 rs->rules[rs_num].inactive.rcount = old_rcount;
1056
1057 rs->rules[rs_num].active.ticket =
1058 rs->rules[rs_num].inactive.ticket;
1059 pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
1060
1061
1062 /* Purge the old rule list. */
1063 while ((rule = TAILQ_FIRST(old_rules)) != NULL)
1064 pf_unlink_rule(old_rules, rule);
1065 if (rs->rules[rs_num].inactive.ptr_array)
1066 free(rs->rules[rs_num].inactive.ptr_array, M_TEMP);
1067 rs->rules[rs_num].inactive.ptr_array = NULL;
1068 rs->rules[rs_num].inactive.rcount = 0;
1069 rs->rules[rs_num].inactive.open = 0;
1070 pf_remove_if_empty_ruleset(rs);
1071
1072 return (0);
1073 }
1074
1075 static int
pf_setup_pfsync_matching(struct pf_ruleset * rs)1076 pf_setup_pfsync_matching(struct pf_ruleset *rs)
1077 {
1078 MD5_CTX ctx;
1079 struct pf_rule *rule;
1080 int rs_cnt;
1081 u_int8_t digest[PF_MD5_DIGEST_LENGTH];
1082
1083 MD5Init(&ctx);
1084 for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
1085 /* XXX PF_RULESET_SCRUB as well? */
1086 if (rs_cnt == PF_RULESET_SCRUB)
1087 continue;
1088
1089 if (rs->rules[rs_cnt].inactive.ptr_array)
1090 free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
1091 rs->rules[rs_cnt].inactive.ptr_array = NULL;
1092
1093 if (rs->rules[rs_cnt].inactive.rcount) {
1094 rs->rules[rs_cnt].inactive.ptr_array =
1095 malloc(sizeof(caddr_t) *
1096 rs->rules[rs_cnt].inactive.rcount,
1097 M_TEMP, M_NOWAIT);
1098
1099 if (!rs->rules[rs_cnt].inactive.ptr_array)
1100 return (ENOMEM);
1101 }
1102
1103 TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
1104 entries) {
1105 pf_hash_rule(&ctx, rule);
1106 (rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule;
1107 }
1108 }
1109
1110 MD5Final(digest, &ctx);
1111 memcpy(V_pf_status.pf_chksum, digest, sizeof(V_pf_status.pf_chksum));
1112 return (0);
1113 }
1114
1115 static int
pf_addr_setup(struct pf_ruleset * ruleset,struct pf_addr_wrap * addr,sa_family_t af)1116 pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr,
1117 sa_family_t af)
1118 {
1119 int error = 0;
1120
1121 switch (addr->type) {
1122 case PF_ADDR_TABLE:
1123 addr->p.tbl = pfr_attach_table(ruleset, addr->v.tblname);
1124 if (addr->p.tbl == NULL)
1125 error = ENOMEM;
1126 break;
1127 case PF_ADDR_DYNIFTL:
1128 error = pfi_dynaddr_setup(addr, af);
1129 break;
1130 }
1131
1132 return (error);
1133 }
1134
1135 static void
pf_addr_copyout(struct pf_addr_wrap * addr)1136 pf_addr_copyout(struct pf_addr_wrap *addr)
1137 {
1138
1139 switch (addr->type) {
1140 case PF_ADDR_DYNIFTL:
1141 pfi_dynaddr_copyout(addr);
1142 break;
1143 case PF_ADDR_TABLE:
1144 pf_tbladdr_copyout(addr);
1145 break;
1146 }
1147 }
1148
1149 #ifdef ALTQ
1150 /*
1151 * Handle export of struct pf_kaltq to user binaries that may be using any
1152 * version of struct pf_altq.
1153 */
1154 static int
pf_export_kaltq(struct pf_altq * q,struct pfioc_altq_v1 * pa,size_t ioc_size)1155 pf_export_kaltq(struct pf_altq *q, struct pfioc_altq_v1 *pa, size_t ioc_size)
1156 {
1157 u_int32_t version;
1158
1159 if (ioc_size == sizeof(struct pfioc_altq_v0))
1160 version = 0;
1161 else
1162 version = pa->version;
1163
1164 if (version > PFIOC_ALTQ_VERSION)
1165 return (EINVAL);
1166
1167 #define ASSIGN(x) exported_q->x = q->x
1168 #define COPY(x) \
1169 bcopy(&q->x, &exported_q->x, min(sizeof(q->x), sizeof(exported_q->x)))
1170 #define SATU16(x) (u_int32_t)uqmin((x), USHRT_MAX)
1171 #define SATU32(x) (u_int32_t)uqmin((x), UINT_MAX)
1172
1173 switch (version) {
1174 case 0: {
1175 struct pf_altq_v0 *exported_q =
1176 &((struct pfioc_altq_v0 *)pa)->altq;
1177
1178 COPY(ifname);
1179
1180 ASSIGN(scheduler);
1181 ASSIGN(tbrsize);
1182 exported_q->tbrsize = SATU16(q->tbrsize);
1183 exported_q->ifbandwidth = SATU32(q->ifbandwidth);
1184
1185 COPY(qname);
1186 COPY(parent);
1187 ASSIGN(parent_qid);
1188 exported_q->bandwidth = SATU32(q->bandwidth);
1189 ASSIGN(priority);
1190 ASSIGN(local_flags);
1191
1192 ASSIGN(qlimit);
1193 ASSIGN(flags);
1194
1195 if (q->scheduler == ALTQT_HFSC) {
1196 #define ASSIGN_OPT(x) exported_q->pq_u.hfsc_opts.x = q->pq_u.hfsc_opts.x
1197 #define ASSIGN_OPT_SATU32(x) exported_q->pq_u.hfsc_opts.x = \
1198 SATU32(q->pq_u.hfsc_opts.x)
1199
1200 ASSIGN_OPT_SATU32(rtsc_m1);
1201 ASSIGN_OPT(rtsc_d);
1202 ASSIGN_OPT_SATU32(rtsc_m2);
1203
1204 ASSIGN_OPT_SATU32(lssc_m1);
1205 ASSIGN_OPT(lssc_d);
1206 ASSIGN_OPT_SATU32(lssc_m2);
1207
1208 ASSIGN_OPT_SATU32(ulsc_m1);
1209 ASSIGN_OPT(ulsc_d);
1210 ASSIGN_OPT_SATU32(ulsc_m2);
1211
1212 ASSIGN_OPT(flags);
1213
1214 #undef ASSIGN_OPT
1215 #undef ASSIGN_OPT_SATU32
1216 } else
1217 COPY(pq_u);
1218
1219 ASSIGN(qid);
1220 break;
1221 }
1222 case 1: {
1223 struct pf_altq_v1 *exported_q =
1224 &((struct pfioc_altq_v1 *)pa)->altq;
1225
1226 COPY(ifname);
1227
1228 ASSIGN(scheduler);
1229 ASSIGN(tbrsize);
1230 ASSIGN(ifbandwidth);
1231
1232 COPY(qname);
1233 COPY(parent);
1234 ASSIGN(parent_qid);
1235 ASSIGN(bandwidth);
1236 ASSIGN(priority);
1237 ASSIGN(local_flags);
1238
1239 ASSIGN(qlimit);
1240 ASSIGN(flags);
1241 COPY(pq_u);
1242
1243 ASSIGN(qid);
1244 break;
1245 }
1246 default:
1247 panic("%s: unhandled struct pfioc_altq version", __func__);
1248 break;
1249 }
1250
1251 #undef ASSIGN
1252 #undef COPY
1253 #undef SATU16
1254 #undef SATU32
1255
1256 return (0);
1257 }
1258
1259 /*
1260 * Handle import to struct pf_kaltq of struct pf_altq from user binaries
1261 * that may be using any version of it.
1262 */
1263 static int
pf_import_kaltq(struct pfioc_altq_v1 * pa,struct pf_altq * q,size_t ioc_size)1264 pf_import_kaltq(struct pfioc_altq_v1 *pa, struct pf_altq *q, size_t ioc_size)
1265 {
1266 u_int32_t version;
1267
1268 if (ioc_size == sizeof(struct pfioc_altq_v0))
1269 version = 0;
1270 else
1271 version = pa->version;
1272
1273 if (version > PFIOC_ALTQ_VERSION)
1274 return (EINVAL);
1275
1276 #define ASSIGN(x) q->x = imported_q->x
1277 #define COPY(x) \
1278 bcopy(&imported_q->x, &q->x, min(sizeof(imported_q->x), sizeof(q->x)))
1279
1280 switch (version) {
1281 case 0: {
1282 struct pf_altq_v0 *imported_q =
1283 &((struct pfioc_altq_v0 *)pa)->altq;
1284
1285 COPY(ifname);
1286
1287 ASSIGN(scheduler);
1288 ASSIGN(tbrsize); /* 16-bit -> 32-bit */
1289 ASSIGN(ifbandwidth); /* 32-bit -> 64-bit */
1290
1291 COPY(qname);
1292 COPY(parent);
1293 ASSIGN(parent_qid);
1294 ASSIGN(bandwidth); /* 32-bit -> 64-bit */
1295 ASSIGN(priority);
1296 ASSIGN(local_flags);
1297
1298 ASSIGN(qlimit);
1299 ASSIGN(flags);
1300
1301 if (imported_q->scheduler == ALTQT_HFSC) {
1302 #define ASSIGN_OPT(x) q->pq_u.hfsc_opts.x = imported_q->pq_u.hfsc_opts.x
1303
1304 /*
1305 * The m1 and m2 parameters are being copied from
1306 * 32-bit to 64-bit.
1307 */
1308 ASSIGN_OPT(rtsc_m1);
1309 ASSIGN_OPT(rtsc_d);
1310 ASSIGN_OPT(rtsc_m2);
1311
1312 ASSIGN_OPT(lssc_m1);
1313 ASSIGN_OPT(lssc_d);
1314 ASSIGN_OPT(lssc_m2);
1315
1316 ASSIGN_OPT(ulsc_m1);
1317 ASSIGN_OPT(ulsc_d);
1318 ASSIGN_OPT(ulsc_m2);
1319
1320 ASSIGN_OPT(flags);
1321
1322 #undef ASSIGN_OPT
1323 } else
1324 COPY(pq_u);
1325
1326 ASSIGN(qid);
1327 break;
1328 }
1329 case 1: {
1330 struct pf_altq_v1 *imported_q =
1331 &((struct pfioc_altq_v1 *)pa)->altq;
1332
1333 COPY(ifname);
1334
1335 ASSIGN(scheduler);
1336 ASSIGN(tbrsize);
1337 ASSIGN(ifbandwidth);
1338
1339 COPY(qname);
1340 COPY(parent);
1341 ASSIGN(parent_qid);
1342 ASSIGN(bandwidth);
1343 ASSIGN(priority);
1344 ASSIGN(local_flags);
1345
1346 ASSIGN(qlimit);
1347 ASSIGN(flags);
1348 COPY(pq_u);
1349
1350 ASSIGN(qid);
1351 break;
1352 }
1353 default:
1354 panic("%s: unhandled struct pfioc_altq version", __func__);
1355 break;
1356 }
1357
1358 #undef ASSIGN
1359 #undef COPY
1360
1361 return (0);
1362 }
1363
1364 static struct pf_altq *
pf_altq_get_nth_active(u_int32_t n)1365 pf_altq_get_nth_active(u_int32_t n)
1366 {
1367 struct pf_altq *altq;
1368 u_int32_t nr;
1369
1370 nr = 0;
1371 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
1372 if (nr == n)
1373 return (altq);
1374 nr++;
1375 }
1376
1377 TAILQ_FOREACH(altq, V_pf_altqs_active, entries) {
1378 if (nr == n)
1379 return (altq);
1380 nr++;
1381 }
1382
1383 return (NULL);
1384 }
1385 #endif /* ALTQ */
1386
1387 static int
pfioctl(struct cdev * dev,u_long cmd,caddr_t addr,int flags,struct thread * td)1388 pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
1389 {
1390 int error = 0;
1391 PF_RULES_RLOCK_TRACKER;
1392
1393 /* XXX keep in sync with switch() below */
1394 if (securelevel_gt(td->td_ucred, 2))
1395 switch (cmd) {
1396 case DIOCGETRULES:
1397 case DIOCGETRULE:
1398 case DIOCGETADDRS:
1399 case DIOCGETADDR:
1400 case DIOCGETSTATE:
1401 case DIOCSETSTATUSIF:
1402 case DIOCGETSTATUS:
1403 case DIOCCLRSTATUS:
1404 case DIOCNATLOOK:
1405 case DIOCSETDEBUG:
1406 case DIOCGETSTATES:
1407 case DIOCGETTIMEOUT:
1408 case DIOCCLRRULECTRS:
1409 case DIOCGETLIMIT:
1410 case DIOCGETALTQSV0:
1411 case DIOCGETALTQSV1:
1412 case DIOCGETALTQV0:
1413 case DIOCGETALTQV1:
1414 case DIOCGETQSTATSV0:
1415 case DIOCGETQSTATSV1:
1416 case DIOCGETRULESETS:
1417 case DIOCGETRULESET:
1418 case DIOCRGETTABLES:
1419 case DIOCRGETTSTATS:
1420 case DIOCRCLRTSTATS:
1421 case DIOCRCLRADDRS:
1422 case DIOCRADDADDRS:
1423 case DIOCRDELADDRS:
1424 case DIOCRSETADDRS:
1425 case DIOCRGETADDRS:
1426 case DIOCRGETASTATS:
1427 case DIOCRCLRASTATS:
1428 case DIOCRTSTADDRS:
1429 case DIOCOSFPGET:
1430 case DIOCGETSRCNODES:
1431 case DIOCCLRSRCNODES:
1432 case DIOCIGETIFACES:
1433 case DIOCGIFSPEEDV0:
1434 case DIOCGIFSPEEDV1:
1435 case DIOCSETIFFLAG:
1436 case DIOCCLRIFFLAG:
1437 break;
1438 case DIOCRCLRTABLES:
1439 case DIOCRADDTABLES:
1440 case DIOCRDELTABLES:
1441 case DIOCRSETTFLAGS:
1442 if (((struct pfioc_table *)addr)->pfrio_flags &
1443 PFR_FLAG_DUMMY)
1444 break; /* dummy operation ok */
1445 return (EPERM);
1446 default:
1447 return (EPERM);
1448 }
1449
1450 if (!(flags & FWRITE))
1451 switch (cmd) {
1452 case DIOCGETRULES:
1453 case DIOCGETADDRS:
1454 case DIOCGETADDR:
1455 case DIOCGETSTATE:
1456 case DIOCGETSTATUS:
1457 case DIOCGETSTATES:
1458 case DIOCGETTIMEOUT:
1459 case DIOCGETLIMIT:
1460 case DIOCGETALTQSV0:
1461 case DIOCGETALTQSV1:
1462 case DIOCGETALTQV0:
1463 case DIOCGETALTQV1:
1464 case DIOCGETQSTATSV0:
1465 case DIOCGETQSTATSV1:
1466 case DIOCGETRULESETS:
1467 case DIOCGETRULESET:
1468 case DIOCNATLOOK:
1469 case DIOCRGETTABLES:
1470 case DIOCRGETTSTATS:
1471 case DIOCRGETADDRS:
1472 case DIOCRGETASTATS:
1473 case DIOCRTSTADDRS:
1474 case DIOCOSFPGET:
1475 case DIOCGETSRCNODES:
1476 case DIOCIGETIFACES:
1477 case DIOCGIFSPEEDV1:
1478 case DIOCGIFSPEEDV0:
1479 break;
1480 case DIOCRCLRTABLES:
1481 case DIOCRADDTABLES:
1482 case DIOCRDELTABLES:
1483 case DIOCRCLRTSTATS:
1484 case DIOCRCLRADDRS:
1485 case DIOCRADDADDRS:
1486 case DIOCRDELADDRS:
1487 case DIOCRSETADDRS:
1488 case DIOCRSETTFLAGS:
1489 if (((struct pfioc_table *)addr)->pfrio_flags &
1490 PFR_FLAG_DUMMY) {
1491 flags |= FWRITE; /* need write lock for dummy */
1492 break; /* dummy operation ok */
1493 }
1494 return (EACCES);
1495 case DIOCGETRULE:
1496 if (((struct pfioc_rule *)addr)->action ==
1497 PF_GET_CLR_CNTR)
1498 return (EACCES);
1499 break;
1500 default:
1501 return (EACCES);
1502 }
1503
1504 CURVNET_SET(TD_TO_VNET(td));
1505
1506 switch (cmd) {
1507 case DIOCSTART:
1508 sx_xlock(&pf_ioctl_lock);
1509 if (V_pf_status.running)
1510 error = EEXIST;
1511 else {
1512 int cpu;
1513
1514 error = hook_pf();
1515 if (error) {
1516 DPFPRINTF(PF_DEBUG_MISC,
1517 ("pf: pfil registration failed\n"));
1518 break;
1519 }
1520 V_pf_status.running = 1;
1521 V_pf_status.since = time_second;
1522
1523 CPU_FOREACH(cpu)
1524 V_pf_stateid[cpu] = time_second;
1525
1526 DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
1527 }
1528 break;
1529
1530 case DIOCSTOP:
1531 sx_xlock(&pf_ioctl_lock);
1532 if (!V_pf_status.running)
1533 error = ENOENT;
1534 else {
1535 V_pf_status.running = 0;
1536 error = dehook_pf();
1537 if (error) {
1538 V_pf_status.running = 1;
1539 DPFPRINTF(PF_DEBUG_MISC,
1540 ("pf: pfil unregistration failed\n"));
1541 }
1542 V_pf_status.since = time_second;
1543 DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
1544 }
1545 break;
1546
1547 case DIOCADDRULE: {
1548 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1549 struct pf_ruleset *ruleset;
1550 struct pf_rule *rule, *tail;
1551 struct pf_pooladdr *pa;
1552 struct pfi_kif *kif = NULL;
1553 int rs_num;
1554
1555 if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1556 error = EINVAL;
1557 break;
1558 }
1559 #ifndef INET
1560 if (pr->rule.af == AF_INET) {
1561 error = EAFNOSUPPORT;
1562 break;
1563 }
1564 #endif /* INET */
1565 #ifndef INET6
1566 if (pr->rule.af == AF_INET6) {
1567 error = EAFNOSUPPORT;
1568 break;
1569 }
1570 #endif /* INET6 */
1571
1572 rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK);
1573 bcopy(&pr->rule, rule, sizeof(struct pf_rule));
1574 if (rule->ifname[0])
1575 kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK);
1576 rule->states_cur = counter_u64_alloc(M_WAITOK);
1577 rule->states_tot = counter_u64_alloc(M_WAITOK);
1578 rule->src_nodes = counter_u64_alloc(M_WAITOK);
1579 rule->cuid = td->td_ucred->cr_ruid;
1580 rule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
1581 TAILQ_INIT(&rule->rpool.list);
1582
1583 #define ERROUT(x) { error = (x); goto DIOCADDRULE_error; }
1584
1585 PF_RULES_WLOCK();
1586 pr->anchor[sizeof(pr->anchor) - 1] = 0;
1587 ruleset = pf_find_ruleset(pr->anchor);
1588 if (ruleset == NULL)
1589 ERROUT(EINVAL);
1590 rs_num = pf_get_ruleset_number(pr->rule.action);
1591 if (rs_num >= PF_RULESET_MAX)
1592 ERROUT(EINVAL);
1593 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
1594 DPFPRINTF(PF_DEBUG_MISC,
1595 ("ticket: %d != [%d]%d\n", pr->ticket, rs_num,
1596 ruleset->rules[rs_num].inactive.ticket));
1597 ERROUT(EBUSY);
1598 }
1599 if (pr->pool_ticket != V_ticket_pabuf) {
1600 DPFPRINTF(PF_DEBUG_MISC,
1601 ("pool_ticket: %d != %d\n", pr->pool_ticket,
1602 V_ticket_pabuf));
1603 ERROUT(EBUSY);
1604 }
1605
1606 tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
1607 pf_rulequeue);
1608 if (tail)
1609 rule->nr = tail->nr + 1;
1610 else
1611 rule->nr = 0;
1612 if (rule->ifname[0]) {
1613 rule->kif = pfi_kif_attach(kif, rule->ifname);
1614 pfi_kif_ref(rule->kif);
1615 } else
1616 rule->kif = NULL;
1617
1618 if (rule->rtableid > 0 && rule->rtableid >= rt_numfibs)
1619 error = EBUSY;
1620
1621 #ifdef ALTQ
1622 /* set queue IDs */
1623 if (rule->qname[0] != 0) {
1624 if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
1625 error = EBUSY;
1626 else if (rule->pqname[0] != 0) {
1627 if ((rule->pqid =
1628 pf_qname2qid(rule->pqname)) == 0)
1629 error = EBUSY;
1630 } else
1631 rule->pqid = rule->qid;
1632 }
1633 #endif
1634 if (rule->tagname[0])
1635 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
1636 error = EBUSY;
1637 if (rule->match_tagname[0])
1638 if ((rule->match_tag =
1639 pf_tagname2tag(rule->match_tagname)) == 0)
1640 error = EBUSY;
1641 if (rule->rt && !rule->direction)
1642 error = EINVAL;
1643 if (!rule->log)
1644 rule->logif = 0;
1645 if (rule->logif >= PFLOGIFS_MAX)
1646 error = EINVAL;
1647 if (pf_addr_setup(ruleset, &rule->src.addr, rule->af))
1648 error = ENOMEM;
1649 if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
1650 error = ENOMEM;
1651 if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
1652 error = EINVAL;
1653 if (rule->scrub_flags & PFSTATE_SETPRIO &&
1654 (rule->set_prio[0] > PF_PRIO_MAX ||
1655 rule->set_prio[1] > PF_PRIO_MAX))
1656 error = EINVAL;
1657 TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
1658 if (pa->addr.type == PF_ADDR_TABLE) {
1659 pa->addr.p.tbl = pfr_attach_table(ruleset,
1660 pa->addr.v.tblname);
1661 if (pa->addr.p.tbl == NULL)
1662 error = ENOMEM;
1663 }
1664
1665 rule->overload_tbl = NULL;
1666 if (rule->overload_tblname[0]) {
1667 if ((rule->overload_tbl = pfr_attach_table(ruleset,
1668 rule->overload_tblname)) == NULL)
1669 error = EINVAL;
1670 else
1671 rule->overload_tbl->pfrkt_flags |=
1672 PFR_TFLAG_ACTIVE;
1673 }
1674
1675 pf_mv_pool(&V_pf_pabuf, &rule->rpool.list);
1676 if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
1677 (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
1678 (rule->rt > PF_NOPFROUTE)) &&
1679 (TAILQ_FIRST(&rule->rpool.list) == NULL))
1680 error = EINVAL;
1681
1682 if (error) {
1683 pf_free_rule(rule);
1684 PF_RULES_WUNLOCK();
1685 break;
1686 }
1687
1688 rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
1689 rule->evaluations = rule->packets[0] = rule->packets[1] =
1690 rule->bytes[0] = rule->bytes[1] = 0;
1691 TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
1692 rule, entries);
1693 ruleset->rules[rs_num].inactive.rcount++;
1694 PF_RULES_WUNLOCK();
1695 break;
1696
1697 #undef ERROUT
1698 DIOCADDRULE_error:
1699 PF_RULES_WUNLOCK();
1700 counter_u64_free(rule->states_cur);
1701 counter_u64_free(rule->states_tot);
1702 counter_u64_free(rule->src_nodes);
1703 free(rule, M_PFRULE);
1704 if (kif)
1705 free(kif, PFI_MTYPE);
1706 break;
1707 }
1708
1709 case DIOCGETRULES: {
1710 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1711 struct pf_ruleset *ruleset;
1712 struct pf_rule *tail;
1713 int rs_num;
1714
1715 PF_RULES_WLOCK();
1716 pr->anchor[sizeof(pr->anchor) - 1] = 0;
1717 ruleset = pf_find_ruleset(pr->anchor);
1718 if (ruleset == NULL) {
1719 PF_RULES_WUNLOCK();
1720 error = EINVAL;
1721 break;
1722 }
1723 rs_num = pf_get_ruleset_number(pr->rule.action);
1724 if (rs_num >= PF_RULESET_MAX) {
1725 PF_RULES_WUNLOCK();
1726 error = EINVAL;
1727 break;
1728 }
1729 tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
1730 pf_rulequeue);
1731 if (tail)
1732 pr->nr = tail->nr + 1;
1733 else
1734 pr->nr = 0;
1735 pr->ticket = ruleset->rules[rs_num].active.ticket;
1736 PF_RULES_WUNLOCK();
1737 break;
1738 }
1739
1740 case DIOCGETRULE: {
1741 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1742 struct pf_ruleset *ruleset;
1743 struct pf_rule *rule;
1744 int rs_num, i;
1745
1746 PF_RULES_WLOCK();
1747 pr->anchor[sizeof(pr->anchor) - 1] = 0;
1748 ruleset = pf_find_ruleset(pr->anchor);
1749 if (ruleset == NULL) {
1750 PF_RULES_WUNLOCK();
1751 error = EINVAL;
1752 break;
1753 }
1754 rs_num = pf_get_ruleset_number(pr->rule.action);
1755 if (rs_num >= PF_RULESET_MAX) {
1756 PF_RULES_WUNLOCK();
1757 error = EINVAL;
1758 break;
1759 }
1760 if (pr->ticket != ruleset->rules[rs_num].active.ticket) {
1761 PF_RULES_WUNLOCK();
1762 error = EBUSY;
1763 break;
1764 }
1765 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
1766 while ((rule != NULL) && (rule->nr != pr->nr))
1767 rule = TAILQ_NEXT(rule, entries);
1768 if (rule == NULL) {
1769 PF_RULES_WUNLOCK();
1770 error = EBUSY;
1771 break;
1772 }
1773 bcopy(rule, &pr->rule, sizeof(struct pf_rule));
1774 pr->rule.u_states_cur = counter_u64_fetch(rule->states_cur);
1775 pr->rule.u_states_tot = counter_u64_fetch(rule->states_tot);
1776 pr->rule.u_src_nodes = counter_u64_fetch(rule->src_nodes);
1777 if (pf_anchor_copyout(ruleset, rule, pr)) {
1778 PF_RULES_WUNLOCK();
1779 error = EBUSY;
1780 break;
1781 }
1782 pf_addr_copyout(&pr->rule.src.addr);
1783 pf_addr_copyout(&pr->rule.dst.addr);
1784 for (i = 0; i < PF_SKIP_COUNT; ++i)
1785 if (rule->skip[i].ptr == NULL)
1786 pr->rule.skip[i].nr = -1;
1787 else
1788 pr->rule.skip[i].nr =
1789 rule->skip[i].ptr->nr;
1790
1791 if (pr->action == PF_GET_CLR_CNTR) {
1792 rule->evaluations = 0;
1793 rule->packets[0] = rule->packets[1] = 0;
1794 rule->bytes[0] = rule->bytes[1] = 0;
1795 counter_u64_zero(rule->states_tot);
1796 }
1797 PF_RULES_WUNLOCK();
1798 break;
1799 }
1800
1801 case DIOCCHANGERULE: {
1802 struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
1803 struct pf_ruleset *ruleset;
1804 struct pf_rule *oldrule = NULL, *newrule = NULL;
1805 struct pfi_kif *kif = NULL;
1806 struct pf_pooladdr *pa;
1807 u_int32_t nr = 0;
1808 int rs_num;
1809
1810 if (pcr->action < PF_CHANGE_ADD_HEAD ||
1811 pcr->action > PF_CHANGE_GET_TICKET) {
1812 error = EINVAL;
1813 break;
1814 }
1815 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1816 error = EINVAL;
1817 break;
1818 }
1819
1820 if (pcr->action != PF_CHANGE_REMOVE) {
1821 #ifndef INET
1822 if (pcr->rule.af == AF_INET) {
1823 error = EAFNOSUPPORT;
1824 break;
1825 }
1826 #endif /* INET */
1827 #ifndef INET6
1828 if (pcr->rule.af == AF_INET6) {
1829 error = EAFNOSUPPORT;
1830 break;
1831 }
1832 #endif /* INET6 */
1833 newrule = malloc(sizeof(*newrule), M_PFRULE, M_WAITOK);
1834 bcopy(&pcr->rule, newrule, sizeof(struct pf_rule));
1835 if (newrule->ifname[0])
1836 kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK);
1837 newrule->states_cur = counter_u64_alloc(M_WAITOK);
1838 newrule->states_tot = counter_u64_alloc(M_WAITOK);
1839 newrule->src_nodes = counter_u64_alloc(M_WAITOK);
1840 newrule->cuid = td->td_ucred->cr_ruid;
1841 newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
1842 TAILQ_INIT(&newrule->rpool.list);
1843 }
1844
1845 #define ERROUT(x) { error = (x); goto DIOCCHANGERULE_error; }
1846
1847 PF_RULES_WLOCK();
1848 if (!(pcr->action == PF_CHANGE_REMOVE ||
1849 pcr->action == PF_CHANGE_GET_TICKET) &&
1850 pcr->pool_ticket != V_ticket_pabuf)
1851 ERROUT(EBUSY);
1852
1853 ruleset = pf_find_ruleset(pcr->anchor);
1854 if (ruleset == NULL)
1855 ERROUT(EINVAL);
1856
1857 rs_num = pf_get_ruleset_number(pcr->rule.action);
1858 if (rs_num >= PF_RULESET_MAX)
1859 ERROUT(EINVAL);
1860
1861 if (pcr->action == PF_CHANGE_GET_TICKET) {
1862 pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
1863 ERROUT(0);
1864 } else if (pcr->ticket !=
1865 ruleset->rules[rs_num].active.ticket)
1866 ERROUT(EINVAL);
1867
1868 if (pcr->action != PF_CHANGE_REMOVE) {
1869 if (newrule->ifname[0]) {
1870 newrule->kif = pfi_kif_attach(kif,
1871 newrule->ifname);
1872 pfi_kif_ref(newrule->kif);
1873 } else
1874 newrule->kif = NULL;
1875
1876 if (newrule->rtableid > 0 &&
1877 newrule->rtableid >= rt_numfibs)
1878 error = EBUSY;
1879
1880 #ifdef ALTQ
1881 /* set queue IDs */
1882 if (newrule->qname[0] != 0) {
1883 if ((newrule->qid =
1884 pf_qname2qid(newrule->qname)) == 0)
1885 error = EBUSY;
1886 else if (newrule->pqname[0] != 0) {
1887 if ((newrule->pqid =
1888 pf_qname2qid(newrule->pqname)) == 0)
1889 error = EBUSY;
1890 } else
1891 newrule->pqid = newrule->qid;
1892 }
1893 #endif /* ALTQ */
1894 if (newrule->tagname[0])
1895 if ((newrule->tag =
1896 pf_tagname2tag(newrule->tagname)) == 0)
1897 error = EBUSY;
1898 if (newrule->match_tagname[0])
1899 if ((newrule->match_tag = pf_tagname2tag(
1900 newrule->match_tagname)) == 0)
1901 error = EBUSY;
1902 if (newrule->rt && !newrule->direction)
1903 error = EINVAL;
1904 if (!newrule->log)
1905 newrule->logif = 0;
1906 if (newrule->logif >= PFLOGIFS_MAX)
1907 error = EINVAL;
1908 if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af))
1909 error = ENOMEM;
1910 if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
1911 error = ENOMEM;
1912 if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
1913 error = EINVAL;
1914 TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
1915 if (pa->addr.type == PF_ADDR_TABLE) {
1916 pa->addr.p.tbl =
1917 pfr_attach_table(ruleset,
1918 pa->addr.v.tblname);
1919 if (pa->addr.p.tbl == NULL)
1920 error = ENOMEM;
1921 }
1922
1923 newrule->overload_tbl = NULL;
1924 if (newrule->overload_tblname[0]) {
1925 if ((newrule->overload_tbl = pfr_attach_table(
1926 ruleset, newrule->overload_tblname)) ==
1927 NULL)
1928 error = EINVAL;
1929 else
1930 newrule->overload_tbl->pfrkt_flags |=
1931 PFR_TFLAG_ACTIVE;
1932 }
1933
1934 pf_mv_pool(&V_pf_pabuf, &newrule->rpool.list);
1935 if (((((newrule->action == PF_NAT) ||
1936 (newrule->action == PF_RDR) ||
1937 (newrule->action == PF_BINAT) ||
1938 (newrule->rt > PF_NOPFROUTE)) &&
1939 !newrule->anchor)) &&
1940 (TAILQ_FIRST(&newrule->rpool.list) == NULL))
1941 error = EINVAL;
1942
1943 if (error) {
1944 pf_free_rule(newrule);
1945 PF_RULES_WUNLOCK();
1946 break;
1947 }
1948
1949 newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
1950 newrule->evaluations = 0;
1951 newrule->packets[0] = newrule->packets[1] = 0;
1952 newrule->bytes[0] = newrule->bytes[1] = 0;
1953 }
1954 pf_empty_pool(&V_pf_pabuf);
1955
1956 if (pcr->action == PF_CHANGE_ADD_HEAD)
1957 oldrule = TAILQ_FIRST(
1958 ruleset->rules[rs_num].active.ptr);
1959 else if (pcr->action == PF_CHANGE_ADD_TAIL)
1960 oldrule = TAILQ_LAST(
1961 ruleset->rules[rs_num].active.ptr, pf_rulequeue);
1962 else {
1963 oldrule = TAILQ_FIRST(
1964 ruleset->rules[rs_num].active.ptr);
1965 while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
1966 oldrule = TAILQ_NEXT(oldrule, entries);
1967 if (oldrule == NULL) {
1968 if (newrule != NULL)
1969 pf_free_rule(newrule);
1970 PF_RULES_WUNLOCK();
1971 error = EINVAL;
1972 break;
1973 }
1974 }
1975
1976 if (pcr->action == PF_CHANGE_REMOVE) {
1977 pf_unlink_rule(ruleset->rules[rs_num].active.ptr,
1978 oldrule);
1979 ruleset->rules[rs_num].active.rcount--;
1980 } else {
1981 if (oldrule == NULL)
1982 TAILQ_INSERT_TAIL(
1983 ruleset->rules[rs_num].active.ptr,
1984 newrule, entries);
1985 else if (pcr->action == PF_CHANGE_ADD_HEAD ||
1986 pcr->action == PF_CHANGE_ADD_BEFORE)
1987 TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
1988 else
1989 TAILQ_INSERT_AFTER(
1990 ruleset->rules[rs_num].active.ptr,
1991 oldrule, newrule, entries);
1992 ruleset->rules[rs_num].active.rcount++;
1993 }
1994
1995 nr = 0;
1996 TAILQ_FOREACH(oldrule,
1997 ruleset->rules[rs_num].active.ptr, entries)
1998 oldrule->nr = nr++;
1999
2000 ruleset->rules[rs_num].active.ticket++;
2001
2002 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
2003 pf_remove_if_empty_ruleset(ruleset);
2004
2005 PF_RULES_WUNLOCK();
2006 break;
2007
2008 #undef ERROUT
2009 DIOCCHANGERULE_error:
2010 PF_RULES_WUNLOCK();
2011 if (newrule != NULL) {
2012 counter_u64_free(newrule->states_cur);
2013 counter_u64_free(newrule->states_tot);
2014 counter_u64_free(newrule->src_nodes);
2015 free(newrule, M_PFRULE);
2016 }
2017 if (kif != NULL)
2018 free(kif, PFI_MTYPE);
2019 break;
2020 }
2021
2022 case DIOCCLRSTATES: {
2023 struct pf_state *s;
2024 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
2025 u_int i, killed = 0;
2026
2027 for (i = 0; i <= pf_hashmask; i++) {
2028 struct pf_idhash *ih = &V_pf_idhash[i];
2029
2030 relock_DIOCCLRSTATES:
2031 PF_HASHROW_LOCK(ih);
2032 LIST_FOREACH(s, &ih->states, entry)
2033 if (!psk->psk_ifname[0] ||
2034 !strcmp(psk->psk_ifname,
2035 s->kif->pfik_name)) {
2036 /*
2037 * Don't send out individual
2038 * delete messages.
2039 */
2040 s->state_flags |= PFSTATE_NOSYNC;
2041 pf_unlink_state(s, PF_ENTER_LOCKED);
2042 killed++;
2043 goto relock_DIOCCLRSTATES;
2044 }
2045 PF_HASHROW_UNLOCK(ih);
2046 }
2047 psk->psk_killed = killed;
2048 if (V_pfsync_clear_states_ptr != NULL)
2049 V_pfsync_clear_states_ptr(V_pf_status.hostid, psk->psk_ifname);
2050 break;
2051 }
2052
2053 case DIOCKILLSTATES: {
2054 struct pf_state *s;
2055 struct pf_state_key *sk;
2056 struct pf_addr *srcaddr, *dstaddr;
2057 u_int16_t srcport, dstport;
2058 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
2059 u_int i, killed = 0;
2060
2061 if (psk->psk_pfcmp.id) {
2062 if (psk->psk_pfcmp.creatorid == 0)
2063 psk->psk_pfcmp.creatorid = V_pf_status.hostid;
2064 if ((s = pf_find_state_byid(psk->psk_pfcmp.id,
2065 psk->psk_pfcmp.creatorid))) {
2066 pf_unlink_state(s, PF_ENTER_LOCKED);
2067 psk->psk_killed = 1;
2068 }
2069 break;
2070 }
2071
2072 for (i = 0; i <= pf_hashmask; i++) {
2073 struct pf_idhash *ih = &V_pf_idhash[i];
2074
2075 relock_DIOCKILLSTATES:
2076 PF_HASHROW_LOCK(ih);
2077 LIST_FOREACH(s, &ih->states, entry) {
2078 sk = s->key[PF_SK_WIRE];
2079 if (s->direction == PF_OUT) {
2080 srcaddr = &sk->addr[1];
2081 dstaddr = &sk->addr[0];
2082 srcport = sk->port[1];
2083 dstport = sk->port[0];
2084 } else {
2085 srcaddr = &sk->addr[0];
2086 dstaddr = &sk->addr[1];
2087 srcport = sk->port[0];
2088 dstport = sk->port[1];
2089 }
2090
2091 if ((!psk->psk_af || sk->af == psk->psk_af)
2092 && (!psk->psk_proto || psk->psk_proto ==
2093 sk->proto) &&
2094 PF_MATCHA(psk->psk_src.neg,
2095 &psk->psk_src.addr.v.a.addr,
2096 &psk->psk_src.addr.v.a.mask,
2097 srcaddr, sk->af) &&
2098 PF_MATCHA(psk->psk_dst.neg,
2099 &psk->psk_dst.addr.v.a.addr,
2100 &psk->psk_dst.addr.v.a.mask,
2101 dstaddr, sk->af) &&
2102 (psk->psk_src.port_op == 0 ||
2103 pf_match_port(psk->psk_src.port_op,
2104 psk->psk_src.port[0], psk->psk_src.port[1],
2105 srcport)) &&
2106 (psk->psk_dst.port_op == 0 ||
2107 pf_match_port(psk->psk_dst.port_op,
2108 psk->psk_dst.port[0], psk->psk_dst.port[1],
2109 dstport)) &&
2110 (!psk->psk_label[0] ||
2111 (s->rule.ptr->label[0] &&
2112 !strcmp(psk->psk_label,
2113 s->rule.ptr->label))) &&
2114 (!psk->psk_ifname[0] ||
2115 !strcmp(psk->psk_ifname,
2116 s->kif->pfik_name))) {
2117 pf_unlink_state(s, PF_ENTER_LOCKED);
2118 killed++;
2119 goto relock_DIOCKILLSTATES;
2120 }
2121 }
2122 PF_HASHROW_UNLOCK(ih);
2123 }
2124 psk->psk_killed = killed;
2125 break;
2126 }
2127
2128 case DIOCADDSTATE: {
2129 struct pfioc_state *ps = (struct pfioc_state *)addr;
2130 struct pfsync_state *sp = &ps->state;
2131
2132 if (sp->timeout >= PFTM_MAX) {
2133 error = EINVAL;
2134 break;
2135 }
2136 if (V_pfsync_state_import_ptr != NULL) {
2137 PF_RULES_RLOCK();
2138 error = V_pfsync_state_import_ptr(sp, PFSYNC_SI_IOCTL);
2139 PF_RULES_RUNLOCK();
2140 } else
2141 error = EOPNOTSUPP;
2142 break;
2143 }
2144
2145 case DIOCGETSTATE: {
2146 struct pfioc_state *ps = (struct pfioc_state *)addr;
2147 struct pf_state *s;
2148
2149 s = pf_find_state_byid(ps->state.id, ps->state.creatorid);
2150 if (s == NULL) {
2151 error = ENOENT;
2152 break;
2153 }
2154
2155 pfsync_state_export(&ps->state, s);
2156 PF_STATE_UNLOCK(s);
2157 break;
2158 }
2159
2160 case DIOCGETSTATES: {
2161 struct pfioc_states *ps = (struct pfioc_states *)addr;
2162 struct pf_state *s;
2163 struct pfsync_state *pstore, *p;
2164 int i, nr;
2165
2166 if (ps->ps_len == 0) {
2167 nr = uma_zone_get_cur(V_pf_state_z);
2168 ps->ps_len = sizeof(struct pfsync_state) * nr;
2169 break;
2170 }
2171
2172 p = pstore = malloc(ps->ps_len, M_TEMP, M_WAITOK);
2173 nr = 0;
2174
2175 for (i = 0; i <= pf_hashmask; i++) {
2176 struct pf_idhash *ih = &V_pf_idhash[i];
2177
2178 PF_HASHROW_LOCK(ih);
2179 LIST_FOREACH(s, &ih->states, entry) {
2180
2181 if (s->timeout == PFTM_UNLINKED)
2182 continue;
2183
2184 if ((nr+1) * sizeof(*p) > ps->ps_len) {
2185 PF_HASHROW_UNLOCK(ih);
2186 goto DIOCGETSTATES_full;
2187 }
2188 pfsync_state_export(p, s);
2189 p++;
2190 nr++;
2191 }
2192 PF_HASHROW_UNLOCK(ih);
2193 }
2194 DIOCGETSTATES_full:
2195 error = copyout(pstore, ps->ps_states,
2196 sizeof(struct pfsync_state) * nr);
2197 if (error) {
2198 free(pstore, M_TEMP);
2199 break;
2200 }
2201 ps->ps_len = sizeof(struct pfsync_state) * nr;
2202 free(pstore, M_TEMP);
2203
2204 break;
2205 }
2206
2207 case DIOCGETSTATUS: {
2208 struct pf_status *s = (struct pf_status *)addr;
2209
2210 PF_RULES_RLOCK();
2211 s->running = V_pf_status.running;
2212 s->since = V_pf_status.since;
2213 s->debug = V_pf_status.debug;
2214 s->hostid = V_pf_status.hostid;
2215 s->states = V_pf_status.states;
2216 s->src_nodes = V_pf_status.src_nodes;
2217
2218 for (int i = 0; i < PFRES_MAX; i++)
2219 s->counters[i] =
2220 counter_u64_fetch(V_pf_status.counters[i]);
2221 for (int i = 0; i < LCNT_MAX; i++)
2222 s->lcounters[i] =
2223 counter_u64_fetch(V_pf_status.lcounters[i]);
2224 for (int i = 0; i < FCNT_MAX; i++)
2225 s->fcounters[i] =
2226 counter_u64_fetch(V_pf_status.fcounters[i]);
2227 for (int i = 0; i < SCNT_MAX; i++)
2228 s->scounters[i] =
2229 counter_u64_fetch(V_pf_status.scounters[i]);
2230
2231 bcopy(V_pf_status.ifname, s->ifname, IFNAMSIZ);
2232 bcopy(V_pf_status.pf_chksum, s->pf_chksum,
2233 PF_MD5_DIGEST_LENGTH);
2234
2235 pfi_update_status(s->ifname, s);
2236 PF_RULES_RUNLOCK();
2237 break;
2238 }
2239
2240 case DIOCSETSTATUSIF: {
2241 struct pfioc_if *pi = (struct pfioc_if *)addr;
2242
2243 if (pi->ifname[0] == 0) {
2244 bzero(V_pf_status.ifname, IFNAMSIZ);
2245 break;
2246 }
2247 PF_RULES_WLOCK();
2248 strlcpy(V_pf_status.ifname, pi->ifname, IFNAMSIZ);
2249 PF_RULES_WUNLOCK();
2250 break;
2251 }
2252
2253 case DIOCCLRSTATUS: {
2254 PF_RULES_WLOCK();
2255 for (int i = 0; i < PFRES_MAX; i++)
2256 counter_u64_zero(V_pf_status.counters[i]);
2257 for (int i = 0; i < FCNT_MAX; i++)
2258 counter_u64_zero(V_pf_status.fcounters[i]);
2259 for (int i = 0; i < SCNT_MAX; i++)
2260 counter_u64_zero(V_pf_status.scounters[i]);
2261 for (int i = 0; i < LCNT_MAX; i++)
2262 counter_u64_zero(V_pf_status.lcounters[i]);
2263 V_pf_status.since = time_second;
2264 if (*V_pf_status.ifname)
2265 pfi_update_status(V_pf_status.ifname, NULL);
2266 PF_RULES_WUNLOCK();
2267 break;
2268 }
2269
2270 case DIOCNATLOOK: {
2271 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
2272 struct pf_state_key *sk;
2273 struct pf_state *state;
2274 struct pf_state_key_cmp key;
2275 int m = 0, direction = pnl->direction;
2276 int sidx, didx;
2277
2278 /* NATLOOK src and dst are reversed, so reverse sidx/didx */
2279 sidx = (direction == PF_IN) ? 1 : 0;
2280 didx = (direction == PF_IN) ? 0 : 1;
2281
2282 if (!pnl->proto ||
2283 PF_AZERO(&pnl->saddr, pnl->af) ||
2284 PF_AZERO(&pnl->daddr, pnl->af) ||
2285 ((pnl->proto == IPPROTO_TCP ||
2286 pnl->proto == IPPROTO_UDP) &&
2287 (!pnl->dport || !pnl->sport)))
2288 error = EINVAL;
2289 else {
2290 bzero(&key, sizeof(key));
2291 key.af = pnl->af;
2292 key.proto = pnl->proto;
2293 PF_ACPY(&key.addr[sidx], &pnl->saddr, pnl->af);
2294 key.port[sidx] = pnl->sport;
2295 PF_ACPY(&key.addr[didx], &pnl->daddr, pnl->af);
2296 key.port[didx] = pnl->dport;
2297
2298 state = pf_find_state_all(&key, direction, &m);
2299
2300 if (m > 1)
2301 error = E2BIG; /* more than one state */
2302 else if (state != NULL) {
2303 /* XXXGL: not locked read */
2304 sk = state->key[sidx];
2305 PF_ACPY(&pnl->rsaddr, &sk->addr[sidx], sk->af);
2306 pnl->rsport = sk->port[sidx];
2307 PF_ACPY(&pnl->rdaddr, &sk->addr[didx], sk->af);
2308 pnl->rdport = sk->port[didx];
2309 } else
2310 error = ENOENT;
2311 }
2312 break;
2313 }
2314
2315 case DIOCSETTIMEOUT: {
2316 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
2317 int old;
2318
2319 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
2320 pt->seconds < 0) {
2321 error = EINVAL;
2322 break;
2323 }
2324 PF_RULES_WLOCK();
2325 old = V_pf_default_rule.timeout[pt->timeout];
2326 if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
2327 pt->seconds = 1;
2328 V_pf_default_rule.timeout[pt->timeout] = pt->seconds;
2329 if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
2330 wakeup(pf_purge_thread);
2331 pt->seconds = old;
2332 PF_RULES_WUNLOCK();
2333 break;
2334 }
2335
2336 case DIOCGETTIMEOUT: {
2337 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
2338
2339 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
2340 error = EINVAL;
2341 break;
2342 }
2343 PF_RULES_RLOCK();
2344 pt->seconds = V_pf_default_rule.timeout[pt->timeout];
2345 PF_RULES_RUNLOCK();
2346 break;
2347 }
2348
2349 case DIOCGETLIMIT: {
2350 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
2351
2352 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
2353 error = EINVAL;
2354 break;
2355 }
2356 PF_RULES_RLOCK();
2357 pl->limit = V_pf_limits[pl->index].limit;
2358 PF_RULES_RUNLOCK();
2359 break;
2360 }
2361
2362 case DIOCSETLIMIT: {
2363 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
2364 int old_limit;
2365
2366 PF_RULES_WLOCK();
2367 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
2368 V_pf_limits[pl->index].zone == NULL) {
2369 PF_RULES_WUNLOCK();
2370 error = EINVAL;
2371 break;
2372 }
2373 uma_zone_set_max(V_pf_limits[pl->index].zone, pl->limit);
2374 old_limit = V_pf_limits[pl->index].limit;
2375 V_pf_limits[pl->index].limit = pl->limit;
2376 pl->limit = old_limit;
2377 PF_RULES_WUNLOCK();
2378 break;
2379 }
2380
2381 case DIOCSETDEBUG: {
2382 u_int32_t *level = (u_int32_t *)addr;
2383
2384 PF_RULES_WLOCK();
2385 V_pf_status.debug = *level;
2386 PF_RULES_WUNLOCK();
2387 break;
2388 }
2389
2390 case DIOCCLRRULECTRS: {
2391 /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
2392 struct pf_ruleset *ruleset = &pf_main_ruleset;
2393 struct pf_rule *rule;
2394
2395 PF_RULES_WLOCK();
2396 TAILQ_FOREACH(rule,
2397 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
2398 rule->evaluations = 0;
2399 rule->packets[0] = rule->packets[1] = 0;
2400 rule->bytes[0] = rule->bytes[1] = 0;
2401 }
2402 PF_RULES_WUNLOCK();
2403 break;
2404 }
2405
2406 case DIOCGIFSPEEDV0:
2407 case DIOCGIFSPEEDV1: {
2408 struct pf_ifspeed_v1 *psp = (struct pf_ifspeed_v1 *)addr;
2409 struct pf_ifspeed_v1 ps;
2410 struct ifnet *ifp;
2411
2412 if (psp->ifname[0] != 0) {
2413 /* Can we completely trust user-land? */
2414 strlcpy(ps.ifname, psp->ifname, IFNAMSIZ);
2415 ifp = ifunit(ps.ifname);
2416 if (ifp != NULL) {
2417 psp->baudrate32 =
2418 (u_int32_t)uqmin(ifp->if_baudrate, UINT_MAX);
2419 if (cmd == DIOCGIFSPEEDV1)
2420 psp->baudrate = ifp->if_baudrate;
2421 } else
2422 error = EINVAL;
2423 } else
2424 error = EINVAL;
2425 break;
2426 }
2427
2428 #ifdef ALTQ
2429 case DIOCSTARTALTQ: {
2430 struct pf_altq *altq;
2431
2432 PF_RULES_WLOCK();
2433 /* enable all altq interfaces on active list */
2434 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
2435 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
2436 error = pf_enable_altq(altq);
2437 if (error != 0)
2438 break;
2439 }
2440 }
2441 if (error == 0)
2442 V_pf_altq_running = 1;
2443 PF_RULES_WUNLOCK();
2444 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
2445 break;
2446 }
2447
2448 case DIOCSTOPALTQ: {
2449 struct pf_altq *altq;
2450
2451 PF_RULES_WLOCK();
2452 /* disable all altq interfaces on active list */
2453 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
2454 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
2455 error = pf_disable_altq(altq);
2456 if (error != 0)
2457 break;
2458 }
2459 }
2460 if (error == 0)
2461 V_pf_altq_running = 0;
2462 PF_RULES_WUNLOCK();
2463 DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
2464 break;
2465 }
2466
2467 case DIOCADDALTQV0:
2468 case DIOCADDALTQV1: {
2469 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
2470 struct pf_altq *altq, *a;
2471 struct ifnet *ifp;
2472
2473 altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK | M_ZERO);
2474 error = pf_import_kaltq(pa, altq, IOCPARM_LEN(cmd));
2475 if (error)
2476 break;
2477 altq->local_flags = 0;
2478
2479 PF_RULES_WLOCK();
2480 if (pa->ticket != V_ticket_altqs_inactive) {
2481 PF_RULES_WUNLOCK();
2482 free(altq, M_PFALTQ);
2483 error = EBUSY;
2484 break;
2485 }
2486
2487 /*
2488 * if this is for a queue, find the discipline and
2489 * copy the necessary fields
2490 */
2491 if (altq->qname[0] != 0) {
2492 if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
2493 PF_RULES_WUNLOCK();
2494 error = EBUSY;
2495 free(altq, M_PFALTQ);
2496 break;
2497 }
2498 altq->altq_disc = NULL;
2499 TAILQ_FOREACH(a, V_pf_altq_ifs_inactive, entries) {
2500 if (strncmp(a->ifname, altq->ifname,
2501 IFNAMSIZ) == 0) {
2502 altq->altq_disc = a->altq_disc;
2503 break;
2504 }
2505 }
2506 }
2507
2508 if ((ifp = ifunit(altq->ifname)) == NULL)
2509 altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
2510 else
2511 error = altq_add(ifp, altq);
2512
2513 if (error) {
2514 PF_RULES_WUNLOCK();
2515 free(altq, M_PFALTQ);
2516 break;
2517 }
2518
2519 if (altq->qname[0] != 0)
2520 TAILQ_INSERT_TAIL(V_pf_altqs_inactive, altq, entries);
2521 else
2522 TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, altq, entries);
2523 /* version error check done on import above */
2524 pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
2525 PF_RULES_WUNLOCK();
2526 break;
2527 }
2528
2529 case DIOCGETALTQSV0:
2530 case DIOCGETALTQSV1: {
2531 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
2532 struct pf_altq *altq;
2533
2534 PF_RULES_RLOCK();
2535 pa->nr = 0;
2536 TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries)
2537 pa->nr++;
2538 TAILQ_FOREACH(altq, V_pf_altqs_active, entries)
2539 pa->nr++;
2540 pa->ticket = V_ticket_altqs_active;
2541 PF_RULES_RUNLOCK();
2542 break;
2543 }
2544
2545 case DIOCGETALTQV0:
2546 case DIOCGETALTQV1: {
2547 struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
2548 struct pf_altq *altq;
2549
2550 PF_RULES_RLOCK();
2551 if (pa->ticket != V_ticket_altqs_active) {
2552 PF_RULES_RUNLOCK();
2553 error = EBUSY;
2554 break;
2555 }
2556 altq = pf_altq_get_nth_active(pa->nr);
2557 if (altq == NULL) {
2558 PF_RULES_RUNLOCK();
2559 error = EBUSY;
2560 break;
2561 }
2562 pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
2563 PF_RULES_RUNLOCK();
2564 break;
2565 }
2566
2567 case DIOCCHANGEALTQV0:
2568 case DIOCCHANGEALTQV1:
2569 /* CHANGEALTQ not supported yet! */
2570 error = ENODEV;
2571 break;
2572
2573 case DIOCGETQSTATSV0:
2574 case DIOCGETQSTATSV1: {
2575 struct pfioc_qstats_v1 *pq = (struct pfioc_qstats_v1 *)addr;
2576 struct pf_altq *altq;
2577 int nbytes;
2578 u_int32_t version;
2579
2580 PF_RULES_RLOCK();
2581 if (pq->ticket != V_ticket_altqs_active) {
2582 PF_RULES_RUNLOCK();
2583 error = EBUSY;
2584 break;
2585 }
2586 nbytes = pq->nbytes;
2587 altq = pf_altq_get_nth_active(pq->nr);
2588 if (altq == NULL) {
2589 PF_RULES_RUNLOCK();
2590 error = EBUSY;
2591 break;
2592 }
2593
2594 if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
2595 PF_RULES_RUNLOCK();
2596 error = ENXIO;
2597 break;
2598 }
2599 PF_RULES_RUNLOCK();
2600 if (cmd == DIOCGETQSTATSV0)
2601 version = 0; /* DIOCGETQSTATSV0 means stats struct v0 */
2602 else
2603 version = pq->version;
2604 error = altq_getqstats(altq, pq->buf, &nbytes, version);
2605 if (error == 0) {
2606 pq->scheduler = altq->scheduler;
2607 pq->nbytes = nbytes;
2608 }
2609 break;
2610 }
2611 #endif /* ALTQ */
2612
2613 case DIOCBEGINADDRS: {
2614 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2615
2616 PF_RULES_WLOCK();
2617 pf_empty_pool(&V_pf_pabuf);
2618 pp->ticket = ++V_ticket_pabuf;
2619 PF_RULES_WUNLOCK();
2620 break;
2621 }
2622
2623 case DIOCADDADDR: {
2624 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2625 struct pf_pooladdr *pa;
2626 struct pfi_kif *kif = NULL;
2627
2628 #ifndef INET
2629 if (pp->af == AF_INET) {
2630 error = EAFNOSUPPORT;
2631 break;
2632 }
2633 #endif /* INET */
2634 #ifndef INET6
2635 if (pp->af == AF_INET6) {
2636 error = EAFNOSUPPORT;
2637 break;
2638 }
2639 #endif /* INET6 */
2640 if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
2641 pp->addr.addr.type != PF_ADDR_DYNIFTL &&
2642 pp->addr.addr.type != PF_ADDR_TABLE) {
2643 error = EINVAL;
2644 break;
2645 }
2646 pa = malloc(sizeof(*pa), M_PFRULE, M_WAITOK);
2647 bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
2648 if (pa->ifname[0])
2649 kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK);
2650 PF_RULES_WLOCK();
2651 if (pp->ticket != V_ticket_pabuf) {
2652 PF_RULES_WUNLOCK();
2653 if (pa->ifname[0])
2654 free(kif, PFI_MTYPE);
2655 free(pa, M_PFRULE);
2656 error = EBUSY;
2657 break;
2658 }
2659 if (pa->ifname[0]) {
2660 pa->kif = pfi_kif_attach(kif, pa->ifname);
2661 pfi_kif_ref(pa->kif);
2662 } else
2663 pa->kif = NULL;
2664 if (pa->addr.type == PF_ADDR_DYNIFTL && ((error =
2665 pfi_dynaddr_setup(&pa->addr, pp->af)) != 0)) {
2666 if (pa->ifname[0])
2667 pfi_kif_unref(pa->kif);
2668 PF_RULES_WUNLOCK();
2669 free(pa, M_PFRULE);
2670 break;
2671 }
2672 TAILQ_INSERT_TAIL(&V_pf_pabuf, pa, entries);
2673 PF_RULES_WUNLOCK();
2674 break;
2675 }
2676
2677 case DIOCGETADDRS: {
2678 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2679 struct pf_pool *pool;
2680 struct pf_pooladdr *pa;
2681
2682 PF_RULES_RLOCK();
2683 pp->nr = 0;
2684 pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
2685 pp->r_num, 0, 1, 0);
2686 if (pool == NULL) {
2687 PF_RULES_RUNLOCK();
2688 error = EBUSY;
2689 break;
2690 }
2691 TAILQ_FOREACH(pa, &pool->list, entries)
2692 pp->nr++;
2693 PF_RULES_RUNLOCK();
2694 break;
2695 }
2696
2697 case DIOCGETADDR: {
2698 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2699 struct pf_pool *pool;
2700 struct pf_pooladdr *pa;
2701 u_int32_t nr = 0;
2702
2703 PF_RULES_RLOCK();
2704 pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
2705 pp->r_num, 0, 1, 1);
2706 if (pool == NULL) {
2707 PF_RULES_RUNLOCK();
2708 error = EBUSY;
2709 break;
2710 }
2711 pa = TAILQ_FIRST(&pool->list);
2712 while ((pa != NULL) && (nr < pp->nr)) {
2713 pa = TAILQ_NEXT(pa, entries);
2714 nr++;
2715 }
2716 if (pa == NULL) {
2717 PF_RULES_RUNLOCK();
2718 error = EBUSY;
2719 break;
2720 }
2721 bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
2722 pf_addr_copyout(&pp->addr.addr);
2723 PF_RULES_RUNLOCK();
2724 break;
2725 }
2726
2727 case DIOCCHANGEADDR: {
2728 struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr;
2729 struct pf_pool *pool;
2730 struct pf_pooladdr *oldpa = NULL, *newpa = NULL;
2731 struct pf_ruleset *ruleset;
2732 struct pfi_kif *kif = NULL;
2733
2734 if (pca->action < PF_CHANGE_ADD_HEAD ||
2735 pca->action > PF_CHANGE_REMOVE) {
2736 error = EINVAL;
2737 break;
2738 }
2739 if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
2740 pca->addr.addr.type != PF_ADDR_DYNIFTL &&
2741 pca->addr.addr.type != PF_ADDR_TABLE) {
2742 error = EINVAL;
2743 break;
2744 }
2745
2746 if (pca->action != PF_CHANGE_REMOVE) {
2747 #ifndef INET
2748 if (pca->af == AF_INET) {
2749 error = EAFNOSUPPORT;
2750 break;
2751 }
2752 #endif /* INET */
2753 #ifndef INET6
2754 if (pca->af == AF_INET6) {
2755 error = EAFNOSUPPORT;
2756 break;
2757 }
2758 #endif /* INET6 */
2759 newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK);
2760 bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
2761 if (newpa->ifname[0])
2762 kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK);
2763 newpa->kif = NULL;
2764 }
2765
2766 #define ERROUT(x) { error = (x); goto DIOCCHANGEADDR_error; }
2767 PF_RULES_WLOCK();
2768 ruleset = pf_find_ruleset(pca->anchor);
2769 if (ruleset == NULL)
2770 ERROUT(EBUSY);
2771
2772 pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
2773 pca->r_num, pca->r_last, 1, 1);
2774 if (pool == NULL)
2775 ERROUT(EBUSY);
2776
2777 if (pca->action != PF_CHANGE_REMOVE) {
2778 if (newpa->ifname[0]) {
2779 newpa->kif = pfi_kif_attach(kif, newpa->ifname);
2780 pfi_kif_ref(newpa->kif);
2781 kif = NULL;
2782 }
2783
2784 switch (newpa->addr.type) {
2785 case PF_ADDR_DYNIFTL:
2786 error = pfi_dynaddr_setup(&newpa->addr,
2787 pca->af);
2788 break;
2789 case PF_ADDR_TABLE:
2790 newpa->addr.p.tbl = pfr_attach_table(ruleset,
2791 newpa->addr.v.tblname);
2792 if (newpa->addr.p.tbl == NULL)
2793 error = ENOMEM;
2794 break;
2795 }
2796 if (error)
2797 goto DIOCCHANGEADDR_error;
2798 }
2799
2800 switch (pca->action) {
2801 case PF_CHANGE_ADD_HEAD:
2802 oldpa = TAILQ_FIRST(&pool->list);
2803 break;
2804 case PF_CHANGE_ADD_TAIL:
2805 oldpa = TAILQ_LAST(&pool->list, pf_palist);
2806 break;
2807 default:
2808 oldpa = TAILQ_FIRST(&pool->list);
2809 for (int i = 0; oldpa && i < pca->nr; i++)
2810 oldpa = TAILQ_NEXT(oldpa, entries);
2811
2812 if (oldpa == NULL)
2813 ERROUT(EINVAL);
2814 }
2815
2816 if (pca->action == PF_CHANGE_REMOVE) {
2817 TAILQ_REMOVE(&pool->list, oldpa, entries);
2818 switch (oldpa->addr.type) {
2819 case PF_ADDR_DYNIFTL:
2820 pfi_dynaddr_remove(oldpa->addr.p.dyn);
2821 break;
2822 case PF_ADDR_TABLE:
2823 pfr_detach_table(oldpa->addr.p.tbl);
2824 break;
2825 }
2826 if (oldpa->kif)
2827 pfi_kif_unref(oldpa->kif);
2828 free(oldpa, M_PFRULE);
2829 } else {
2830 if (oldpa == NULL)
2831 TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
2832 else if (pca->action == PF_CHANGE_ADD_HEAD ||
2833 pca->action == PF_CHANGE_ADD_BEFORE)
2834 TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
2835 else
2836 TAILQ_INSERT_AFTER(&pool->list, oldpa,
2837 newpa, entries);
2838 }
2839
2840 pool->cur = TAILQ_FIRST(&pool->list);
2841 PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, pca->af);
2842 PF_RULES_WUNLOCK();
2843 break;
2844
2845 #undef ERROUT
2846 DIOCCHANGEADDR_error:
2847 if (newpa != NULL) {
2848 if (newpa->kif)
2849 pfi_kif_unref(newpa->kif);
2850 free(newpa, M_PFRULE);
2851 }
2852 PF_RULES_WUNLOCK();
2853 if (kif != NULL)
2854 free(kif, PFI_MTYPE);
2855 break;
2856 }
2857
2858 case DIOCGETRULESETS: {
2859 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
2860 struct pf_ruleset *ruleset;
2861 struct pf_anchor *anchor;
2862
2863 PF_RULES_RLOCK();
2864 pr->path[sizeof(pr->path) - 1] = 0;
2865 if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
2866 PF_RULES_RUNLOCK();
2867 error = ENOENT;
2868 break;
2869 }
2870 pr->nr = 0;
2871 if (ruleset->anchor == NULL) {
2872 /* XXX kludge for pf_main_ruleset */
2873 RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors)
2874 if (anchor->parent == NULL)
2875 pr->nr++;
2876 } else {
2877 RB_FOREACH(anchor, pf_anchor_node,
2878 &ruleset->anchor->children)
2879 pr->nr++;
2880 }
2881 PF_RULES_RUNLOCK();
2882 break;
2883 }
2884
2885 case DIOCGETRULESET: {
2886 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
2887 struct pf_ruleset *ruleset;
2888 struct pf_anchor *anchor;
2889 u_int32_t nr = 0;
2890
2891 PF_RULES_RLOCK();
2892 pr->path[sizeof(pr->path) - 1] = 0;
2893 if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
2894 PF_RULES_RUNLOCK();
2895 error = ENOENT;
2896 break;
2897 }
2898 pr->name[0] = 0;
2899 if (ruleset->anchor == NULL) {
2900 /* XXX kludge for pf_main_ruleset */
2901 RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors)
2902 if (anchor->parent == NULL && nr++ == pr->nr) {
2903 strlcpy(pr->name, anchor->name,
2904 sizeof(pr->name));
2905 break;
2906 }
2907 } else {
2908 RB_FOREACH(anchor, pf_anchor_node,
2909 &ruleset->anchor->children)
2910 if (nr++ == pr->nr) {
2911 strlcpy(pr->name, anchor->name,
2912 sizeof(pr->name));
2913 break;
2914 }
2915 }
2916 if (!pr->name[0])
2917 error = EBUSY;
2918 PF_RULES_RUNLOCK();
2919 break;
2920 }
2921
2922 case DIOCRCLRTABLES: {
2923 struct pfioc_table *io = (struct pfioc_table *)addr;
2924
2925 if (io->pfrio_esize != 0) {
2926 error = ENODEV;
2927 break;
2928 }
2929 PF_RULES_WLOCK();
2930 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
2931 io->pfrio_flags | PFR_FLAG_USERIOCTL);
2932 PF_RULES_WUNLOCK();
2933 break;
2934 }
2935
2936 case DIOCRADDTABLES: {
2937 struct pfioc_table *io = (struct pfioc_table *)addr;
2938 struct pfr_table *pfrts;
2939 size_t totlen;
2940
2941 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2942 error = ENODEV;
2943 break;
2944 }
2945
2946 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
2947 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
2948 error = ENOMEM;
2949 break;
2950 }
2951
2952 totlen = io->pfrio_size * sizeof(struct pfr_table);
2953 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
2954 M_TEMP, M_WAITOK);
2955 error = copyin(io->pfrio_buffer, pfrts, totlen);
2956 if (error) {
2957 free(pfrts, M_TEMP);
2958 break;
2959 }
2960 PF_RULES_WLOCK();
2961 error = pfr_add_tables(pfrts, io->pfrio_size,
2962 &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2963 PF_RULES_WUNLOCK();
2964 free(pfrts, M_TEMP);
2965 break;
2966 }
2967
2968 case DIOCRDELTABLES: {
2969 struct pfioc_table *io = (struct pfioc_table *)addr;
2970 struct pfr_table *pfrts;
2971 size_t totlen;
2972
2973 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2974 error = ENODEV;
2975 break;
2976 }
2977
2978 if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
2979 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
2980 error = ENOMEM;
2981 break;
2982 }
2983
2984 totlen = io->pfrio_size * sizeof(struct pfr_table);
2985 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
2986 M_TEMP, M_WAITOK);
2987 error = copyin(io->pfrio_buffer, pfrts, totlen);
2988 if (error) {
2989 free(pfrts, M_TEMP);
2990 break;
2991 }
2992 PF_RULES_WLOCK();
2993 error = pfr_del_tables(pfrts, io->pfrio_size,
2994 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2995 PF_RULES_WUNLOCK();
2996 free(pfrts, M_TEMP);
2997 break;
2998 }
2999
3000 case DIOCRGETTABLES: {
3001 struct pfioc_table *io = (struct pfioc_table *)addr;
3002 struct pfr_table *pfrts;
3003 size_t totlen, n;
3004
3005 if (io->pfrio_esize != sizeof(struct pfr_table)) {
3006 error = ENODEV;
3007 break;
3008 }
3009 PF_RULES_RLOCK();
3010 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
3011 io->pfrio_size = min(io->pfrio_size, n);
3012
3013 totlen = io->pfrio_size * sizeof(struct pfr_table);
3014
3015 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
3016 M_TEMP, M_NOWAIT);
3017 if (pfrts == NULL) {
3018 error = ENOMEM;
3019 PF_RULES_RUNLOCK();
3020 break;
3021 }
3022 error = pfr_get_tables(&io->pfrio_table, pfrts,
3023 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
3024 PF_RULES_RUNLOCK();
3025 if (error == 0)
3026 error = copyout(pfrts, io->pfrio_buffer, totlen);
3027 free(pfrts, M_TEMP);
3028 break;
3029 }
3030
3031 case DIOCRGETTSTATS: {
3032 struct pfioc_table *io = (struct pfioc_table *)addr;
3033 struct pfr_tstats *pfrtstats;
3034 size_t totlen, n;
3035
3036 if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
3037 error = ENODEV;
3038 break;
3039 }
3040 PF_RULES_WLOCK();
3041 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
3042 io->pfrio_size = min(io->pfrio_size, n);
3043
3044 totlen = io->pfrio_size * sizeof(struct pfr_tstats);
3045 pfrtstats = mallocarray(io->pfrio_size,
3046 sizeof(struct pfr_tstats), M_TEMP, M_NOWAIT);
3047 if (pfrtstats == NULL) {
3048 error = ENOMEM;
3049 PF_RULES_WUNLOCK();
3050 break;
3051 }
3052 error = pfr_get_tstats(&io->pfrio_table, pfrtstats,
3053 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
3054 PF_RULES_WUNLOCK();
3055 if (error == 0)
3056 error = copyout(pfrtstats, io->pfrio_buffer, totlen);
3057 free(pfrtstats, M_TEMP);
3058 break;
3059 }
3060
3061 case DIOCRCLRTSTATS: {
3062 struct pfioc_table *io = (struct pfioc_table *)addr;
3063 struct pfr_table *pfrts;
3064 size_t totlen, n;
3065
3066 if (io->pfrio_esize != sizeof(struct pfr_table)) {
3067 error = ENODEV;
3068 break;
3069 }
3070
3071 PF_RULES_WLOCK();
3072 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
3073 io->pfrio_size = min(io->pfrio_size, n);
3074
3075 totlen = io->pfrio_size * sizeof(struct pfr_table);
3076 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
3077 M_TEMP, M_NOWAIT);
3078 if (pfrts == NULL) {
3079 error = ENOMEM;
3080 PF_RULES_WUNLOCK();
3081 break;
3082 }
3083 error = copyin(io->pfrio_buffer, pfrts, totlen);
3084 if (error) {
3085 free(pfrts, M_TEMP);
3086 PF_RULES_WUNLOCK();
3087 break;
3088 }
3089 error = pfr_clr_tstats(pfrts, io->pfrio_size,
3090 &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
3091 PF_RULES_WUNLOCK();
3092 free(pfrts, M_TEMP);
3093 break;
3094 }
3095
3096 case DIOCRSETTFLAGS: {
3097 struct pfioc_table *io = (struct pfioc_table *)addr;
3098 struct pfr_table *pfrts;
3099 size_t totlen, n;
3100
3101 if (io->pfrio_esize != sizeof(struct pfr_table)) {
3102 error = ENODEV;
3103 break;
3104 }
3105
3106 PF_RULES_RLOCK();
3107 n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
3108 io->pfrio_size = min(io->pfrio_size, n);
3109 PF_RULES_RUNLOCK();
3110
3111 totlen = io->pfrio_size * sizeof(struct pfr_table);
3112 pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
3113 M_TEMP, M_WAITOK);
3114 error = copyin(io->pfrio_buffer, pfrts, totlen);
3115 if (error) {
3116 free(pfrts, M_TEMP);
3117 break;
3118 }
3119 PF_RULES_WLOCK();
3120 error = pfr_set_tflags(pfrts, io->pfrio_size,
3121 io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
3122 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
3123 PF_RULES_WUNLOCK();
3124 free(pfrts, M_TEMP);
3125 break;
3126 }
3127
3128 case DIOCRCLRADDRS: {
3129 struct pfioc_table *io = (struct pfioc_table *)addr;
3130
3131 if (io->pfrio_esize != 0) {
3132 error = ENODEV;
3133 break;
3134 }
3135 PF_RULES_WLOCK();
3136 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
3137 io->pfrio_flags | PFR_FLAG_USERIOCTL);
3138 PF_RULES_WUNLOCK();
3139 break;
3140 }
3141
3142 case DIOCRADDADDRS: {
3143 struct pfioc_table *io = (struct pfioc_table *)addr;
3144 struct pfr_addr *pfras;
3145 size_t totlen;
3146
3147 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
3148 error = ENODEV;
3149 break;
3150 }
3151 if (io->pfrio_size < 0 ||
3152 io->pfrio_size > pf_ioctl_maxcount ||
3153 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
3154 error = EINVAL;
3155 break;
3156 }
3157 totlen = io->pfrio_size * sizeof(struct pfr_addr);
3158 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
3159 M_TEMP, M_NOWAIT);
3160 if (! pfras) {
3161 error = ENOMEM;
3162 break;
3163 }
3164 error = copyin(io->pfrio_buffer, pfras, totlen);
3165 if (error) {
3166 free(pfras, M_TEMP);
3167 break;
3168 }
3169 PF_RULES_WLOCK();
3170 error = pfr_add_addrs(&io->pfrio_table, pfras,
3171 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
3172 PFR_FLAG_USERIOCTL);
3173 PF_RULES_WUNLOCK();
3174 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
3175 error = copyout(pfras, io->pfrio_buffer, totlen);
3176 free(pfras, M_TEMP);
3177 break;
3178 }
3179
3180 case DIOCRDELADDRS: {
3181 struct pfioc_table *io = (struct pfioc_table *)addr;
3182 struct pfr_addr *pfras;
3183 size_t totlen;
3184
3185 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
3186 error = ENODEV;
3187 break;
3188 }
3189 if (io->pfrio_size < 0 ||
3190 io->pfrio_size > pf_ioctl_maxcount ||
3191 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
3192 error = EINVAL;
3193 break;
3194 }
3195 totlen = io->pfrio_size * sizeof(struct pfr_addr);
3196 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
3197 M_TEMP, M_NOWAIT);
3198 if (! pfras) {
3199 error = ENOMEM;
3200 break;
3201 }
3202 error = copyin(io->pfrio_buffer, pfras, totlen);
3203 if (error) {
3204 free(pfras, M_TEMP);
3205 break;
3206 }
3207 PF_RULES_WLOCK();
3208 error = pfr_del_addrs(&io->pfrio_table, pfras,
3209 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
3210 PFR_FLAG_USERIOCTL);
3211 PF_RULES_WUNLOCK();
3212 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
3213 error = copyout(pfras, io->pfrio_buffer, totlen);
3214 free(pfras, M_TEMP);
3215 break;
3216 }
3217
3218 case DIOCRSETADDRS: {
3219 struct pfioc_table *io = (struct pfioc_table *)addr;
3220 struct pfr_addr *pfras;
3221 size_t totlen, count;
3222
3223 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
3224 error = ENODEV;
3225 break;
3226 }
3227 if (io->pfrio_size < 0 || io->pfrio_size2 < 0) {
3228 error = EINVAL;
3229 break;
3230 }
3231 count = max(io->pfrio_size, io->pfrio_size2);
3232 if (count > pf_ioctl_maxcount ||
3233 WOULD_OVERFLOW(count, sizeof(struct pfr_addr))) {
3234 error = EINVAL;
3235 break;
3236 }
3237 totlen = count * sizeof(struct pfr_addr);
3238 pfras = mallocarray(count, sizeof(struct pfr_addr), M_TEMP,
3239 M_NOWAIT);
3240 if (! pfras) {
3241 error = ENOMEM;
3242 break;
3243 }
3244 error = copyin(io->pfrio_buffer, pfras, totlen);
3245 if (error) {
3246 free(pfras, M_TEMP);
3247 break;
3248 }
3249 PF_RULES_WLOCK();
3250 error = pfr_set_addrs(&io->pfrio_table, pfras,
3251 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
3252 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
3253 PFR_FLAG_USERIOCTL, 0);
3254 PF_RULES_WUNLOCK();
3255 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
3256 error = copyout(pfras, io->pfrio_buffer, totlen);
3257 free(pfras, M_TEMP);
3258 break;
3259 }
3260
3261 case DIOCRGETADDRS: {
3262 struct pfioc_table *io = (struct pfioc_table *)addr;
3263 struct pfr_addr *pfras;
3264 size_t totlen;
3265
3266 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
3267 error = ENODEV;
3268 break;
3269 }
3270 if (io->pfrio_size < 0 ||
3271 io->pfrio_size > pf_ioctl_maxcount ||
3272 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
3273 error = EINVAL;
3274 break;
3275 }
3276 totlen = io->pfrio_size * sizeof(struct pfr_addr);
3277 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
3278 M_TEMP, M_NOWAIT);
3279 if (! pfras) {
3280 error = ENOMEM;
3281 break;
3282 }
3283 PF_RULES_RLOCK();
3284 error = pfr_get_addrs(&io->pfrio_table, pfras,
3285 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
3286 PF_RULES_RUNLOCK();
3287 if (error == 0)
3288 error = copyout(pfras, io->pfrio_buffer, totlen);
3289 free(pfras, M_TEMP);
3290 break;
3291 }
3292
3293 case DIOCRGETASTATS: {
3294 struct pfioc_table *io = (struct pfioc_table *)addr;
3295 struct pfr_astats *pfrastats;
3296 size_t totlen;
3297
3298 if (io->pfrio_esize != sizeof(struct pfr_astats)) {
3299 error = ENODEV;
3300 break;
3301 }
3302 if (io->pfrio_size < 0 ||
3303 io->pfrio_size > pf_ioctl_maxcount ||
3304 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_astats))) {
3305 error = EINVAL;
3306 break;
3307 }
3308 totlen = io->pfrio_size * sizeof(struct pfr_astats);
3309 pfrastats = mallocarray(io->pfrio_size,
3310 sizeof(struct pfr_astats), M_TEMP, M_NOWAIT);
3311 if (! pfrastats) {
3312 error = ENOMEM;
3313 break;
3314 }
3315 PF_RULES_RLOCK();
3316 error = pfr_get_astats(&io->pfrio_table, pfrastats,
3317 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
3318 PF_RULES_RUNLOCK();
3319 if (error == 0)
3320 error = copyout(pfrastats, io->pfrio_buffer, totlen);
3321 free(pfrastats, M_TEMP);
3322 break;
3323 }
3324
3325 case DIOCRCLRASTATS: {
3326 struct pfioc_table *io = (struct pfioc_table *)addr;
3327 struct pfr_addr *pfras;
3328 size_t totlen;
3329
3330 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
3331 error = ENODEV;
3332 break;
3333 }
3334 if (io->pfrio_size < 0 ||
3335 io->pfrio_size > pf_ioctl_maxcount ||
3336 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
3337 error = EINVAL;
3338 break;
3339 }
3340 totlen = io->pfrio_size * sizeof(struct pfr_addr);
3341 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
3342 M_TEMP, M_NOWAIT);
3343 if (! pfras) {
3344 error = ENOMEM;
3345 break;
3346 }
3347 error = copyin(io->pfrio_buffer, pfras, totlen);
3348 if (error) {
3349 free(pfras, M_TEMP);
3350 break;
3351 }
3352 PF_RULES_WLOCK();
3353 error = pfr_clr_astats(&io->pfrio_table, pfras,
3354 io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
3355 PFR_FLAG_USERIOCTL);
3356 PF_RULES_WUNLOCK();
3357 if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
3358 error = copyout(pfras, io->pfrio_buffer, totlen);
3359 free(pfras, M_TEMP);
3360 break;
3361 }
3362
3363 case DIOCRTSTADDRS: {
3364 struct pfioc_table *io = (struct pfioc_table *)addr;
3365 struct pfr_addr *pfras;
3366 size_t totlen;
3367
3368 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
3369 error = ENODEV;
3370 break;
3371 }
3372 if (io->pfrio_size < 0 ||
3373 io->pfrio_size > pf_ioctl_maxcount ||
3374 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
3375 error = EINVAL;
3376 break;
3377 }
3378 totlen = io->pfrio_size * sizeof(struct pfr_addr);
3379 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
3380 M_TEMP, M_NOWAIT);
3381 if (! pfras) {
3382 error = ENOMEM;
3383 break;
3384 }
3385 error = copyin(io->pfrio_buffer, pfras, totlen);
3386 if (error) {
3387 free(pfras, M_TEMP);
3388 break;
3389 }
3390 PF_RULES_RLOCK();
3391 error = pfr_tst_addrs(&io->pfrio_table, pfras,
3392 io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
3393 PFR_FLAG_USERIOCTL);
3394 PF_RULES_RUNLOCK();
3395 if (error == 0)
3396 error = copyout(pfras, io->pfrio_buffer, totlen);
3397 free(pfras, M_TEMP);
3398 break;
3399 }
3400
3401 case DIOCRINADEFINE: {
3402 struct pfioc_table *io = (struct pfioc_table *)addr;
3403 struct pfr_addr *pfras;
3404 size_t totlen;
3405
3406 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
3407 error = ENODEV;
3408 break;
3409 }
3410 if (io->pfrio_size < 0 ||
3411 io->pfrio_size > pf_ioctl_maxcount ||
3412 WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
3413 error = EINVAL;
3414 break;
3415 }
3416 totlen = io->pfrio_size * sizeof(struct pfr_addr);
3417 pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
3418 M_TEMP, M_NOWAIT);
3419 if (! pfras) {
3420 error = ENOMEM;
3421 break;
3422 }
3423 error = copyin(io->pfrio_buffer, pfras, totlen);
3424 if (error) {
3425 free(pfras, M_TEMP);
3426 break;
3427 }
3428 PF_RULES_WLOCK();
3429 error = pfr_ina_define(&io->pfrio_table, pfras,
3430 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
3431 io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
3432 PF_RULES_WUNLOCK();
3433 free(pfras, M_TEMP);
3434 break;
3435 }
3436
3437 case DIOCOSFPADD: {
3438 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
3439 PF_RULES_WLOCK();
3440 error = pf_osfp_add(io);
3441 PF_RULES_WUNLOCK();
3442 break;
3443 }
3444
3445 case DIOCOSFPGET: {
3446 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
3447 PF_RULES_RLOCK();
3448 error = pf_osfp_get(io);
3449 PF_RULES_RUNLOCK();
3450 break;
3451 }
3452
3453 case DIOCXBEGIN: {
3454 struct pfioc_trans *io = (struct pfioc_trans *)addr;
3455 struct pfioc_trans_e *ioes, *ioe;
3456 size_t totlen;
3457 int i;
3458
3459 if (io->esize != sizeof(*ioe)) {
3460 error = ENODEV;
3461 break;
3462 }
3463 if (io->size < 0 ||
3464 io->size > pf_ioctl_maxcount ||
3465 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
3466 error = EINVAL;
3467 break;
3468 }
3469 totlen = sizeof(struct pfioc_trans_e) * io->size;
3470 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
3471 M_TEMP, M_NOWAIT);
3472 if (! ioes) {
3473 error = ENOMEM;
3474 break;
3475 }
3476 error = copyin(io->array, ioes, totlen);
3477 if (error) {
3478 free(ioes, M_TEMP);
3479 break;
3480 }
3481 PF_RULES_WLOCK();
3482 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
3483 switch (ioe->rs_num) {
3484 #ifdef ALTQ
3485 case PF_RULESET_ALTQ:
3486 if (ioe->anchor[0]) {
3487 PF_RULES_WUNLOCK();
3488 free(ioes, M_TEMP);
3489 error = EINVAL;
3490 goto fail;
3491 }
3492 if ((error = pf_begin_altq(&ioe->ticket))) {
3493 PF_RULES_WUNLOCK();
3494 free(ioes, M_TEMP);
3495 goto fail;
3496 }
3497 break;
3498 #endif /* ALTQ */
3499 case PF_RULESET_TABLE:
3500 {
3501 struct pfr_table table;
3502
3503 bzero(&table, sizeof(table));
3504 strlcpy(table.pfrt_anchor, ioe->anchor,
3505 sizeof(table.pfrt_anchor));
3506 if ((error = pfr_ina_begin(&table,
3507 &ioe->ticket, NULL, 0))) {
3508 PF_RULES_WUNLOCK();
3509 free(ioes, M_TEMP);
3510 goto fail;
3511 }
3512 break;
3513 }
3514 default:
3515 if ((error = pf_begin_rules(&ioe->ticket,
3516 ioe->rs_num, ioe->anchor))) {
3517 PF_RULES_WUNLOCK();
3518 free(ioes, M_TEMP);
3519 goto fail;
3520 }
3521 break;
3522 }
3523 }
3524 PF_RULES_WUNLOCK();
3525 error = copyout(ioes, io->array, totlen);
3526 free(ioes, M_TEMP);
3527 break;
3528 }
3529
3530 case DIOCXROLLBACK: {
3531 struct pfioc_trans *io = (struct pfioc_trans *)addr;
3532 struct pfioc_trans_e *ioe, *ioes;
3533 size_t totlen;
3534 int i;
3535
3536 if (io->esize != sizeof(*ioe)) {
3537 error = ENODEV;
3538 break;
3539 }
3540 if (io->size < 0 ||
3541 io->size > pf_ioctl_maxcount ||
3542 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
3543 error = EINVAL;
3544 break;
3545 }
3546 totlen = sizeof(struct pfioc_trans_e) * io->size;
3547 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
3548 M_TEMP, M_NOWAIT);
3549 if (! ioes) {
3550 error = ENOMEM;
3551 break;
3552 }
3553 error = copyin(io->array, ioes, totlen);
3554 if (error) {
3555 free(ioes, M_TEMP);
3556 break;
3557 }
3558 PF_RULES_WLOCK();
3559 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
3560 switch (ioe->rs_num) {
3561 #ifdef ALTQ
3562 case PF_RULESET_ALTQ:
3563 if (ioe->anchor[0]) {
3564 PF_RULES_WUNLOCK();
3565 free(ioes, M_TEMP);
3566 error = EINVAL;
3567 goto fail;
3568 }
3569 if ((error = pf_rollback_altq(ioe->ticket))) {
3570 PF_RULES_WUNLOCK();
3571 free(ioes, M_TEMP);
3572 goto fail; /* really bad */
3573 }
3574 break;
3575 #endif /* ALTQ */
3576 case PF_RULESET_TABLE:
3577 {
3578 struct pfr_table table;
3579
3580 bzero(&table, sizeof(table));
3581 strlcpy(table.pfrt_anchor, ioe->anchor,
3582 sizeof(table.pfrt_anchor));
3583 if ((error = pfr_ina_rollback(&table,
3584 ioe->ticket, NULL, 0))) {
3585 PF_RULES_WUNLOCK();
3586 free(ioes, M_TEMP);
3587 goto fail; /* really bad */
3588 }
3589 break;
3590 }
3591 default:
3592 if ((error = pf_rollback_rules(ioe->ticket,
3593 ioe->rs_num, ioe->anchor))) {
3594 PF_RULES_WUNLOCK();
3595 free(ioes, M_TEMP);
3596 goto fail; /* really bad */
3597 }
3598 break;
3599 }
3600 }
3601 PF_RULES_WUNLOCK();
3602 free(ioes, M_TEMP);
3603 break;
3604 }
3605
3606 case DIOCXCOMMIT: {
3607 struct pfioc_trans *io = (struct pfioc_trans *)addr;
3608 struct pfioc_trans_e *ioe, *ioes;
3609 struct pf_ruleset *rs;
3610 size_t totlen;
3611 int i;
3612
3613 if (io->esize != sizeof(*ioe)) {
3614 error = ENODEV;
3615 break;
3616 }
3617
3618 if (io->size < 0 ||
3619 io->size > pf_ioctl_maxcount ||
3620 WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
3621 error = EINVAL;
3622 break;
3623 }
3624
3625 totlen = sizeof(struct pfioc_trans_e) * io->size;
3626 ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
3627 M_TEMP, M_NOWAIT);
3628 if (ioes == NULL) {
3629 error = ENOMEM;
3630 break;
3631 }
3632 error = copyin(io->array, ioes, totlen);
3633 if (error) {
3634 free(ioes, M_TEMP);
3635 break;
3636 }
3637 PF_RULES_WLOCK();
3638 /* First makes sure everything will succeed. */
3639 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
3640 switch (ioe->rs_num) {
3641 #ifdef ALTQ
3642 case PF_RULESET_ALTQ:
3643 if (ioe->anchor[0]) {
3644 PF_RULES_WUNLOCK();
3645 free(ioes, M_TEMP);
3646 error = EINVAL;
3647 goto fail;
3648 }
3649 if (!V_altqs_inactive_open || ioe->ticket !=
3650 V_ticket_altqs_inactive) {
3651 PF_RULES_WUNLOCK();
3652 free(ioes, M_TEMP);
3653 error = EBUSY;
3654 goto fail;
3655 }
3656 break;
3657 #endif /* ALTQ */
3658 case PF_RULESET_TABLE:
3659 rs = pf_find_ruleset(ioe->anchor);
3660 if (rs == NULL || !rs->topen || ioe->ticket !=
3661 rs->tticket) {
3662 PF_RULES_WUNLOCK();
3663 free(ioes, M_TEMP);
3664 error = EBUSY;
3665 goto fail;
3666 }
3667 break;
3668 default:
3669 if (ioe->rs_num < 0 || ioe->rs_num >=
3670 PF_RULESET_MAX) {
3671 PF_RULES_WUNLOCK();
3672 free(ioes, M_TEMP);
3673 error = EINVAL;
3674 goto fail;
3675 }
3676 rs = pf_find_ruleset(ioe->anchor);
3677 if (rs == NULL ||
3678 !rs->rules[ioe->rs_num].inactive.open ||
3679 rs->rules[ioe->rs_num].inactive.ticket !=
3680 ioe->ticket) {
3681 PF_RULES_WUNLOCK();
3682 free(ioes, M_TEMP);
3683 error = EBUSY;
3684 goto fail;
3685 }
3686 break;
3687 }
3688 }
3689 /* Now do the commit - no errors should happen here. */
3690 for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
3691 switch (ioe->rs_num) {
3692 #ifdef ALTQ
3693 case PF_RULESET_ALTQ:
3694 if ((error = pf_commit_altq(ioe->ticket))) {
3695 PF_RULES_WUNLOCK();
3696 free(ioes, M_TEMP);
3697 goto fail; /* really bad */
3698 }
3699 break;
3700 #endif /* ALTQ */
3701 case PF_RULESET_TABLE:
3702 {
3703 struct pfr_table table;
3704
3705 bzero(&table, sizeof(table));
3706 strlcpy(table.pfrt_anchor, ioe->anchor,
3707 sizeof(table.pfrt_anchor));
3708 if ((error = pfr_ina_commit(&table,
3709 ioe->ticket, NULL, NULL, 0))) {
3710 PF_RULES_WUNLOCK();
3711 free(ioes, M_TEMP);
3712 goto fail; /* really bad */
3713 }
3714 break;
3715 }
3716 default:
3717 if ((error = pf_commit_rules(ioe->ticket,
3718 ioe->rs_num, ioe->anchor))) {
3719 PF_RULES_WUNLOCK();
3720 free(ioes, M_TEMP);
3721 goto fail; /* really bad */
3722 }
3723 break;
3724 }
3725 }
3726 PF_RULES_WUNLOCK();
3727 free(ioes, M_TEMP);
3728 break;
3729 }
3730
3731 case DIOCGETSRCNODES: {
3732 struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
3733 struct pf_srchash *sh;
3734 struct pf_src_node *n, *p, *pstore;
3735 uint32_t i, nr = 0;
3736
3737 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask;
3738 i++, sh++) {
3739 PF_HASHROW_LOCK(sh);
3740 LIST_FOREACH(n, &sh->nodes, entry)
3741 nr++;
3742 PF_HASHROW_UNLOCK(sh);
3743 }
3744
3745 psn->psn_len = min(psn->psn_len,
3746 sizeof(struct pf_src_node) * nr);
3747
3748 if (psn->psn_len == 0) {
3749 psn->psn_len = sizeof(struct pf_src_node) * nr;
3750 break;
3751 }
3752
3753 nr = 0;
3754
3755 p = pstore = malloc(psn->psn_len, M_TEMP, M_WAITOK);
3756 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask;
3757 i++, sh++) {
3758 PF_HASHROW_LOCK(sh);
3759 LIST_FOREACH(n, &sh->nodes, entry) {
3760 int secs = time_uptime, diff;
3761
3762 if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
3763 break;
3764
3765 bcopy(n, p, sizeof(struct pf_src_node));
3766 if (n->rule.ptr != NULL)
3767 p->rule.nr = n->rule.ptr->nr;
3768 p->creation = secs - p->creation;
3769 if (p->expire > secs)
3770 p->expire -= secs;
3771 else
3772 p->expire = 0;
3773
3774 /* Adjust the connection rate estimate. */
3775 diff = secs - n->conn_rate.last;
3776 if (diff >= n->conn_rate.seconds)
3777 p->conn_rate.count = 0;
3778 else
3779 p->conn_rate.count -=
3780 n->conn_rate.count * diff /
3781 n->conn_rate.seconds;
3782 p++;
3783 nr++;
3784 }
3785 PF_HASHROW_UNLOCK(sh);
3786 }
3787 error = copyout(pstore, psn->psn_src_nodes,
3788 sizeof(struct pf_src_node) * nr);
3789 if (error) {
3790 free(pstore, M_TEMP);
3791 break;
3792 }
3793 psn->psn_len = sizeof(struct pf_src_node) * nr;
3794 free(pstore, M_TEMP);
3795 break;
3796 }
3797
3798 case DIOCCLRSRCNODES: {
3799
3800 pf_clear_srcnodes(NULL);
3801 pf_purge_expired_src_nodes();
3802 break;
3803 }
3804
3805 case DIOCKILLSRCNODES:
3806 pf_kill_srcnodes((struct pfioc_src_node_kill *)addr);
3807 break;
3808
3809 case DIOCSETHOSTID: {
3810 u_int32_t *hostid = (u_int32_t *)addr;
3811
3812 PF_RULES_WLOCK();
3813 if (*hostid == 0)
3814 V_pf_status.hostid = arc4random();
3815 else
3816 V_pf_status.hostid = *hostid;
3817 PF_RULES_WUNLOCK();
3818 break;
3819 }
3820
3821 case DIOCOSFPFLUSH:
3822 PF_RULES_WLOCK();
3823 pf_osfp_flush();
3824 PF_RULES_WUNLOCK();
3825 break;
3826
3827 case DIOCIGETIFACES: {
3828 struct pfioc_iface *io = (struct pfioc_iface *)addr;
3829 struct pfi_kif *ifstore;
3830 size_t bufsiz;
3831
3832 if (io->pfiio_esize != sizeof(struct pfi_kif)) {
3833 error = ENODEV;
3834 break;
3835 }
3836
3837 if (io->pfiio_size < 0 ||
3838 io->pfiio_size > pf_ioctl_maxcount ||
3839 WOULD_OVERFLOW(io->pfiio_size, sizeof(struct pfi_kif))) {
3840 error = EINVAL;
3841 break;
3842 }
3843
3844 bufsiz = io->pfiio_size * sizeof(struct pfi_kif);
3845 ifstore = mallocarray(io->pfiio_size, sizeof(struct pfi_kif),
3846 M_TEMP, M_NOWAIT);
3847 if (ifstore == NULL) {
3848 error = ENOMEM;
3849 break;
3850 }
3851
3852 PF_RULES_RLOCK();
3853 pfi_get_ifaces(io->pfiio_name, ifstore, &io->pfiio_size);
3854 PF_RULES_RUNLOCK();
3855 error = copyout(ifstore, io->pfiio_buffer, bufsiz);
3856 free(ifstore, M_TEMP);
3857 break;
3858 }
3859
3860 case DIOCSETIFFLAG: {
3861 struct pfioc_iface *io = (struct pfioc_iface *)addr;
3862
3863 PF_RULES_WLOCK();
3864 error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
3865 PF_RULES_WUNLOCK();
3866 break;
3867 }
3868
3869 case DIOCCLRIFFLAG: {
3870 struct pfioc_iface *io = (struct pfioc_iface *)addr;
3871
3872 PF_RULES_WLOCK();
3873 error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
3874 PF_RULES_WUNLOCK();
3875 break;
3876 }
3877
3878 default:
3879 error = ENODEV;
3880 break;
3881 }
3882 fail:
3883 if (sx_xlocked(&pf_ioctl_lock))
3884 sx_xunlock(&pf_ioctl_lock);
3885 CURVNET_RESTORE();
3886
3887 return (error);
3888 }
3889
3890 void
pfsync_state_export(struct pfsync_state * sp,struct pf_state * st)3891 pfsync_state_export(struct pfsync_state *sp, struct pf_state *st)
3892 {
3893 bzero(sp, sizeof(struct pfsync_state));
3894
3895 /* copy from state key */
3896 sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
3897 sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
3898 sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
3899 sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
3900 sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
3901 sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
3902 sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
3903 sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
3904 sp->proto = st->key[PF_SK_WIRE]->proto;
3905 sp->af = st->key[PF_SK_WIRE]->af;
3906
3907 /* copy from state */
3908 strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
3909 bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
3910 sp->creation = htonl(time_uptime - st->creation);
3911 sp->expire = pf_state_expires(st);
3912 if (sp->expire <= time_uptime)
3913 sp->expire = htonl(0);
3914 else
3915 sp->expire = htonl(sp->expire - time_uptime);
3916
3917 sp->direction = st->direction;
3918 sp->log = st->log;
3919 sp->timeout = st->timeout;
3920 sp->state_flags = st->state_flags;
3921 if (st->src_node)
3922 sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
3923 if (st->nat_src_node)
3924 sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
3925
3926 sp->id = st->id;
3927 sp->creatorid = st->creatorid;
3928 pf_state_peer_hton(&st->src, &sp->src);
3929 pf_state_peer_hton(&st->dst, &sp->dst);
3930
3931 if (st->rule.ptr == NULL)
3932 sp->rule = htonl(-1);
3933 else
3934 sp->rule = htonl(st->rule.ptr->nr);
3935 if (st->anchor.ptr == NULL)
3936 sp->anchor = htonl(-1);
3937 else
3938 sp->anchor = htonl(st->anchor.ptr->nr);
3939 if (st->nat_rule.ptr == NULL)
3940 sp->nat_rule = htonl(-1);
3941 else
3942 sp->nat_rule = htonl(st->nat_rule.ptr->nr);
3943
3944 pf_state_counter_hton(st->packets[0], sp->packets[0]);
3945 pf_state_counter_hton(st->packets[1], sp->packets[1]);
3946 pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
3947 pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
3948
3949 }
3950
3951 static void
pf_tbladdr_copyout(struct pf_addr_wrap * aw)3952 pf_tbladdr_copyout(struct pf_addr_wrap *aw)
3953 {
3954 struct pfr_ktable *kt;
3955
3956 KASSERT(aw->type == PF_ADDR_TABLE, ("%s: type %u", __func__, aw->type));
3957
3958 kt = aw->p.tbl;
3959 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
3960 kt = kt->pfrkt_root;
3961 aw->p.tbl = NULL;
3962 aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
3963 kt->pfrkt_cnt : -1;
3964 }
3965
3966 /*
3967 * XXX - Check for version missmatch!!!
3968 */
3969 static void
pf_clear_states(void)3970 pf_clear_states(void)
3971 {
3972 struct pf_state *s;
3973 u_int i;
3974
3975 for (i = 0; i <= pf_hashmask; i++) {
3976 struct pf_idhash *ih = &V_pf_idhash[i];
3977 relock:
3978 PF_HASHROW_LOCK(ih);
3979 LIST_FOREACH(s, &ih->states, entry) {
3980 s->timeout = PFTM_PURGE;
3981 /* Don't send out individual delete messages. */
3982 s->state_flags |= PFSTATE_NOSYNC;
3983 pf_unlink_state(s, PF_ENTER_LOCKED);
3984 goto relock;
3985 }
3986 PF_HASHROW_UNLOCK(ih);
3987 }
3988 }
3989
3990 static int
pf_clear_tables(void)3991 pf_clear_tables(void)
3992 {
3993 struct pfioc_table io;
3994 int error;
3995
3996 bzero(&io, sizeof(io));
3997
3998 error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel,
3999 io.pfrio_flags);
4000
4001 return (error);
4002 }
4003
4004 static void
pf_clear_srcnodes(struct pf_src_node * n)4005 pf_clear_srcnodes(struct pf_src_node *n)
4006 {
4007 struct pf_state *s;
4008 int i;
4009
4010 for (i = 0; i <= pf_hashmask; i++) {
4011 struct pf_idhash *ih = &V_pf_idhash[i];
4012
4013 PF_HASHROW_LOCK(ih);
4014 LIST_FOREACH(s, &ih->states, entry) {
4015 if (n == NULL || n == s->src_node)
4016 s->src_node = NULL;
4017 if (n == NULL || n == s->nat_src_node)
4018 s->nat_src_node = NULL;
4019 }
4020 PF_HASHROW_UNLOCK(ih);
4021 }
4022
4023 if (n == NULL) {
4024 struct pf_srchash *sh;
4025
4026 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask;
4027 i++, sh++) {
4028 PF_HASHROW_LOCK(sh);
4029 LIST_FOREACH(n, &sh->nodes, entry) {
4030 n->expire = 1;
4031 n->states = 0;
4032 }
4033 PF_HASHROW_UNLOCK(sh);
4034 }
4035 } else {
4036 /* XXX: hash slot should already be locked here. */
4037 n->expire = 1;
4038 n->states = 0;
4039 }
4040 }
4041
4042 static void
pf_kill_srcnodes(struct pfioc_src_node_kill * psnk)4043 pf_kill_srcnodes(struct pfioc_src_node_kill *psnk)
4044 {
4045 struct pf_src_node_list kill;
4046
4047 LIST_INIT(&kill);
4048 for (int i = 0; i <= pf_srchashmask; i++) {
4049 struct pf_srchash *sh = &V_pf_srchash[i];
4050 struct pf_src_node *sn, *tmp;
4051
4052 PF_HASHROW_LOCK(sh);
4053 LIST_FOREACH_SAFE(sn, &sh->nodes, entry, tmp)
4054 if (PF_MATCHA(psnk->psnk_src.neg,
4055 &psnk->psnk_src.addr.v.a.addr,
4056 &psnk->psnk_src.addr.v.a.mask,
4057 &sn->addr, sn->af) &&
4058 PF_MATCHA(psnk->psnk_dst.neg,
4059 &psnk->psnk_dst.addr.v.a.addr,
4060 &psnk->psnk_dst.addr.v.a.mask,
4061 &sn->raddr, sn->af)) {
4062 pf_unlink_src_node(sn);
4063 LIST_INSERT_HEAD(&kill, sn, entry);
4064 sn->expire = 1;
4065 }
4066 PF_HASHROW_UNLOCK(sh);
4067 }
4068
4069 for (int i = 0; i <= pf_hashmask; i++) {
4070 struct pf_idhash *ih = &V_pf_idhash[i];
4071 struct pf_state *s;
4072
4073 PF_HASHROW_LOCK(ih);
4074 LIST_FOREACH(s, &ih->states, entry) {
4075 if (s->src_node && s->src_node->expire == 1)
4076 s->src_node = NULL;
4077 if (s->nat_src_node && s->nat_src_node->expire == 1)
4078 s->nat_src_node = NULL;
4079 }
4080 PF_HASHROW_UNLOCK(ih);
4081 }
4082
4083 psnk->psnk_killed = pf_free_src_nodes(&kill);
4084 }
4085
4086 /*
4087 * XXX - Check for version missmatch!!!
4088 */
4089
4090 /*
4091 * Duplicate pfctl -Fa operation to get rid of as much as we can.
4092 */
4093 static int
shutdown_pf(void)4094 shutdown_pf(void)
4095 {
4096 int error = 0;
4097 u_int32_t t[5];
4098 char nn = '\0';
4099
4100 do {
4101 if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
4102 != 0) {
4103 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: SCRUB\n"));
4104 break;
4105 }
4106 if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn))
4107 != 0) {
4108 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: FILTER\n"));
4109 break; /* XXX: rollback? */
4110 }
4111 if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn))
4112 != 0) {
4113 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: NAT\n"));
4114 break; /* XXX: rollback? */
4115 }
4116 if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn))
4117 != 0) {
4118 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: BINAT\n"));
4119 break; /* XXX: rollback? */
4120 }
4121 if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn))
4122 != 0) {
4123 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: RDR\n"));
4124 break; /* XXX: rollback? */
4125 }
4126
4127 /* XXX: these should always succeed here */
4128 pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn);
4129 pf_commit_rules(t[1], PF_RULESET_FILTER, &nn);
4130 pf_commit_rules(t[2], PF_RULESET_NAT, &nn);
4131 pf_commit_rules(t[3], PF_RULESET_BINAT, &nn);
4132 pf_commit_rules(t[4], PF_RULESET_RDR, &nn);
4133
4134 if ((error = pf_clear_tables()) != 0)
4135 break;
4136
4137 #ifdef ALTQ
4138 if ((error = pf_begin_altq(&t[0])) != 0) {
4139 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: ALTQ\n"));
4140 break;
4141 }
4142 pf_commit_altq(t[0]);
4143 #endif
4144
4145 pf_clear_states();
4146
4147 pf_clear_srcnodes(NULL);
4148
4149 /* status does not use malloced mem so no need to cleanup */
4150 /* fingerprints and interfaces have their own cleanup code */
4151 } while(0);
4152
4153 return (error);
4154 }
4155
4156 #ifdef INET
4157 static int
pf_check_in(void * arg,struct mbuf ** m,struct ifnet * ifp,int dir,int flags,struct inpcb * inp)4158 pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
4159 struct inpcb *inp)
4160 {
4161 int chk;
4162
4163 chk = pf_test(PF_IN, flags, ifp, m, inp);
4164 if (chk && *m) {
4165 m_freem(*m);
4166 *m = NULL;
4167 }
4168
4169 if (chk != PF_PASS)
4170 return (EACCES);
4171 return (0);
4172 }
4173
4174 static int
pf_check_out(void * arg,struct mbuf ** m,struct ifnet * ifp,int dir,int flags,struct inpcb * inp)4175 pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
4176 struct inpcb *inp)
4177 {
4178 int chk;
4179
4180 chk = pf_test(PF_OUT, flags, ifp, m, inp);
4181 if (chk && *m) {
4182 m_freem(*m);
4183 *m = NULL;
4184 }
4185
4186 if (chk != PF_PASS)
4187 return (EACCES);
4188 return (0);
4189 }
4190 #endif
4191
4192 #ifdef INET6
4193 static int
pf_check6_in(void * arg,struct mbuf ** m,struct ifnet * ifp,int dir,int flags,struct inpcb * inp)4194 pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
4195 struct inpcb *inp)
4196 {
4197 int chk;
4198
4199 /*
4200 * In case of loopback traffic IPv6 uses the real interface in
4201 * order to support scoped addresses. In order to support stateful
4202 * filtering we have change this to lo0 as it is the case in IPv4.
4203 */
4204 CURVNET_SET(ifp->if_vnet);
4205 chk = pf_test6(PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp, m, inp);
4206 CURVNET_RESTORE();
4207 if (chk && *m) {
4208 m_freem(*m);
4209 *m = NULL;
4210 }
4211 if (chk != PF_PASS)
4212 return (EACCES);
4213 return (0);
4214 }
4215
4216 static int
pf_check6_out(void * arg,struct mbuf ** m,struct ifnet * ifp,int dir,int flags,struct inpcb * inp)4217 pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
4218 struct inpcb *inp)
4219 {
4220 int chk;
4221
4222 CURVNET_SET(ifp->if_vnet);
4223 chk = pf_test6(PF_OUT, flags, ifp, m, inp);
4224 CURVNET_RESTORE();
4225 if (chk && *m) {
4226 m_freem(*m);
4227 *m = NULL;
4228 }
4229 if (chk != PF_PASS)
4230 return (EACCES);
4231 return (0);
4232 }
4233 #endif /* INET6 */
4234
4235 static int
hook_pf(void)4236 hook_pf(void)
4237 {
4238 #ifdef INET
4239 struct pfil_head *pfh_inet;
4240 #endif
4241 #ifdef INET6
4242 struct pfil_head *pfh_inet6;
4243 #endif
4244
4245 if (V_pf_pfil_hooked)
4246 return (0);
4247
4248 #ifdef INET
4249 pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
4250 if (pfh_inet == NULL)
4251 return (ESRCH); /* XXX */
4252 pfil_add_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
4253 pfil_add_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
4254 #endif
4255 #ifdef INET6
4256 pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
4257 if (pfh_inet6 == NULL) {
4258 #ifdef INET
4259 pfil_remove_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
4260 pfh_inet);
4261 pfil_remove_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
4262 pfh_inet);
4263 #endif
4264 return (ESRCH); /* XXX */
4265 }
4266 pfil_add_hook_flags(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
4267 pfil_add_hook_flags(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
4268 #endif
4269
4270 V_pf_pfil_hooked = 1;
4271 return (0);
4272 }
4273
4274 static int
dehook_pf(void)4275 dehook_pf(void)
4276 {
4277 #ifdef INET
4278 struct pfil_head *pfh_inet;
4279 #endif
4280 #ifdef INET6
4281 struct pfil_head *pfh_inet6;
4282 #endif
4283
4284 if (V_pf_pfil_hooked == 0)
4285 return (0);
4286
4287 #ifdef INET
4288 pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
4289 if (pfh_inet == NULL)
4290 return (ESRCH); /* XXX */
4291 pfil_remove_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
4292 pfh_inet);
4293 pfil_remove_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
4294 pfh_inet);
4295 #endif
4296 #ifdef INET6
4297 pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
4298 if (pfh_inet6 == NULL)
4299 return (ESRCH); /* XXX */
4300 pfil_remove_hook_flags(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK,
4301 pfh_inet6);
4302 pfil_remove_hook_flags(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK,
4303 pfh_inet6);
4304 #endif
4305
4306 V_pf_pfil_hooked = 0;
4307 return (0);
4308 }
4309
4310 static void
pf_load_vnet(void)4311 pf_load_vnet(void)
4312 {
4313 V_pf_tag_z = uma_zcreate("pf tags", sizeof(struct pf_tagname),
4314 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
4315
4316 pf_init_tagset(&V_pf_tags, &pf_rule_tag_hashsize,
4317 PF_RULE_TAG_HASH_SIZE_DEFAULT);
4318 #ifdef ALTQ
4319 pf_init_tagset(&V_pf_qids, &pf_queue_tag_hashsize,
4320 PF_QUEUE_TAG_HASH_SIZE_DEFAULT);
4321 #endif
4322
4323 pfattach_vnet();
4324 V_pf_vnet_active = 1;
4325 }
4326
4327 static int
pf_load(void)4328 pf_load(void)
4329 {
4330 int error;
4331
4332 rm_init(&pf_rules_lock, "pf rulesets");
4333 sx_init(&pf_ioctl_lock, "pf ioctl");
4334 sx_init(&pf_end_lock, "pf end thread");
4335
4336 pf_mtag_initialize();
4337
4338 pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME);
4339 if (pf_dev == NULL)
4340 return (ENOMEM);
4341
4342 pf_end_threads = 0;
4343 error = kproc_create(pf_purge_thread, NULL, &pf_purge_proc, 0, 0, "pf purge");
4344 if (error != 0)
4345 return (error);
4346
4347 pfi_initialize();
4348
4349 return (0);
4350 }
4351
4352 static void
pf_unload_vnet(void)4353 pf_unload_vnet(void)
4354 {
4355 int error;
4356
4357 V_pf_vnet_active = 0;
4358 V_pf_status.running = 0;
4359 error = dehook_pf();
4360 if (error) {
4361 /*
4362 * Should not happen!
4363 * XXX Due to error code ESRCH, kldunload will show
4364 * a message like 'No such process'.
4365 */
4366 printf("%s : pfil unregisteration fail\n", __FUNCTION__);
4367 return;
4368 }
4369
4370 PF_RULES_WLOCK();
4371 shutdown_pf();
4372 PF_RULES_WUNLOCK();
4373
4374 swi_remove(V_pf_swi_cookie);
4375
4376 pf_unload_vnet_purge();
4377
4378 pf_normalize_cleanup();
4379 PF_RULES_WLOCK();
4380 pfi_cleanup_vnet();
4381 PF_RULES_WUNLOCK();
4382 pfr_cleanup();
4383 pf_osfp_flush();
4384 pf_cleanup();
4385 if (IS_DEFAULT_VNET(curvnet))
4386 pf_mtag_cleanup();
4387
4388 pf_cleanup_tagset(&V_pf_tags);
4389 #ifdef ALTQ
4390 pf_cleanup_tagset(&V_pf_qids);
4391 #endif
4392 uma_zdestroy(V_pf_tag_z);
4393
4394 /* Free counters last as we updated them during shutdown. */
4395 counter_u64_free(V_pf_default_rule.states_cur);
4396 counter_u64_free(V_pf_default_rule.states_tot);
4397 counter_u64_free(V_pf_default_rule.src_nodes);
4398
4399 for (int i = 0; i < PFRES_MAX; i++)
4400 counter_u64_free(V_pf_status.counters[i]);
4401 for (int i = 0; i < LCNT_MAX; i++)
4402 counter_u64_free(V_pf_status.lcounters[i]);
4403 for (int i = 0; i < FCNT_MAX; i++)
4404 counter_u64_free(V_pf_status.fcounters[i]);
4405 for (int i = 0; i < SCNT_MAX; i++)
4406 counter_u64_free(V_pf_status.scounters[i]);
4407 }
4408
4409 static void
pf_unload(void)4410 pf_unload(void)
4411 {
4412
4413 sx_xlock(&pf_end_lock);
4414 pf_end_threads = 1;
4415 while (pf_end_threads < 2) {
4416 wakeup_one(pf_purge_thread);
4417 sx_sleep(pf_purge_proc, &pf_end_lock, 0, "pftmo", 0);
4418 }
4419 sx_xunlock(&pf_end_lock);
4420
4421 if (pf_dev != NULL)
4422 destroy_dev(pf_dev);
4423
4424 pfi_cleanup();
4425
4426 rm_destroy(&pf_rules_lock);
4427 sx_destroy(&pf_ioctl_lock);
4428 sx_destroy(&pf_end_lock);
4429 }
4430
4431 static void
vnet_pf_init(void * unused __unused)4432 vnet_pf_init(void *unused __unused)
4433 {
4434
4435 pf_load_vnet();
4436 }
4437 VNET_SYSINIT(vnet_pf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
4438 vnet_pf_init, NULL);
4439
4440 static void
vnet_pf_uninit(const void * unused __unused)4441 vnet_pf_uninit(const void *unused __unused)
4442 {
4443
4444 pf_unload_vnet();
4445 }
4446 SYSUNINIT(pf_unload, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND, pf_unload, NULL);
4447 VNET_SYSUNINIT(vnet_pf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
4448 vnet_pf_uninit, NULL);
4449
4450
4451 static int
pf_modevent(module_t mod,int type,void * data)4452 pf_modevent(module_t mod, int type, void *data)
4453 {
4454 int error = 0;
4455
4456 switch(type) {
4457 case MOD_LOAD:
4458 error = pf_load();
4459 break;
4460 case MOD_UNLOAD:
4461 /* Handled in SYSUNINIT(pf_unload) to ensure it's done after
4462 * the vnet_pf_uninit()s */
4463 break;
4464 default:
4465 error = EINVAL;
4466 break;
4467 }
4468
4469 return (error);
4470 }
4471
4472 static moduledata_t pf_mod = {
4473 "pf",
4474 pf_modevent,
4475 0
4476 };
4477
4478 DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
4479 MODULE_VERSION(pf, PF_MODVER);
4480