1 /* $FreeBSD: src/sys/contrib/pf/net/pf_if.c,v 1.6 2004/09/14 15:20:24 mlaier Exp $ */
2 /* $OpenBSD: pf_if.c,v 1.11 2004/03/15 11:38:23 cedric Exp $ */
3 /* add $OpenBSD: pf_if.c,v 1.19 2004/08/11 12:06:44 henning Exp $ */
4 /* $DragonFly: src/sys/net/pf/pf_if.c,v 1.10 2008/03/07 11:34:20 sephe Exp $ */
7 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
9 * Copyright (c) 2001 Daniel Hartmeier
10 * Copyright (c) 2003 Cedric Berger
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
17 * - Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 #include "opt_inet6.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
45 #include <sys/eventhandler.h>
46 #include <sys/filio.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/kernel.h>
50 #include <sys/thread2.h>
52 #include <vm/vm_zone.h>
55 #include <net/if_types.h>
56 #include <net/route.h>
58 #include <netinet/in.h>
59 #include <netinet/in_var.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/ip.h>
62 #include <netinet/ip_var.h>
64 #include <net/pf/pfvar.h>
67 #include <netinet/ip6.h>
70 #define ACCEPT_FLAGS(oklist) \
72 if ((flags & ~(oklist)) & \
77 #define senderr(e) do { rv = (e); goto _bad; } while (0)
79 struct pfi_kif
**pfi_index2kif
;
80 struct pfi_kif
*pfi_self
, *pfi_dummy
;
82 struct pfi_ifhead pfi_ifs
;
83 struct pfi_statehead pfi_statehead
;
85 vm_zone_t pfi_addr_pl
;
87 struct pfr_addr
*pfi_buffer
;
90 char pfi_reserved_anchor
[PF_ANCHOR_NAME_SIZE
] =
92 char pfi_interface_ruleset
[PF_RULESET_NAME_SIZE
] =
95 eventhandler_tag pfi_clone_cookie
= NULL
;
96 eventhandler_tag pfi_attach_cookie
= NULL
;
97 eventhandler_tag pfi_detach_cookie
= NULL
;
99 void pfi_dynaddr_update(void *);
100 void pfi_kifaddr_update(void *);
101 void pfi_table_update(struct pfr_ktable
*, struct pfi_kif
*,
103 void pfi_instance_add(struct ifnet
*, int, int);
104 void pfi_address_add(struct sockaddr
*, int, int);
105 int pfi_if_compare(struct pfi_kif
*, struct pfi_kif
*);
106 struct pfi_kif
*pfi_if_create(const char *, struct pfi_kif
*, int);
107 void pfi_copy_group(char *, const char *, int);
108 void pfi_dynamic_drivers(void);
109 void pfi_newgroup(const char *, int);
110 int pfi_skip_if(const char *, struct pfi_kif
*, int);
111 int pfi_unmask(void *);
112 void pfi_dohooks(struct pfi_kif
*);
113 void pfi_kifaddr_update_event(void *, struct ifnet
*,
114 enum ifaddr_event
, struct ifaddr
*);
115 void pfi_attach_clone_event(void *, struct if_clone
*);
116 void pfi_attach_ifnet_event(void *, struct ifnet
*);
117 void pfi_detach_ifnet_event(void *, struct ifnet
*);
119 RB_PROTOTYPE(pfi_ifhead
, pfi_kif
, pfik_tree
, pfi_if_compare
);
120 RB_GENERATE(pfi_ifhead
, pfi_kif
, pfik_tree
, pfi_if_compare
);
122 #define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" }
123 #define PFI_BUFFER_MAX 0x10000
124 MALLOC_DEFINE(PFI_MTYPE
, "pf_if", "pf interface table");
131 if (pfi_self
!= NULL
) /* already initialized */
134 TAILQ_INIT(&pfi_statehead
);
136 pfi_buffer
= kmalloc(pfi_buffer_max
* sizeof(*pfi_buffer
),
137 PFI_MTYPE
, M_WAITOK
);
138 pfi_self
= pfi_if_create("self", NULL
, PFI_IFLAG_GROUP
);
139 pfi_dynamic_drivers();
141 TAILQ_FOREACH(ifp
, &ifnet
, if_link
) {
142 if (ifp
->if_dunit
!= IF_DUNIT_NONE
)
143 pfi_attach_ifnet(ifp
);
145 pfi_dummy
= pfi_if_create("notyet", pfi_self
,
146 PFI_IFLAG_GROUP
| PFI_IFLAG_DYNAMIC
);
147 pfi_attach_cookie
= EVENTHANDLER_REGISTER(ifnet_attach_event
,
148 pfi_attach_ifnet_event
, NULL
, EVENTHANDLER_PRI_ANY
);
149 pfi_detach_cookie
= EVENTHANDLER_REGISTER(ifnet_detach_event
,
150 pfi_detach_ifnet_event
, NULL
, EVENTHANDLER_PRI_ANY
);
151 pfi_clone_cookie
= EVENTHANDLER_REGISTER(if_clone_event
,
152 pfi_attach_clone_event
, NULL
, EVENTHANDLER_PRI_ANY
);
158 struct pfi_kif
*p
, key
;
161 EVENTHANDLER_DEREGISTER(ifnet_attach_event
, pfi_attach_cookie
);
162 EVENTHANDLER_DEREGISTER(ifnet_detach_event
, pfi_detach_cookie
);
163 EVENTHANDLER_DEREGISTER(if_clone_event
, pfi_clone_cookie
);
165 /* release PFI_IFLAG_INSTANCE */
166 TAILQ_FOREACH(ifp
, &ifnet
, if_link
) {
167 strlcpy(key
.pfik_name
, ifp
->if_xname
, sizeof(key
.pfik_name
));
168 p
= RB_FIND(pfi_ifhead
, &pfi_ifs
, &key
);
170 pfi_detach_ifnet(ifp
);
173 /* XXX clear all other interface group */
174 while ((p
= RB_MIN(pfi_ifhead
, &pfi_ifs
))) {
175 RB_REMOVE(pfi_ifhead
, &pfi_ifs
, p
);
177 kfree(p
->pfik_ah_head
, PFI_MTYPE
);
180 kfree(pfi_index2kif
, PFI_MTYPE
);
181 kfree(pfi_buffer
, PFI_MTYPE
);
182 pfi_index2kif
= NULL
;
188 * Wrapper functions for FreeBSD eventhandler
191 pfi_kifaddr_update_event(void *arg
, struct ifnet
*ifp
,
192 enum ifaddr_event event __unused
, struct ifaddr
*ifa __unused
)
194 struct pfi_kif
*p
= arg
;
197 * Check to see if it is 'our' interface as we do not have per
198 * interface hooks and thus get an update for every interface.
200 if (p
&& p
->pfik_ifp
== ifp
)
201 pfi_kifaddr_update(p
);
205 pfi_attach_clone_event(void *arg __unused
, struct if_clone
*ifc
)
207 pfi_attach_clone(ifc
);
211 pfi_attach_ifnet_event(void *arg __unused
, struct ifnet
*ifp
)
213 if (ifp
->if_dunit
!= IF_DUNIT_NONE
)
214 pfi_attach_ifnet(ifp
);
218 pfi_detach_ifnet_event(void *arg __unused
, struct ifnet
*ifp
)
220 pfi_detach_ifnet(ifp
);
224 pfi_attach_clone(struct if_clone
*ifc
)
227 pfi_newgroup(ifc
->ifc_name
, PFI_IFLAG_CLONABLE
);
231 pfi_attach_ifnet(struct ifnet
*ifp
)
233 struct pfi_kif
*p
, *q
, key
;
239 if (ifp
->if_index
>= pfi_indexlim
) {
241 * grow pfi_index2kif, similar to ifindex2ifnet code in if.c
244 struct pfi_kif
**mp
, **np
;
246 oldlim
= pfi_indexlim
;
247 if (pfi_indexlim
== 0)
249 while (ifp
->if_index
>= pfi_indexlim
)
252 m
= oldlim
* sizeof(struct pfi_kif
*);
254 n
= pfi_indexlim
* sizeof(struct pfi_kif
*);
255 np
= kmalloc(n
, PFI_MTYPE
, M_NOWAIT
| M_ZERO
);
257 panic("pfi_attach_ifnet: "
258 "cannot allocate translation table");
263 kfree(mp
, PFI_MTYPE
);
266 strlcpy(key
.pfik_name
, ifp
->if_xname
, sizeof(key
.pfik_name
));
267 p
= RB_FIND(pfi_ifhead
, &pfi_ifs
, &key
);
268 /* some additional trickery for placeholders */
269 if ((p
== NULL
) || (p
->pfik_parent
== pfi_dummy
)) {
270 /* are we looking at a renamed instance or not? */
271 pfi_copy_group(key
.pfik_name
, ifp
->if_xname
,
272 sizeof(key
.pfik_name
));
273 realname
= (strncmp(key
.pfik_name
, ifp
->if_dname
,
274 sizeof(key
.pfik_name
)) == 0);
276 /* we can change if_xname, hence use if_dname as group id */
277 pfi_copy_group(key
.pfik_name
, ifp
->if_dname
,
278 sizeof(key
.pfik_name
));
279 q
= RB_FIND(pfi_ifhead
, &pfi_ifs
, &key
);
281 q
= pfi_if_create(key
.pfik_name
, pfi_self
,
282 PFI_IFLAG_GROUP
|PFI_IFLAG_DYNAMIC
);
283 else if (q
->pfik_parent
== pfi_dummy
) {
284 q
->pfik_parent
= pfi_self
;
285 q
->pfik_flags
= (PFI_IFLAG_GROUP
| PFI_IFLAG_DYNAMIC
);
288 panic("pfi_attach_ifnet: "
289 "cannot allocate '%s' group", key
.pfik_name
);
291 /* add/modify interface */
293 p
= pfi_if_create(ifp
->if_xname
, q
,
294 realname
?PFI_IFLAG_INSTANCE
:PFI_IFLAG_PLACEHOLDER
);
296 /* remove from the dummy group */
297 /* XXX: copy stats? We should not have any!!! */
298 pfi_dummy
->pfik_delcnt
++;
299 TAILQ_REMOVE(&pfi_dummy
->pfik_grouphead
, p
,
301 /* move to the right group */
304 TAILQ_INSERT_TAIL(&q
->pfik_grouphead
, p
,
307 p
->pfik_flags
&= ~PFI_IFLAG_PLACEHOLDER
;
308 p
->pfik_flags
|= PFI_IFLAG_INSTANCE
;
312 panic("pfi_attach_ifnet: "
313 "cannot allocate '%s' interface", ifp
->if_xname
);
317 p
->pfik_flags
|= PFI_IFLAG_ATTACHED
;
318 p
->pfik_ah_cookie
= EVENTHANDLER_REGISTER(ifaddr_event
,
319 pfi_kifaddr_update_event
, p
, EVENTHANDLER_PRI_ANY
);
320 pfi_index2kif
[ifp
->if_index
] = p
;
326 pfi_detach_ifnet(struct ifnet
*ifp
)
328 struct pfi_kif
*p
, *q
, key
;
330 strlcpy(key
.pfik_name
, ifp
->if_xname
, sizeof(key
.pfik_name
));
334 p
= RB_FIND(pfi_ifhead
, &pfi_ifs
, &key
);
336 kprintf("pfi_detach_ifnet: cannot find %s", ifp
->if_xname
);
340 EVENTHANDLER_DEREGISTER(ifaddr_event
, p
->pfik_ah_cookie
);
343 p
->pfik_flags
&= ~PFI_IFLAG_ATTACHED
;
344 pfi_index2kif
[ifp
->if_index
] = NULL
;
346 pfi_maybe_destroy(p
);
351 pfi_lookup_create(const char *name
)
353 struct pfi_kif
*p
, *q
, key
;
356 p
= pfi_lookup_if(name
);
358 pfi_copy_group(key
.pfik_name
, name
, sizeof(key
.pfik_name
));
359 q
= pfi_lookup_if(key
.pfik_name
);
360 if ((q
!= NULL
) && (q
->pfik_parent
!= pfi_dummy
))
361 p
= pfi_if_create(name
, q
, PFI_IFLAG_INSTANCE
);
363 if (pfi_dummy
== NULL
)
364 panic("no 'notyet' dummy group");
365 p
= pfi_if_create(name
, pfi_dummy
,
366 PFI_IFLAG_PLACEHOLDER
);
374 pfi_attach_rule(const char *name
)
378 p
= pfi_lookup_create(name
);
385 pfi_detach_rule(struct pfi_kif
*p
)
389 if (p
->pfik_rules
> 0)
392 kprintf("pfi_detach_rule: reference count at 0\n");
393 pfi_maybe_destroy(p
);
397 pfi_attach_state(struct pfi_kif
*p
)
399 if (!p
->pfik_states
++)
400 TAILQ_INSERT_TAIL(&pfi_statehead
, p
, pfik_w_states
);
404 pfi_detach_state(struct pfi_kif
*p
)
408 if (p
->pfik_states
<= 0) {
409 kprintf("pfi_detach_state: reference count <= 0\n");
412 if (!--p
->pfik_states
)
413 TAILQ_REMOVE(&pfi_statehead
, p
, pfik_w_states
);
414 pfi_maybe_destroy(p
);
418 pfi_dynaddr_setup(struct pf_addr_wrap
*aw
, sa_family_t af
)
420 struct pfi_dynaddr
*dyn
;
421 char tblname
[PF_TABLE_NAME_SIZE
];
422 struct pf_ruleset
*ruleset
= NULL
;
425 if (aw
->type
!= PF_ADDR_DYNIFTL
)
427 dyn
= pool_get(&pfi_addr_pl
, PR_NOWAIT
);
430 bzero(dyn
, sizeof(*dyn
));
433 dyn
->pfid_kif
= pfi_attach_rule(aw
->v
.ifname
);
434 if (dyn
->pfid_kif
== NULL
)
437 dyn
->pfid_net
= pfi_unmask(&aw
->v
.a
.mask
);
438 if (af
== AF_INET
&& dyn
->pfid_net
== 32)
440 strlcpy(tblname
, aw
->v
.ifname
, sizeof(tblname
));
441 if (aw
->iflags
& PFI_AFLAG_NETWORK
)
442 strlcat(tblname
, ":network", sizeof(tblname
));
443 if (aw
->iflags
& PFI_AFLAG_BROADCAST
)
444 strlcat(tblname
, ":broadcast", sizeof(tblname
));
445 if (aw
->iflags
& PFI_AFLAG_PEER
)
446 strlcat(tblname
, ":peer", sizeof(tblname
));
447 if (aw
->iflags
& PFI_AFLAG_NOALIAS
)
448 strlcat(tblname
, ":0", sizeof(tblname
));
449 if (dyn
->pfid_net
!= 128)
450 ksnprintf(tblname
+ strlen(tblname
),
451 sizeof(tblname
) - strlen(tblname
), "/%d", dyn
->pfid_net
);
452 ruleset
= pf_find_or_create_ruleset(pfi_reserved_anchor
,
453 pfi_interface_ruleset
);
457 dyn
->pfid_kt
= pfr_attach_table(ruleset
, tblname
);
458 if (dyn
->pfid_kt
== NULL
)
461 dyn
->pfid_kt
->pfrkt_flags
|= PFR_TFLAG_ACTIVE
;
462 dyn
->pfid_iflags
= aw
->iflags
;
464 dyn
->pfid_hook_cookie
= hook_establish(dyn
->pfid_kif
->pfik_ah_head
, 1,
465 pfi_dynaddr_update
, dyn
);
466 if (dyn
->pfid_hook_cookie
== NULL
)
470 pfi_dynaddr_update(aw
->p
.dyn
);
475 if (dyn
->pfid_kt
!= NULL
)
476 pfr_detach_table(dyn
->pfid_kt
);
478 pf_remove_if_empty_ruleset(ruleset
);
479 if (dyn
->pfid_kif
!= NULL
)
480 pfi_detach_rule(dyn
->pfid_kif
);
481 pool_put(&pfi_addr_pl
, dyn
);
487 pfi_dynaddr_update(void *p
)
489 struct pfi_dynaddr
*dyn
= (struct pfi_dynaddr
*)p
;
490 struct pfi_kif
*kif
= dyn
->pfid_kif
;
491 struct pfr_ktable
*kt
= dyn
->pfid_kt
;
493 if (dyn
== NULL
|| kif
== NULL
|| kt
== NULL
)
494 panic("pfi_dynaddr_update");
495 if (kt
->pfrkt_larg
!= pfi_update
) {
496 /* this table needs to be brought up-to-date */
497 pfi_table_update(kt
, kif
, dyn
->pfid_net
, dyn
->pfid_iflags
);
498 kt
->pfrkt_larg
= pfi_update
;
500 pfr_dynaddr_update(kt
, dyn
);
504 pfi_table_update(struct pfr_ktable
*kt
, struct pfi_kif
*kif
, int net
, int flags
)
510 if ((kif
->pfik_flags
& PFI_IFLAG_INSTANCE
) && kif
->pfik_ifp
== NULL
) {
511 pfr_clr_addrs(&kt
->pfrkt_t
, NULL
, 0);
515 if ((kif
->pfik_flags
& PFI_IFLAG_INSTANCE
))
516 pfi_instance_add(kif
->pfik_ifp
, net
, flags
);
517 else if (strcmp(kif
->pfik_name
, "self")) {
518 TAILQ_FOREACH(p
, &kif
->pfik_grouphead
, pfik_instances
)
519 pfi_instance_add(p
->pfik_ifp
, net
, flags
);
521 RB_FOREACH(p
, pfi_ifhead
, &pfi_ifs
)
522 if (p
->pfik_flags
& PFI_IFLAG_INSTANCE
)
523 pfi_instance_add(p
->pfik_ifp
, net
, flags
);
527 if ((e
= pfr_set_addrs(&t
, pfi_buffer
, pfi_buffer_cnt
, &size2
,
528 NULL
, NULL
, NULL
, 0)))
529 kprintf("pfi_table_update: cannot set %d new addresses "
530 "into table %s: %d\n", pfi_buffer_cnt
, kt
->pfrkt_name
, e
);
534 pfi_instance_add(struct ifnet
*ifp
, int net
, int flags
)
536 struct ifaddr_container
*ifac
;
537 int got4
= 0, got6
= 0;
542 TAILQ_FOREACH(ifac
, &ifp
->if_addrheads
[mycpuid
], ifa_link
) {
543 struct ifaddr
*ia
= ifac
->ifa
;
545 if (ia
->ifa_addr
== NULL
)
547 af
= ia
->ifa_addr
->sa_family
;
548 if (af
!= AF_INET
&& af
!= AF_INET6
)
551 * XXX: For point-to-point interfaces, (ifname:0) and IPv4,
552 * jump over address without a proper route to work
553 * around a problem with ppp not fully removing the
554 * address used during IPCP.
556 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
557 !(ia
->ifa_flags
& IFA_ROUTE
) &&
558 (flags
& PFI_AFLAG_NOALIAS
) && (af
== AF_INET
))
560 if ((flags
& PFI_AFLAG_BROADCAST
) && af
== AF_INET6
)
562 if ((flags
& PFI_AFLAG_BROADCAST
) &&
563 !(ifp
->if_flags
& IFF_BROADCAST
))
565 if ((flags
& PFI_AFLAG_PEER
) &&
566 !(ifp
->if_flags
& IFF_POINTOPOINT
))
568 if ((flags
& PFI_AFLAG_NETWORK
) && af
== AF_INET6
&&
569 IN6_IS_ADDR_LINKLOCAL(
570 &((struct sockaddr_in6
*)ia
->ifa_addr
)->sin6_addr
))
572 if (flags
& PFI_AFLAG_NOALIAS
) {
573 if (af
== AF_INET
&& got4
)
575 if (af
== AF_INET6
&& got6
)
583 if (net2
== 128 && (flags
& PFI_AFLAG_NETWORK
)) {
585 net2
= pfi_unmask(&((struct sockaddr_in
*)
586 ia
->ifa_netmask
)->sin_addr
);
588 net2
= pfi_unmask(&((struct sockaddr_in6
*)
589 ia
->ifa_netmask
)->sin6_addr
);
592 if (af
== AF_INET
&& net2
> 32)
594 if (flags
& PFI_AFLAG_BROADCAST
)
595 pfi_address_add(ia
->ifa_broadaddr
, af
, net2
);
596 else if (flags
& PFI_AFLAG_PEER
)
597 pfi_address_add(ia
->ifa_dstaddr
, af
, net2
);
599 pfi_address_add(ia
->ifa_addr
, af
, net2
);
604 pfi_address_add(struct sockaddr
*sa
, int af
, int net
)
609 if (pfi_buffer_cnt
>= pfi_buffer_max
) {
610 int new_max
= pfi_buffer_max
* 2;
612 if (new_max
> PFI_BUFFER_MAX
) {
613 kprintf("pfi_address_add: address buffer full (%d/%d)\n",
614 pfi_buffer_cnt
, PFI_BUFFER_MAX
);
617 p
= kmalloc(new_max
* sizeof(*pfi_buffer
), PFI_MTYPE
,
620 kprintf("pfi_address_add: no memory to grow buffer "
621 "(%d/%d)\n", pfi_buffer_cnt
, PFI_BUFFER_MAX
);
624 memcpy(pfi_buffer
, p
, pfi_buffer_cnt
* sizeof(*pfi_buffer
));
625 /* no need to zero buffer */
626 kfree(pfi_buffer
, PFI_MTYPE
);
628 pfi_buffer_max
= new_max
;
630 if (af
== AF_INET
&& net
> 32)
632 p
= pfi_buffer
+ pfi_buffer_cnt
++;
633 bzero(p
, sizeof(*p
));
637 p
->pfra_ip4addr
= ((struct sockaddr_in
*)sa
)->sin_addr
;
638 if (af
== AF_INET6
) {
639 p
->pfra_ip6addr
= ((struct sockaddr_in6
*)sa
)->sin6_addr
;
640 if (IN6_IS_ADDR_LINKLOCAL(&p
->pfra_ip6addr
))
641 p
->pfra_ip6addr
.s6_addr16
[1] = 0;
643 /* mask network address bits */
645 ((caddr_t
)p
)[p
->pfra_net
/8] &= ~(0xFF >> (p
->pfra_net
%8));
646 for (i
= (p
->pfra_net
+7)/8; i
< sizeof(p
->pfra_u
); i
++)
651 pfi_dynaddr_remove(struct pf_addr_wrap
*aw
)
653 if (aw
->type
!= PF_ADDR_DYNIFTL
|| aw
->p
.dyn
== NULL
||
654 aw
->p
.dyn
->pfid_kif
== NULL
|| aw
->p
.dyn
->pfid_kt
== NULL
)
658 hook_disestablish(aw
->p
.dyn
->pfid_kif
->pfik_ah_head
,
659 aw
->p
.dyn
->pfid_hook_cookie
);
660 pfi_detach_rule(aw
->p
.dyn
->pfid_kif
);
661 aw
->p
.dyn
->pfid_kif
= NULL
;
662 pfr_detach_table(aw
->p
.dyn
->pfid_kt
);
663 aw
->p
.dyn
->pfid_kt
= NULL
;
664 pool_put(&pfi_addr_pl
, aw
->p
.dyn
);
670 pfi_dynaddr_copyout(struct pf_addr_wrap
*aw
)
672 if (aw
->type
!= PF_ADDR_DYNIFTL
|| aw
->p
.dyn
== NULL
||
673 aw
->p
.dyn
->pfid_kif
== NULL
)
675 aw
->p
.dyncnt
= aw
->p
.dyn
->pfid_acnt4
+ aw
->p
.dyn
->pfid_acnt6
;
679 pfi_kifaddr_update(void *v
)
688 pfi_if_compare(struct pfi_kif
*p
, struct pfi_kif
*q
)
690 return (strncmp(p
->pfik_name
, q
->pfik_name
, IFNAMSIZ
));
694 pfi_if_create(const char *name
, struct pfi_kif
*q
, int flags
)
698 p
= kmalloc(sizeof(*p
), PFI_MTYPE
, M_NOWAIT
| M_ZERO
);
701 p
->pfik_ah_head
= kmalloc(sizeof(*p
->pfik_ah_head
), PFI_MTYPE
,
703 if (p
->pfik_ah_head
== NULL
) {
707 TAILQ_INIT(p
->pfik_ah_head
);
708 TAILQ_INIT(&p
->pfik_grouphead
);
709 strlcpy(p
->pfik_name
, name
, sizeof(p
->pfik_name
));
710 RB_INIT(&p
->pfik_lan_ext
);
711 RB_INIT(&p
->pfik_ext_gwy
);
712 p
->pfik_flags
= flags
;
714 p
->pfik_tzero
= time_second
;
716 RB_INSERT(pfi_ifhead
, &pfi_ifs
, p
);
719 TAILQ_INSERT_TAIL(&q
->pfik_grouphead
, p
, pfik_instances
);
726 pfi_maybe_destroy(struct pfi_kif
*p
)
729 struct pfi_kif
*q
= p
->pfik_parent
;
731 if ((p
->pfik_flags
& (PFI_IFLAG_ATTACHED
| PFI_IFLAG_GROUP
)) ||
732 p
->pfik_rules
> 0 || p
->pfik_states
> 0)
733 if (!(p
->pfik_flags
& PFI_IFLAG_PLACEHOLDER
))
738 for (i
= 0; i
< 2; i
++)
739 for (j
= 0; j
< 2; j
++)
740 for (k
= 0; k
< 2; k
++) {
741 q
->pfik_bytes
[i
][j
][k
] +=
742 p
->pfik_bytes
[i
][j
][k
];
743 q
->pfik_packets
[i
][j
][k
] +=
744 p
->pfik_packets
[i
][j
][k
];
745 /* clear stats in case we return to the dummy group */
746 p
->pfik_bytes
[i
][j
][k
] = 0;
747 p
->pfik_packets
[i
][j
][k
] = 0;
750 TAILQ_REMOVE(&q
->pfik_grouphead
, p
, pfik_instances
);
752 if (p
->pfik_rules
> 0 || p
->pfik_states
> 0) {
753 /* move back to the dummy group */
754 p
->pfik_parent
= pfi_dummy
;
755 pfi_dummy
->pfik_addcnt
++;
756 TAILQ_INSERT_TAIL(&pfi_dummy
->pfik_grouphead
, p
,
762 RB_REMOVE(pfi_ifhead
, &pfi_ifs
, p
);
765 kfree(p
->pfik_ah_head
, PFI_MTYPE
);
771 pfi_copy_group(char *p
, const char *q
, int m
)
773 while (m
> 1 && *q
&& !(*q
>= '0' && *q
<= '9')) {
782 pfi_dynamic_drivers(void)
787 * For FreeBSD basically every interface is "dynamic" as we can unload
790 TAILQ_FOREACH(ifp
, &ifnet
, if_link
) {
791 if (ifp
->if_dunit
== IF_DUNIT_NONE
)
793 pfi_newgroup(ifp
->if_dname
, PFI_IFLAG_DYNAMIC
);
798 pfi_newgroup(const char *name
, int flags
)
802 p
= pfi_lookup_if(name
);
804 p
= pfi_if_create(name
, pfi_self
, PFI_IFLAG_GROUP
);
806 kprintf("pfi_newgroup: cannot allocate '%s' group", name
);
809 p
->pfik_flags
|= flags
;
813 pfi_fill_oldstatus(struct pf_status
*pfs
)
815 struct pfi_kif
*p
, key
;
818 strlcpy(key
.pfik_name
, pfs
->ifname
, sizeof(key
.pfik_name
));
820 p
= RB_FIND(pfi_ifhead
, &pfi_ifs
, &key
);
825 bzero(pfs
->pcounters
, sizeof(pfs
->pcounters
));
826 bzero(pfs
->bcounters
, sizeof(pfs
->bcounters
));
827 for (i
= 0; i
< 2; i
++)
828 for (j
= 0; j
< 2; j
++)
829 for (k
= 0; k
< 2; k
++) {
830 pfs
->pcounters
[i
][j
][k
] =
831 p
->pfik_packets
[i
][j
][k
];
832 pfs
->bcounters
[i
][j
] +=
833 p
->pfik_bytes
[i
][j
][k
];
839 pfi_clr_istats(const char *name
, int *nzero
, int flags
)
843 long tzero
= time_second
;
846 ACCEPT_FLAGS(PFI_FLAG_GROUP
|PFI_FLAG_INSTANCE
);
847 RB_FOREACH(p
, pfi_ifhead
, &pfi_ifs
) {
848 if (pfi_skip_if(name
, p
, flags
))
850 bzero(p
->pfik_packets
, sizeof(p
->pfik_packets
));
851 bzero(p
->pfik_bytes
, sizeof(p
->pfik_bytes
));
852 p
->pfik_tzero
= tzero
;
862 pfi_get_ifaces(const char *name
, struct pfi_if
*buf
, int *size
, int flags
)
867 ACCEPT_FLAGS(PFI_FLAG_GROUP
|PFI_FLAG_INSTANCE
);
869 RB_FOREACH(p
, pfi_ifhead
, &pfi_ifs
) {
870 if (pfi_skip_if(name
, p
, flags
))
874 p
->pfik_tzero
= boottime
.tv_sec
;
875 if (copyout(p
, buf
++, sizeof(*buf
))) {
887 pfi_lookup_if(const char *name
)
889 struct pfi_kif
*p
, key
;
891 strlcpy(key
.pfik_name
, name
, sizeof(key
.pfik_name
));
892 p
= RB_FIND(pfi_ifhead
, &pfi_ifs
, &key
);
897 pfi_skip_if(const char *filter
, struct pfi_kif
*p
, int f
)
901 if ((p
->pfik_flags
& PFI_IFLAG_GROUP
) && !(f
& PFI_FLAG_GROUP
))
903 if ((p
->pfik_flags
& PFI_IFLAG_INSTANCE
) && !(f
& PFI_FLAG_INSTANCE
))
905 if (filter
== NULL
|| !*filter
)
907 if (!strcmp(p
->pfik_name
, filter
))
908 return (0); /* exact match */
910 if (n
< 1 || n
>= IFNAMSIZ
)
911 return (1); /* sanity check */
912 if (filter
[n
-1] >= '0' && filter
[n
-1] <= '9')
913 return (1); /* only do exact match in that case */
914 if (strncmp(p
->pfik_name
, filter
, n
))
915 return (1); /* prefix doesn't match */
916 return (p
->pfik_name
[n
] < '0' || p
->pfik_name
[n
] > '9');
919 /* from pf_print_state.c */
921 pfi_unmask(void *addr
)
923 struct pf_addr
*m
= addr
;
924 int i
= 31, j
= 0, b
= 0;
927 while (j
< 4 && m
->addr32
[j
] == 0xffffffff) {
932 tmp
= ntohl(m
->addr32
[j
]);
933 for (i
= 31; tmp
& (1 << i
); --i
)
940 pfi_dohooks(struct pfi_kif
*p
)
942 for (; p
!= NULL
; p
= p
->pfik_parent
)
943 dohooks(p
->pfik_ah_head
, 0);
947 pfi_match_addr(struct pfi_dynaddr
*dyn
, struct pf_addr
*a
, sa_family_t af
)
950 switch (dyn
->pfid_acnt4
) {
954 return (PF_MATCHA(0, &dyn
->pfid_addr4
,
955 &dyn
->pfid_mask4
, a
, AF_INET
));
957 return (pfr_match_addr(dyn
->pfid_kt
, a
, AF_INET
));
960 switch (dyn
->pfid_acnt6
) {
964 return (PF_MATCHA(0, &dyn
->pfid_addr6
,
965 &dyn
->pfid_mask6
, a
, AF_INET6
));
967 return (pfr_match_addr(dyn
->pfid_kt
, a
, AF_INET6
));