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