1 /* $NetBSD: pf_if.c,v 1.19 2009/07/28 18:15:26 minskim Exp $ */
2 /* $OpenBSD: pf_if.c,v 1.47 2007/07/13 09:17:48 markus Exp $ */
5 * Copyright 2005 Henning Brauer <henning@openbsd.org>
6 * Copyright 2005 Ryan McBride <mcbride@openbsd.org>
7 * Copyright (c) 2001 Daniel Hartmeier
8 * Copyright (c) 2003 Cedric Berger
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * - Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: pf_if.c,v 1.19 2009/07/28 18:15:26 minskim Exp $");
41 #include "opt_pfil_hooks.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
47 #include <sys/filio.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/kernel.h>
51 #include <sys/device.h>
55 #include <net/if_types.h>
57 #include <netinet/in.h>
58 #include <netinet/in_var.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/ip.h>
61 #include <netinet/ip_var.h>
63 #include <net/pfvar.h>
66 #include <netinet/ip6.h>
69 struct pfi_kif
*pfi_all
= NULL
;
70 struct pool pfi_addr_pl
;
71 struct pfi_ifhead pfi_ifs
;
73 struct pfr_addr
*pfi_buffer
;
77 void pfi_kif_update(struct pfi_kif
*);
78 void pfi_dynaddr_update(struct pfi_dynaddr
*dyn
);
79 void pfi_table_update(struct pfr_ktable
*, struct pfi_kif
*,
81 void pfi_kifaddr_update(void *);
82 void pfi_instance_add(struct ifnet
*, int, int);
83 void pfi_address_add(struct sockaddr
*, int, int);
84 int pfi_if_compare(struct pfi_kif
*, struct pfi_kif
*);
85 int pfi_skip_if(const char *, struct pfi_kif
*);
86 int pfi_unmask(void *);
88 void pfi_init_groups(struct ifnet
*);
89 void pfi_destroy_groups(struct ifnet
*);
91 int pfil_ifnet_wrapper(void *, struct mbuf
**, struct ifnet
*, int);
92 int pfil_ifaddr_wrapper(void *, struct mbuf
**, struct ifnet
*, int);
95 RB_PROTOTYPE(pfi_ifhead
, pfi_kif
, pfik_tree
, pfi_if_compare
);
96 RB_GENERATE(pfi_ifhead
, pfi_kif
, pfik_tree
, pfi_if_compare
);
98 #define PFI_BUFFER_MAX 0x10000
99 #define PFI_MTYPE M_IFADDR
106 #endif /* __NetBSD__ */
108 if (pfi_all
!= NULL
) /* already initialized */
112 pool_init(&pfi_addr_pl
, sizeof(struct pfi_dynaddr
), 0, 0, 0,
113 "pfiaddrpl", &pool_allocator_nointr
, IPL_NONE
);
115 pool_init(&pfi_addr_pl
, sizeof(struct pfi_dynaddr
), 0, 0, 0,
116 "pfiaddrpl", &pool_allocator_nointr
);
117 #endif /* !__NetBSD__ */
119 pfi_buffer
= malloc(pfi_buffer_max
* sizeof(*pfi_buffer
),
120 PFI_MTYPE
, M_WAITOK
);
122 if ((pfi_all
= pfi_kif_get(IFG_ALL
)) == NULL
)
123 panic("pfi_kif_get for pfi_all failed");
126 for (i
= 0; i
< if_indexlim
; i
++) {
127 struct ifnet
*ifp
= ifindex2ifnet
[i
];
130 pfi_init_groups(ifp
);
132 pfi_attach_ifnet(ifp
);
136 pfil_add_hook(pfil_ifnet_wrapper
, NULL
, PFIL_IFNET
, &if_pfil
);
137 pfil_add_hook(pfil_ifaddr_wrapper
, NULL
, PFIL_IFADDR
, &if_pfil
);
138 #endif /* __NetBSD__ */
142 pfi_kif_get(const char *kif_name
)
145 struct pfi_kif_cmp s
;
147 bzero(&s
, sizeof(s
));
148 strlcpy(s
.pfik_name
, kif_name
, sizeof(s
.pfik_name
));
149 if ((kif
= RB_FIND(pfi_ifhead
, &pfi_ifs
, (struct pfi_kif
*)&s
)) != NULL
)
153 if ((kif
= malloc(sizeof(*kif
), PFI_MTYPE
, M_NOWAIT
|M_ZERO
)) == NULL
)
156 strlcpy(kif
->pfik_name
, kif_name
, sizeof(kif
->pfik_name
));
158 /* time_second is not valid yet */
159 kif
->pfik_tzero
= (time_second
> 7200) ? time_second
: 0;
161 kif
->pfik_tzero
= time_second
;
162 #endif /* !__NetBSD__ */
163 TAILQ_INIT(&kif
->pfik_dynaddrs
);
165 RB_INSERT(pfi_ifhead
, &pfi_ifs
, kif
);
170 pfi_kif_ref(struct pfi_kif
*kif
, enum pfi_kif_refs what
)
173 case PFI_KIF_REF_RULE
:
176 case PFI_KIF_REF_STATE
:
180 panic("pfi_kif_ref with unknown type");
185 pfi_kif_unref(struct pfi_kif
*kif
, enum pfi_kif_refs what
)
191 case PFI_KIF_REF_NONE
:
193 case PFI_KIF_REF_RULE
:
194 if (kif
->pfik_rules
<= 0) {
195 printf("pfi_kif_unref: rules refcount <= 0\n");
200 case PFI_KIF_REF_STATE
:
201 if (kif
->pfik_states
<= 0) {
202 printf("pfi_kif_unref: state refcount <= 0\n");
208 panic("pfi_kif_unref with unknown type");
211 if (kif
->pfik_ifp
!= NULL
|| kif
->pfik_group
!= NULL
|| kif
== pfi_all
)
214 if (kif
->pfik_rules
|| kif
->pfik_states
)
217 RB_REMOVE(pfi_ifhead
, &pfi_ifs
, kif
);
218 free(kif
, PFI_MTYPE
);
222 pfi_kif_match(struct pfi_kif
*rule_kif
, struct pfi_kif
*packet_kif
)
226 if (rule_kif
== NULL
|| rule_kif
== packet_kif
)
229 if (rule_kif
->pfik_group
!= NULL
) {
230 struct ifg_list_head
*ifgh
=
231 if_get_groups(packet_kif
->pfik_ifp
);
233 TAILQ_FOREACH(p
, ifgh
, ifgl_next
)
234 if (p
->ifgl_group
== rule_kif
->pfik_group
)
242 pfi_attach_ifnet(struct ifnet
*ifp
)
250 if ((kif
= pfi_kif_get(ifp
->if_xname
)) == NULL
)
251 panic("pfi_kif_get failed");
254 ifp
->if_pf_kif
= kif
;
257 if ((kif
->pfik_ah_cookie
= hook_establish(ifp
->if_addrhooks
, 1,
258 pfi_kifaddr_update
, kif
)) == NULL
)
259 panic("pfi_attach_ifnet: cannot allocate '%s' address hook",
261 #endif /* !__NetBSD__ */
269 pfi_detach_ifnet(struct ifnet
*ifp
)
274 if ((kif
= (struct pfi_kif
*)ifp
->if_pf_kif
) == NULL
)
280 hook_disestablish(ifp
->if_addrhooks
, kif
->pfik_ah_cookie
);
281 #endif /* !__NetBSD__ */
284 kif
->pfik_ifp
= NULL
;
285 ifp
->if_pf_kif
= NULL
;
286 pfi_kif_unref(kif
, PFI_KIF_REF_NONE
);
291 pfi_attach_ifgroup(struct ifg_group
*ifg
)
299 if ((kif
= pfi_kif_get(ifg
->ifg_group
)) == NULL
)
300 panic("pfi_kif_get failed");
302 kif
->pfik_group
= ifg
;
303 ifg
->ifg_pf_kif
= kif
;
309 pfi_detach_ifgroup(struct ifg_group
*ifg
)
314 if ((kif
= (struct pfi_kif
*)ifg
->ifg_pf_kif
) == NULL
)
320 kif
->pfik_group
= NULL
;
321 ifg
->ifg_pf_kif
= NULL
;
322 pfi_kif_unref(kif
, PFI_KIF_REF_NONE
);
327 pfi_group_change(const char *group
)
334 if ((kif
= pfi_kif_get(group
)) == NULL
)
335 panic("pfi_kif_get failed");
343 pfi_match_addr(struct pfi_dynaddr
*dyn
, struct pf_addr
*a
, sa_family_t af
)
348 switch (dyn
->pfid_acnt4
) {
352 return (PF_MATCHA(0, &dyn
->pfid_addr4
,
353 &dyn
->pfid_mask4
, a
, AF_INET
));
355 return (pfr_match_addr(dyn
->pfid_kt
, a
, AF_INET
));
361 switch (dyn
->pfid_acnt6
) {
365 return (PF_MATCHA(0, &dyn
->pfid_addr6
,
366 &dyn
->pfid_mask6
, a
, AF_INET6
));
368 return (pfr_match_addr(dyn
->pfid_kt
, a
, AF_INET6
));
378 pfi_dynaddr_setup(struct pf_addr_wrap
*aw
, sa_family_t af
)
380 struct pfi_dynaddr
*dyn
;
381 char tblname
[PF_TABLE_NAME_SIZE
];
382 struct pf_ruleset
*ruleset
= NULL
;
385 if (aw
->type
!= PF_ADDR_DYNIFTL
)
387 if ((dyn
= pool_get(&pfi_addr_pl
, PR_NOWAIT
)) == NULL
)
389 bzero(dyn
, sizeof(*dyn
));
392 if (!strcmp(aw
->v
.ifname
, "self"))
393 dyn
->pfid_kif
= pfi_kif_get(IFG_ALL
);
395 dyn
->pfid_kif
= pfi_kif_get(aw
->v
.ifname
);
396 if (dyn
->pfid_kif
== NULL
) {
400 pfi_kif_ref(dyn
->pfid_kif
, PFI_KIF_REF_RULE
);
402 dyn
->pfid_net
= pfi_unmask(&aw
->v
.a
.mask
);
403 if (af
== AF_INET
&& dyn
->pfid_net
== 32)
405 strlcpy(tblname
, aw
->v
.ifname
, sizeof(tblname
));
406 if (aw
->iflags
& PFI_AFLAG_NETWORK
)
407 strlcat(tblname
, ":network", sizeof(tblname
));
408 if (aw
->iflags
& PFI_AFLAG_BROADCAST
)
409 strlcat(tblname
, ":broadcast", sizeof(tblname
));
410 if (aw
->iflags
& PFI_AFLAG_PEER
)
411 strlcat(tblname
, ":peer", sizeof(tblname
));
412 if (aw
->iflags
& PFI_AFLAG_NOALIAS
)
413 strlcat(tblname
, ":0", sizeof(tblname
));
414 if (dyn
->pfid_net
!= 128)
415 snprintf(tblname
+ strlen(tblname
),
416 sizeof(tblname
) - strlen(tblname
), "/%d", dyn
->pfid_net
);
417 if ((ruleset
= pf_find_or_create_ruleset(PF_RESERVED_ANCHOR
)) == NULL
) {
422 if ((dyn
->pfid_kt
= pfr_attach_table(ruleset
, tblname
)) == NULL
) {
427 dyn
->pfid_kt
->pfrkt_flags
|= PFR_TFLAG_ACTIVE
;
428 dyn
->pfid_iflags
= aw
->iflags
;
431 TAILQ_INSERT_TAIL(&dyn
->pfid_kif
->pfik_dynaddrs
, dyn
, entry
);
433 pfi_kif_update(dyn
->pfid_kif
);
438 if (dyn
->pfid_kt
!= NULL
)
439 pfr_detach_table(dyn
->pfid_kt
);
441 pf_remove_if_empty_ruleset(ruleset
);
442 if (dyn
->pfid_kif
!= NULL
)
443 pfi_kif_unref(dyn
->pfid_kif
, PFI_KIF_REF_RULE
);
444 pool_put(&pfi_addr_pl
, dyn
);
450 pfi_kif_update(struct pfi_kif
*kif
)
452 struct ifg_list
*ifgl
;
453 struct pfi_dynaddr
*p
;
455 /* update all dynaddr */
456 TAILQ_FOREACH(p
, &kif
->pfik_dynaddrs
, entry
)
457 pfi_dynaddr_update(p
);
459 /* again for all groups kif is member of */
460 if (kif
->pfik_ifp
!= NULL
) {
461 struct ifg_list_head
*ifgh
= if_get_groups(kif
->pfik_ifp
);
463 TAILQ_FOREACH(ifgl
, ifgh
, ifgl_next
)
464 pfi_kif_update((struct pfi_kif
*)
465 ifgl
->ifgl_group
->ifg_pf_kif
);
470 pfi_dynaddr_update(struct pfi_dynaddr
*dyn
)
473 struct pfr_ktable
*kt
;
475 if (dyn
== NULL
|| dyn
->pfid_kif
== NULL
|| dyn
->pfid_kt
== NULL
)
476 panic("pfi_dynaddr_update");
481 if (kt
->pfrkt_larg
!= pfi_update
) {
482 /* this table needs to be brought up-to-date */
483 pfi_table_update(kt
, kif
, dyn
->pfid_net
, dyn
->pfid_iflags
);
484 kt
->pfrkt_larg
= pfi_update
;
486 pfr_dynaddr_update(kt
, dyn
);
490 pfi_table_update(struct pfr_ktable
*kt
, struct pfi_kif
*kif
, int net
, int flags
)
493 struct ifg_member
*ifgm
;
497 if (kif
->pfik_ifp
!= NULL
)
498 pfi_instance_add(kif
->pfik_ifp
, net
, flags
);
499 else if (kif
->pfik_group
!= NULL
)
500 TAILQ_FOREACH(ifgm
, &kif
->pfik_group
->ifg_members
, ifgm_next
)
501 pfi_instance_add(ifgm
->ifgm_ifp
, net
, flags
);
503 if ((e
= pfr_set_addrs(&kt
->pfrkt_t
, pfi_buffer
, pfi_buffer_cnt
, &size2
,
504 NULL
, NULL
, NULL
, 0, PFR_TFLAG_ALLMASK
)))
505 printf("pfi_table_update: cannot set %d new addresses "
506 "into table %s: %d\n", pfi_buffer_cnt
, kt
->pfrkt_name
, e
);
510 pfi_instance_add(struct ifnet
*ifp
, int net
, int flags
)
513 int got4
= 0, got6
= 0;
518 IFADDR_FOREACH(ia
, ifp
) {
519 if (ia
->ifa_addr
== NULL
)
521 af
= ia
->ifa_addr
->sa_family
;
522 if (af
!= AF_INET
&& af
!= AF_INET6
)
524 if ((flags
& PFI_AFLAG_BROADCAST
) && af
== AF_INET6
)
526 if ((flags
& PFI_AFLAG_BROADCAST
) &&
527 !(ifp
->if_flags
& IFF_BROADCAST
))
529 if ((flags
& PFI_AFLAG_PEER
) &&
530 !(ifp
->if_flags
& IFF_POINTOPOINT
))
532 if ((flags
& PFI_AFLAG_NETWORK
) && af
== AF_INET6
&&
533 IN6_IS_ADDR_LINKLOCAL(
534 &((struct sockaddr_in6
*)ia
->ifa_addr
)->sin6_addr
))
536 if (flags
& PFI_AFLAG_NOALIAS
) {
537 if (af
== AF_INET
&& got4
)
539 if (af
== AF_INET6
&& got6
)
544 else if (af
== AF_INET6
)
547 if (net2
== 128 && (flags
& PFI_AFLAG_NETWORK
)) {
549 net2
= pfi_unmask(&((struct sockaddr_in
*)
550 ia
->ifa_netmask
)->sin_addr
);
551 else if (af
== AF_INET6
)
552 net2
= pfi_unmask(&((struct sockaddr_in6
*)
553 ia
->ifa_netmask
)->sin6_addr
);
555 if (af
== AF_INET
&& net2
> 32)
557 if (flags
& PFI_AFLAG_BROADCAST
)
558 pfi_address_add(ia
->ifa_broadaddr
, af
, net2
);
559 else if (flags
& PFI_AFLAG_PEER
)
560 pfi_address_add(ia
->ifa_dstaddr
, af
, net2
);
562 pfi_address_add(ia
->ifa_addr
, af
, net2
);
567 pfi_address_add(struct sockaddr
*sa
, int af
, int net
)
572 if (pfi_buffer_cnt
>= pfi_buffer_max
) {
573 int new_max
= pfi_buffer_max
* 2;
575 if (new_max
> PFI_BUFFER_MAX
) {
576 printf("pfi_address_add: address buffer full (%d/%d)\n",
577 pfi_buffer_cnt
, PFI_BUFFER_MAX
);
580 p
= malloc(new_max
* sizeof(*pfi_buffer
), PFI_MTYPE
, M_NOWAIT
);
582 printf("pfi_address_add: no memory to grow buffer "
583 "(%d/%d)\n", pfi_buffer_cnt
, PFI_BUFFER_MAX
);
586 memcpy(p
, pfi_buffer
, pfi_buffer_cnt
* sizeof(*pfi_buffer
));
587 /* no need to zero buffer */
588 free(pfi_buffer
, PFI_MTYPE
);
590 pfi_buffer_max
= new_max
;
592 if (af
== AF_INET
&& net
> 32)
594 p
= pfi_buffer
+ pfi_buffer_cnt
++;
595 bzero(p
, sizeof(*p
));
599 p
->pfra_ip4addr
= ((struct sockaddr_in
*)sa
)->sin_addr
;
600 else if (af
== AF_INET6
) {
601 p
->pfra_ip6addr
= ((struct sockaddr_in6
*)sa
)->sin6_addr
;
602 if (IN6_IS_SCOPE_EMBEDDABLE(&p
->pfra_ip6addr
))
603 p
->pfra_ip6addr
.s6_addr16
[1] = 0;
605 /* mask network address bits */
607 ((char *)p
)[p
->pfra_net
/8] &= ~(0xFF >> (p
->pfra_net
%8));
608 for (i
= (p
->pfra_net
+7)/8; i
< sizeof(p
->pfra_u
); i
++)
613 pfi_dynaddr_remove(struct pf_addr_wrap
*aw
)
617 if (aw
->type
!= PF_ADDR_DYNIFTL
|| aw
->p
.dyn
== NULL
||
618 aw
->p
.dyn
->pfid_kif
== NULL
|| aw
->p
.dyn
->pfid_kt
== NULL
)
622 TAILQ_REMOVE(&aw
->p
.dyn
->pfid_kif
->pfik_dynaddrs
, aw
->p
.dyn
, entry
);
623 pfi_kif_unref(aw
->p
.dyn
->pfid_kif
, PFI_KIF_REF_RULE
);
624 aw
->p
.dyn
->pfid_kif
= NULL
;
625 pfr_detach_table(aw
->p
.dyn
->pfid_kt
);
626 aw
->p
.dyn
->pfid_kt
= NULL
;
627 pool_put(&pfi_addr_pl
, aw
->p
.dyn
);
633 pfi_dynaddr_copyout(struct pf_addr_wrap
*aw
)
635 if (aw
->type
!= PF_ADDR_DYNIFTL
|| aw
->p
.dyn
== NULL
||
636 aw
->p
.dyn
->pfid_kif
== NULL
)
638 aw
->p
.dyncnt
= aw
->p
.dyn
->pfid_acnt4
+ aw
->p
.dyn
->pfid_acnt6
;
642 pfi_kifaddr_update(void *v
)
645 struct pfi_kif
*kif
= (struct pfi_kif
*)v
;
654 pfi_if_compare(struct pfi_kif
*p
, struct pfi_kif
*q
)
656 return (strncmp(p
->pfik_name
, q
->pfik_name
, IFNAMSIZ
));
660 pfi_fill_oldstatus(struct pf_status
*pfs
)
663 struct pfi_kif_cmp key
;
666 strlcpy(key
.pfik_name
, pfs
->ifname
, sizeof(key
.pfik_name
));
668 p
= RB_FIND(pfi_ifhead
, &pfi_ifs
, (struct pfi_kif
*)&key
);
673 bzero(pfs
->pcounters
, sizeof(pfs
->pcounters
));
674 bzero(pfs
->bcounters
, sizeof(pfs
->bcounters
));
675 for (i
= 0; i
< 2; i
++)
676 for (j
= 0; j
< 2; j
++)
677 for (k
= 0; k
< 2; k
++) {
678 pfs
->pcounters
[i
][j
][k
] =
679 p
->pfik_packets
[i
][j
][k
];
680 pfs
->bcounters
[i
][j
] +=
681 p
->pfik_bytes
[i
][j
][k
];
687 pfi_clr_istats(const char *name
)
693 RB_FOREACH(p
, pfi_ifhead
, &pfi_ifs
) {
694 if (pfi_skip_if(name
, p
))
696 bzero(p
->pfik_packets
, sizeof(p
->pfik_packets
));
697 bzero(p
->pfik_bytes
, sizeof(p
->pfik_bytes
));
698 p
->pfik_tzero
= time_second
;
706 pfi_get_ifaces(const char *name
, struct pfi_kif
*buf
, int *size
)
708 struct pfi_kif
*p
, *nextp
;
712 for (p
= RB_MIN(pfi_ifhead
, &pfi_ifs
); p
; p
= nextp
) {
713 nextp
= RB_NEXT(pfi_ifhead
, &pfi_ifs
, p
);
714 if (pfi_skip_if(name
, p
))
718 p
->pfik_tzero
= time_second
;
719 pfi_kif_ref(p
, PFI_KIF_REF_RULE
);
720 if (copyout(p
, buf
++, sizeof(*buf
))) {
721 pfi_kif_unref(p
, PFI_KIF_REF_RULE
);
725 nextp
= RB_NEXT(pfi_ifhead
, &pfi_ifs
, p
);
726 pfi_kif_unref(p
, PFI_KIF_REF_RULE
);
735 pfi_skip_if(const char *filter
, struct pfi_kif
*p
)
739 if (filter
== NULL
|| !*filter
)
741 if (!strcmp(p
->pfik_name
, filter
))
742 return (0); /* exact match */
744 if (n
< 1 || n
>= IFNAMSIZ
)
745 return (1); /* sanity check */
746 if (filter
[n
-1] >= '0' && filter
[n
-1] <= '9')
747 return (1); /* only do exact match in that case */
748 if (strncmp(p
->pfik_name
, filter
, n
))
749 return (1); /* prefix doesn't match */
750 return (p
->pfik_name
[n
] < '0' || p
->pfik_name
[n
] > '9');
754 pfi_set_flags(const char *name
, int flags
)
760 RB_FOREACH(p
, pfi_ifhead
, &pfi_ifs
) {
761 if (pfi_skip_if(name
, p
))
763 p
->pfik_flags
|= flags
;
770 pfi_clear_flags(const char *name
, int flags
)
776 RB_FOREACH(p
, pfi_ifhead
, &pfi_ifs
) {
777 if (pfi_skip_if(name
, p
))
779 p
->pfik_flags
&= ~flags
;
785 /* from pf_print_state.c */
787 pfi_unmask(void *addr
)
789 struct pf_addr
*m
= addr
;
790 int i
= 31, j
= 0, b
= 0;
793 while (j
< 4 && m
->addr32
[j
] == 0xffffffff) {
798 tmp
= ntohl(m
->addr32
[j
]);
799 for (i
= 31; tmp
& (1 << i
); --i
)
807 pfi_copy_group(char *dest
, const char *src
, ssize_t sz
)
809 while (sz
> 1 && *src
&& !(*src
>= '0' && *src
<= '9')) {
818 pfi_init_groups(struct ifnet
*ifp
)
820 char group
[IFNAMSIZ
];
823 if_addgroup(ifp
, IFG_ALL
);
825 pfi_copy_group(group
, ifp
->if_xname
, sizeof(group
));
826 if_addgroup(ifp
, group
);
830 pfi_destroy_groups(struct ifnet
*ifp
)
832 char group
[IFNAMSIZ
];
834 pfi_copy_group(group
, ifp
->if_xname
, sizeof(group
));
835 if_delgroup(ifp
, group
);
837 if_delgroup(ifp
, IFG_ALL
);
838 if_destroy_groups(ifp
);
842 pfil_ifnet_wrapper(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
, int dir
)
844 u_long cmd
= (u_long
)mp
;
847 case PFIL_IFNET_ATTACH
:
848 pfi_init_groups(ifp
);
850 pfi_attach_ifnet(ifp
);
852 case PFIL_IFNET_DETACH
:
853 pfi_detach_ifnet(ifp
);
855 pfi_destroy_groups(ifp
);
858 panic("pfil_ifnet_wrapper: unexpected cmd %lu", cmd
);
865 pfil_ifaddr_wrapper(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
, int dir
)
867 u_long cmd
= (u_long
)mp
;
874 case SIOCAIFADDR_IN6
:
875 case SIOCDIFADDR_IN6
:
877 pfi_kifaddr_update(ifp
->if_pf_kif
);
880 panic("pfil_ifaddr_wrapper: unexpected ioctl %lu", cmd
);
885 #endif /* __NetBSD__ */