1 /* $NetBSD: pf_ioctl.c,v 1.51 2015/08/20 14:40:18 christos Exp $ */
2 /* $OpenBSD: pf_ioctl.c,v 1.182 2007/06/24 11:17:13 mcbride Exp $ */
3
4 /*
5 * Copyright (c) 2001 Daniel Hartmeier
6 * Copyright (c) 2002,2003 Henning Brauer
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Effort sponsored in part by the Defense Advanced Research Projects
34 * Agency (DARPA) and Air Force Research Laboratory, Air Force
35 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
36 *
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: pf_ioctl.c,v 1.51 2015/08/20 14:40:18 christos Exp $");
41
42 #ifdef _KERNEL_OPT
43 #include "opt_inet.h"
44 #endif
45
46 #include "pfsync.h"
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/mbuf.h>
51 #include <sys/filio.h>
52 #include <sys/fcntl.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
55 #include <sys/kernel.h>
56 #include <sys/time.h>
57 #include <sys/pool.h>
58 #include <sys/proc.h>
59 #include <sys/malloc.h>
60 #include <sys/kthread.h>
61 #include <sys/rwlock.h>
62 #include <uvm/uvm_extern.h>
63 #ifdef __NetBSD__
64 #include <sys/conf.h>
65 #include <sys/lwp.h>
66 #include <sys/kauth.h>
67 #include <sys/module.h>
68 #include <sys/cprng.h>
69 #endif /* __NetBSD__ */
70
71 #include <net/if.h>
72 #include <net/if_types.h>
73 #include <net/route.h>
74
75 #include <netinet/in.h>
76 #include <netinet/in_var.h>
77 #include <netinet/in_systm.h>
78 #include <netinet/ip.h>
79 #include <netinet/ip_var.h>
80 #include <netinet/ip_icmp.h>
81
82 #ifndef __NetBSD__
83 #include <dev/rndvar.h>
84 #include <crypto/md5.h>
85 #else
86 #include <sys/md5.h>
87 #endif /* __NetBSD__ */
88 #include <net/pfvar.h>
89
90 #if NPFSYNC > 0
91 #include <net/if_pfsync.h>
92 #endif /* NPFSYNC > 0 */
93
94 #if NPFLOG > 0
95 #include <net/if_pflog.h>
96 #endif /* NPFLOG > 0 */
97
98 #ifdef INET6
99 #include <netinet/ip6.h>
100 #include <netinet/in_pcb.h>
101 #endif /* INET6 */
102
103 #ifdef ALTQ
104 #include <altq/altq.h>
105 #endif
106
107 #include "ioconf.h"
108
109 #ifdef _MODULE
110 void pfdetach(void);
111 #endif /* _MODULE */
112 #ifndef __NetBSD__
113 void pf_thread_create(void *);
114 #endif /* !__NetBSD__ */
115 int pfopen(dev_t, int, int, struct lwp *);
116 int pfclose(dev_t, int, int, struct lwp *);
117 struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
118 u_int8_t, u_int8_t, u_int8_t);
119
120 void pf_mv_pool(struct pf_palist *, struct pf_palist *);
121 void pf_empty_pool(struct pf_palist *);
122 int pfioctl(dev_t, u_long, void *, int, struct lwp *);
123 #ifdef ALTQ
124 int pf_begin_altq(u_int32_t *);
125 int pf_rollback_altq(u_int32_t);
126 int pf_commit_altq(u_int32_t);
127 int pf_enable_altq(struct pf_altq *);
128 int pf_disable_altq(struct pf_altq *);
129 #endif /* ALTQ */
130 int pf_begin_rules(u_int32_t *, int, const char *);
131 int pf_rollback_rules(u_int32_t, int, char *);
132 int pf_setup_pfsync_matching(struct pf_ruleset *);
133 void pf_hash_rule(MD5_CTX *, struct pf_rule *);
134 void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
135 int pf_commit_rules(u_int32_t, int, char *);
136 void pf_state_export(struct pfsync_state *,
137 struct pf_state_key *, struct pf_state *);
138 void pf_state_import(struct pfsync_state *,
139 struct pf_state_key *, struct pf_state *);
140
141 static int pf_state_add(struct pfsync_state*);
142
143 struct pf_rule pf_default_rule;
144 #ifdef __NetBSD__
145 krwlock_t pf_consistency_lock;
146 #else
147 struct rwlock pf_consistency_lock = RWLOCK_INITIALIZER("pfcnslk");
148 #endif /* __NetBSD__ */
149 #ifdef ALTQ
150 static int pf_altq_running;
151 #endif
152
153 int pf_state_lock = 0;
154
155 #define TAGID_MAX 50000
156 TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
157 pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
158
159 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
160 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
161 #endif
162 u_int16_t tagname2tag(struct pf_tags *, char *);
163 void tag2tagname(struct pf_tags *, u_int16_t, char *);
164 void tag_unref(struct pf_tags *, u_int16_t);
165 int pf_rtlabel_add(struct pf_addr_wrap *);
166 void pf_rtlabel_remove(struct pf_addr_wrap *);
167 void pf_rtlabel_copyout(struct pf_addr_wrap *);
168
169 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
170
171 #ifdef __NetBSD__
172 const struct cdevsw pf_cdevsw = {
173 .d_open = pfopen,
174 .d_close = pfclose,
175 .d_read = noread,
176 .d_write = nowrite,
177 .d_ioctl = pfioctl,
178 .d_stop = nostop,
179 .d_tty = notty,
180 .d_poll = nopoll,
181 .d_mmap = nommap,
182 .d_kqfilter = nokqfilter,
183 .d_discard = nodiscard,
184 .d_flag = D_OTHER
185 };
186
187 static int pfil4_wrapper(void *, struct mbuf **, struct ifnet *, int);
188 #ifdef INET6
189 static int pfil6_wrapper(void *, struct mbuf **, struct ifnet *, int);
190 #endif /* INET6 */
191
192 static int pf_pfil_attach(void);
193 static int pf_pfil_detach(void);
194
195 static int pf_pfil_attached;
196
197 static kauth_listener_t pf_listener;
198 #endif /* __NetBSD__ */
199
200 #ifdef __NetBSD__
201 static int
pf_listener_cb(kauth_cred_t cred,kauth_action_t action,void * cookie,void * arg0,void * arg1,void * arg2,void * arg3)202 pf_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
203 void *arg0, void *arg1, void *arg2, void *arg3)
204 {
205 int result;
206 enum kauth_network_req req;
207
208 result = KAUTH_RESULT_DEFER;
209 req = (enum kauth_network_req)arg0;
210
211 if (action != KAUTH_NETWORK_FIREWALL)
212 return result;
213
214 /* These must have came from device context. */
215 if ((req == KAUTH_REQ_NETWORK_FIREWALL_FW) ||
216 (req == KAUTH_REQ_NETWORK_FIREWALL_NAT))
217 result = KAUTH_RESULT_ALLOW;
218
219 return result;
220 }
221 #endif /* __NetBSD__ */
222
223 void
pfattach(int num)224 pfattach(int num)
225 {
226 u_int32_t *timeout = pf_default_rule.timeout;
227
228 #ifdef __NetBSD__
229 pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
230 &pool_allocator_nointr, IPL_NONE);
231 pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0,
232 "pfsrctrpl", NULL, IPL_SOFTNET);
233 pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
234 NULL, IPL_SOFTNET);
235 pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0, 0, 0,
236 "pfstatekeypl", NULL, IPL_SOFTNET);
237 pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
238 &pool_allocator_nointr, IPL_NONE);
239 pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
240 "pfpooladdrpl", &pool_allocator_nointr, IPL_NONE);
241 #else
242 pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
243 &pool_allocator_nointr);
244 pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0,
245 "pfsrctrpl", NULL);
246 pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
247 NULL);
248 pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0, 0, 0,
249 "pfstatekeypl", NULL);
250 pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
251 &pool_allocator_nointr);
252 pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
253 "pfpooladdrpl", &pool_allocator_nointr);
254 #endif /* !__NetBSD__ */
255
256 pfr_initialize();
257 pfi_initialize();
258 pf_osfp_initialize();
259
260 pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
261 pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
262
263 if (ctob(physmem) <= 100*1024*1024)
264 pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
265 PFR_KENTRY_HIWAT_SMALL;
266
267 RB_INIT(&tree_src_tracking);
268 RB_INIT(&pf_anchors);
269 pf_init_ruleset(&pf_main_ruleset);
270 TAILQ_INIT(&pf_altqs[0]);
271 TAILQ_INIT(&pf_altqs[1]);
272 TAILQ_INIT(&pf_pabuf);
273 pf_altqs_active = &pf_altqs[0];
274 pf_altqs_inactive = &pf_altqs[1];
275 TAILQ_INIT(&state_list);
276
277 #ifdef __NetBSD__
278 rw_init(&pf_consistency_lock);
279 #endif /* __NetBSD__ */
280
281 /* default rule should never be garbage collected */
282 pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
283 pf_default_rule.action = PF_PASS;
284 pf_default_rule.nr = -1;
285 pf_default_rule.rtableid = -1;
286
287 /* initialize default timeouts */
288 timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
289 timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
290 timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
291 timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
292 timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
293 timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
294 timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
295 timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
296 timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
297 timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
298 timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
299 timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
300 timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
301 timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
302 timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
303 timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
304 timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
305 timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
306 timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
307 timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
308
309 pf_normalize_init();
310 bzero(&pf_status, sizeof(pf_status));
311 pf_status.debug = PF_DEBUG_URGENT;
312
313 /* XXX do our best to avoid a conflict */
314 pf_status.hostid = cprng_fast32();
315
316 /* require process context to purge states, so perform in a thread */
317 #ifdef __NetBSD__
318 if (kthread_create(PRI_NONE, 0, NULL, pf_purge_thread, NULL, NULL,
319 "pfpurge"))
320 panic("pfpurge thread");
321 #else
322 kthread_create_deferred(pf_thread_create, NULL);
323 #endif /* !__NetBSD__ */
324
325 #ifdef __NetBSD__
326 pf_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
327 pf_listener_cb, NULL);
328 #endif /* __NetBSD__ */
329 }
330
331 #ifdef _MODULE
332 void
pfdetach(void)333 pfdetach(void)
334 {
335 extern int pf_purge_thread_running;
336 extern int pf_purge_thread_stop;
337 struct pf_anchor *anchor;
338 struct pf_state *state;
339 struct pf_src_node *node;
340 struct pfioc_table pt;
341 u_int32_t ticket;
342 int i;
343 char r = '\0';
344
345 pf_purge_thread_stop = 1;
346 wakeup(pf_purge_thread);
347
348 /* wait until the kthread exits */
349 while (pf_purge_thread_running)
350 tsleep(&pf_purge_thread_running, PWAIT, "pfdown", 0);
351
352 (void)pf_pfil_detach();
353
354 pf_status.running = 0;
355
356 /* clear the rulesets */
357 for (i = 0; i < PF_RULESET_MAX; i++)
358 if (pf_begin_rules(&ticket, i, &r) == 0)
359 pf_commit_rules(ticket, i, &r);
360 #ifdef ALTQ
361 if (pf_begin_altq(&ticket) == 0)
362 pf_commit_altq(ticket);
363 #endif /* ALTQ */
364
365 /* clear states */
366 RB_FOREACH(state, pf_state_tree_id, &tree_id) {
367 state->timeout = PFTM_PURGE;
368 #if NPFSYNC > 0
369 state->sync_flags = PFSTATE_NOSYNC;
370 #endif /* NPFSYNC > 0 */
371 }
372 pf_purge_expired_states(pf_status.states);
373 #if NPFSYNC > 0
374 pfsync_clear_states(pf_status.hostid, NULL);
375 #endif /* NPFSYNC > 0 */
376
377 /* clear source nodes */
378 RB_FOREACH(state, pf_state_tree_id, &tree_id) {
379 state->src_node = NULL;
380 state->nat_src_node = NULL;
381 }
382 RB_FOREACH(node, pf_src_tree, &tree_src_tracking) {
383 node->expire = 1;
384 node->states = 0;
385 }
386 pf_purge_expired_src_nodes(0);
387
388 /* clear tables */
389 memset(&pt, '\0', sizeof(pt));
390 pfr_clr_tables(&pt.pfrio_table, &pt.pfrio_ndel, pt.pfrio_flags);
391
392 /* destroy anchors */
393 while ((anchor = RB_MIN(pf_anchor_global, &pf_anchors)) != NULL) {
394 for (i = 0; i < PF_RULESET_MAX; i++)
395 if (pf_begin_rules(&ticket, i, anchor->name) == 0)
396 pf_commit_rules(ticket, i, anchor->name);
397 }
398
399 /* destroy main ruleset */
400 pf_remove_if_empty_ruleset(&pf_main_ruleset);
401
402 /* destroy the pools */
403 pool_destroy(&pf_pooladdr_pl);
404 pool_destroy(&pf_altq_pl);
405 pool_destroy(&pf_state_key_pl);
406 pool_destroy(&pf_state_pl);
407 pool_destroy(&pf_rule_pl);
408 pool_destroy(&pf_src_tree_pl);
409
410 rw_destroy(&pf_consistency_lock);
411
412 /* destroy subsystems */
413 pf_normalize_destroy();
414 pf_osfp_destroy();
415 pfr_destroy();
416 pfi_destroy();
417
418 /* cleanup kauth listener */
419 kauth_unlisten_scope(pf_listener);
420 }
421 #endif /* _MODULE */
422
423 #ifndef __NetBSD__
424 void
pf_thread_create(void * v)425 pf_thread_create(void *v)
426 {
427 if (kthread_create(pf_purge_thread, NULL, NULL, "pfpurge"))
428 panic("pfpurge thread");
429 }
430 #endif /* !__NetBSD__ */
431
432 int
pfopen(dev_t dev,int flags,int fmt,struct lwp * l)433 pfopen(dev_t dev, int flags, int fmt, struct lwp *l)
434 {
435 if (minor(dev) >= 1)
436 return (ENXIO);
437 return (0);
438 }
439
440 int
pfclose(dev_t dev,int flags,int fmt,struct lwp * l)441 pfclose(dev_t dev, int flags, int fmt, struct lwp *l)
442 {
443 if (minor(dev) >= 1)
444 return (ENXIO);
445 return (0);
446 }
447
448 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)449 pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
450 u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
451 u_int8_t check_ticket)
452 {
453 struct pf_ruleset *ruleset;
454 struct pf_rule *rule;
455 int rs_num;
456
457 ruleset = pf_find_ruleset(anchor);
458 if (ruleset == NULL)
459 return (NULL);
460 rs_num = pf_get_ruleset_number(rule_action);
461 if (rs_num >= PF_RULESET_MAX)
462 return (NULL);
463 if (active) {
464 if (check_ticket && ticket !=
465 ruleset->rules[rs_num].active.ticket)
466 return (NULL);
467 if (r_last)
468 rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
469 pf_rulequeue);
470 else
471 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
472 } else {
473 if (check_ticket && ticket !=
474 ruleset->rules[rs_num].inactive.ticket)
475 return (NULL);
476 if (r_last)
477 rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
478 pf_rulequeue);
479 else
480 rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
481 }
482 if (!r_last) {
483 while ((rule != NULL) && (rule->nr != rule_number))
484 rule = TAILQ_NEXT(rule, entries);
485 }
486 if (rule == NULL)
487 return (NULL);
488
489 return (&rule->rpool);
490 }
491
492 void
pf_mv_pool(struct pf_palist * poola,struct pf_palist * poolb)493 pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
494 {
495 struct pf_pooladdr *mv_pool_pa;
496
497 while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
498 TAILQ_REMOVE(poola, mv_pool_pa, entries);
499 TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
500 }
501 }
502
503 void
pf_empty_pool(struct pf_palist * poola)504 pf_empty_pool(struct pf_palist *poola)
505 {
506 struct pf_pooladdr *empty_pool_pa;
507
508 while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
509 pfi_dynaddr_remove(&empty_pool_pa->addr);
510 pf_tbladdr_remove(&empty_pool_pa->addr);
511 pfi_kif_unref(empty_pool_pa->kif, PFI_KIF_REF_RULE);
512 TAILQ_REMOVE(poola, empty_pool_pa, entries);
513 pool_put(&pf_pooladdr_pl, empty_pool_pa);
514 }
515 }
516
517 void
pf_rm_rule(struct pf_rulequeue * rulequeue,struct pf_rule * rule)518 pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
519 {
520 if (rulequeue != NULL) {
521 if (rule->states <= 0) {
522 /*
523 * XXX - we need to remove the table *before* detaching
524 * the rule to make sure the table code does not delete
525 * the anchor under our feet.
526 */
527 pf_tbladdr_remove(&rule->src.addr);
528 pf_tbladdr_remove(&rule->dst.addr);
529 if (rule->overload_tbl)
530 pfr_detach_table(rule->overload_tbl);
531 }
532 TAILQ_REMOVE(rulequeue, rule, entries);
533 rule->entries.tqe_prev = NULL;
534 rule->nr = -1;
535 }
536
537 if (rule->states > 0 || rule->src_nodes > 0 ||
538 rule->entries.tqe_prev != NULL)
539 return;
540 pf_tag_unref(rule->tag);
541 pf_tag_unref(rule->match_tag);
542 #ifdef ALTQ
543 if (rule->pqid != rule->qid)
544 pf_qid_unref(rule->pqid);
545 pf_qid_unref(rule->qid);
546 #endif
547 pf_rtlabel_remove(&rule->src.addr);
548 pf_rtlabel_remove(&rule->dst.addr);
549 pfi_dynaddr_remove(&rule->src.addr);
550 pfi_dynaddr_remove(&rule->dst.addr);
551 if (rulequeue == NULL) {
552 pf_tbladdr_remove(&rule->src.addr);
553 pf_tbladdr_remove(&rule->dst.addr);
554 if (rule->overload_tbl)
555 pfr_detach_table(rule->overload_tbl);
556 }
557 pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
558 pf_anchor_remove(rule);
559 pf_empty_pool(&rule->rpool.list);
560 pool_put(&pf_rule_pl, rule);
561 }
562
563 u_int16_t
tagname2tag(struct pf_tags * head,char * tagname)564 tagname2tag(struct pf_tags *head, char *tagname)
565 {
566 struct pf_tagname *tag, *p = NULL;
567 u_int16_t new_tagid = 1;
568
569 TAILQ_FOREACH(tag, head, entries)
570 if (strcmp(tagname, tag->name) == 0) {
571 tag->ref++;
572 return (tag->tag);
573 }
574
575 /*
576 * to avoid fragmentation, we do a linear search from the beginning
577 * and take the first free slot we find. if there is none or the list
578 * is empty, append a new entry at the end.
579 */
580
581 /* new entry */
582 if (!TAILQ_EMPTY(head))
583 for (p = TAILQ_FIRST(head); p != NULL &&
584 p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
585 new_tagid = p->tag + 1;
586
587 if (new_tagid > TAGID_MAX)
588 return (0);
589
590 /* allocate and fill new struct pf_tagname */
591 tag = (struct pf_tagname *)malloc(sizeof(struct pf_tagname),
592 M_TEMP, M_NOWAIT);
593 if (tag == NULL)
594 return (0);
595 bzero(tag, sizeof(struct pf_tagname));
596 strlcpy(tag->name, tagname, sizeof(tag->name));
597 tag->tag = new_tagid;
598 tag->ref++;
599
600 if (p != NULL) /* insert new entry before p */
601 TAILQ_INSERT_BEFORE(p, tag, entries);
602 else /* either list empty or no free slot in between */
603 TAILQ_INSERT_TAIL(head, tag, entries);
604
605 return (tag->tag);
606 }
607
608 void
tag2tagname(struct pf_tags * head,u_int16_t tagid,char * p)609 tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
610 {
611 struct pf_tagname *tag;
612
613 TAILQ_FOREACH(tag, head, entries)
614 if (tag->tag == tagid) {
615 strlcpy(p, tag->name, PF_TAG_NAME_SIZE);
616 return;
617 }
618 }
619
620 void
tag_unref(struct pf_tags * head,u_int16_t tag)621 tag_unref(struct pf_tags *head, u_int16_t tag)
622 {
623 struct pf_tagname *p, *next;
624
625 if (tag == 0)
626 return;
627
628 for (p = TAILQ_FIRST(head); p != NULL; p = next) {
629 next = TAILQ_NEXT(p, entries);
630 if (tag == p->tag) {
631 if (--p->ref == 0) {
632 TAILQ_REMOVE(head, p, entries);
633 free(p, M_TEMP);
634 }
635 break;
636 }
637 }
638 }
639
640 u_int16_t
pf_tagname2tag(char * tagname)641 pf_tagname2tag(char *tagname)
642 {
643 return (tagname2tag(&pf_tags, tagname));
644 }
645
646 void
pf_tag2tagname(u_int16_t tagid,char * p)647 pf_tag2tagname(u_int16_t tagid, char *p)
648 {
649 tag2tagname(&pf_tags, tagid, p);
650 }
651
652 void
pf_tag_ref(u_int16_t tag)653 pf_tag_ref(u_int16_t tag)
654 {
655 struct pf_tagname *t;
656
657 TAILQ_FOREACH(t, &pf_tags, entries)
658 if (t->tag == tag)
659 break;
660 if (t != NULL)
661 t->ref++;
662 }
663
664 void
pf_tag_unref(u_int16_t tag)665 pf_tag_unref(u_int16_t tag)
666 {
667 tag_unref(&pf_tags, tag);
668 }
669
670 int
pf_rtlabel_add(struct pf_addr_wrap * a)671 pf_rtlabel_add(struct pf_addr_wrap *a)
672 {
673 #ifndef __NetBSD__
674 if (a->type == PF_ADDR_RTLABEL &&
675 (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0)
676 return (-1);
677 #endif /* !__NetBSD__ */
678 return (0);
679 }
680
681 void
pf_rtlabel_remove(struct pf_addr_wrap * a)682 pf_rtlabel_remove(struct pf_addr_wrap *a)
683 {
684 #ifndef __NetBSD__
685 if (a->type == PF_ADDR_RTLABEL)
686 rtlabel_unref(a->v.rtlabel);
687 #endif /* !__NetBSD__ */
688 }
689
690 void
pf_rtlabel_copyout(struct pf_addr_wrap * a)691 pf_rtlabel_copyout(struct pf_addr_wrap *a)
692 {
693 #ifndef __NetBSD__
694 const char *name;
695
696 if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) {
697 if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL)
698 strlcpy(a->v.rtlabelname, "?",
699 sizeof(a->v.rtlabelname));
700 else
701 strlcpy(a->v.rtlabelname, name,
702 sizeof(a->v.rtlabelname));
703 }
704 #endif /* !__NetBSD__ */
705 }
706
707 #ifdef ALTQ
708 u_int32_t
pf_qname2qid(char * qname)709 pf_qname2qid(char *qname)
710 {
711 return ((u_int32_t)tagname2tag(&pf_qids, qname));
712 }
713
714 void
pf_qid2qname(u_int32_t qid,char * p)715 pf_qid2qname(u_int32_t qid, char *p)
716 {
717 tag2tagname(&pf_qids, (u_int16_t)qid, p);
718 }
719
720 void
pf_qid_unref(u_int32_t qid)721 pf_qid_unref(u_int32_t qid)
722 {
723 tag_unref(&pf_qids, (u_int16_t)qid);
724 }
725
726 int
pf_begin_altq(u_int32_t * ticket)727 pf_begin_altq(u_int32_t *ticket)
728 {
729 struct pf_altq *altq;
730 int error = 0;
731
732 /* Purge the old altq list */
733 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
734 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
735 if (altq->qname[0] == 0) {
736 /* detach and destroy the discipline */
737 error = altq_remove(altq);
738 } else
739 pf_qid_unref(altq->qid);
740 pool_put(&pf_altq_pl, altq);
741 }
742 if (error)
743 return (error);
744 *ticket = ++ticket_altqs_inactive;
745 altqs_inactive_open = 1;
746 return (0);
747 }
748
749 int
pf_rollback_altq(u_int32_t ticket)750 pf_rollback_altq(u_int32_t ticket)
751 {
752 struct pf_altq *altq;
753 int error = 0;
754
755 if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
756 return (0);
757 /* Purge the old altq list */
758 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
759 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
760 if (altq->qname[0] == 0) {
761 /* detach and destroy the discipline */
762 error = altq_remove(altq);
763 } else
764 pf_qid_unref(altq->qid);
765 pool_put(&pf_altq_pl, altq);
766 }
767 altqs_inactive_open = 0;
768 return (error);
769 }
770
771 int
pf_commit_altq(u_int32_t ticket)772 pf_commit_altq(u_int32_t ticket)
773 {
774 struct pf_altqqueue *old_altqs;
775 struct pf_altq *altq;
776 int s, err, error = 0;
777
778 if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
779 return (EBUSY);
780
781 /* swap altqs, keep the old. */
782 s = splsoftnet();
783 old_altqs = pf_altqs_active;
784 pf_altqs_active = pf_altqs_inactive;
785 pf_altqs_inactive = old_altqs;
786 ticket_altqs_active = ticket_altqs_inactive;
787
788 /* Attach new disciplines */
789 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
790 if (altq->qname[0] == 0) {
791 /* attach the discipline */
792 error = altq_pfattach(altq);
793 if (error == 0 && pf_altq_running)
794 error = pf_enable_altq(altq);
795 if (error != 0) {
796 splx(s);
797 return (error);
798 }
799 }
800 }
801
802 /* Purge the old altq list */
803 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
804 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
805 if (altq->qname[0] == 0) {
806 /* detach and destroy the discipline */
807 if (pf_altq_running)
808 error = pf_disable_altq(altq);
809 err = altq_pfdetach(altq);
810 if (err != 0 && error == 0)
811 error = err;
812 err = altq_remove(altq);
813 if (err != 0 && error == 0)
814 error = err;
815 } else
816 pf_qid_unref(altq->qid);
817 pool_put(&pf_altq_pl, altq);
818 }
819 splx(s);
820
821 altqs_inactive_open = 0;
822 return (error);
823 }
824
825 int
pf_enable_altq(struct pf_altq * altq)826 pf_enable_altq(struct pf_altq *altq)
827 {
828 struct ifnet *ifp;
829 struct tb_profile tb;
830 int s, error = 0;
831
832 if ((ifp = ifunit(altq->ifname)) == NULL)
833 return (EINVAL);
834
835 if (ifp->if_snd.altq_type != ALTQT_NONE)
836 error = altq_enable(&ifp->if_snd);
837
838 /* set tokenbucket regulator */
839 if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
840 tb.rate = altq->ifbandwidth;
841 tb.depth = altq->tbrsize;
842 s = splnet();
843 error = tbr_set(&ifp->if_snd, &tb);
844 splx(s);
845 }
846
847 return (error);
848 }
849
850 int
pf_disable_altq(struct pf_altq * altq)851 pf_disable_altq(struct pf_altq *altq)
852 {
853 struct ifnet *ifp;
854 struct tb_profile tb;
855 int s, error;
856
857 if ((ifp = ifunit(altq->ifname)) == NULL)
858 return (EINVAL);
859
860 /*
861 * when the discipline is no longer referenced, it was overridden
862 * by a new one. if so, just return.
863 */
864 if (altq->altq_disc != ifp->if_snd.altq_disc)
865 return (0);
866
867 error = altq_disable(&ifp->if_snd);
868
869 if (error == 0) {
870 /* clear tokenbucket regulator */
871 tb.rate = 0;
872 s = splnet();
873 error = tbr_set(&ifp->if_snd, &tb);
874 splx(s);
875 }
876
877 return (error);
878 }
879 #endif /* ALTQ */
880
881 int
pf_begin_rules(u_int32_t * ticket,int rs_num,const char * anchor)882 pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
883 {
884 struct pf_ruleset *rs;
885 struct pf_rule *rule;
886
887 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
888 return (EINVAL);
889 rs = pf_find_or_create_ruleset(anchor);
890 if (rs == NULL)
891 return (EINVAL);
892 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
893 pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
894 rs->rules[rs_num].inactive.rcount--;
895 }
896 *ticket = ++rs->rules[rs_num].inactive.ticket;
897 rs->rules[rs_num].inactive.open = 1;
898 return (0);
899 }
900
901 int
pf_rollback_rules(u_int32_t ticket,int rs_num,char * anchor)902 pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
903 {
904 struct pf_ruleset *rs;
905 struct pf_rule *rule;
906
907 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
908 return (EINVAL);
909 rs = pf_find_ruleset(anchor);
910 if (rs == NULL || !rs->rules[rs_num].inactive.open ||
911 rs->rules[rs_num].inactive.ticket != ticket)
912 return (0);
913 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
914 pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
915 rs->rules[rs_num].inactive.rcount--;
916 }
917 rs->rules[rs_num].inactive.open = 0;
918 return (0);
919 }
920
921 #define PF_MD5_UPD(st, elm) \
922 MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
923
924 #define PF_MD5_UPD_STR(st, elm) \
925 MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
926
927 #define PF_MD5_UPD_HTONL(st, elm, stor) do { \
928 (stor) = htonl((st)->elm); \
929 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
930 } while (0)
931
932 #define PF_MD5_UPD_HTONS(st, elm, stor) do { \
933 (stor) = htons((st)->elm); \
934 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
935 } while (0)
936
937 void
pf_hash_rule_addr(MD5_CTX * ctx,struct pf_rule_addr * pfr)938 pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
939 {
940 PF_MD5_UPD(pfr, addr.type);
941 switch (pfr->addr.type) {
942 case PF_ADDR_DYNIFTL:
943 PF_MD5_UPD(pfr, addr.v.ifname);
944 PF_MD5_UPD(pfr, addr.iflags);
945 break;
946 case PF_ADDR_TABLE:
947 PF_MD5_UPD(pfr, addr.v.tblname);
948 break;
949 case PF_ADDR_ADDRMASK:
950 /* XXX ignore af? */
951 PF_MD5_UPD(pfr, addr.v.a.addr.addr32);
952 PF_MD5_UPD(pfr, addr.v.a.mask.addr32);
953 break;
954 case PF_ADDR_RTLABEL:
955 PF_MD5_UPD(pfr, addr.v.rtlabelname);
956 break;
957 }
958
959 PF_MD5_UPD(pfr, port[0]);
960 PF_MD5_UPD(pfr, port[1]);
961 PF_MD5_UPD(pfr, neg);
962 PF_MD5_UPD(pfr, port_op);
963 }
964
965 void
pf_hash_rule(MD5_CTX * ctx,struct pf_rule * rule)966 pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule)
967 {
968 u_int16_t x;
969 u_int32_t y;
970
971 pf_hash_rule_addr(ctx, &rule->src);
972 pf_hash_rule_addr(ctx, &rule->dst);
973 PF_MD5_UPD_STR(rule, label);
974 PF_MD5_UPD_STR(rule, ifname);
975 PF_MD5_UPD_STR(rule, match_tagname);
976 PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */
977 PF_MD5_UPD_HTONL(rule, os_fingerprint, y);
978 PF_MD5_UPD_HTONL(rule, prob, y);
979 PF_MD5_UPD_HTONL(rule, uid.uid[0], y);
980 PF_MD5_UPD_HTONL(rule, uid.uid[1], y);
981 PF_MD5_UPD(rule, uid.op);
982 PF_MD5_UPD_HTONL(rule, gid.gid[0], y);
983 PF_MD5_UPD_HTONL(rule, gid.gid[1], y);
984 PF_MD5_UPD(rule, gid.op);
985 PF_MD5_UPD_HTONL(rule, rule_flag, y);
986 PF_MD5_UPD(rule, action);
987 PF_MD5_UPD(rule, direction);
988 PF_MD5_UPD(rule, af);
989 PF_MD5_UPD(rule, quick);
990 PF_MD5_UPD(rule, ifnot);
991 PF_MD5_UPD(rule, match_tag_not);
992 PF_MD5_UPD(rule, natpass);
993 PF_MD5_UPD(rule, keep_state);
994 PF_MD5_UPD(rule, proto);
995 PF_MD5_UPD(rule, type);
996 PF_MD5_UPD(rule, code);
997 PF_MD5_UPD(rule, flags);
998 PF_MD5_UPD(rule, flagset);
999 PF_MD5_UPD(rule, allow_opts);
1000 PF_MD5_UPD(rule, rt);
1001 PF_MD5_UPD(rule, tos);
1002 }
1003
1004 int
pf_commit_rules(u_int32_t ticket,int rs_num,char * anchor)1005 pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
1006 {
1007 struct pf_ruleset *rs;
1008 struct pf_rule *rule, **old_array;
1009 struct pf_rulequeue *old_rules;
1010 int s, error;
1011 u_int32_t old_rcount;
1012
1013 if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1014 return (EINVAL);
1015 rs = pf_find_ruleset(anchor);
1016 if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1017 ticket != rs->rules[rs_num].inactive.ticket)
1018 return (EBUSY);
1019
1020 /* Calculate checksum for the main ruleset */
1021 if (rs == &pf_main_ruleset) {
1022 error = pf_setup_pfsync_matching(rs);
1023 if (error != 0)
1024 return (error);
1025 }
1026
1027 /* Swap rules, keep the old. */
1028 s = splsoftnet();
1029 old_rules = rs->rules[rs_num].active.ptr;
1030 old_rcount = rs->rules[rs_num].active.rcount;
1031 old_array = rs->rules[rs_num].active.ptr_array;
1032
1033 rs->rules[rs_num].active.ptr =
1034 rs->rules[rs_num].inactive.ptr;
1035 rs->rules[rs_num].active.ptr_array =
1036 rs->rules[rs_num].inactive.ptr_array;
1037 rs->rules[rs_num].active.rcount =
1038 rs->rules[rs_num].inactive.rcount;
1039 rs->rules[rs_num].inactive.ptr = old_rules;
1040 rs->rules[rs_num].inactive.ptr_array = old_array;
1041 rs->rules[rs_num].inactive.rcount = old_rcount;
1042
1043 rs->rules[rs_num].active.ticket =
1044 rs->rules[rs_num].inactive.ticket;
1045 pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
1046
1047
1048 /* Purge the old rule list. */
1049 while ((rule = TAILQ_FIRST(old_rules)) != NULL)
1050 pf_rm_rule(old_rules, rule);
1051 if (rs->rules[rs_num].inactive.ptr_array)
1052 free(rs->rules[rs_num].inactive.ptr_array, M_TEMP);
1053 rs->rules[rs_num].inactive.ptr_array = NULL;
1054 rs->rules[rs_num].inactive.rcount = 0;
1055 rs->rules[rs_num].inactive.open = 0;
1056 pf_remove_if_empty_ruleset(rs);
1057 splx(s);
1058 return (0);
1059 }
1060
1061 void
pf_state_export(struct pfsync_state * sp,struct pf_state_key * sk,struct pf_state * s)1062 pf_state_export(struct pfsync_state *sp, struct pf_state_key *sk,
1063 struct pf_state *s)
1064 {
1065 int secs = time_second;
1066 bzero(sp, sizeof(struct pfsync_state));
1067
1068 /* copy from state key */
1069 sp->lan.addr = sk->lan.addr;
1070 sp->lan.port = sk->lan.port;
1071 sp->gwy.addr = sk->gwy.addr;
1072 sp->gwy.port = sk->gwy.port;
1073 sp->ext.addr = sk->ext.addr;
1074 sp->ext.port = sk->ext.port;
1075 sp->proto = sk->proto;
1076 sp->af = sk->af;
1077 sp->direction = sk->direction;
1078
1079 /* copy from state */
1080 memcpy(&sp->id, &s->id, sizeof(sp->id));
1081 sp->creatorid = s->creatorid;
1082 strlcpy(sp->ifname, s->kif->pfik_name, sizeof(sp->ifname));
1083 pf_state_peer_to_pfsync(&s->src, &sp->src);
1084 pf_state_peer_to_pfsync(&s->dst, &sp->dst);
1085
1086 sp->rule = s->rule.ptr->nr;
1087 sp->nat_rule = (s->nat_rule.ptr == NULL) ? -1 : s->nat_rule.ptr->nr;
1088 sp->anchor = (s->anchor.ptr == NULL) ? -1 : s->anchor.ptr->nr;
1089
1090 pf_state_counter_to_pfsync(s->bytes[0], sp->bytes[0]);
1091 pf_state_counter_to_pfsync(s->bytes[1], sp->bytes[1]);
1092 pf_state_counter_to_pfsync(s->packets[0], sp->packets[0]);
1093 pf_state_counter_to_pfsync(s->packets[1], sp->packets[1]);
1094 sp->creation = secs - s->creation;
1095 sp->expire = pf_state_expires(s);
1096 sp->log = s->log;
1097 sp->allow_opts = s->allow_opts;
1098 sp->timeout = s->timeout;
1099
1100 if (s->src_node)
1101 sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
1102 if (s->nat_src_node)
1103 sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
1104
1105 if (sp->expire > secs)
1106 sp->expire -= secs;
1107 else
1108 sp->expire = 0;
1109
1110 }
1111
1112 void
pf_state_import(struct pfsync_state * sp,struct pf_state_key * sk,struct pf_state * s)1113 pf_state_import(struct pfsync_state *sp, struct pf_state_key *sk,
1114 struct pf_state *s)
1115 {
1116 /* copy to state key */
1117 sk->lan.addr = sp->lan.addr;
1118 sk->lan.port = sp->lan.port;
1119 sk->gwy.addr = sp->gwy.addr;
1120 sk->gwy.port = sp->gwy.port;
1121 sk->ext.addr = sp->ext.addr;
1122 sk->ext.port = sp->ext.port;
1123 sk->proto = sp->proto;
1124 sk->af = sp->af;
1125 sk->direction = sp->direction;
1126
1127 /* copy to state */
1128 memcpy(&s->id, &sp->id, sizeof(sp->id));
1129 s->creatorid = sp->creatorid;
1130 pf_state_peer_from_pfsync(&sp->src, &s->src);
1131 pf_state_peer_from_pfsync(&sp->dst, &s->dst);
1132
1133 s->rule.ptr = &pf_default_rule;
1134 s->rule.ptr->states++;
1135 s->nat_rule.ptr = NULL;
1136 s->anchor.ptr = NULL;
1137 s->rt_kif = NULL;
1138 s->creation = time_second;
1139 s->expire = time_second;
1140 s->timeout = sp->timeout;
1141 if (sp->expire > 0)
1142 s->expire -= pf_default_rule.timeout[sp->timeout] - sp->expire;
1143 s->pfsync_time = 0;
1144 s->packets[0] = s->packets[1] = 0;
1145 s->bytes[0] = s->bytes[1] = 0;
1146 }
1147
1148 int
pf_state_add(struct pfsync_state * sp)1149 pf_state_add(struct pfsync_state* sp)
1150 {
1151 struct pf_state *s;
1152 struct pf_state_key *sk;
1153 struct pfi_kif *kif;
1154
1155 if (sp->timeout >= PFTM_MAX &&
1156 sp->timeout != PFTM_UNTIL_PACKET) {
1157 return EINVAL;
1158 }
1159 s = pool_get(&pf_state_pl, PR_NOWAIT);
1160 if (s == NULL) {
1161 return ENOMEM;
1162 }
1163 bzero(s, sizeof(struct pf_state));
1164 if ((sk = pf_alloc_state_key(s)) == NULL) {
1165 pool_put(&pf_state_pl, s);
1166 return ENOMEM;
1167 }
1168 pf_state_import(sp, sk, s);
1169 kif = pfi_kif_get(sp->ifname);
1170 if (kif == NULL) {
1171 pool_put(&pf_state_pl, s);
1172 pool_put(&pf_state_key_pl, sk);
1173 return ENOENT;
1174 }
1175 if (pf_insert_state(kif, s)) {
1176 pfi_kif_unref(kif, PFI_KIF_REF_NONE);
1177 pool_put(&pf_state_pl, s);
1178 return ENOMEM;
1179 }
1180
1181 return 0;
1182 }
1183
1184
1185 int
pf_setup_pfsync_matching(struct pf_ruleset * rs)1186 pf_setup_pfsync_matching(struct pf_ruleset *rs)
1187 {
1188 MD5_CTX ctx;
1189 struct pf_rule *rule;
1190 int rs_cnt;
1191 u_int8_t digest[PF_MD5_DIGEST_LENGTH];
1192
1193 MD5Init(&ctx);
1194 for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
1195 /* XXX PF_RULESET_SCRUB as well? */
1196 if (rs_cnt == PF_RULESET_SCRUB)
1197 continue;
1198
1199 if (rs->rules[rs_cnt].inactive.ptr_array)
1200 free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
1201 rs->rules[rs_cnt].inactive.ptr_array = NULL;
1202
1203 if (rs->rules[rs_cnt].inactive.rcount) {
1204 rs->rules[rs_cnt].inactive.ptr_array =
1205 malloc(sizeof(void *) *
1206 rs->rules[rs_cnt].inactive.rcount,
1207 M_TEMP, M_NOWAIT);
1208
1209 if (!rs->rules[rs_cnt].inactive.ptr_array)
1210 return (ENOMEM);
1211 }
1212
1213 TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
1214 entries) {
1215 pf_hash_rule(&ctx, rule);
1216 (rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule;
1217 }
1218 }
1219
1220 MD5Final(digest, &ctx);
1221 memcpy(pf_status.pf_chksum, digest, sizeof(pf_status.pf_chksum));
1222 return (0);
1223 }
1224
1225 int
pfioctl(dev_t dev,u_long cmd,void * addr,int flags,struct lwp * l)1226 pfioctl(dev_t dev, u_long cmd, void *addr, int flags, struct lwp *l)
1227 {
1228 struct pf_pooladdr *pa = NULL;
1229 struct pf_pool *pool = NULL;
1230 int s;
1231 int error = 0;
1232
1233 /* XXX keep in sync with switch() below */
1234 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL,
1235 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL))
1236 switch (cmd) {
1237 case DIOCGETRULES:
1238 case DIOCGETRULE:
1239 case DIOCGETADDRS:
1240 case DIOCGETADDR:
1241 case DIOCGETSTATE:
1242 case DIOCSETSTATUSIF:
1243 case DIOCGETSTATUS:
1244 case DIOCCLRSTATUS:
1245 case DIOCNATLOOK:
1246 case DIOCSETDEBUG:
1247 case DIOCGETSTATES:
1248 case DIOCGETTIMEOUT:
1249 case DIOCCLRRULECTRS:
1250 case DIOCGETLIMIT:
1251 case DIOCGETALTQS:
1252 case DIOCGETALTQ:
1253 case DIOCGETQSTATS:
1254 case DIOCGETRULESETS:
1255 case DIOCGETRULESET:
1256 case DIOCRGETTABLES:
1257 case DIOCRGETTSTATS:
1258 case DIOCRCLRTSTATS:
1259 case DIOCRCLRADDRS:
1260 case DIOCRADDADDRS:
1261 case DIOCRDELADDRS:
1262 case DIOCRSETADDRS:
1263 case DIOCRGETADDRS:
1264 case DIOCRGETASTATS:
1265 case DIOCRCLRASTATS:
1266 case DIOCRTSTADDRS:
1267 case DIOCOSFPGET:
1268 case DIOCGETSRCNODES:
1269 case DIOCCLRSRCNODES:
1270 case DIOCIGETIFACES:
1271 case DIOCSETIFFLAG:
1272 case DIOCCLRIFFLAG:
1273 case DIOCSETLCK:
1274 case DIOCADDSTATES:
1275 break;
1276 case DIOCRCLRTABLES:
1277 case DIOCRADDTABLES:
1278 case DIOCRDELTABLES:
1279 case DIOCRSETTFLAGS:
1280 if (((struct pfioc_table *)addr)->pfrio_flags &
1281 PFR_FLAG_DUMMY)
1282 break; /* dummy operation ok */
1283 return (EPERM);
1284 default:
1285 return (EPERM);
1286 }
1287
1288 if (!(flags & FWRITE))
1289 switch (cmd) {
1290 case DIOCGETRULES:
1291 case DIOCGETADDRS:
1292 case DIOCGETADDR:
1293 case DIOCGETSTATE:
1294 case DIOCGETSTATUS:
1295 case DIOCGETSTATES:
1296 case DIOCGETTIMEOUT:
1297 case DIOCGETLIMIT:
1298 case DIOCGETALTQS:
1299 case DIOCGETALTQ:
1300 case DIOCGETQSTATS:
1301 case DIOCGETRULESETS:
1302 case DIOCGETRULESET:
1303 case DIOCNATLOOK:
1304 case DIOCRGETTABLES:
1305 case DIOCRGETTSTATS:
1306 case DIOCRGETADDRS:
1307 case DIOCRGETASTATS:
1308 case DIOCRTSTADDRS:
1309 case DIOCOSFPGET:
1310 case DIOCGETSRCNODES:
1311 case DIOCIGETIFACES:
1312 case DIOCSETLCK:
1313 break;
1314 case DIOCRCLRTABLES:
1315 case DIOCRADDTABLES:
1316 case DIOCRDELTABLES:
1317 case DIOCRCLRTSTATS:
1318 case DIOCRCLRADDRS:
1319 case DIOCRADDADDRS:
1320 case DIOCRDELADDRS:
1321 case DIOCRSETADDRS:
1322 case DIOCRSETTFLAGS:
1323 case DIOCADDSTATES:
1324 if (((struct pfioc_table *)addr)->pfrio_flags &
1325 PFR_FLAG_DUMMY) {
1326 flags |= FWRITE; /* need write lock for dummy */
1327 break; /* dummy operation ok */
1328 }
1329 return (EACCES);
1330 case DIOCGETRULE:
1331 if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR)
1332 return (EACCES);
1333 break;
1334 default:
1335 return (EACCES);
1336 }
1337
1338 if (flags & FWRITE)
1339 rw_enter_write(&pf_consistency_lock);
1340 else
1341 rw_enter_read(&pf_consistency_lock);
1342
1343 s = splsoftnet();
1344 switch (cmd) {
1345
1346 case DIOCSTART:
1347 if (pf_status.running)
1348 error = EEXIST;
1349 else {
1350 #ifdef __NetBSD__
1351 error = pf_pfil_attach();
1352 if (error)
1353 break;
1354 #endif /* __NetBSD__ */
1355 pf_status.running = 1;
1356 pf_status.since = time_second;
1357 if (pf_status.stateid == 0) {
1358 pf_status.stateid = time_second;
1359 pf_status.stateid = pf_status.stateid << 32;
1360 }
1361 DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
1362 }
1363 break;
1364
1365 case DIOCSTOP:
1366 if (!pf_status.running)
1367 error = ENOENT;
1368 else {
1369 #ifdef __NetBSD__
1370 error = pf_pfil_detach();
1371 if (error)
1372 break;
1373 #endif /* __NetBSD__ */
1374 pf_status.running = 0;
1375 pf_status.since = time_second;
1376 DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
1377 }
1378 break;
1379
1380 case DIOCADDRULE: {
1381 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1382 struct pf_ruleset *ruleset;
1383 struct pf_rule *rule, *tail;
1384 int rs_num;
1385
1386 pr->anchor[sizeof(pr->anchor) - 1] = 0;
1387 ruleset = pf_find_ruleset(pr->anchor);
1388 if (ruleset == NULL) {
1389 error = EINVAL;
1390 break;
1391 }
1392 rs_num = pf_get_ruleset_number(pr->rule.action);
1393 if (rs_num >= PF_RULESET_MAX) {
1394 error = EINVAL;
1395 break;
1396 }
1397 if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1398 error = EINVAL;
1399 break;
1400 }
1401 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
1402 error = EBUSY;
1403 break;
1404 }
1405 if (pr->pool_ticket != ticket_pabuf) {
1406 error = EBUSY;
1407 break;
1408 }
1409 rule = pool_get(&pf_rule_pl, PR_NOWAIT);
1410 if (rule == NULL) {
1411 error = ENOMEM;
1412 break;
1413 }
1414 bcopy(&pr->rule, rule, sizeof(struct pf_rule));
1415 #ifdef __NetBSD__
1416 rule->cuid = kauth_cred_getuid(l->l_cred);
1417 rule->cpid = l->l_proc->p_pid;
1418 #else
1419 rule->cuid = p->p_cred->p_ruid;
1420 rule->cpid = p->p_pid;
1421 #endif /* !__NetBSD__ */
1422 rule->anchor = NULL;
1423 rule->kif = NULL;
1424 TAILQ_INIT(&rule->rpool.list);
1425 /* initialize refcounting */
1426 rule->states = 0;
1427 rule->src_nodes = 0;
1428 rule->entries.tqe_prev = NULL;
1429 #ifndef INET
1430 if (rule->af == AF_INET) {
1431 pool_put(&pf_rule_pl, rule);
1432 error = EAFNOSUPPORT;
1433 break;
1434 }
1435 #endif /* INET */
1436 #ifndef INET6
1437 if (rule->af == AF_INET6) {
1438 pool_put(&pf_rule_pl, rule);
1439 error = EAFNOSUPPORT;
1440 break;
1441 }
1442 #endif /* INET6 */
1443 tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
1444 pf_rulequeue);
1445 if (tail)
1446 rule->nr = tail->nr + 1;
1447 else
1448 rule->nr = 0;
1449 if (rule->ifname[0]) {
1450 rule->kif = pfi_kif_get(rule->ifname);
1451 if (rule->kif == NULL) {
1452 pool_put(&pf_rule_pl, rule);
1453 error = EINVAL;
1454 break;
1455 }
1456 pfi_kif_ref(rule->kif, PFI_KIF_REF_RULE);
1457 }
1458
1459 #ifndef __NetBSD__
1460 if (rule->rtableid > 0 && !rtable_exists(rule->rtableid))
1461 error = EBUSY;
1462 #endif /* !__NetBSD__ */
1463
1464 #ifdef ALTQ
1465 /* set queue IDs */
1466 if (rule->qname[0] != 0) {
1467 if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
1468 error = EBUSY;
1469 else if (rule->pqname[0] != 0) {
1470 if ((rule->pqid =
1471 pf_qname2qid(rule->pqname)) == 0)
1472 error = EBUSY;
1473 } else
1474 rule->pqid = rule->qid;
1475 }
1476 #endif
1477 if (rule->tagname[0])
1478 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
1479 error = EBUSY;
1480 if (rule->match_tagname[0])
1481 if ((rule->match_tag =
1482 pf_tagname2tag(rule->match_tagname)) == 0)
1483 error = EBUSY;
1484 if (rule->rt && !rule->direction)
1485 error = EINVAL;
1486 #if NPFLOG > 0
1487 if (!rule->log)
1488 rule->logif = 0;
1489 if (rule->logif >= PFLOGIFS_MAX)
1490 error = EINVAL;
1491 #endif
1492 if (pf_rtlabel_add(&rule->src.addr) ||
1493 pf_rtlabel_add(&rule->dst.addr))
1494 error = EBUSY;
1495 if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
1496 error = EINVAL;
1497 if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
1498 error = EINVAL;
1499 if (pf_tbladdr_setup(ruleset, &rule->src.addr))
1500 error = EINVAL;
1501 if (pf_tbladdr_setup(ruleset, &rule->dst.addr))
1502 error = EINVAL;
1503 if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
1504 error = EINVAL;
1505 TAILQ_FOREACH(pa, &pf_pabuf, entries)
1506 if (pf_tbladdr_setup(ruleset, &pa->addr))
1507 error = EINVAL;
1508
1509 rule->overload_tbl = NULL;
1510 if (rule->overload_tblname[0]) {
1511 if ((rule->overload_tbl = pfr_attach_table(ruleset,
1512 rule->overload_tblname)) == NULL)
1513 error = EINVAL;
1514 else
1515 rule->overload_tbl->pfrkt_flags |=
1516 PFR_TFLAG_ACTIVE;
1517 }
1518
1519 pf_mv_pool(&pf_pabuf, &rule->rpool.list);
1520 if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
1521 (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
1522 (rule->rt > PF_FASTROUTE)) &&
1523 (TAILQ_FIRST(&rule->rpool.list) == NULL))
1524 error = EINVAL;
1525
1526 if (error) {
1527 pf_rm_rule(NULL, rule);
1528 break;
1529 }
1530 rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
1531 rule->evaluations = rule->packets[0] = rule->packets[1] =
1532 rule->bytes[0] = rule->bytes[1] = 0;
1533 TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
1534 rule, entries);
1535 ruleset->rules[rs_num].inactive.rcount++;
1536 break;
1537 }
1538
1539 case DIOCGETRULES: {
1540 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1541 struct pf_ruleset *ruleset;
1542 struct pf_rule *tail;
1543 int rs_num;
1544
1545 pr->anchor[sizeof(pr->anchor) - 1] = 0;
1546 ruleset = pf_find_ruleset(pr->anchor);
1547 if (ruleset == NULL) {
1548 error = EINVAL;
1549 break;
1550 }
1551 rs_num = pf_get_ruleset_number(pr->rule.action);
1552 if (rs_num >= PF_RULESET_MAX) {
1553 error = EINVAL;
1554 break;
1555 }
1556 tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
1557 pf_rulequeue);
1558 if (tail)
1559 pr->nr = tail->nr + 1;
1560 else
1561 pr->nr = 0;
1562 pr->ticket = ruleset->rules[rs_num].active.ticket;
1563 break;
1564 }
1565
1566 case DIOCGETRULE: {
1567 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
1568 struct pf_ruleset *ruleset;
1569 struct pf_rule *rule;
1570 int rs_num, i;
1571
1572 pr->anchor[sizeof(pr->anchor) - 1] = 0;
1573 ruleset = pf_find_ruleset(pr->anchor);
1574 if (ruleset == NULL) {
1575 error = EINVAL;
1576 break;
1577 }
1578 rs_num = pf_get_ruleset_number(pr->rule.action);
1579 if (rs_num >= PF_RULESET_MAX) {
1580 error = EINVAL;
1581 break;
1582 }
1583 if (pr->ticket != ruleset->rules[rs_num].active.ticket) {
1584 error = EBUSY;
1585 break;
1586 }
1587 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
1588 while ((rule != NULL) && (rule->nr != pr->nr))
1589 rule = TAILQ_NEXT(rule, entries);
1590 if (rule == NULL) {
1591 error = EBUSY;
1592 break;
1593 }
1594 bcopy(rule, &pr->rule, sizeof(struct pf_rule));
1595 if (pf_anchor_copyout(ruleset, rule, pr)) {
1596 error = EBUSY;
1597 break;
1598 }
1599 pfi_dynaddr_copyout(&pr->rule.src.addr);
1600 pfi_dynaddr_copyout(&pr->rule.dst.addr);
1601 pf_tbladdr_copyout(&pr->rule.src.addr);
1602 pf_tbladdr_copyout(&pr->rule.dst.addr);
1603 pf_rtlabel_copyout(&pr->rule.src.addr);
1604 pf_rtlabel_copyout(&pr->rule.dst.addr);
1605 for (i = 0; i < PF_SKIP_COUNT; ++i)
1606 if (rule->skip[i].ptr == NULL)
1607 pr->rule.skip[i].nr = -1;
1608 else
1609 pr->rule.skip[i].nr =
1610 rule->skip[i].ptr->nr;
1611
1612 if (pr->action == PF_GET_CLR_CNTR) {
1613 rule->evaluations = 0;
1614 rule->packets[0] = rule->packets[1] = 0;
1615 rule->bytes[0] = rule->bytes[1] = 0;
1616 }
1617 break;
1618 }
1619
1620 case DIOCCHANGERULE: {
1621 struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
1622 struct pf_ruleset *ruleset;
1623 struct pf_rule *oldrule = NULL, *newrule = NULL;
1624 u_int32_t nr = 0;
1625 int rs_num;
1626
1627 if (!(pcr->action == PF_CHANGE_REMOVE ||
1628 pcr->action == PF_CHANGE_GET_TICKET) &&
1629 pcr->pool_ticket != ticket_pabuf) {
1630 error = EBUSY;
1631 break;
1632 }
1633
1634 if (pcr->action < PF_CHANGE_ADD_HEAD ||
1635 pcr->action > PF_CHANGE_GET_TICKET) {
1636 error = EINVAL;
1637 break;
1638 }
1639 ruleset = pf_find_ruleset(pcr->anchor);
1640 if (ruleset == NULL) {
1641 error = EINVAL;
1642 break;
1643 }
1644 rs_num = pf_get_ruleset_number(pcr->rule.action);
1645 if (rs_num >= PF_RULESET_MAX) {
1646 error = EINVAL;
1647 break;
1648 }
1649
1650 if (pcr->action == PF_CHANGE_GET_TICKET) {
1651 pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
1652 break;
1653 } else {
1654 if (pcr->ticket !=
1655 ruleset->rules[rs_num].active.ticket) {
1656 error = EINVAL;
1657 break;
1658 }
1659 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1660 error = EINVAL;
1661 break;
1662 }
1663 }
1664
1665 if (pcr->action != PF_CHANGE_REMOVE) {
1666 newrule = pool_get(&pf_rule_pl, PR_NOWAIT);
1667 if (newrule == NULL) {
1668 error = ENOMEM;
1669 break;
1670 }
1671 bcopy(&pcr->rule, newrule, sizeof(struct pf_rule));
1672 #ifdef __NetBSD__
1673 newrule->cuid = kauth_cred_getuid(l->l_cred);
1674 newrule->cpid = l->l_proc->p_pid;
1675 #else
1676 newrule->cuid = p->p_cred->p_ruid;
1677 newrule->cpid = p->p_pid;
1678 #endif /* !__NetBSD__ */
1679 TAILQ_INIT(&newrule->rpool.list);
1680 /* initialize refcounting */
1681 newrule->states = 0;
1682 newrule->entries.tqe_prev = NULL;
1683 #ifndef INET
1684 if (newrule->af == AF_INET) {
1685 pool_put(&pf_rule_pl, newrule);
1686 error = EAFNOSUPPORT;
1687 break;
1688 }
1689 #endif /* INET */
1690 #ifndef INET6
1691 if (newrule->af == AF_INET6) {
1692 pool_put(&pf_rule_pl, newrule);
1693 error = EAFNOSUPPORT;
1694 break;
1695 }
1696 #endif /* INET6 */
1697 if (newrule->ifname[0]) {
1698 newrule->kif = pfi_kif_get(newrule->ifname);
1699 if (newrule->kif == NULL) {
1700 pool_put(&pf_rule_pl, newrule);
1701 error = EINVAL;
1702 break;
1703 }
1704 pfi_kif_ref(newrule->kif, PFI_KIF_REF_RULE);
1705 } else
1706 newrule->kif = NULL;
1707
1708 #ifndef __NetBSD__
1709 if (newrule->rtableid > 0 &&
1710 !rtable_exists(newrule->rtableid))
1711 error = EBUSY;
1712 #endif /* !__NetBSD__ */
1713
1714 #ifdef ALTQ
1715 /* set queue IDs */
1716 if (newrule->qname[0] != 0) {
1717 if ((newrule->qid =
1718 pf_qname2qid(newrule->qname)) == 0)
1719 error = EBUSY;
1720 else if (newrule->pqname[0] != 0) {
1721 if ((newrule->pqid =
1722 pf_qname2qid(newrule->pqname)) == 0)
1723 error = EBUSY;
1724 } else
1725 newrule->pqid = newrule->qid;
1726 }
1727 #endif /* ALTQ */
1728 if (newrule->tagname[0])
1729 if ((newrule->tag =
1730 pf_tagname2tag(newrule->tagname)) == 0)
1731 error = EBUSY;
1732 if (newrule->match_tagname[0])
1733 if ((newrule->match_tag = pf_tagname2tag(
1734 newrule->match_tagname)) == 0)
1735 error = EBUSY;
1736 if (newrule->rt && !newrule->direction)
1737 error = EINVAL;
1738 #if NPFLOG > 0
1739 if (!newrule->log)
1740 newrule->logif = 0;
1741 if (newrule->logif >= PFLOGIFS_MAX)
1742 error = EINVAL;
1743 #endif
1744 if (pf_rtlabel_add(&newrule->src.addr) ||
1745 pf_rtlabel_add(&newrule->dst.addr))
1746 error = EBUSY;
1747 if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
1748 error = EINVAL;
1749 if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
1750 error = EINVAL;
1751 if (pf_tbladdr_setup(ruleset, &newrule->src.addr))
1752 error = EINVAL;
1753 if (pf_tbladdr_setup(ruleset, &newrule->dst.addr))
1754 error = EINVAL;
1755 if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
1756 error = EINVAL;
1757 TAILQ_FOREACH(pa, &pf_pabuf, entries)
1758 if (pf_tbladdr_setup(ruleset, &pa->addr))
1759 error = EINVAL;
1760
1761 newrule->overload_tbl = NULL;
1762 if (newrule->overload_tblname[0]) {
1763 if ((newrule->overload_tbl = pfr_attach_table(
1764 ruleset, newrule->overload_tblname)) ==
1765 NULL)
1766 error = EINVAL;
1767 else
1768 newrule->overload_tbl->pfrkt_flags |=
1769 PFR_TFLAG_ACTIVE;
1770 }
1771
1772 pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
1773 if (((((newrule->action == PF_NAT) ||
1774 (newrule->action == PF_RDR) ||
1775 (newrule->action == PF_BINAT) ||
1776 (newrule->rt > PF_FASTROUTE)) &&
1777 !newrule->anchor)) &&
1778 (TAILQ_FIRST(&newrule->rpool.list) == NULL))
1779 error = EINVAL;
1780
1781 if (error) {
1782 pf_rm_rule(NULL, newrule);
1783 break;
1784 }
1785 newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
1786 newrule->evaluations = 0;
1787 newrule->packets[0] = newrule->packets[1] = 0;
1788 newrule->bytes[0] = newrule->bytes[1] = 0;
1789 }
1790 pf_empty_pool(&pf_pabuf);
1791
1792 if (pcr->action == PF_CHANGE_ADD_HEAD)
1793 oldrule = TAILQ_FIRST(
1794 ruleset->rules[rs_num].active.ptr);
1795 else if (pcr->action == PF_CHANGE_ADD_TAIL)
1796 oldrule = TAILQ_LAST(
1797 ruleset->rules[rs_num].active.ptr, pf_rulequeue);
1798 else {
1799 oldrule = TAILQ_FIRST(
1800 ruleset->rules[rs_num].active.ptr);
1801 while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
1802 oldrule = TAILQ_NEXT(oldrule, entries);
1803 if (oldrule == NULL) {
1804 if (newrule != NULL)
1805 pf_rm_rule(NULL, newrule);
1806 error = EINVAL;
1807 break;
1808 }
1809 }
1810
1811 if (pcr->action == PF_CHANGE_REMOVE) {
1812 pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule);
1813 ruleset->rules[rs_num].active.rcount--;
1814 } else {
1815 if (oldrule == NULL)
1816 TAILQ_INSERT_TAIL(
1817 ruleset->rules[rs_num].active.ptr,
1818 newrule, entries);
1819 else if (pcr->action == PF_CHANGE_ADD_HEAD ||
1820 pcr->action == PF_CHANGE_ADD_BEFORE)
1821 TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
1822 else
1823 TAILQ_INSERT_AFTER(
1824 ruleset->rules[rs_num].active.ptr,
1825 oldrule, newrule, entries);
1826 ruleset->rules[rs_num].active.rcount++;
1827 }
1828
1829 nr = 0;
1830 TAILQ_FOREACH(oldrule,
1831 ruleset->rules[rs_num].active.ptr, entries)
1832 oldrule->nr = nr++;
1833
1834 ruleset->rules[rs_num].active.ticket++;
1835
1836 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
1837 pf_remove_if_empty_ruleset(ruleset);
1838
1839 break;
1840 }
1841
1842 case DIOCCLRSTATES: {
1843 struct pf_state *ps, *nexts;
1844 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
1845 int killed = 0;
1846
1847 for (ps = RB_MIN(pf_state_tree_id, &tree_id); ps; ps = nexts) {
1848 nexts = RB_NEXT(pf_state_tree_id, &tree_id, ps);
1849
1850 if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
1851 ps->kif->pfik_name)) {
1852 #if NPFSYNC
1853 /* don't send out individual delete messages */
1854 ps->sync_flags = PFSTATE_NOSYNC;
1855 #endif
1856 pf_unlink_state(ps);
1857 killed++;
1858 }
1859 }
1860 psk->psk_af = killed;
1861 #if NPFSYNC
1862 pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
1863 #endif
1864 break;
1865 }
1866
1867 case DIOCKILLSTATES: {
1868 struct pf_state *ps, *nexts;
1869 struct pf_state_key *sk;
1870 struct pf_state_host *src, *dst;
1871 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
1872 int killed = 0;
1873
1874 for (ps = RB_MIN(pf_state_tree_id, &tree_id); ps;
1875 ps = nexts) {
1876 nexts = RB_NEXT(pf_state_tree_id, &tree_id, ps);
1877 sk = ps->state_key;
1878
1879 if (sk->direction == PF_OUT) {
1880 src = &sk->lan;
1881 dst = &sk->ext;
1882 } else {
1883 src = &sk->ext;
1884 dst = &sk->lan;
1885 }
1886 if ((!psk->psk_af || sk->af == psk->psk_af)
1887 && (!psk->psk_proto || psk->psk_proto ==
1888 sk->proto) &&
1889 PF_MATCHA(psk->psk_src.neg,
1890 &psk->psk_src.addr.v.a.addr,
1891 &psk->psk_src.addr.v.a.mask,
1892 &src->addr, sk->af) &&
1893 PF_MATCHA(psk->psk_dst.neg,
1894 &psk->psk_dst.addr.v.a.addr,
1895 &psk->psk_dst.addr.v.a.mask,
1896 &dst->addr, sk->af) &&
1897 (psk->psk_src.port_op == 0 ||
1898 pf_match_port(psk->psk_src.port_op,
1899 psk->psk_src.port[0], psk->psk_src.port[1],
1900 src->port)) &&
1901 (psk->psk_dst.port_op == 0 ||
1902 pf_match_port(psk->psk_dst.port_op,
1903 psk->psk_dst.port[0], psk->psk_dst.port[1],
1904 dst->port)) &&
1905 (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
1906 ps->kif->pfik_name))) {
1907 #if NPFSYNC > 0
1908 /* send immediate delete of state */
1909 pfsync_delete_state(ps);
1910 ps->sync_flags |= PFSTATE_NOSYNC;
1911 #endif
1912 pf_unlink_state(ps);
1913 killed++;
1914 }
1915 }
1916 psk->psk_af = killed;
1917 break;
1918 }
1919
1920 case DIOCADDSTATE: {
1921 struct pfioc_state *ps = (struct pfioc_state *)addr;
1922 struct pfsync_state *sp = (struct pfsync_state *)ps->state;
1923
1924 error = pf_state_add(sp);
1925 break;
1926 }
1927
1928 case DIOCADDSTATES: {
1929 struct pfioc_states *ps = (struct pfioc_states *)addr;
1930 struct pfsync_state *p = (struct pfsync_state *) ps->ps_states;
1931 struct pfsync_state *pk;
1932 int size = ps->ps_len;
1933 int i = 0;
1934 error = 0;
1935
1936 pk = malloc(sizeof(*pk), M_TEMP,M_WAITOK);
1937
1938 while (error == 0 && i < size)
1939 {
1940 if (copyin(p, pk, sizeof(struct pfsync_state)))
1941 {
1942 error = EFAULT;
1943 free(pk, M_TEMP);
1944 } else {
1945 error = pf_state_add(pk);
1946 i += sizeof(*p);
1947 p++;
1948 }
1949 }
1950
1951 free(pk, M_TEMP);
1952 break;
1953 }
1954
1955
1956 case DIOCGETSTATE: {
1957 struct pfioc_state *ps = (struct pfioc_state *)addr;
1958 struct pf_state *pfs;
1959 u_int32_t nr;
1960
1961 nr = 0;
1962 RB_FOREACH(pfs, pf_state_tree_id, &tree_id) {
1963 if (nr >= ps->nr)
1964 break;
1965 nr++;
1966 }
1967 if (pfs == NULL) {
1968 error = EBUSY;
1969 break;
1970 }
1971
1972 pf_state_export((struct pfsync_state *)&ps->state,
1973 pfs->state_key, pfs);
1974 break;
1975 }
1976
1977 case DIOCGETSTATES: {
1978 struct pfioc_states *ps = (struct pfioc_states *)addr;
1979 struct pf_state *state;
1980 struct pfsync_state *p, *pstore;
1981 u_int32_t nr = 0;
1982
1983 if (ps->ps_len == 0) {
1984 nr = pf_status.states;
1985 ps->ps_len = sizeof(struct pfsync_state) * nr;
1986 break;
1987 }
1988
1989 pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
1990
1991 p = ps->ps_states;
1992
1993 state = TAILQ_FIRST(&state_list);
1994 while (state) {
1995 if (state->timeout != PFTM_UNLINKED) {
1996 if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
1997 break;
1998
1999 pf_state_export(pstore,
2000 state->state_key, state);
2001 error = copyout(pstore, p, sizeof(*p));
2002 if (error) {
2003 free(pstore, M_TEMP);
2004 goto fail;
2005 }
2006 p++;
2007 nr++;
2008 }
2009 state = TAILQ_NEXT(state, entry_list);
2010 }
2011
2012 ps->ps_len = sizeof(struct pfsync_state) * nr;
2013
2014 free(pstore, M_TEMP);
2015 break;
2016 }
2017
2018 case DIOCGETSTATUS: {
2019 struct pf_status *ps = (struct pf_status *)addr;
2020 bcopy(&pf_status, ps, sizeof(struct pf_status));
2021 pfi_fill_oldstatus(ps);
2022 break;
2023 }
2024
2025 case DIOCSETSTATUSIF: {
2026 struct pfioc_if *pi = (struct pfioc_if *)addr;
2027
2028 if (pi->ifname[0] == 0) {
2029 bzero(pf_status.ifname, IFNAMSIZ);
2030 break;
2031 }
2032 if (ifunit(pi->ifname) == NULL) {
2033 error = EINVAL;
2034 break;
2035 }
2036 strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
2037 break;
2038 }
2039
2040 case DIOCCLRSTATUS: {
2041 bzero(pf_status.counters, sizeof(pf_status.counters));
2042 bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
2043 bzero(pf_status.scounters, sizeof(pf_status.scounters));
2044 pf_status.since = time_second;
2045 if (*pf_status.ifname)
2046 pfi_clr_istats(pf_status.ifname);
2047 break;
2048 }
2049
2050 case DIOCNATLOOK: {
2051 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
2052 struct pf_state_key *sk;
2053 struct pf_state *state;
2054 struct pf_state_key_cmp key;
2055 int m = 0, direction = pnl->direction;
2056
2057 key.af = pnl->af;
2058 key.proto = pnl->proto;
2059
2060 if (!pnl->proto ||
2061 PF_AZERO(&pnl->saddr, pnl->af) ||
2062 PF_AZERO(&pnl->daddr, pnl->af) ||
2063 ((pnl->proto == IPPROTO_TCP ||
2064 pnl->proto == IPPROTO_UDP) &&
2065 (!pnl->dport || !pnl->sport)))
2066 error = EINVAL;
2067 else {
2068 /*
2069 * userland gives us source and dest of connection,
2070 * reverse the lookup so we ask for what happens with
2071 * the return traffic, enabling us to find it in the
2072 * state tree.
2073 */
2074 if (direction == PF_IN) {
2075 PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
2076 key.ext.port = pnl->dport;
2077 PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
2078 key.gwy.port = pnl->sport;
2079 state = pf_find_state_all(&key, PF_EXT_GWY, &m);
2080 } else {
2081 PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
2082 key.lan.port = pnl->dport;
2083 PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
2084 key.ext.port = pnl->sport;
2085 state = pf_find_state_all(&key, PF_LAN_EXT, &m);
2086 }
2087 if (m > 1)
2088 error = E2BIG; /* more than one state */
2089 else if (state != NULL) {
2090 sk = state->state_key;
2091 if (direction == PF_IN) {
2092 PF_ACPY(&pnl->rsaddr, &sk->lan.addr,
2093 sk->af);
2094 pnl->rsport = sk->lan.port;
2095 PF_ACPY(&pnl->rdaddr, &pnl->daddr,
2096 pnl->af);
2097 pnl->rdport = pnl->dport;
2098 } else {
2099 PF_ACPY(&pnl->rdaddr, &sk->gwy.addr,
2100 sk->af);
2101 pnl->rdport = sk->gwy.port;
2102 PF_ACPY(&pnl->rsaddr, &pnl->saddr,
2103 pnl->af);
2104 pnl->rsport = pnl->sport;
2105 }
2106 } else
2107 error = ENOENT;
2108 }
2109 break;
2110 }
2111
2112 case DIOCSETTIMEOUT: {
2113 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
2114 int old;
2115
2116 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
2117 pt->seconds < 0) {
2118 error = EINVAL;
2119 goto fail;
2120 }
2121 old = pf_default_rule.timeout[pt->timeout];
2122 if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
2123 pt->seconds = 1;
2124 pf_default_rule.timeout[pt->timeout] = pt->seconds;
2125 if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
2126 wakeup(pf_purge_thread);
2127 pt->seconds = old;
2128 break;
2129 }
2130
2131 case DIOCGETTIMEOUT: {
2132 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
2133
2134 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
2135 error = EINVAL;
2136 goto fail;
2137 }
2138 pt->seconds = pf_default_rule.timeout[pt->timeout];
2139 break;
2140 }
2141
2142 case DIOCGETLIMIT: {
2143 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
2144
2145 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
2146 error = EINVAL;
2147 goto fail;
2148 }
2149 pl->limit = pf_pool_limits[pl->index].limit;
2150 break;
2151 }
2152
2153 case DIOCSETLIMIT: {
2154 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
2155 int old_limit;
2156
2157 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
2158 pf_pool_limits[pl->index].pp == NULL) {
2159 error = EINVAL;
2160 goto fail;
2161 }
2162 #ifdef __NetBSD__
2163 pool_sethardlimit(pf_pool_limits[pl->index].pp,
2164 pl->limit, NULL, 0);
2165 #else
2166 if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
2167 pl->limit, NULL, 0) != 0) {
2168 error = EBUSY;
2169 goto fail;
2170 }
2171 #endif /* !__NetBSD__ */
2172 old_limit = pf_pool_limits[pl->index].limit;
2173 pf_pool_limits[pl->index].limit = pl->limit;
2174 pl->limit = old_limit;
2175 break;
2176 }
2177
2178 case DIOCSETDEBUG: {
2179 u_int32_t *level = (u_int32_t *)addr;
2180
2181 pf_status.debug = *level;
2182 break;
2183 }
2184
2185 case DIOCCLRRULECTRS: {
2186 /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
2187 struct pf_ruleset *ruleset = &pf_main_ruleset;
2188 struct pf_rule *rule;
2189
2190 TAILQ_FOREACH(rule,
2191 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
2192 rule->evaluations = 0;
2193 rule->packets[0] = rule->packets[1] = 0;
2194 rule->bytes[0] = rule->bytes[1] = 0;
2195 }
2196 break;
2197 }
2198
2199 #ifdef ALTQ
2200 case DIOCSTARTALTQ: {
2201 struct pf_altq *altq;
2202
2203 /* enable all altq interfaces on active list */
2204 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
2205 if (altq->qname[0] == 0) {
2206 error = pf_enable_altq(altq);
2207 if (error != 0)
2208 break;
2209 }
2210 }
2211 if (error == 0)
2212 pf_altq_running = 1;
2213 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
2214 break;
2215 }
2216
2217 case DIOCSTOPALTQ: {
2218 struct pf_altq *altq;
2219
2220 /* disable all altq interfaces on active list */
2221 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
2222 if (altq->qname[0] == 0) {
2223 error = pf_disable_altq(altq);
2224 if (error != 0)
2225 break;
2226 }
2227 }
2228 if (error == 0)
2229 pf_altq_running = 0;
2230 DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
2231 break;
2232 }
2233
2234 case DIOCADDALTQ: {
2235 struct pfioc_altq *paa = (struct pfioc_altq *)addr;
2236 struct pf_altq *altq, *a;
2237
2238 if (paa->ticket != ticket_altqs_inactive) {
2239 error = EBUSY;
2240 break;
2241 }
2242 altq = pool_get(&pf_altq_pl, PR_NOWAIT);
2243 if (altq == NULL) {
2244 error = ENOMEM;
2245 break;
2246 }
2247 bcopy(&paa->altq, altq, sizeof(struct pf_altq));
2248
2249 /*
2250 * if this is for a queue, find the discipline and
2251 * copy the necessary fields
2252 */
2253 if (altq->qname[0] != 0) {
2254 if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
2255 error = EBUSY;
2256 pool_put(&pf_altq_pl, altq);
2257 break;
2258 }
2259 TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
2260 if (strncmp(a->ifname, altq->ifname,
2261 IFNAMSIZ) == 0 && a->qname[0] == 0) {
2262 altq->altq_disc = a->altq_disc;
2263 break;
2264 }
2265 }
2266 }
2267
2268 error = altq_add(altq);
2269 if (error) {
2270 pool_put(&pf_altq_pl, altq);
2271 break;
2272 }
2273
2274 TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
2275 bcopy(altq, &paa->altq, sizeof(struct pf_altq));
2276 break;
2277 }
2278
2279 case DIOCGETALTQS: {
2280 struct pfioc_altq *paa = (struct pfioc_altq *)addr;
2281 struct pf_altq *altq;
2282
2283 paa->nr = 0;
2284 TAILQ_FOREACH(altq, pf_altqs_active, entries)
2285 paa->nr++;
2286 paa->ticket = ticket_altqs_active;
2287 break;
2288 }
2289
2290 case DIOCGETALTQ: {
2291 struct pfioc_altq *paa = (struct pfioc_altq *)addr;
2292 struct pf_altq *altq;
2293 u_int32_t nr;
2294
2295 if (paa->ticket != ticket_altqs_active) {
2296 error = EBUSY;
2297 break;
2298 }
2299 nr = 0;
2300 altq = TAILQ_FIRST(pf_altqs_active);
2301 while ((altq != NULL) && (nr < paa->nr)) {
2302 altq = TAILQ_NEXT(altq, entries);
2303 nr++;
2304 }
2305 if (altq == NULL) {
2306 error = EBUSY;
2307 break;
2308 }
2309 bcopy(altq, &paa->altq, sizeof(struct pf_altq));
2310 break;
2311 }
2312
2313 case DIOCCHANGEALTQ:
2314 /* CHANGEALTQ not supported yet! */
2315 error = ENODEV;
2316 break;
2317
2318 case DIOCGETQSTATS: {
2319 struct pfioc_qstats *pq = (struct pfioc_qstats *)addr;
2320 struct pf_altq *altq;
2321 u_int32_t nr;
2322 int nbytes;
2323
2324 if (pq->ticket != ticket_altqs_active) {
2325 error = EBUSY;
2326 break;
2327 }
2328 nbytes = pq->nbytes;
2329 nr = 0;
2330 altq = TAILQ_FIRST(pf_altqs_active);
2331 while ((altq != NULL) && (nr < pq->nr)) {
2332 altq = TAILQ_NEXT(altq, entries);
2333 nr++;
2334 }
2335 if (altq == NULL) {
2336 error = EBUSY;
2337 break;
2338 }
2339 error = altq_getqstats(altq, pq->buf, &nbytes);
2340 if (error == 0) {
2341 pq->scheduler = altq->scheduler;
2342 pq->nbytes = nbytes;
2343 }
2344 break;
2345 }
2346 #endif /* ALTQ */
2347
2348 case DIOCBEGINADDRS: {
2349 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2350
2351 pf_empty_pool(&pf_pabuf);
2352 pp->ticket = ++ticket_pabuf;
2353 break;
2354 }
2355
2356 case DIOCADDADDR: {
2357 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2358
2359 if (pp->ticket != ticket_pabuf) {
2360 error = EBUSY;
2361 break;
2362 }
2363 #ifndef INET
2364 if (pp->af == AF_INET) {
2365 error = EAFNOSUPPORT;
2366 break;
2367 }
2368 #endif /* INET */
2369 #ifndef INET6
2370 if (pp->af == AF_INET6) {
2371 error = EAFNOSUPPORT;
2372 break;
2373 }
2374 #endif /* INET6 */
2375 if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
2376 pp->addr.addr.type != PF_ADDR_DYNIFTL &&
2377 pp->addr.addr.type != PF_ADDR_TABLE) {
2378 error = EINVAL;
2379 break;
2380 }
2381 pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
2382 if (pa == NULL) {
2383 error = ENOMEM;
2384 break;
2385 }
2386 bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
2387 if (pa->ifname[0]) {
2388 pa->kif = pfi_kif_get(pa->ifname);
2389 if (pa->kif == NULL) {
2390 pool_put(&pf_pooladdr_pl, pa);
2391 error = EINVAL;
2392 break;
2393 }
2394 pfi_kif_ref(pa->kif, PFI_KIF_REF_RULE);
2395 }
2396 if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
2397 pfi_dynaddr_remove(&pa->addr);
2398 pfi_kif_unref(pa->kif, PFI_KIF_REF_RULE);
2399 pool_put(&pf_pooladdr_pl, pa);
2400 error = EINVAL;
2401 break;
2402 }
2403 TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
2404 break;
2405 }
2406
2407 case DIOCGETADDRS: {
2408 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2409
2410 pp->nr = 0;
2411 pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
2412 pp->r_num, 0, 1, 0);
2413 if (pool == NULL) {
2414 error = EBUSY;
2415 break;
2416 }
2417 TAILQ_FOREACH(pa, &pool->list, entries)
2418 pp->nr++;
2419 break;
2420 }
2421
2422 case DIOCGETADDR: {
2423 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
2424 u_int32_t nr = 0;
2425
2426 pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
2427 pp->r_num, 0, 1, 1);
2428 if (pool == NULL) {
2429 error = EBUSY;
2430 break;
2431 }
2432 pa = TAILQ_FIRST(&pool->list);
2433 while ((pa != NULL) && (nr < pp->nr)) {
2434 pa = TAILQ_NEXT(pa, entries);
2435 nr++;
2436 }
2437 if (pa == NULL) {
2438 error = EBUSY;
2439 break;
2440 }
2441 bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
2442 pfi_dynaddr_copyout(&pp->addr.addr);
2443 pf_tbladdr_copyout(&pp->addr.addr);
2444 pf_rtlabel_copyout(&pp->addr.addr);
2445 break;
2446 }
2447
2448 case DIOCCHANGEADDR: {
2449 struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr;
2450 struct pf_pooladdr *oldpa = NULL, *newpa = NULL;
2451 struct pf_ruleset *ruleset;
2452
2453 if (pca->action < PF_CHANGE_ADD_HEAD ||
2454 pca->action > PF_CHANGE_REMOVE) {
2455 error = EINVAL;
2456 break;
2457 }
2458 if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
2459 pca->addr.addr.type != PF_ADDR_DYNIFTL &&
2460 pca->addr.addr.type != PF_ADDR_TABLE) {
2461 error = EINVAL;
2462 break;
2463 }
2464
2465 ruleset = pf_find_ruleset(pca->anchor);
2466 if (ruleset == NULL) {
2467 error = EBUSY;
2468 break;
2469 }
2470 pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
2471 pca->r_num, pca->r_last, 1, 1);
2472 if (pool == NULL) {
2473 error = EBUSY;
2474 break;
2475 }
2476 if (pca->action != PF_CHANGE_REMOVE) {
2477 newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
2478 if (newpa == NULL) {
2479 error = ENOMEM;
2480 break;
2481 }
2482 bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
2483 #ifndef INET
2484 if (pca->af == AF_INET) {
2485 pool_put(&pf_pooladdr_pl, newpa);
2486 error = EAFNOSUPPORT;
2487 break;
2488 }
2489 #endif /* INET */
2490 #ifndef INET6
2491 if (pca->af == AF_INET6) {
2492 pool_put(&pf_pooladdr_pl, newpa);
2493 error = EAFNOSUPPORT;
2494 break;
2495 }
2496 #endif /* INET6 */
2497 if (newpa->ifname[0]) {
2498 newpa->kif = pfi_kif_get(newpa->ifname);
2499 if (newpa->kif == NULL) {
2500 pool_put(&pf_pooladdr_pl, newpa);
2501 error = EINVAL;
2502 break;
2503 }
2504 pfi_kif_ref(newpa->kif, PFI_KIF_REF_RULE);
2505 } else
2506 newpa->kif = NULL;
2507 if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
2508 pf_tbladdr_setup(ruleset, &newpa->addr)) {
2509 pfi_dynaddr_remove(&newpa->addr);
2510 pfi_kif_unref(newpa->kif, PFI_KIF_REF_RULE);
2511 pool_put(&pf_pooladdr_pl, newpa);
2512 error = EINVAL;
2513 break;
2514 }
2515 }
2516
2517 if (pca->action == PF_CHANGE_ADD_HEAD)
2518 oldpa = TAILQ_FIRST(&pool->list);
2519 else if (pca->action == PF_CHANGE_ADD_TAIL)
2520 oldpa = TAILQ_LAST(&pool->list, pf_palist);
2521 else {
2522 int i = 0;
2523
2524 oldpa = TAILQ_FIRST(&pool->list);
2525 while ((oldpa != NULL) && (i < pca->nr)) {
2526 oldpa = TAILQ_NEXT(oldpa, entries);
2527 i++;
2528 }
2529 if (oldpa == NULL) {
2530 error = EINVAL;
2531 break;
2532 }
2533 }
2534
2535 if (pca->action == PF_CHANGE_REMOVE) {
2536 TAILQ_REMOVE(&pool->list, oldpa, entries);
2537 pfi_dynaddr_remove(&oldpa->addr);
2538 pf_tbladdr_remove(&oldpa->addr);
2539 pfi_kif_unref(oldpa->kif, PFI_KIF_REF_RULE);
2540 pool_put(&pf_pooladdr_pl, oldpa);
2541 } else {
2542 if (oldpa == NULL)
2543 TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
2544 else if (pca->action == PF_CHANGE_ADD_HEAD ||
2545 pca->action == PF_CHANGE_ADD_BEFORE)
2546 TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
2547 else
2548 TAILQ_INSERT_AFTER(&pool->list, oldpa,
2549 newpa, entries);
2550 }
2551
2552 pool->cur = TAILQ_FIRST(&pool->list);
2553 PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
2554 pca->af);
2555 break;
2556 }
2557
2558 case DIOCGETRULESETS: {
2559 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
2560 struct pf_ruleset *ruleset;
2561 struct pf_anchor *anchor;
2562
2563 pr->path[sizeof(pr->path) - 1] = 0;
2564 if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
2565 error = EINVAL;
2566 break;
2567 }
2568 pr->nr = 0;
2569 if (ruleset->anchor == NULL) {
2570 /* XXX kludge for pf_main_ruleset */
2571 RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
2572 if (anchor->parent == NULL)
2573 pr->nr++;
2574 } else {
2575 RB_FOREACH(anchor, pf_anchor_node,
2576 &ruleset->anchor->children)
2577 pr->nr++;
2578 }
2579 break;
2580 }
2581
2582 case DIOCGETRULESET: {
2583 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
2584 struct pf_ruleset *ruleset;
2585 struct pf_anchor *anchor;
2586 u_int32_t nr = 0;
2587
2588 pr->path[sizeof(pr->path) - 1] = 0;
2589 if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
2590 error = EINVAL;
2591 break;
2592 }
2593 pr->name[0] = 0;
2594 if (ruleset->anchor == NULL) {
2595 /* XXX kludge for pf_main_ruleset */
2596 RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
2597 if (anchor->parent == NULL && nr++ == pr->nr) {
2598 strlcpy(pr->name, anchor->name,
2599 sizeof(pr->name));
2600 break;
2601 }
2602 } else {
2603 RB_FOREACH(anchor, pf_anchor_node,
2604 &ruleset->anchor->children)
2605 if (nr++ == pr->nr) {
2606 strlcpy(pr->name, anchor->name,
2607 sizeof(pr->name));
2608 break;
2609 }
2610 }
2611 if (!pr->name[0])
2612 error = EBUSY;
2613 break;
2614 }
2615
2616 case DIOCRCLRTABLES: {
2617 struct pfioc_table *io = (struct pfioc_table *)addr;
2618
2619 if (io->pfrio_esize != 0) {
2620 error = ENODEV;
2621 break;
2622 }
2623 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
2624 io->pfrio_flags | PFR_FLAG_USERIOCTL);
2625 break;
2626 }
2627
2628 case DIOCRADDTABLES: {
2629 struct pfioc_table *io = (struct pfioc_table *)addr;
2630
2631 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2632 error = ENODEV;
2633 break;
2634 }
2635 error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
2636 &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2637 break;
2638 }
2639
2640 case DIOCRDELTABLES: {
2641 struct pfioc_table *io = (struct pfioc_table *)addr;
2642
2643 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2644 error = ENODEV;
2645 break;
2646 }
2647 error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
2648 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2649 break;
2650 }
2651
2652 case DIOCRGETTABLES: {
2653 struct pfioc_table *io = (struct pfioc_table *)addr;
2654
2655 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2656 error = ENODEV;
2657 break;
2658 }
2659 error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
2660 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2661 break;
2662 }
2663
2664 case DIOCRGETTSTATS: {
2665 struct pfioc_table *io = (struct pfioc_table *)addr;
2666
2667 if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
2668 error = ENODEV;
2669 break;
2670 }
2671 error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
2672 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2673 break;
2674 }
2675
2676 case DIOCRCLRTSTATS: {
2677 struct pfioc_table *io = (struct pfioc_table *)addr;
2678
2679 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2680 error = ENODEV;
2681 break;
2682 }
2683 error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
2684 &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2685 break;
2686 }
2687
2688 case DIOCRSETTFLAGS: {
2689 struct pfioc_table *io = (struct pfioc_table *)addr;
2690
2691 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2692 error = ENODEV;
2693 break;
2694 }
2695 error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
2696 io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
2697 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2698 break;
2699 }
2700
2701 case DIOCRCLRADDRS: {
2702 struct pfioc_table *io = (struct pfioc_table *)addr;
2703
2704 if (io->pfrio_esize != 0) {
2705 error = ENODEV;
2706 break;
2707 }
2708 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
2709 io->pfrio_flags | PFR_FLAG_USERIOCTL);
2710 break;
2711 }
2712
2713 case DIOCRADDADDRS: {
2714 struct pfioc_table *io = (struct pfioc_table *)addr;
2715
2716 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2717 error = ENODEV;
2718 break;
2719 }
2720 error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
2721 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
2722 PFR_FLAG_USERIOCTL);
2723 break;
2724 }
2725
2726 case DIOCRDELADDRS: {
2727 struct pfioc_table *io = (struct pfioc_table *)addr;
2728
2729 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2730 error = ENODEV;
2731 break;
2732 }
2733 error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
2734 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
2735 PFR_FLAG_USERIOCTL);
2736 break;
2737 }
2738
2739 case DIOCRSETADDRS: {
2740 struct pfioc_table *io = (struct pfioc_table *)addr;
2741
2742 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2743 error = ENODEV;
2744 break;
2745 }
2746 error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
2747 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
2748 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
2749 PFR_FLAG_USERIOCTL, 0);
2750 break;
2751 }
2752
2753 case DIOCRGETADDRS: {
2754 struct pfioc_table *io = (struct pfioc_table *)addr;
2755
2756 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2757 error = ENODEV;
2758 break;
2759 }
2760 error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
2761 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2762 break;
2763 }
2764
2765 case DIOCRGETASTATS: {
2766 struct pfioc_table *io = (struct pfioc_table *)addr;
2767
2768 if (io->pfrio_esize != sizeof(struct pfr_astats)) {
2769 error = ENODEV;
2770 break;
2771 }
2772 error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
2773 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2774 break;
2775 }
2776
2777 case DIOCRCLRASTATS: {
2778 struct pfioc_table *io = (struct pfioc_table *)addr;
2779
2780 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2781 error = ENODEV;
2782 break;
2783 }
2784 error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
2785 io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
2786 PFR_FLAG_USERIOCTL);
2787 break;
2788 }
2789
2790 case DIOCRTSTADDRS: {
2791 struct pfioc_table *io = (struct pfioc_table *)addr;
2792
2793 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2794 error = ENODEV;
2795 break;
2796 }
2797 error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
2798 io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
2799 PFR_FLAG_USERIOCTL);
2800 break;
2801 }
2802
2803 case DIOCRINADEFINE: {
2804 struct pfioc_table *io = (struct pfioc_table *)addr;
2805
2806 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2807 error = ENODEV;
2808 break;
2809 }
2810 error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
2811 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
2812 io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2813 break;
2814 }
2815
2816 case DIOCOSFPADD: {
2817 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2818 error = pf_osfp_add(io);
2819 break;
2820 }
2821
2822 case DIOCOSFPGET: {
2823 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2824 error = pf_osfp_get(io);
2825 break;
2826 }
2827
2828 case DIOCXBEGIN: {
2829 struct pfioc_trans *io = (struct pfioc_trans *)addr;
2830 struct pfioc_trans_e *ioe;
2831 struct pfr_table *table;
2832 int i;
2833
2834 if (io->esize != sizeof(*ioe)) {
2835 error = ENODEV;
2836 goto fail;
2837 }
2838 ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
2839 M_TEMP, M_WAITOK);
2840 table = (struct pfr_table *)malloc(sizeof(*table),
2841 M_TEMP, M_WAITOK);
2842 for (i = 0; i < io->size; i++) {
2843 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2844 free(table, M_TEMP);
2845 free(ioe, M_TEMP);
2846 error = EFAULT;
2847 goto fail;
2848 }
2849 switch (ioe->rs_num) {
2850 #ifdef ALTQ
2851 case PF_RULESET_ALTQ:
2852 if (ioe->anchor[0]) {
2853 free(table, M_TEMP);
2854 free(ioe, M_TEMP);
2855 error = EINVAL;
2856 goto fail;
2857 }
2858 if ((error = pf_begin_altq(&ioe->ticket))) {
2859 free(table, M_TEMP);
2860 free(ioe, M_TEMP);
2861 goto fail;
2862 }
2863 break;
2864 #endif /* ALTQ */
2865 case PF_RULESET_TABLE:
2866 bzero(table, sizeof(*table));
2867 strlcpy(table->pfrt_anchor, ioe->anchor,
2868 sizeof(table->pfrt_anchor));
2869 if ((error = pfr_ina_begin(table,
2870 &ioe->ticket, NULL, 0))) {
2871 free(table, M_TEMP);
2872 free(ioe, M_TEMP);
2873 goto fail;
2874 }
2875 break;
2876 default:
2877 if ((error = pf_begin_rules(&ioe->ticket,
2878 ioe->rs_num, ioe->anchor))) {
2879 free(table, M_TEMP);
2880 free(ioe, M_TEMP);
2881 goto fail;
2882 }
2883 break;
2884 }
2885 if (copyout(ioe, io->array+i, sizeof(io->array[i]))) {
2886 free(table, M_TEMP);
2887 free(ioe, M_TEMP);
2888 error = EFAULT;
2889 goto fail;
2890 }
2891 }
2892 free(table, M_TEMP);
2893 free(ioe, M_TEMP);
2894 break;
2895 }
2896
2897 case DIOCXROLLBACK: {
2898 struct pfioc_trans *io = (struct pfioc_trans *)addr;
2899 struct pfioc_trans_e *ioe;
2900 struct pfr_table *table;
2901 int i;
2902
2903 if (io->esize != sizeof(*ioe)) {
2904 error = ENODEV;
2905 goto fail;
2906 }
2907 ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
2908 M_TEMP, M_WAITOK);
2909 table = (struct pfr_table *)malloc(sizeof(*table),
2910 M_TEMP, M_WAITOK);
2911 for (i = 0; i < io->size; i++) {
2912 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2913 free(table, M_TEMP);
2914 free(ioe, M_TEMP);
2915 error = EFAULT;
2916 goto fail;
2917 }
2918 switch (ioe->rs_num) {
2919 #ifdef ALTQ
2920 case PF_RULESET_ALTQ:
2921 if (ioe->anchor[0]) {
2922 free(table, M_TEMP);
2923 free(ioe, M_TEMP);
2924 error = EINVAL;
2925 goto fail;
2926 }
2927 if ((error = pf_rollback_altq(ioe->ticket))) {
2928 free(table, M_TEMP);
2929 free(ioe, M_TEMP);
2930 goto fail; /* really bad */
2931 }
2932 break;
2933 #endif /* ALTQ */
2934 case PF_RULESET_TABLE:
2935 bzero(table, sizeof(*table));
2936 strlcpy(table->pfrt_anchor, ioe->anchor,
2937 sizeof(table->pfrt_anchor));
2938 if ((error = pfr_ina_rollback(table,
2939 ioe->ticket, NULL, 0))) {
2940 free(table, M_TEMP);
2941 free(ioe, M_TEMP);
2942 goto fail; /* really bad */
2943 }
2944 break;
2945 default:
2946 if ((error = pf_rollback_rules(ioe->ticket,
2947 ioe->rs_num, ioe->anchor))) {
2948 free(table, M_TEMP);
2949 free(ioe, M_TEMP);
2950 goto fail; /* really bad */
2951 }
2952 break;
2953 }
2954 }
2955 free(table, M_TEMP);
2956 free(ioe, M_TEMP);
2957 break;
2958 }
2959
2960 case DIOCXCOMMIT: {
2961 struct pfioc_trans *io = (struct pfioc_trans *)addr;
2962 struct pfioc_trans_e *ioe;
2963 struct pfr_table *table;
2964 struct pf_ruleset *rs;
2965 int i;
2966
2967 if (io->esize != sizeof(*ioe)) {
2968 error = ENODEV;
2969 goto fail;
2970 }
2971 ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
2972 M_TEMP, M_WAITOK);
2973 table = (struct pfr_table *)malloc(sizeof(*table),
2974 M_TEMP, M_WAITOK);
2975 /* first makes sure everything will succeed */
2976 for (i = 0; i < io->size; i++) {
2977 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2978 free(table, M_TEMP);
2979 free(ioe, M_TEMP);
2980 error = EFAULT;
2981 goto fail;
2982 }
2983 switch (ioe->rs_num) {
2984 #ifdef ALTQ
2985 case PF_RULESET_ALTQ:
2986 if (ioe->anchor[0]) {
2987 free(table, M_TEMP);
2988 free(ioe, M_TEMP);
2989 error = EINVAL;
2990 goto fail;
2991 }
2992 if (!altqs_inactive_open || ioe->ticket !=
2993 ticket_altqs_inactive) {
2994 free(table, M_TEMP);
2995 free(ioe, M_TEMP);
2996 error = EBUSY;
2997 goto fail;
2998 }
2999 break;
3000 #endif /* ALTQ */
3001 case PF_RULESET_TABLE:
3002 rs = pf_find_ruleset(ioe->anchor);
3003 if (rs == NULL || !rs->topen || ioe->ticket !=
3004 rs->tticket) {
3005 free(table, M_TEMP);
3006 free(ioe, M_TEMP);
3007 error = EBUSY;
3008 goto fail;
3009 }
3010 break;
3011 default:
3012 if (ioe->rs_num < 0 || ioe->rs_num >=
3013 PF_RULESET_MAX) {
3014 free(table, M_TEMP);
3015 free(ioe, M_TEMP);
3016 error = EINVAL;
3017 goto fail;
3018 }
3019 rs = pf_find_ruleset(ioe->anchor);
3020 if (rs == NULL ||
3021 !rs->rules[ioe->rs_num].inactive.open ||
3022 rs->rules[ioe->rs_num].inactive.ticket !=
3023 ioe->ticket) {
3024 free(table, M_TEMP);
3025 free(ioe, M_TEMP);
3026 error = EBUSY;
3027 goto fail;
3028 }
3029 break;
3030 }
3031 }
3032 /* now do the commit - no errors should happen here */
3033 for (i = 0; i < io->size; i++) {
3034 if (copyin(io->array+i, ioe, sizeof(*ioe))) {
3035 free(table, M_TEMP);
3036 free(ioe, M_TEMP);
3037 error = EFAULT;
3038 goto fail;
3039 }
3040 switch (ioe->rs_num) {
3041 #ifdef ALTQ
3042 case PF_RULESET_ALTQ:
3043 if ((error = pf_commit_altq(ioe->ticket))) {
3044 free(table, M_TEMP);
3045 free(ioe, M_TEMP);
3046 goto fail; /* really bad */
3047 }
3048 break;
3049 #endif /* ALTQ */
3050 case PF_RULESET_TABLE:
3051 bzero(table, sizeof(*table));
3052 strlcpy(table->pfrt_anchor, ioe->anchor,
3053 sizeof(table->pfrt_anchor));
3054 if ((error = pfr_ina_commit(table, ioe->ticket,
3055 NULL, NULL, 0))) {
3056 free(table, M_TEMP);
3057 free(ioe, M_TEMP);
3058 goto fail; /* really bad */
3059 }
3060 break;
3061 default:
3062 if ((error = pf_commit_rules(ioe->ticket,
3063 ioe->rs_num, ioe->anchor))) {
3064 free(table, M_TEMP);
3065 free(ioe, M_TEMP);
3066 goto fail; /* really bad */
3067 }
3068 break;
3069 }
3070 }
3071 free(table, M_TEMP);
3072 free(ioe, M_TEMP);
3073 break;
3074 }
3075
3076 case DIOCGETSRCNODES: {
3077 struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
3078 struct pf_src_node *n, *p, *pstore;
3079 u_int32_t nr = 0;
3080 int space = psn->psn_len;
3081
3082 if (space == 0) {
3083 RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
3084 nr++;
3085 psn->psn_len = sizeof(struct pf_src_node) * nr;
3086 break;
3087 }
3088
3089 pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
3090
3091 p = psn->psn_src_nodes;
3092 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
3093 int secs = time_second, diff;
3094
3095 if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
3096 break;
3097
3098 bcopy(n, pstore, sizeof(*pstore));
3099 if (n->rule.ptr != NULL)
3100 pstore->rule.nr = n->rule.ptr->nr;
3101 pstore->creation = secs - pstore->creation;
3102 if (pstore->expire > secs)
3103 pstore->expire -= secs;
3104 else
3105 pstore->expire = 0;
3106
3107 /* adjust the connection rate estimate */
3108 diff = secs - n->conn_rate.last;
3109 if (diff >= n->conn_rate.seconds)
3110 pstore->conn_rate.count = 0;
3111 else
3112 pstore->conn_rate.count -=
3113 n->conn_rate.count * diff /
3114 n->conn_rate.seconds;
3115
3116 error = copyout(pstore, p, sizeof(*p));
3117 if (error) {
3118 free(pstore, M_TEMP);
3119 goto fail;
3120 }
3121 p++;
3122 nr++;
3123 }
3124 psn->psn_len = sizeof(struct pf_src_node) * nr;
3125
3126 free(pstore, M_TEMP);
3127 break;
3128 }
3129
3130 case DIOCCLRSRCNODES: {
3131 struct pf_src_node *n;
3132 struct pf_state *state;
3133
3134 RB_FOREACH(state, pf_state_tree_id, &tree_id) {
3135 state->src_node = NULL;
3136 state->nat_src_node = NULL;
3137 }
3138 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
3139 n->expire = 1;
3140 n->states = 0;
3141 }
3142 pf_purge_expired_src_nodes(1);
3143 pf_status.src_nodes = 0;
3144 break;
3145 }
3146
3147 case DIOCKILLSRCNODES: {
3148 struct pf_src_node *sn;
3149 struct pf_state *ps;
3150 struct pfioc_src_node_kill *psnk = \
3151 (struct pfioc_src_node_kill *) addr;
3152 int killed = 0;
3153
3154 RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
3155 if (PF_MATCHA(psnk->psnk_src.neg, \
3156 &psnk->psnk_src.addr.v.a.addr, \
3157 &psnk->psnk_src.addr.v.a.mask, \
3158 &sn->addr, sn->af) &&
3159 PF_MATCHA(psnk->psnk_dst.neg, \
3160 &psnk->psnk_dst.addr.v.a.addr, \
3161 &psnk->psnk_dst.addr.v.a.mask, \
3162 &sn->raddr, sn->af)) {
3163 /* Handle state to src_node linkage */
3164 if (sn->states != 0) {
3165 RB_FOREACH(ps, pf_state_tree_id,
3166 &tree_id) {
3167 if (ps->src_node == sn)
3168 ps->src_node = NULL;
3169 if (ps->nat_src_node == sn)
3170 ps->nat_src_node = NULL;
3171 }
3172 sn->states = 0;
3173 }
3174 sn->expire = 1;
3175 killed++;
3176 }
3177 }
3178
3179 if (killed > 0)
3180 pf_purge_expired_src_nodes(1);
3181
3182 psnk->psnk_af = killed;
3183 break;
3184 }
3185
3186 case DIOCSETHOSTID: {
3187 u_int32_t *hid = (u_int32_t *)addr;
3188
3189 if (*hid == 0)
3190 pf_status.hostid = cprng_fast32();
3191 else
3192 pf_status.hostid = *hid;
3193 break;
3194 }
3195
3196 case DIOCOSFPFLUSH:
3197 pf_osfp_flush();
3198 break;
3199
3200 case DIOCIGETIFACES: {
3201 struct pfioc_iface *io = (struct pfioc_iface *)addr;
3202
3203 if (io->pfiio_esize != sizeof(struct pfi_kif)) {
3204 error = ENODEV;
3205 break;
3206 }
3207 error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
3208 &io->pfiio_size);
3209 break;
3210 }
3211
3212 case DIOCSETIFFLAG: {
3213 struct pfioc_iface *io = (struct pfioc_iface *)addr;
3214
3215 error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
3216 break;
3217 }
3218
3219 case DIOCCLRIFFLAG: {
3220 struct pfioc_iface *io = (struct pfioc_iface *)addr;
3221
3222 error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
3223 break;
3224 }
3225
3226 case DIOCSETLCK: {
3227 pf_state_lock = *(uint32_t*)addr;
3228 break;
3229 }
3230
3231 default:
3232 error = ENODEV;
3233 break;
3234 }
3235 fail:
3236 splx(s);
3237 if (flags & FWRITE)
3238 rw_exit_write(&pf_consistency_lock);
3239 else
3240 rw_exit_read(&pf_consistency_lock);
3241 return (error);
3242 }
3243
3244 #ifdef __NetBSD__
3245 #ifdef INET
3246 static int
pfil4_wrapper(void * arg,struct mbuf ** mp,struct ifnet * ifp,int dir)3247 pfil4_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
3248 {
3249 int error;
3250
3251 /*
3252 * ensure that mbufs are writable beforehand
3253 * as it's assumed by pf code.
3254 * ip hdr (60 bytes) + tcp hdr (60 bytes) should be enough.
3255 * XXX inefficient
3256 */
3257 error = m_makewritable(mp, 0, 60 + 60, M_DONTWAIT);
3258 if (error) {
3259 m_freem(*mp);
3260 *mp = NULL;
3261 return error;
3262 }
3263
3264 /*
3265 * If the packet is out-bound, we can't delay checksums
3266 * here. For in-bound, the checksum has already been
3267 * validated.
3268 */
3269 if (dir == PFIL_OUT) {
3270 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
3271 in_delayed_cksum(*mp);
3272 (*mp)->m_pkthdr.csum_flags &=
3273 ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
3274 }
3275 }
3276
3277 if (pf_test(dir == PFIL_OUT ? PF_OUT : PF_IN, ifp, mp, NULL)
3278 != PF_PASS) {
3279 m_freem(*mp);
3280 *mp = NULL;
3281 return EHOSTUNREACH;
3282 }
3283
3284 /*
3285 * we're not compatible with fast-forward.
3286 */
3287
3288 if (dir == PFIL_IN && *mp) {
3289 (*mp)->m_flags &= ~M_CANFASTFWD;
3290 }
3291
3292 return (0);
3293 }
3294 #endif /* INET */
3295
3296 #ifdef INET6
3297 static int
pfil6_wrapper(void * arg,struct mbuf ** mp,struct ifnet * ifp,int dir)3298 pfil6_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
3299 {
3300 int error;
3301
3302 /*
3303 * ensure that mbufs are writable beforehand
3304 * as it's assumed by pf code.
3305 * XXX inefficient
3306 */
3307 error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT);
3308 if (error) {
3309 m_freem(*mp);
3310 *mp = NULL;
3311 return error;
3312 }
3313
3314 /*
3315 * If the packet is out-bound, we can't delay checksums
3316 * here. For in-bound, the checksum has already been
3317 * validated.
3318 */
3319 if (dir == PFIL_OUT) {
3320 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
3321 in6_delayed_cksum(*mp);
3322 (*mp)->m_pkthdr.csum_flags &=
3323 ~(M_CSUM_TCPv6|M_CSUM_UDPv6);
3324 }
3325 }
3326
3327 if (pf_test6(dir == PFIL_OUT ? PF_OUT : PF_IN, ifp, mp, NULL)
3328 != PF_PASS) {
3329 m_freem(*mp);
3330 *mp = NULL;
3331 return EHOSTUNREACH;
3332 } else
3333 return (0);
3334 }
3335 #endif /* INET6 */
3336
3337 static int
pf_pfil_attach(void)3338 pf_pfil_attach(void)
3339 {
3340 pfil_head_t *ph_inet;
3341 #ifdef INET6
3342 pfil_head_t *ph_inet6;
3343 #endif /* INET6 */
3344 int error;
3345
3346 if (pf_pfil_attached)
3347 return (EBUSY);
3348
3349 ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET);
3350 if (ph_inet)
3351 error = pfil_add_hook((void *)pfil4_wrapper, NULL,
3352 PFIL_IN|PFIL_OUT, ph_inet);
3353 else
3354 error = ENOENT;
3355 if (error)
3356 return (error);
3357
3358 #ifdef INET6
3359 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6);
3360 if (ph_inet6)
3361 error = pfil_add_hook((void *)pfil6_wrapper, NULL,
3362 PFIL_IN|PFIL_OUT, ph_inet6);
3363 else
3364 error = ENOENT;
3365 if (error)
3366 goto bad;
3367 #endif /* INET6 */
3368
3369 pf_pfil_attached = 1;
3370
3371 return (0);
3372
3373 #ifdef INET6
3374 bad:
3375 pfil_remove_hook(pfil4_wrapper, NULL, PFIL_IN|PFIL_OUT, ph_inet);
3376 #endif /* INET6 */
3377
3378 return (error);
3379 }
3380
3381 static int
pf_pfil_detach(void)3382 pf_pfil_detach(void)
3383 {
3384 pfil_head_t *ph_inet;
3385 #ifdef INET6
3386 pfil_head_t *ph_inet6;
3387 #endif /* INET6 */
3388
3389 if (pf_pfil_attached == 0)
3390 return (EBUSY);
3391
3392 ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET);
3393 if (ph_inet)
3394 pfil_remove_hook((void *)pfil4_wrapper, NULL,
3395 PFIL_IN|PFIL_OUT, ph_inet);
3396 #ifdef INET6
3397 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6);
3398 if (ph_inet6)
3399 pfil_remove_hook((void *)pfil6_wrapper, NULL,
3400 PFIL_IN|PFIL_OUT, ph_inet6);
3401 #endif /* INET6 */
3402 pf_pfil_attached = 0;
3403
3404 return (0);
3405 }
3406 #endif /* __NetBSD__ */
3407
3408 #if defined(__NetBSD__)
3409 MODULE(MODULE_CLASS_DRIVER, pf, "bpf");
3410
3411 static int
pf_modcmd(modcmd_t cmd,void * opaque)3412 pf_modcmd(modcmd_t cmd, void *opaque)
3413 {
3414 #ifdef _MODULE
3415 extern void pflogattach(int);
3416 extern void pflogdetach(void);
3417
3418 devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR;
3419 int err;
3420
3421 switch (cmd) {
3422 case MODULE_CMD_INIT:
3423 err = devsw_attach("pf", NULL, &bmajor, &pf_cdevsw, &cmajor);
3424 if (err)
3425 return err;
3426 pfattach(1);
3427 pflogattach(1);
3428 return 0;
3429 case MODULE_CMD_FINI:
3430 if (pf_status.running) {
3431 return EBUSY;
3432 } else {
3433 pfdetach();
3434 pflogdetach();
3435 return devsw_detach(NULL, &pf_cdevsw);
3436 }
3437 default:
3438 return ENOTTY;
3439 }
3440 #else
3441 if (cmd == MODULE_CMD_INIT)
3442 return 0;
3443 return ENOTTY;
3444 #endif
3445 }
3446 #endif
3447