Deleted Added
sdiff udiff text old ( 127145 ) new ( 130613 )
full compact
1/* $FreeBSD: head/sys/contrib/pf/net/pf_table.c 130613 2004-06-16 23:24:02Z mlaier $ */
2/* $OpenBSD: pf_table.c,v 1.47 2004/03/09 21:44:41 mcbride Exp $ */
3
4/*
5 * Copyright (c) 2002 Cedric Berger
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:

--- 45 unchanged lines hidden (view full) ---

56
57#define ACCEPT_FLAGS(oklist) \
58 do { \
59 if ((flags & ~(oklist)) & \
60 PFR_FLAG_ALLMASK) \
61 return (EINVAL); \
62 } while (0)
63
64#ifdef __FreeBSD__
65static inline int
66_copyin(const void *uaddr, void *kaddr, size_t len)
67{
68 int r;
69
70 PF_UNLOCK();
71 r = copyin(uaddr, kaddr, len);
72 PF_LOCK();
73
74 return (r);
75}
76
77static inline int
78_copyout(const void *uaddr, void *kaddr, size_t len)
79{
80 int r;
81
82 PF_UNLOCK();
83 r = copyout(uaddr, kaddr, len);
84 PF_LOCK();
85
86 return (r);
87}
88
89#define COPYIN(from, to, size) \
90 ((flags & PFR_FLAG_USERIOCTL) ? \
91 _copyin((from), (to), (size)) : \
92 (bcopy((from), (to), (size)), 0))
93
94#define COPYOUT(from, to, size) \
95 ((flags & PFR_FLAG_USERIOCTL) ? \
96 _copyout((from), (to), (size)) : \
97 (bcopy((from), (to), (size)), 0))
98
99#else
100
101#define COPYIN(from, to, size) \
102 ((flags & PFR_FLAG_USERIOCTL) ? \
103 copyin((from), (to), (size)) : \
104 (bcopy((from), (to), (size)), 0))
105
106#define COPYOUT(from, to, size) \
107 ((flags & PFR_FLAG_USERIOCTL) ? \
108 copyout((from), (to), (size)) : \
109 (bcopy((from), (to), (size)), 0))
110
111#endif
112
113#define FILLIN_SIN(sin, addr) \
114 do { \
115 (sin).sin_len = sizeof(sin); \
116 (sin).sin_family = AF_INET; \
117 (sin).sin_addr = (addr); \
118 } while (0)
119
120#define FILLIN_SIN6(sin6, addr) \

--- 6 unchanged lines hidden (view full) ---

127#define SWAP(type, a1, a2) \
128 do { \
129 type tmp = a1; \
130 a1 = a2; \
131 a2 = tmp; \
132 } while (0)
133
134#define SUNION2PF(su, af) (((af)==AF_INET) ? \
135 (struct pf_addr *)&(su)->sin.sin_addr : \
136 (struct pf_addr *)&(su)->sin6.sin6_addr)
137
138#define AF_BITS(af) (((af)==AF_INET)?32:128)
139#define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af))
140#define KENTRY_NETWORK(ke) ((ke)->pfrke_net < AF_BITS((ke)->pfrke_af))
141#define KENTRY_RNF_ROOT(ke) \
142 ((((struct radix_node *)(ke))->rn_flags & RNF_ROOT) != 0)
143
144#define NO_ADDRESSES (-1)
145#define ENQUEUE_UNMARKED_ONLY (1)
146#define INVERT_NEG_FLAG (1)
147
148struct pfr_walktree {
149 enum pfrw_op {
150 PFRW_MARK,
151 PFRW_SWEEP,
152 PFRW_ENQUEUE,
153 PFRW_GET_ADDRS,
154 PFRW_GET_ASTATS,
155 PFRW_POOL_GET,
156 PFRW_DYNADDR_UPDATE
157 } pfrw_op;
158 union {
159 struct pfr_addr *pfrw1_addr;
160 struct pfr_astats *pfrw1_astats;
161 struct pfr_kentryworkq *pfrw1_workq;
162 struct pfr_kentry *pfrw1_kentry;
163 struct pfi_dynaddr *pfrw1_dyn;
164 } pfrw_1;
165 int pfrw_free;
166 int pfrw_flags;
167};
168#define pfrw_addr pfrw_1.pfrw1_addr
169#define pfrw_astats pfrw_1.pfrw1_astats
170#define pfrw_workq pfrw_1.pfrw1_workq
171#define pfrw_kentry pfrw_1.pfrw1_kentry
172#define pfrw_dyn pfrw_1.pfrw1_dyn
173#define pfrw_cnt pfrw_free
174
175#define senderr(e) do { rv = (e); goto _bad; } while (0)
176
177#ifdef __FreeBSD__
178uma_zone_t pfr_ktable_pl;
179uma_zone_t pfr_kentry_pl;
180#else
181struct pool pfr_ktable_pl;
182struct pool pfr_kentry_pl;
183#endif
184struct sockaddr_in pfr_sin;
185struct sockaddr_in6 pfr_sin6;
186union sockaddr_union pfr_mask;
187struct pf_addr pfr_ffaddr;
188
189void pfr_copyout_addr(struct pfr_addr *,
190 struct pfr_kentry *ke);
191int pfr_validate_addr(struct pfr_addr *);
192void pfr_enqueue_addrs(struct pfr_ktable *,
193 struct pfr_kentryworkq *, int *, int);
194void pfr_mark_addrs(struct pfr_ktable *);
195struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *,
196 struct pfr_addr *, int);
197struct pfr_kentry *pfr_create_kentry(struct pfr_addr *);
198void pfr_destroy_kentries(struct pfr_kentryworkq *);
199void pfr_destroy_kentry(struct pfr_kentry *);
200void pfr_insert_kentries(struct pfr_ktable *,
201 struct pfr_kentryworkq *, long);
202void pfr_remove_kentries(struct pfr_ktable *,
203 struct pfr_kentryworkq *);
204void pfr_clstats_kentries(struct pfr_kentryworkq *, long,
205 int);
206void pfr_reset_feedback(struct pfr_addr *, int, int);
207void pfr_prepare_network(union sockaddr_union *, int, int);
208int pfr_route_kentry(struct pfr_ktable *,
209 struct pfr_kentry *);
210int pfr_unroute_kentry(struct pfr_ktable *,
211 struct pfr_kentry *);
212int pfr_walktree(struct radix_node *, void *);
213int pfr_validate_table(struct pfr_table *, int, int);
214void pfr_commit_ktable(struct pfr_ktable *, long);
215void pfr_insert_ktables(struct pfr_ktableworkq *);
216void pfr_insert_ktable(struct pfr_ktable *);
217void pfr_setflags_ktables(struct pfr_ktableworkq *);
218void pfr_setflags_ktable(struct pfr_ktable *, int);
219void pfr_clstats_ktables(struct pfr_ktableworkq *, long,
220 int);
221void pfr_clstats_ktable(struct pfr_ktable *, long, int);
222struct pfr_ktable *pfr_create_ktable(struct pfr_table *, long, int);
223void pfr_destroy_ktables(struct pfr_ktableworkq *, int);
224void pfr_destroy_ktable(struct pfr_ktable *, int);
225int pfr_ktable_compare(struct pfr_ktable *,
226 struct pfr_ktable *);
227struct pfr_ktable *pfr_lookup_table(struct pfr_table *);
228void pfr_clean_node_mask(struct pfr_ktable *,
229 struct pfr_kentryworkq *);
230int pfr_table_count(struct pfr_table *, int);
231int pfr_skip_table(struct pfr_table *,
232 struct pfr_ktable *, int);
233struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int);
234
235RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
236RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
237
238struct pfr_ktablehead pfr_ktables;
239struct pfr_table pfr_nulltable;
240int pfr_ktable_cnt;
241

--- 18 unchanged lines hidden (view full) ---

260int
261pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
262{
263 struct pfr_ktable *kt;
264 struct pfr_kentryworkq workq;
265 int s;
266
267 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
268 if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
269 return (EINVAL);
270 kt = pfr_lookup_table(tbl);
271 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
272 return (ESRCH);
273 if (kt->pfrkt_flags & PFR_TFLAG_CONST)
274 return (EPERM);
275 pfr_enqueue_addrs(kt, &workq, ndel, 0);
276

--- 17 unchanged lines hidden (view full) ---

294 int *nadd, int flags)
295{
296 struct pfr_ktable *kt, *tmpkt;
297 struct pfr_kentryworkq workq;
298 struct pfr_kentry *p, *q;
299 struct pfr_addr ad;
300 int i, rv, s, xadd = 0;
301#ifdef __FreeBSD__
302 /*
303 * XXX Is it OK under LP64 environments?
304 */
305 long tzero = (long)time_second;
306#else
307 long tzero = time.tv_sec;
308#endif
309
310 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
311 if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
312 return (EINVAL);
313 kt = pfr_lookup_table(tbl);
314 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
315 return (ESRCH);
316 if (kt->pfrkt_flags & PFR_TFLAG_CONST)
317 return (EPERM);
318 tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
319 if (tmpkt == NULL)
320 return (ENOMEM);
321 SLIST_INIT(&workq);
322 for (i = 0; i < size; i++) {
323 if (COPYIN(addr+i, &ad, sizeof(ad)))
324 senderr(EFAULT);
325 if (pfr_validate_addr(&ad))
326 senderr(EINVAL);
327 p = pfr_lookup_addr(kt, &ad, 1);
328 q = pfr_lookup_addr(tmpkt, &ad, 1);
329 if (flags & PFR_FLAG_FEEDBACK) {
330 if (q != NULL)
331 ad.pfra_fback = PFR_FB_DUPLICATE;
332 else if (p == NULL)

--- 10 unchanged lines hidden (view full) ---

343 if (pfr_route_kentry(tmpkt, p)) {
344 pfr_destroy_kentry(p);
345 ad.pfra_fback = PFR_FB_NONE;
346 } else {
347 SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
348 xadd++;
349 }
350 }
351 if (flags & PFR_FLAG_FEEDBACK) {
352 if (COPYOUT(&ad, addr+i, sizeof(ad)))
353 senderr(EFAULT);
354 }
355 }
356 pfr_clean_node_mask(tmpkt, &workq);
357 if (!(flags & PFR_FLAG_DUMMY)) {
358 if (flags & PFR_FLAG_ATOMIC)
359 s = splsoftnet();
360 pfr_insert_kentries(kt, &workq, tzero);
361 if (flags & PFR_FLAG_ATOMIC)
362 splx(s);
363 } else
364 pfr_destroy_kentries(&workq);
365 if (nadd != NULL)
366 *nadd = xadd;
367 pfr_destroy_ktable(tmpkt, 0);
368 return (0);
369_bad:
370 pfr_clean_node_mask(tmpkt, &workq);
371 pfr_destroy_kentries(&workq);
372 if (flags & PFR_FLAG_FEEDBACK)
373 pfr_reset_feedback(addr, size, flags);
374 pfr_destroy_ktable(tmpkt, 0);
375 return (rv);
376}
377
378int
379pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
380 int *ndel, int flags)
381{
382 struct pfr_ktable *kt;
383 struct pfr_kentryworkq workq;
384 struct pfr_kentry *p;
385 struct pfr_addr ad;
386 int i, rv, s, xdel = 0;
387
388 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
389 if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
390 return (EINVAL);
391 kt = pfr_lookup_table(tbl);
392 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
393 return (ESRCH);
394 if (kt->pfrkt_flags & PFR_TFLAG_CONST)
395 return (EPERM);
396 pfr_mark_addrs(kt);
397 SLIST_INIT(&workq);
398 for (i = 0; i < size; i++) {
399 if (COPYIN(addr+i, &ad, sizeof(ad)))
400 senderr(EFAULT);
401 if (pfr_validate_addr(&ad))
402 senderr(EINVAL);
403 p = pfr_lookup_addr(kt, &ad, 1);
404 if (flags & PFR_FLAG_FEEDBACK) {
405 if (p == NULL)
406 ad.pfra_fback = PFR_FB_NONE;
407 else if (p->pfrke_not != ad.pfra_not)
408 ad.pfra_fback = PFR_FB_CONFLICT;
409 else if (p->pfrke_mark)
410 ad.pfra_fback = PFR_FB_DUPLICATE;
411 else
412 ad.pfra_fback = PFR_FB_DELETED;
413 }
414 if (p != NULL && p->pfrke_not == ad.pfra_not &&
415 !p->pfrke_mark) {
416 p->pfrke_mark = 1;
417 SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
418 xdel++;
419 }
420 if (flags & PFR_FLAG_FEEDBACK)
421 if (COPYOUT(&ad, addr+i, sizeof(ad)))
422 senderr(EFAULT);
423 }
424 if (!(flags & PFR_FLAG_DUMMY)) {
425 if (flags & PFR_FLAG_ATOMIC)
426 s = splsoftnet();
427 pfr_remove_kentries(kt, &workq);
428 if (flags & PFR_FLAG_ATOMIC)
429 splx(s);
430 }
431 if (ndel != NULL)
432 *ndel = xdel;
433 return (0);
434_bad:
435 if (flags & PFR_FLAG_FEEDBACK)
436 pfr_reset_feedback(addr, size, flags);
437 return (rv);
438}
439
440int
441pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
442 int *size2, int *nadd, int *ndel, int *nchange, int flags)
443{
444 struct pfr_ktable *kt, *tmpkt;
445 struct pfr_kentryworkq addq, delq, changeq;
446 struct pfr_kentry *p, *q;
447 struct pfr_addr ad;
448 int i, rv, s, xadd = 0, xdel = 0, xchange = 0;
449#ifdef __FreeBSD__
450 /*
451 * XXX Is it OK under LP64 environments?
452 */
453 long tzero = (long)time_second;
454#else
455 long tzero = time.tv_sec;
456#endif
457
458 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
459 if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
460 return (EINVAL);
461 kt = pfr_lookup_table(tbl);
462 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
463 return (ESRCH);
464 if (kt->pfrkt_flags & PFR_TFLAG_CONST)
465 return (EPERM);
466 tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
467 if (tmpkt == NULL)
468 return (ENOMEM);
469 pfr_mark_addrs(kt);
470 SLIST_INIT(&addq);
471 SLIST_INIT(&delq);
472 SLIST_INIT(&changeq);
473 for (i = 0; i < size; i++) {
474 if (COPYIN(addr+i, &ad, sizeof(ad)))
475 senderr(EFAULT);
476 if (pfr_validate_addr(&ad))
477 senderr(EINVAL);
478 ad.pfra_fback = PFR_FB_NONE;
479 p = pfr_lookup_addr(kt, &ad, 1);
480 if (p != NULL) {
481 if (p->pfrke_mark) {
482 ad.pfra_fback = PFR_FB_DUPLICATE;
483 goto _skip;

--- 18 unchanged lines hidden (view full) ---

502 ad.pfra_fback = PFR_FB_NONE;
503 } else {
504 SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
505 ad.pfra_fback = PFR_FB_ADDED;
506 xadd++;
507 }
508 }
509_skip:
510 if (flags & PFR_FLAG_FEEDBACK)
511 if (COPYOUT(&ad, addr+i, sizeof(ad)))
512 senderr(EFAULT);
513 }
514 pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
515 if ((flags & PFR_FLAG_FEEDBACK) && *size2) {
516 if (*size2 < size+xdel) {
517 *size2 = size+xdel;
518 senderr(0);
519 }
520 i = 0;
521 SLIST_FOREACH(p, &delq, pfrke_workq) {
522 pfr_copyout_addr(&ad, p);
523 ad.pfra_fback = PFR_FB_DELETED;
524 if (COPYOUT(&ad, addr+size+i, sizeof(ad)))
525 senderr(EFAULT);
526 i++;
527 }
528 }
529 pfr_clean_node_mask(tmpkt, &addq);
530 if (!(flags & PFR_FLAG_DUMMY)) {
531 if (flags & PFR_FLAG_ATOMIC)
532 s = splsoftnet();
533 pfr_insert_kentries(kt, &addq, tzero);

--- 4 unchanged lines hidden (view full) ---

538 } else
539 pfr_destroy_kentries(&addq);
540 if (nadd != NULL)
541 *nadd = xadd;
542 if (ndel != NULL)
543 *ndel = xdel;
544 if (nchange != NULL)
545 *nchange = xchange;
546 if ((flags & PFR_FLAG_FEEDBACK) && size2)
547 *size2 = size+xdel;
548 pfr_destroy_ktable(tmpkt, 0);
549 return (0);
550_bad:
551 pfr_clean_node_mask(tmpkt, &addq);
552 pfr_destroy_kentries(&addq);
553 if (flags & PFR_FLAG_FEEDBACK)
554 pfr_reset_feedback(addr, size, flags);
555 pfr_destroy_ktable(tmpkt, 0);
556 return (rv);
557}
558
559int
560pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
561 int *nmatch, int flags)
562{
563 struct pfr_ktable *kt;
564 struct pfr_kentry *p;
565 struct pfr_addr ad;
566 int i, xmatch = 0;
567
568 ACCEPT_FLAGS(PFR_FLAG_REPLACE);
569 if (pfr_validate_table(tbl, 0, 0))
570 return (EINVAL);
571 kt = pfr_lookup_table(tbl);
572 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
573 return (ESRCH);
574
575 for (i = 0; i < size; i++) {
576 if (COPYIN(addr+i, &ad, sizeof(ad)))
577 return (EFAULT);
578 if (pfr_validate_addr(&ad))
579 return (EINVAL);
580 if (ADDR_NETWORK(&ad))
581 return (EINVAL);
582 p = pfr_lookup_addr(kt, &ad, 0);
583 if (flags & PFR_FLAG_REPLACE)
584 pfr_copyout_addr(&ad, p);
585 ad.pfra_fback = (p == NULL) ? PFR_FB_NONE :
586 (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
587 if (p != NULL && !p->pfrke_not)
588 xmatch++;
589 if (COPYOUT(&ad, addr+i, sizeof(ad)))
590 return (EFAULT);
591 }
592 if (nmatch != NULL)
593 *nmatch = xmatch;
594 return (0);
595}
596
597int
598pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
599 int flags)
600{
601 struct pfr_ktable *kt;
602 struct pfr_walktree w;
603 int rv;
604
605 ACCEPT_FLAGS(0);
606 if (pfr_validate_table(tbl, 0, 0))
607 return (EINVAL);
608 kt = pfr_lookup_table(tbl);
609 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
610 return (ESRCH);
611 if (kt->pfrkt_cnt > *size) {
612 *size = kt->pfrkt_cnt;
613 return (0);
614 }
615
616 bzero(&w, sizeof(w));
617 w.pfrw_op = PFRW_GET_ADDRS;
618 w.pfrw_addr = addr;
619 w.pfrw_free = kt->pfrkt_cnt;
620 w.pfrw_flags = flags;
621#ifdef __FreeBSD__
622 rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
623#else
624 rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
625#endif
626 if (!rv)
627#ifdef __FreeBSD__
628 rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,

--- 26 unchanged lines hidden (view full) ---

655 * XXX Is it OK under LP64 environments?
656 */
657 long tzero = (long)time_second;
658#else
659 long tzero = time.tv_sec;
660#endif
661
662 ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
663 if (pfr_validate_table(tbl, 0, 0))
664 return (EINVAL);
665 kt = pfr_lookup_table(tbl);
666 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
667 return (ESRCH);
668 if (kt->pfrkt_cnt > *size) {
669 *size = kt->pfrkt_cnt;
670 return (0);
671 }
672
673 bzero(&w, sizeof(w));
674 w.pfrw_op = PFRW_GET_ASTATS;
675 w.pfrw_astats = addr;
676 w.pfrw_free = kt->pfrkt_cnt;
677 w.pfrw_flags = flags;
678 if (flags & PFR_FLAG_ATOMIC)
679 s = splsoftnet();
680#ifdef __FreeBSD__
681 rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
682#else
683 rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
684#endif
685 if (!rv)

--- 25 unchanged lines hidden (view full) ---

711pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
712 int *nzero, int flags)
713{
714 struct pfr_ktable *kt;
715 struct pfr_kentryworkq workq;
716 struct pfr_kentry *p;
717 struct pfr_addr ad;
718 int i, rv, s, xzero = 0;
719
720 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
721 if (pfr_validate_table(tbl, 0, 0))
722 return (EINVAL);
723 kt = pfr_lookup_table(tbl);
724 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
725 return (ESRCH);
726 SLIST_INIT(&workq);
727 for (i = 0; i < size; i++) {
728 if (COPYIN(addr+i, &ad, sizeof(ad)))
729 senderr(EFAULT);
730 if (pfr_validate_addr(&ad))
731 senderr(EINVAL);
732 p = pfr_lookup_addr(kt, &ad, 1);
733 if (flags & PFR_FLAG_FEEDBACK) {
734 ad.pfra_fback = (p != NULL) ?
735 PFR_FB_CLEARED : PFR_FB_NONE;
736 if (COPYOUT(&ad, addr+i, sizeof(ad)))
737 senderr(EFAULT);
738 }
739 if (p != NULL) {
740 SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
741 xzero++;
742 }
743 }
744
745 if (!(flags & PFR_FLAG_DUMMY)) {
746 if (flags & PFR_FLAG_ATOMIC)
747 s = splsoftnet();
748 pfr_clstats_kentries(&workq, 0, 0);
749 if (flags & PFR_FLAG_ATOMIC)
750 splx(s);
751 }
752 if (nzero != NULL)
753 *nzero = xzero;
754 return (0);
755_bad:
756 if (flags & PFR_FLAG_FEEDBACK)
757 pfr_reset_feedback(addr, size, flags);
758 return (rv);
759}
760
761int
762pfr_validate_addr(struct pfr_addr *ad)
763{
764 int i;
765

--- 184 unchanged lines hidden (view full) ---

950 kt->pfrkt_cnt -= n;
951 pfr_destroy_kentries(workq);
952}
953
954void
955pfr_clean_node_mask(struct pfr_ktable *kt,
956 struct pfr_kentryworkq *workq)
957{
958 struct pfr_kentry *p;
959
960 SLIST_FOREACH(p, workq, pfrke_workq)
961 pfr_unroute_kentry(kt, p);
962}
963
964void
965pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange)
966{
967 struct pfr_kentry *p;
968 int s;
969

--- 4 unchanged lines hidden (view full) ---

974 bzero(p->pfrke_packets, sizeof(p->pfrke_packets));
975 bzero(p->pfrke_bytes, sizeof(p->pfrke_bytes));
976 splx(s);
977 p->pfrke_tzero = tzero;
978 }
979}
980
981void
982pfr_reset_feedback(struct pfr_addr *addr, int size, int flags)
983{
984 struct pfr_addr ad;
985 int i;
986
987 for (i = 0; i < size; i++) {
988 if (COPYIN(addr+i, &ad, sizeof(ad)))
989 break;
990 ad.pfra_fback = PFR_FB_NONE;
991 if (COPYOUT(&ad, addr+i, sizeof(ad)))
992 break;
993 }
994}
995
996void
997pfr_prepare_network(union sockaddr_union *sa, int af, int net)
998{
999 int i;
1000

--- 97 unchanged lines hidden (view full) ---

1098 ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr;
1099}
1100
1101int
1102pfr_walktree(struct radix_node *rn, void *arg)
1103{
1104 struct pfr_kentry *ke = (struct pfr_kentry *)rn;
1105 struct pfr_walktree *w = arg;
1106 int s, flags = w->pfrw_flags;
1107
1108 switch (w->pfrw_op) {
1109 case PFRW_MARK:
1110 ke->pfrke_mark = 0;
1111 break;
1112 case PFRW_SWEEP:
1113 if (ke->pfrke_mark)
1114 break;
1115 /* FALLTHROUGH */
1116 case PFRW_ENQUEUE:
1117 SLIST_INSERT_HEAD(w->pfrw_workq, ke, pfrke_workq);
1118 w->pfrw_cnt++;
1119 break;
1120 case PFRW_GET_ADDRS:
1121 if (w->pfrw_free-- > 0) {
1122 struct pfr_addr ad;
1123
1124 pfr_copyout_addr(&ad, ke);
1125 if (copyout(&ad, w->pfrw_addr, sizeof(ad)))
1126 return (EFAULT);
1127 w->pfrw_addr++;
1128 }
1129 break;
1130 case PFRW_GET_ASTATS:
1131 if (w->pfrw_free-- > 0) {
1132 struct pfr_astats as;
1133
1134 pfr_copyout_addr(&as.pfras_a, ke);
1135
1136 s = splsoftnet();
1137 bcopy(ke->pfrke_packets, as.pfras_packets,
1138 sizeof(as.pfras_packets));
1139 bcopy(ke->pfrke_bytes, as.pfras_bytes,
1140 sizeof(as.pfras_bytes));
1141 splx(s);
1142 as.pfras_tzero = ke->pfrke_tzero;
1143
1144 if (COPYOUT(&as, w->pfrw_astats, sizeof(as)))
1145 return (EFAULT);
1146 w->pfrw_astats++;
1147 }
1148 break;
1149 case PFRW_POOL_GET:
1150 if (ke->pfrke_not)
1151 break; /* negative entries are ignored */
1152 if (!w->pfrw_cnt--) {
1153 w->pfrw_kentry = ke;
1154 return (1); /* finish search */
1155 }
1156 break;
1157 case PFRW_DYNADDR_UPDATE:
1158 if (ke->pfrke_af == AF_INET) {
1159 if (w->pfrw_dyn->pfid_acnt4++ > 0)
1160 break;
1161 pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net);
1162 w->pfrw_dyn->pfid_addr4 = *SUNION2PF(
1163 &ke->pfrke_sa, AF_INET);
1164 w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
1165 &pfr_mask, AF_INET);
1166 } else {
1167 if (w->pfrw_dyn->pfid_acnt6++ > 0)
1168 break;
1169 pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
1170 w->pfrw_dyn->pfid_addr6 = *SUNION2PF(
1171 &ke->pfrke_sa, AF_INET6);
1172 w->pfrw_dyn->pfid_mask6 = *SUNION2PF(
1173 &pfr_mask, AF_INET6);
1174 }
1175 break;
1176 }
1177 return (0);
1178}
1179
1180int
1181pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
1182{
1183 struct pfr_ktableworkq workq;
1184 struct pfr_ktable *p;
1185 int s, xdel = 0;
1186
1187 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ALLRSETS);
1188 if (pfr_table_count(filter, flags) < 0)
1189 return (ENOENT);
1190
1191 SLIST_INIT(&workq);
1192 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1193 if (pfr_skip_table(filter, p, flags))
1194 continue;
1195 if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR))
1196 continue;
1197 if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE))
1198 continue;
1199 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
1200 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1201 xdel++;
1202 }
1203 if (!(flags & PFR_FLAG_DUMMY)) {
1204 if (flags & PFR_FLAG_ATOMIC)

--- 9 unchanged lines hidden (view full) ---

1214
1215int
1216pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
1217{
1218 struct pfr_ktableworkq addq, changeq;
1219 struct pfr_ktable *p, *q, *r, key;
1220 int i, rv, s, xadd = 0;
1221#ifdef __FreeBSD__
1222 /*
1223 * XXX Is it OK under LP64 environments?
1224 */
1225 long tzero = (long)time_second;
1226#else
1227 long tzero = time.tv_sec;
1228#endif
1229
1230 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
1231 SLIST_INIT(&addq);
1232 SLIST_INIT(&changeq);
1233 for (i = 0; i < size; i++) {
1234 if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
1235 senderr(EFAULT);
1236 if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK,
1237 flags & PFR_FLAG_USERIOCTL))
1238 senderr(EINVAL);
1239 key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
1240 p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1241 if (p == NULL) {
1242 p = pfr_create_ktable(&key.pfrkt_t, tzero, 1);
1243 if (p == NULL)
1244 senderr(ENOMEM);
1245 SLIST_FOREACH(q, &addq, pfrkt_workq) {

--- 55 unchanged lines hidden (view full) ---

1301}
1302
1303int
1304pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
1305{
1306 struct pfr_ktableworkq workq;
1307 struct pfr_ktable *p, *q, key;
1308 int i, s, xdel = 0;
1309
1310 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
1311 SLIST_INIT(&workq);
1312 for (i = 0; i < size; i++) {
1313 if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
1314 return (EFAULT);
1315 if (pfr_validate_table(&key.pfrkt_t, 0,
1316 flags & PFR_FLAG_USERIOCTL))
1317 return (EINVAL);
1318 p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1319 if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1320 SLIST_FOREACH(q, &workq, pfrkt_workq)
1321 if (!pfr_ktable_compare(p, q))
1322 goto _skip;
1323 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
1324 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);

--- 16 unchanged lines hidden (view full) ---

1341}
1342
1343int
1344pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
1345 int flags)
1346{
1347 struct pfr_ktable *p;
1348 int n, nn;
1349
1350 ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
1351 n = nn = pfr_table_count(filter, flags);
1352 if (n < 0)
1353 return (ENOENT);
1354 if (n > *size) {
1355 *size = n;
1356 return (0);
1357 }
1358 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1359 if (pfr_skip_table(filter, p, flags))
1360 continue;
1361 if (n-- <= 0)
1362 continue;
1363 if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl)))
1364 return (EFAULT);
1365 }
1366 if (n) {
1367 printf("pfr_get_tables: corruption detected (%d).\n", n);
1368 return (ENOTTY);
1369 }
1370 *size = nn;
1371 return (0);
1372}
1373
1374int
1375pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
1376 int flags)
1377{
1378 struct pfr_ktable *p;
1379 struct pfr_ktableworkq workq;
1380 int s, n, nn;
1381#ifdef __FreeBSD__
1382 /*
1383 * XXX Is it OK under LP64 environments?
1384 */
1385 long tzero = (long)time_second;
1386#else
1387 long tzero = time.tv_sec;
1388#endif
1389

--- 11 unchanged lines hidden (view full) ---

1401 s = splsoftnet();
1402 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1403 if (pfr_skip_table(filter, p, flags))
1404 continue;
1405 if (n-- <= 0)
1406 continue;
1407 if (!(flags & PFR_FLAG_ATOMIC))
1408 s = splsoftnet();
1409 if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
1410 splx(s);
1411 return (EFAULT);
1412 }
1413 if (!(flags & PFR_FLAG_ATOMIC))
1414 splx(s);
1415 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1416 }
1417 if (flags & PFR_FLAG_CLSTATS)
1418 pfr_clstats_ktables(&workq, tzero,
1419 flags & PFR_FLAG_ADDRSTOO);
1420 if (flags & PFR_FLAG_ATOMIC)

--- 8 unchanged lines hidden (view full) ---

1429
1430int
1431pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
1432{
1433 struct pfr_ktableworkq workq;
1434 struct pfr_ktable *p, key;
1435 int i, s, xzero = 0;
1436#ifdef __FreeBSD__
1437 /*
1438 * XXX Is it OK under LP64 environments?
1439 */
1440 long tzero = (long)time_second;
1441#else
1442 long tzero = time.tv_sec;
1443#endif
1444
1445 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
1446 SLIST_INIT(&workq);
1447 for (i = 0; i < size; i++) {
1448 if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
1449 return (EFAULT);
1450 if (pfr_validate_table(&key.pfrkt_t, 0, 0))
1451 return (EINVAL);
1452 p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1453 if (p != NULL) {
1454 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1455 xzero++;
1456 }
1457 }
1458 if (!(flags & PFR_FLAG_DUMMY)) {

--- 10 unchanged lines hidden (view full) ---

1469
1470int
1471pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
1472 int *nchange, int *ndel, int flags)
1473{
1474 struct pfr_ktableworkq workq;
1475 struct pfr_ktable *p, *q, key;
1476 int i, s, xchange = 0, xdel = 0;
1477
1478 ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
1479 if ((setflag & ~PFR_TFLAG_USRMASK) ||
1480 (clrflag & ~PFR_TFLAG_USRMASK) ||
1481 (setflag & clrflag))
1482 return (EINVAL);
1483 SLIST_INIT(&workq);
1484 for (i = 0; i < size; i++) {
1485 if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
1486 return (EFAULT);
1487 if (pfr_validate_table(&key.pfrkt_t, 0,
1488 flags & PFR_FLAG_USERIOCTL))
1489 return (EINVAL);
1490 p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1491 if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1492 p->pfrkt_nflags = (p->pfrkt_flags | setflag) &
1493 ~clrflag;
1494 if (p->pfrkt_nflags == p->pfrkt_flags)
1495 goto _skip;
1496 SLIST_FOREACH(q, &workq, pfrkt_workq)

--- 63 unchanged lines hidden (view full) ---

1560{
1561 struct pfr_ktableworkq tableq;
1562 struct pfr_kentryworkq addrq;
1563 struct pfr_ktable *kt, *rt, *shadow, key;
1564 struct pfr_kentry *p;
1565 struct pfr_addr ad;
1566 struct pf_ruleset *rs;
1567 int i, rv, xadd = 0, xaddr = 0;
1568
1569 ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO);
1570 if (size && !(flags & PFR_FLAG_ADDRSTOO))
1571 return (EINVAL);
1572 if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
1573 flags & PFR_FLAG_USERIOCTL))
1574 return (EINVAL);
1575 rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset);
1576 if (rs == NULL || !rs->topen || ticket != rs->tticket)
1577 return (EBUSY);
1578 tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
1579 SLIST_INIT(&tableq);
1580 kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
1581 if (kt == NULL) {

--- 25 unchanged lines hidden (view full) ---

1607_skip:
1608 shadow = pfr_create_ktable(tbl, 0, 0);
1609 if (shadow == NULL) {
1610 pfr_destroy_ktables(&tableq, 0);
1611 return (ENOMEM);
1612 }
1613 SLIST_INIT(&addrq);
1614 for (i = 0; i < size; i++) {
1615 if (COPYIN(addr+i, &ad, sizeof(ad)))
1616 senderr(EFAULT);
1617 if (pfr_validate_addr(&ad))
1618 senderr(EINVAL);
1619 if (pfr_lookup_addr(shadow, &ad, 1) != NULL)
1620 continue;
1621 p = pfr_create_kentry(&ad);
1622 if (p == NULL)
1623 senderr(ENOMEM);
1624 if (pfr_route_kentry(shadow, p)) {

--- 25 unchanged lines hidden (view full) ---

1650_bad:
1651 pfr_destroy_ktable(shadow, 0);
1652 pfr_destroy_ktables(&tableq, 0);
1653 pfr_destroy_kentries(&addrq);
1654 return (rv);
1655}
1656
1657int
1658pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
1659{
1660 struct pfr_ktableworkq workq;
1661 struct pfr_ktable *p;
1662 struct pf_ruleset *rs;
1663 int xdel = 0;
1664
1665 ACCEPT_FLAGS(PFR_FLAG_DUMMY);
1666 rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
1667 if (rs == NULL || !rs->topen || ticket != rs->tticket)
1668 return (0);
1669 SLIST_INIT(&workq);
1670 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1671 if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1672 pfr_skip_table(trs, p, 0))
1673 continue;
1674 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
1675 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1676 xdel++;
1677 }
1678 if (!(flags & PFR_FLAG_DUMMY)) {
1679 pfr_setflags_ktables(&workq);
1680 rs->topen = 0;
1681 pf_remove_if_empty_ruleset(rs);
1682 }
1683 if (ndel != NULL)
1684 *ndel = xdel;
1685 return (0);
1686}
1687
1688int
1689pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
1690 int *nchange, int flags)
1691{
1692 struct pfr_ktable *p;
1693 struct pfr_ktableworkq workq;
1694 struct pf_ruleset *rs;
1695 int s, xadd = 0, xchange = 0;
1696#ifdef __FreeBSD__

--- 95 unchanged lines hidden (view full) ---

1792 (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE)
1793 & ~PFR_TFLAG_INACTIVE;
1794 pfr_destroy_ktable(shadow, 0);
1795 kt->pfrkt_shadow = NULL;
1796 pfr_setflags_ktable(kt, nflags);
1797}
1798
1799int
1800pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
1801{
1802 int i;
1803
1804 if (!tbl->pfrt_name[0])
1805 return (-1);
1806 if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR))
1807 return (-1);
1808 if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1])
1809 return (-1);
1810 for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
1811 if (tbl->pfrt_name[i])
1812 return (-1);
1813 if (tbl->pfrt_flags & ~allowedflags)
1814 return (-1);
1815 return (0);

--- 212 unchanged lines hidden (view full) ---

2028{
2029 int d;
2030
2031 if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
2032 return (d);
2033 if ((d = strncmp(p->pfrkt_anchor, q->pfrkt_anchor,
2034 PF_ANCHOR_NAME_SIZE)))
2035 return (d);
2036 return (strncmp(p->pfrkt_ruleset, q->pfrkt_ruleset,
2037 PF_RULESET_NAME_SIZE));
2038}
2039
2040struct pfr_ktable *
2041pfr_lookup_table(struct pfr_table *tbl)
2042{
2043 /* struct pfr_ktable start like a struct pfr_table */
2044 return (RB_FIND(pfr_ktablehead, &pfr_ktables,
2045 (struct pfr_ktable *)tbl));
2046}
2047
2048int
2049pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
2050{
2051 struct pfr_kentry *ke = NULL;
2052 int match;
2053
2054 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
2055 kt = kt->pfrkt_root;
2056 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
2057 return (0);
2058
2059 switch (af) {
2060 case AF_INET:
2061 pfr_sin.sin_addr.s_addr = a->addr32[0];
2062 ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
2063 if (ke && KENTRY_RNF_ROOT(ke))
2064 ke = NULL;
2065 break;

--- 88 unchanged lines hidden (view full) ---

2154 pfr_insert_ktable(rt);
2155 }
2156 kt->pfrkt_root = rt;
2157 }
2158 pfr_insert_ktable(kt);
2159 }
2160 if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++)
2161 pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED);
2162 return (kt);
2163}
2164
2165void
2166pfr_detach_table(struct pfr_ktable *kt)
2167{
2168 if (kt->pfrkt_refcnt[PFR_REFCNT_RULE] <= 0)
2169 printf("pfr_detach_table: refcount = %d.\n",
2170 kt->pfrkt_refcnt[PFR_REFCNT_RULE]);

--- 50 unchanged lines hidden (view full) ---

2221 if (!KENTRY_NETWORK(ke)) {
2222 /* this is a single IP address - no possible nested block */
2223 PF_ACPY(counter, addr, af);
2224 *pidx = idx;
2225 return (0);
2226 }
2227 for (;;) {
2228 /* we don't want to use a nested block */
2229 ke2 = (struct pfr_kentry *)(af == AF_INET ?
2230 rn_match(&pfr_sin, kt->pfrkt_ip4) :
2231 rn_match(&pfr_sin6, kt->pfrkt_ip6));
2232 /* no need to check KENTRY_RNF_ROOT() here */
2233 if (ke2 == ke) {
2234 /* lookup return the same block - perfect */
2235 PF_ACPY(counter, addr, af);
2236 *pidx = idx;
2237 return (0);

--- 13 unchanged lines hidden (view full) ---

2251 }
2252}
2253
2254struct pfr_kentry *
2255pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
2256{
2257 struct pfr_walktree w;
2258
2259 bzero(&w, sizeof(w));
2260 w.pfrw_op = PFRW_POOL_GET;
2261 w.pfrw_cnt = idx;
2262
2263 switch (af) {
2264 case AF_INET:
2265#ifdef __FreeBSD__
2266 kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2267#else
2268 rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2269#endif
2270 return (w.pfrw_kentry);
2271 case AF_INET6:
2272#ifdef __FreeBSD__
2273 kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2274#else
2275 rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2276#endif
2277 return (w.pfrw_kentry);
2278 default:
2279 return (NULL);
2280 }
2281}
2282
2283void
2284pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
2285{
2286 struct pfr_walktree w;
2287 int s;
2288
2289 bzero(&w, sizeof(w));
2290 w.pfrw_op = PFRW_DYNADDR_UPDATE;
2291 w.pfrw_dyn = dyn;
2292
2293 s = splsoftnet();
2294 dyn->pfid_acnt4 = 0;
2295 dyn->pfid_acnt6 = 0;
2296 if (!dyn->pfid_af || dyn->pfid_af == AF_INET)
2297#ifdef __FreeBSD__
2298 kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2299#else
2300 rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2301#endif
2302 if (!dyn->pfid_af || dyn->pfid_af == AF_INET6)
2303#ifdef __FreeBSD__
2304 kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2305#else
2306 rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2307#endif
2308 splx(s);
2309}