1*210ed929Srmind /* $NetBSD: pf_if.c,v 1.25 2014/05/17 20:44:24 rmind Exp $ */ 2fff57c55Syamt /* $OpenBSD: pf_if.c,v 1.47 2007/07/13 09:17:48 markus Exp $ */ 36adffbf9Sitojun 46adffbf9Sitojun /* 5fff57c55Syamt * Copyright 2005 Henning Brauer <henning@openbsd.org> 6fff57c55Syamt * Copyright 2005 Ryan McBride <mcbride@openbsd.org> 76adffbf9Sitojun * Copyright (c) 2001 Daniel Hartmeier 86adffbf9Sitojun * Copyright (c) 2003 Cedric Berger 96adffbf9Sitojun * All rights reserved. 106adffbf9Sitojun * 116adffbf9Sitojun * Redistribution and use in source and binary forms, with or without 126adffbf9Sitojun * modification, are permitted provided that the following conditions 136adffbf9Sitojun * are met: 146adffbf9Sitojun * 156adffbf9Sitojun * - Redistributions of source code must retain the above copyright 166adffbf9Sitojun * notice, this list of conditions and the following disclaimer. 176adffbf9Sitojun * - Redistributions in binary form must reproduce the above 186adffbf9Sitojun * copyright notice, this list of conditions and the following 196adffbf9Sitojun * disclaimer in the documentation and/or other materials provided 206adffbf9Sitojun * with the distribution. 216adffbf9Sitojun * 226adffbf9Sitojun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 236adffbf9Sitojun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 246adffbf9Sitojun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 256adffbf9Sitojun * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 266adffbf9Sitojun * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 276adffbf9Sitojun * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 286adffbf9Sitojun * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 296adffbf9Sitojun * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 306adffbf9Sitojun * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 316adffbf9Sitojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 326adffbf9Sitojun * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 336adffbf9Sitojun * POSSIBILITY OF SUCH DAMAGE. 346adffbf9Sitojun */ 356adffbf9Sitojun 36a0dda790Slukem #include <sys/cdefs.h> 37*210ed929Srmind __KERNEL_RCSID(0, "$NetBSD: pf_if.c,v 1.25 2014/05/17 20:44:24 rmind Exp $"); 38a0dda790Slukem 39bfcdaa57Sitojun #ifdef _KERNEL_OPT 40bfcdaa57Sitojun #include "opt_inet.h" 41bfcdaa57Sitojun #endif 42bfcdaa57Sitojun 436adffbf9Sitojun #include <sys/param.h> 446adffbf9Sitojun #include <sys/systm.h> 456adffbf9Sitojun #include <sys/mbuf.h> 466adffbf9Sitojun #include <sys/filio.h> 476adffbf9Sitojun #include <sys/socket.h> 486adffbf9Sitojun #include <sys/socketvar.h> 496adffbf9Sitojun #include <sys/kernel.h> 506adffbf9Sitojun #include <sys/device.h> 516adffbf9Sitojun #include <sys/time.h> 526adffbf9Sitojun 536adffbf9Sitojun #include <net/if.h> 546adffbf9Sitojun #include <net/if_types.h> 556adffbf9Sitojun 566adffbf9Sitojun #include <netinet/in.h> 576adffbf9Sitojun #include <netinet/in_var.h> 586adffbf9Sitojun #include <netinet/in_systm.h> 596adffbf9Sitojun #include <netinet/ip.h> 606adffbf9Sitojun #include <netinet/ip_var.h> 616adffbf9Sitojun 626adffbf9Sitojun #include <net/pfvar.h> 636adffbf9Sitojun 646adffbf9Sitojun #ifdef INET6 656adffbf9Sitojun #include <netinet/ip6.h> 666adffbf9Sitojun #endif /* INET6 */ 676adffbf9Sitojun 68fff57c55Syamt struct pfi_kif *pfi_all = NULL; 696adffbf9Sitojun struct pool pfi_addr_pl; 70fff57c55Syamt struct pfi_ifhead pfi_ifs; 716adffbf9Sitojun long pfi_update = 1; 726adffbf9Sitojun struct pfr_addr *pfi_buffer; 736adffbf9Sitojun int pfi_buffer_cnt; 746adffbf9Sitojun int pfi_buffer_max; 756adffbf9Sitojun 76fff57c55Syamt void pfi_kif_update(struct pfi_kif *); 77fff57c55Syamt void pfi_dynaddr_update(struct pfi_dynaddr *dyn); 786adffbf9Sitojun void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, 796adffbf9Sitojun int, int); 80fff57c55Syamt void pfi_kifaddr_update(void *); 816adffbf9Sitojun void pfi_instance_add(struct ifnet *, int, int); 826adffbf9Sitojun void pfi_address_add(struct sockaddr *, int, int); 836adffbf9Sitojun int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); 84fff57c55Syamt int pfi_skip_if(const char *, struct pfi_kif *); 856adffbf9Sitojun int pfi_unmask(void *); 86fff57c55Syamt #ifdef __NetBSD__ 87fff57c55Syamt void pfi_init_groups(struct ifnet *); 88fff57c55Syamt void pfi_destroy_groups(struct ifnet *); 89fff57c55Syamt 90fff57c55Syamt int pfil_ifnet_wrapper(void *, struct mbuf **, struct ifnet *, int); 91fff57c55Syamt int pfil_ifaddr_wrapper(void *, struct mbuf **, struct ifnet *, int); 92fff57c55Syamt #endif 936adffbf9Sitojun 946adffbf9Sitojun RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 956adffbf9Sitojun RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 966adffbf9Sitojun 976adffbf9Sitojun #define PFI_BUFFER_MAX 0x10000 986adffbf9Sitojun #define PFI_MTYPE M_IFADDR 996adffbf9Sitojun 1006adffbf9Sitojun void 1016adffbf9Sitojun pfi_initialize(void) 1026adffbf9Sitojun { 103fff57c55Syamt if (pfi_all != NULL) /* already initialized */ 1046adffbf9Sitojun return; 1056adffbf9Sitojun 10659d979c5Sad #ifdef __NetBSD__ 10759d979c5Sad pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 10859d979c5Sad "pfiaddrpl", &pool_allocator_nointr, IPL_NONE); 10959d979c5Sad #else 1106adffbf9Sitojun pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 1116adffbf9Sitojun "pfiaddrpl", &pool_allocator_nointr); 112fff57c55Syamt #endif /* !__NetBSD__ */ 1136adffbf9Sitojun pfi_buffer_max = 64; 1146adffbf9Sitojun pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer), 1156adffbf9Sitojun PFI_MTYPE, M_WAITOK); 116fff57c55Syamt 117fff57c55Syamt if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL) 118fff57c55Syamt panic("pfi_kif_get for pfi_all failed"); 119fff57c55Syamt 120fff57c55Syamt #ifdef __NetBSD__ 121*210ed929Srmind ifnet_t *ifp; 122*210ed929Srmind IFNET_FOREACH(ifp) { 123fff57c55Syamt pfi_init_groups(ifp); 124fff57c55Syamt pfi_attach_ifnet(ifp); 125fff57c55Syamt } 126fff57c55Syamt 1274c722818Srmind pfil_add_hook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, if_pfil); 1284c722818Srmind pfil_add_hook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, if_pfil); 129fff57c55Syamt #endif /* __NetBSD__ */ 1306adffbf9Sitojun } 1316adffbf9Sitojun 132f6a8ba3dSahoka #ifdef _MODULE 133f6a8ba3dSahoka void 134f6a8ba3dSahoka pfi_destroy(void) 135f6a8ba3dSahoka { 136f6a8ba3dSahoka struct pfi_kif *p; 137f6a8ba3dSahoka int i; 138f6a8ba3dSahoka 1398e2c1788Snjoly pfil_remove_hook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, if_pfil); 1408e2c1788Snjoly pfil_remove_hook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, if_pfil); 141f6a8ba3dSahoka 142*210ed929Srmind ifnet_t *ifp; 143*210ed929Srmind IFNET_FOREACH(ifp) { 144*210ed929Srmind if ((ifp = if_byindex(i)) != NULL) { 145f6a8ba3dSahoka pfi_detach_ifnet(ifp); 146f6a8ba3dSahoka pfi_destroy_groups(ifp); 147f6a8ba3dSahoka } 148f6a8ba3dSahoka } 149f6a8ba3dSahoka 150f6a8ba3dSahoka while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) { 151f6a8ba3dSahoka RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 152f6a8ba3dSahoka free(p, PFI_MTYPE); 153f6a8ba3dSahoka } 154f6a8ba3dSahoka 155f6a8ba3dSahoka pool_destroy(&pfi_addr_pl); 156f6a8ba3dSahoka 157f6a8ba3dSahoka free(pfi_buffer, PFI_MTYPE); 158f6a8ba3dSahoka } 159f6a8ba3dSahoka #endif /* _MODULE */ 160f6a8ba3dSahoka 161fff57c55Syamt struct pfi_kif * 162fff57c55Syamt pfi_kif_get(const char *kif_name) 163fff57c55Syamt { 164fff57c55Syamt struct pfi_kif *kif; 165fff57c55Syamt struct pfi_kif_cmp s; 166fff57c55Syamt 167fff57c55Syamt bzero(&s, sizeof(s)); 168fff57c55Syamt strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name)); 169fff57c55Syamt if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL) 170fff57c55Syamt return (kif); 171fff57c55Syamt 172fff57c55Syamt /* create new one */ 173dcf70589Scegger if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT|M_ZERO)) == NULL) 174fff57c55Syamt return (NULL); 175fff57c55Syamt 176fff57c55Syamt strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name)); 177fff57c55Syamt #ifdef __NetBSD__ 178fff57c55Syamt /* time_second is not valid yet */ 179fff57c55Syamt kif->pfik_tzero = (time_second > 7200) ? time_second : 0; 180fff57c55Syamt #else 181fff57c55Syamt kif->pfik_tzero = time_second; 182fff57c55Syamt #endif /* !__NetBSD__ */ 183fff57c55Syamt TAILQ_INIT(&kif->pfik_dynaddrs); 184fff57c55Syamt 185fff57c55Syamt RB_INSERT(pfi_ifhead, &pfi_ifs, kif); 186fff57c55Syamt return (kif); 187fff57c55Syamt } 1880407dd42Sitojun 1896adffbf9Sitojun void 190fff57c55Syamt pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what) 1916adffbf9Sitojun { 192fff57c55Syamt switch (what) { 193fff57c55Syamt case PFI_KIF_REF_RULE: 194fff57c55Syamt kif->pfik_rules++; 195fff57c55Syamt break; 196fff57c55Syamt case PFI_KIF_REF_STATE: 197fff57c55Syamt kif->pfik_states++; 198fff57c55Syamt break; 199fff57c55Syamt default: 200fff57c55Syamt panic("pfi_kif_ref with unknown type"); 201fff57c55Syamt } 202fff57c55Syamt } 203fff57c55Syamt 204fff57c55Syamt void 205fff57c55Syamt pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what) 206fff57c55Syamt { 207fff57c55Syamt if (kif == NULL) 208fff57c55Syamt return; 209fff57c55Syamt 210fff57c55Syamt switch (what) { 211fff57c55Syamt case PFI_KIF_REF_NONE: 212fff57c55Syamt break; 213fff57c55Syamt case PFI_KIF_REF_RULE: 214fff57c55Syamt if (kif->pfik_rules <= 0) { 215fff57c55Syamt printf("pfi_kif_unref: rules refcount <= 0\n"); 216fff57c55Syamt return; 217fff57c55Syamt } 218fff57c55Syamt kif->pfik_rules--; 219fff57c55Syamt break; 220fff57c55Syamt case PFI_KIF_REF_STATE: 221fff57c55Syamt if (kif->pfik_states <= 0) { 222fff57c55Syamt printf("pfi_kif_unref: state refcount <= 0\n"); 223fff57c55Syamt return; 224fff57c55Syamt } 225fff57c55Syamt kif->pfik_states--; 226fff57c55Syamt break; 227fff57c55Syamt default: 228fff57c55Syamt panic("pfi_kif_unref with unknown type"); 229fff57c55Syamt } 230fff57c55Syamt 231fff57c55Syamt if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all) 232fff57c55Syamt return; 233fff57c55Syamt 234fff57c55Syamt if (kif->pfik_rules || kif->pfik_states) 235fff57c55Syamt return; 236fff57c55Syamt 237fff57c55Syamt RB_REMOVE(pfi_ifhead, &pfi_ifs, kif); 238fff57c55Syamt free(kif, PFI_MTYPE); 239fff57c55Syamt } 240fff57c55Syamt 241fff57c55Syamt int 242fff57c55Syamt pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif) 243fff57c55Syamt { 244fff57c55Syamt struct ifg_list *p; 245fff57c55Syamt 246fff57c55Syamt if (rule_kif == NULL || rule_kif == packet_kif) 247fff57c55Syamt return (1); 248fff57c55Syamt 249fff57c55Syamt if (rule_kif->pfik_group != NULL) { 250fff57c55Syamt struct ifg_list_head *ifgh = 251fff57c55Syamt if_get_groups(packet_kif->pfik_ifp); 252fff57c55Syamt 253fff57c55Syamt TAILQ_FOREACH(p, ifgh, ifgl_next) 254fff57c55Syamt if (p->ifgl_group == rule_kif->pfik_group) 255fff57c55Syamt return (1); 256fff57c55Syamt } 257fff57c55Syamt 258fff57c55Syamt return (0); 2596adffbf9Sitojun } 2606adffbf9Sitojun 2616adffbf9Sitojun void 2626adffbf9Sitojun pfi_attach_ifnet(struct ifnet *ifp) 2636adffbf9Sitojun { 264fff57c55Syamt struct pfi_kif *kif; 2656adffbf9Sitojun int s; 2666adffbf9Sitojun 2676adffbf9Sitojun pfi_initialize(); 2686adffbf9Sitojun s = splsoftnet(); 2696adffbf9Sitojun pfi_update++; 270fff57c55Syamt if ((kif = pfi_kif_get(ifp->if_xname)) == NULL) 271fff57c55Syamt panic("pfi_kif_get failed"); 2726adffbf9Sitojun 273fff57c55Syamt kif->pfik_ifp = ifp; 274fff57c55Syamt ifp->if_pf_kif = kif; 2756adffbf9Sitojun 276fff57c55Syamt #ifndef __NetBSD__ 277fff57c55Syamt if ((kif->pfik_ah_cookie = hook_establish(ifp->if_addrhooks, 1, 278fff57c55Syamt pfi_kifaddr_update, kif)) == NULL) 279fff57c55Syamt panic("pfi_attach_ifnet: cannot allocate '%s' address hook", 280fff57c55Syamt ifp->if_xname); 281fff57c55Syamt #endif /* !__NetBSD__ */ 2826adffbf9Sitojun 283fff57c55Syamt pfi_kif_update(kif); 2846adffbf9Sitojun 2856adffbf9Sitojun splx(s); 2866adffbf9Sitojun } 2876adffbf9Sitojun 2886adffbf9Sitojun void 2896adffbf9Sitojun pfi_detach_ifnet(struct ifnet *ifp) 2906adffbf9Sitojun { 2916adffbf9Sitojun int s; 292fff57c55Syamt struct pfi_kif *kif; 2936adffbf9Sitojun 294fff57c55Syamt if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL) 295fff57c55Syamt return; 2966adffbf9Sitojun 2976adffbf9Sitojun s = splsoftnet(); 2986adffbf9Sitojun pfi_update++; 299fff57c55Syamt #ifndef __NetBSD__ 300fff57c55Syamt hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie); 301fff57c55Syamt #endif /* !__NetBSD__ */ 302fff57c55Syamt pfi_kif_update(kif); 303fff57c55Syamt 304fff57c55Syamt kif->pfik_ifp = NULL; 305fff57c55Syamt ifp->if_pf_kif = NULL; 306fff57c55Syamt pfi_kif_unref(kif, PFI_KIF_REF_NONE); 3076adffbf9Sitojun splx(s); 3086adffbf9Sitojun } 3096adffbf9Sitojun 310fff57c55Syamt void 311fff57c55Syamt pfi_attach_ifgroup(struct ifg_group *ifg) 3126adffbf9Sitojun { 313fff57c55Syamt struct pfi_kif *kif; 314fff57c55Syamt int s; 315fff57c55Syamt 316fff57c55Syamt pfi_initialize(); 317fff57c55Syamt s = splsoftnet(); 318fff57c55Syamt pfi_update++; 319fff57c55Syamt if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL) 320fff57c55Syamt panic("pfi_kif_get failed"); 321fff57c55Syamt 322fff57c55Syamt kif->pfik_group = ifg; 323fff57c55Syamt ifg->ifg_pf_kif = kif; 324fff57c55Syamt 325fff57c55Syamt splx(s); 326fff57c55Syamt } 327fff57c55Syamt 328fff57c55Syamt void 329fff57c55Syamt pfi_detach_ifgroup(struct ifg_group *ifg) 330fff57c55Syamt { 331fff57c55Syamt int s; 332fff57c55Syamt struct pfi_kif *kif; 333fff57c55Syamt 334fff57c55Syamt if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL) 335fff57c55Syamt return; 336fff57c55Syamt 337fff57c55Syamt s = splsoftnet(); 338fff57c55Syamt pfi_update++; 339fff57c55Syamt 340fff57c55Syamt kif->pfik_group = NULL; 341fff57c55Syamt ifg->ifg_pf_kif = NULL; 342fff57c55Syamt pfi_kif_unref(kif, PFI_KIF_REF_NONE); 343fff57c55Syamt splx(s); 344fff57c55Syamt } 345fff57c55Syamt 346fff57c55Syamt void 347fff57c55Syamt pfi_group_change(const char *group) 348fff57c55Syamt { 349fff57c55Syamt struct pfi_kif *kif; 3506adffbf9Sitojun int s; 3516adffbf9Sitojun 3526adffbf9Sitojun s = splsoftnet(); 353fff57c55Syamt pfi_update++; 354fff57c55Syamt if ((kif = pfi_kif_get(group)) == NULL) 355fff57c55Syamt panic("pfi_kif_get failed"); 356fff57c55Syamt 357fff57c55Syamt pfi_kif_update(kif); 358fff57c55Syamt 3596adffbf9Sitojun splx(s); 3606adffbf9Sitojun } 3616adffbf9Sitojun 362fff57c55Syamt int 363fff57c55Syamt pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) 3646adffbf9Sitojun { 365fff57c55Syamt switch (af) { 366fff57c55Syamt #ifdef INET 367fff57c55Syamt case AF_INET: 368fff57c55Syamt switch (dyn->pfid_acnt4) { 369fff57c55Syamt case 0: 370fff57c55Syamt return (0); 371fff57c55Syamt case 1: 372fff57c55Syamt return (PF_MATCHA(0, &dyn->pfid_addr4, 373fff57c55Syamt &dyn->pfid_mask4, a, AF_INET)); 374fff57c55Syamt default: 375fff57c55Syamt return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); 3766adffbf9Sitojun } 377fff57c55Syamt break; 378fff57c55Syamt #endif /* INET */ 379fff57c55Syamt #ifdef INET6 380fff57c55Syamt case AF_INET6: 381fff57c55Syamt switch (dyn->pfid_acnt6) { 382fff57c55Syamt case 0: 383fff57c55Syamt return (0); 384fff57c55Syamt case 1: 385fff57c55Syamt return (PF_MATCHA(0, &dyn->pfid_addr6, 386fff57c55Syamt &dyn->pfid_mask6, a, AF_INET6)); 387fff57c55Syamt default: 388fff57c55Syamt return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); 3896adffbf9Sitojun } 390fff57c55Syamt break; 391fff57c55Syamt #endif /* INET6 */ 392fff57c55Syamt default: 393fff57c55Syamt return (0); 3946adffbf9Sitojun } 3956adffbf9Sitojun } 3966adffbf9Sitojun 3976adffbf9Sitojun int 3986adffbf9Sitojun pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) 3996adffbf9Sitojun { 4006adffbf9Sitojun struct pfi_dynaddr *dyn; 4016adffbf9Sitojun char tblname[PF_TABLE_NAME_SIZE]; 4026adffbf9Sitojun struct pf_ruleset *ruleset = NULL; 4036adffbf9Sitojun int s, rv = 0; 4046adffbf9Sitojun 4056adffbf9Sitojun if (aw->type != PF_ADDR_DYNIFTL) 4066adffbf9Sitojun return (0); 407fff57c55Syamt if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL) 4086adffbf9Sitojun return (1); 4096adffbf9Sitojun bzero(dyn, sizeof(*dyn)); 4106adffbf9Sitojun 4116adffbf9Sitojun s = splsoftnet(); 412fff57c55Syamt if (!strcmp(aw->v.ifname, "self")) 413fff57c55Syamt dyn->pfid_kif = pfi_kif_get(IFG_ALL); 414fff57c55Syamt else 415fff57c55Syamt dyn->pfid_kif = pfi_kif_get(aw->v.ifname); 416fff57c55Syamt if (dyn->pfid_kif == NULL) { 417fff57c55Syamt rv = 1; 418fff57c55Syamt goto _bad; 419fff57c55Syamt } 420fff57c55Syamt pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE); 4216adffbf9Sitojun 4226adffbf9Sitojun dyn->pfid_net = pfi_unmask(&aw->v.a.mask); 4236adffbf9Sitojun if (af == AF_INET && dyn->pfid_net == 32) 4246adffbf9Sitojun dyn->pfid_net = 128; 4256adffbf9Sitojun strlcpy(tblname, aw->v.ifname, sizeof(tblname)); 4266adffbf9Sitojun if (aw->iflags & PFI_AFLAG_NETWORK) 4276adffbf9Sitojun strlcat(tblname, ":network", sizeof(tblname)); 4286adffbf9Sitojun if (aw->iflags & PFI_AFLAG_BROADCAST) 4296adffbf9Sitojun strlcat(tblname, ":broadcast", sizeof(tblname)); 4306adffbf9Sitojun if (aw->iflags & PFI_AFLAG_PEER) 4316adffbf9Sitojun strlcat(tblname, ":peer", sizeof(tblname)); 4326adffbf9Sitojun if (aw->iflags & PFI_AFLAG_NOALIAS) 4336adffbf9Sitojun strlcat(tblname, ":0", sizeof(tblname)); 4346adffbf9Sitojun if (dyn->pfid_net != 128) 4356adffbf9Sitojun snprintf(tblname + strlen(tblname), 4366adffbf9Sitojun sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); 437fff57c55Syamt if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) { 438fff57c55Syamt rv = 1; 439fff57c55Syamt goto _bad; 440fff57c55Syamt } 4416adffbf9Sitojun 442fff57c55Syamt if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) { 443fff57c55Syamt rv = 1; 444fff57c55Syamt goto _bad; 445fff57c55Syamt } 4466adffbf9Sitojun 4476adffbf9Sitojun dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; 4486adffbf9Sitojun dyn->pfid_iflags = aw->iflags; 4496adffbf9Sitojun dyn->pfid_af = af; 4506adffbf9Sitojun 451fff57c55Syamt TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry); 4526adffbf9Sitojun aw->p.dyn = dyn; 453fff57c55Syamt pfi_kif_update(dyn->pfid_kif); 4546adffbf9Sitojun splx(s); 4556adffbf9Sitojun return (0); 4566adffbf9Sitojun 4576adffbf9Sitojun _bad: 4586adffbf9Sitojun if (dyn->pfid_kt != NULL) 4596adffbf9Sitojun pfr_detach_table(dyn->pfid_kt); 4606adffbf9Sitojun if (ruleset != NULL) 4616adffbf9Sitojun pf_remove_if_empty_ruleset(ruleset); 4626adffbf9Sitojun if (dyn->pfid_kif != NULL) 463fff57c55Syamt pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE); 4646adffbf9Sitojun pool_put(&pfi_addr_pl, dyn); 4656adffbf9Sitojun splx(s); 4666adffbf9Sitojun return (rv); 4676adffbf9Sitojun } 4686adffbf9Sitojun 4696adffbf9Sitojun void 470fff57c55Syamt pfi_kif_update(struct pfi_kif *kif) 4716adffbf9Sitojun { 472fff57c55Syamt struct ifg_list *ifgl; 473fff57c55Syamt struct pfi_dynaddr *p; 474fff57c55Syamt 475fff57c55Syamt /* update all dynaddr */ 476fff57c55Syamt TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry) 477fff57c55Syamt pfi_dynaddr_update(p); 478fff57c55Syamt 479fff57c55Syamt /* again for all groups kif is member of */ 480fff57c55Syamt if (kif->pfik_ifp != NULL) { 481fff57c55Syamt struct ifg_list_head *ifgh = if_get_groups(kif->pfik_ifp); 482fff57c55Syamt 483fff57c55Syamt TAILQ_FOREACH(ifgl, ifgh, ifgl_next) 484fff57c55Syamt pfi_kif_update((struct pfi_kif *) 485fff57c55Syamt ifgl->ifgl_group->ifg_pf_kif); 486fff57c55Syamt } 487fff57c55Syamt } 488fff57c55Syamt 489fff57c55Syamt void 490fff57c55Syamt pfi_dynaddr_update(struct pfi_dynaddr *dyn) 491fff57c55Syamt { 49297107414Speter struct pfi_kif *kif; 49397107414Speter struct pfr_ktable *kt; 4946adffbf9Sitojun 49597107414Speter if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL) 4966adffbf9Sitojun panic("pfi_dynaddr_update"); 49797107414Speter 49897107414Speter kif = dyn->pfid_kif; 49997107414Speter kt = dyn->pfid_kt; 500fff57c55Syamt 5016adffbf9Sitojun if (kt->pfrkt_larg != pfi_update) { 5026adffbf9Sitojun /* this table needs to be brought up-to-date */ 5036adffbf9Sitojun pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); 5046adffbf9Sitojun kt->pfrkt_larg = pfi_update; 5056adffbf9Sitojun } 5066adffbf9Sitojun pfr_dynaddr_update(kt, dyn); 5076adffbf9Sitojun } 5086adffbf9Sitojun 5096adffbf9Sitojun void 5106adffbf9Sitojun pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) 5116adffbf9Sitojun { 5126adffbf9Sitojun int e, size2 = 0; 513fff57c55Syamt struct ifg_member *ifgm; 5146adffbf9Sitojun 5156adffbf9Sitojun pfi_buffer_cnt = 0; 516fff57c55Syamt 517fff57c55Syamt if (kif->pfik_ifp != NULL) 5186adffbf9Sitojun pfi_instance_add(kif->pfik_ifp, net, flags); 519fff57c55Syamt else if (kif->pfik_group != NULL) 520fff57c55Syamt TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next) 521fff57c55Syamt pfi_instance_add(ifgm->ifgm_ifp, net, flags); 522fff57c55Syamt 523fff57c55Syamt if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2, 524fff57c55Syamt NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK))) 5256adffbf9Sitojun printf("pfi_table_update: cannot set %d new addresses " 5266adffbf9Sitojun "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e); 5276adffbf9Sitojun } 5286adffbf9Sitojun 5296adffbf9Sitojun void 5306adffbf9Sitojun pfi_instance_add(struct ifnet *ifp, int net, int flags) 5316adffbf9Sitojun { 5326adffbf9Sitojun struct ifaddr *ia; 5336adffbf9Sitojun int got4 = 0, got6 = 0; 5346adffbf9Sitojun int net2, af; 5356adffbf9Sitojun 5366adffbf9Sitojun if (ifp == NULL) 5376adffbf9Sitojun return; 5385b90d794Sdyoung IFADDR_FOREACH(ia, ifp) { 5396adffbf9Sitojun if (ia->ifa_addr == NULL) 5406adffbf9Sitojun continue; 5416adffbf9Sitojun af = ia->ifa_addr->sa_family; 5426adffbf9Sitojun if (af != AF_INET && af != AF_INET6) 5436adffbf9Sitojun continue; 5446adffbf9Sitojun if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) 5456adffbf9Sitojun continue; 5466adffbf9Sitojun if ((flags & PFI_AFLAG_BROADCAST) && 5476adffbf9Sitojun !(ifp->if_flags & IFF_BROADCAST)) 5486adffbf9Sitojun continue; 5496adffbf9Sitojun if ((flags & PFI_AFLAG_PEER) && 5506adffbf9Sitojun !(ifp->if_flags & IFF_POINTOPOINT)) 5516adffbf9Sitojun continue; 5526adffbf9Sitojun if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && 5536adffbf9Sitojun IN6_IS_ADDR_LINKLOCAL( 5546adffbf9Sitojun &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr)) 5556adffbf9Sitojun continue; 5566adffbf9Sitojun if (flags & PFI_AFLAG_NOALIAS) { 5576adffbf9Sitojun if (af == AF_INET && got4) 5586adffbf9Sitojun continue; 5596adffbf9Sitojun if (af == AF_INET6 && got6) 5606adffbf9Sitojun continue; 5616adffbf9Sitojun } 5626adffbf9Sitojun if (af == AF_INET) 5636adffbf9Sitojun got4 = 1; 564da186141Syamt else if (af == AF_INET6) 5656adffbf9Sitojun got6 = 1; 5666adffbf9Sitojun net2 = net; 5676adffbf9Sitojun if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { 568fff57c55Syamt if (af == AF_INET) 5696adffbf9Sitojun net2 = pfi_unmask(&((struct sockaddr_in *) 5706adffbf9Sitojun ia->ifa_netmask)->sin_addr); 571fff57c55Syamt else if (af == AF_INET6) 5726adffbf9Sitojun net2 = pfi_unmask(&((struct sockaddr_in6 *) 5736adffbf9Sitojun ia->ifa_netmask)->sin6_addr); 5746adffbf9Sitojun } 5756adffbf9Sitojun if (af == AF_INET && net2 > 32) 5766adffbf9Sitojun net2 = 32; 5776adffbf9Sitojun if (flags & PFI_AFLAG_BROADCAST) 5786adffbf9Sitojun pfi_address_add(ia->ifa_broadaddr, af, net2); 5796adffbf9Sitojun else if (flags & PFI_AFLAG_PEER) 5806adffbf9Sitojun pfi_address_add(ia->ifa_dstaddr, af, net2); 5816adffbf9Sitojun else 5826adffbf9Sitojun pfi_address_add(ia->ifa_addr, af, net2); 5836adffbf9Sitojun } 5846adffbf9Sitojun } 5856adffbf9Sitojun 5866adffbf9Sitojun void 5876adffbf9Sitojun pfi_address_add(struct sockaddr *sa, int af, int net) 5886adffbf9Sitojun { 5896adffbf9Sitojun struct pfr_addr *p; 5906adffbf9Sitojun int i; 5916adffbf9Sitojun 5926adffbf9Sitojun if (pfi_buffer_cnt >= pfi_buffer_max) { 5936adffbf9Sitojun int new_max = pfi_buffer_max * 2; 5946adffbf9Sitojun 5956adffbf9Sitojun if (new_max > PFI_BUFFER_MAX) { 5966adffbf9Sitojun printf("pfi_address_add: address buffer full (%d/%d)\n", 5976adffbf9Sitojun pfi_buffer_cnt, PFI_BUFFER_MAX); 5986adffbf9Sitojun return; 5996adffbf9Sitojun } 6009c1c1ad1Scegger p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE, M_NOWAIT); 6016adffbf9Sitojun if (p == NULL) { 6026adffbf9Sitojun printf("pfi_address_add: no memory to grow buffer " 6036adffbf9Sitojun "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); 6046adffbf9Sitojun return; 6056adffbf9Sitojun } 60683510449Sdsl memcpy(p, pfi_buffer, pfi_buffer_cnt * sizeof(*pfi_buffer)); 6076adffbf9Sitojun /* no need to zero buffer */ 6086adffbf9Sitojun free(pfi_buffer, PFI_MTYPE); 6096adffbf9Sitojun pfi_buffer = p; 6106adffbf9Sitojun pfi_buffer_max = new_max; 6116adffbf9Sitojun } 6126adffbf9Sitojun if (af == AF_INET && net > 32) 6136adffbf9Sitojun net = 128; 6146adffbf9Sitojun p = pfi_buffer + pfi_buffer_cnt++; 6156adffbf9Sitojun bzero(p, sizeof(*p)); 6166adffbf9Sitojun p->pfra_af = af; 6176adffbf9Sitojun p->pfra_net = net; 6186adffbf9Sitojun if (af == AF_INET) 6196adffbf9Sitojun p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; 620fff57c55Syamt else if (af == AF_INET6) { 6216adffbf9Sitojun p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; 622fff57c55Syamt if (IN6_IS_SCOPE_EMBEDDABLE(&p->pfra_ip6addr)) 6236adffbf9Sitojun p->pfra_ip6addr.s6_addr16[1] = 0; 6246adffbf9Sitojun } 6256adffbf9Sitojun /* mask network address bits */ 6266adffbf9Sitojun if (net < 128) 62753524e44Schristos ((char *)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); 6286adffbf9Sitojun for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) 62953524e44Schristos ((char *)p)[i] = 0; 6306adffbf9Sitojun } 6316adffbf9Sitojun 6326adffbf9Sitojun void 6336adffbf9Sitojun pfi_dynaddr_remove(struct pf_addr_wrap *aw) 6346adffbf9Sitojun { 6356adffbf9Sitojun int s; 6366adffbf9Sitojun 6376adffbf9Sitojun if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 6386adffbf9Sitojun aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) 6396adffbf9Sitojun return; 6406adffbf9Sitojun 6416adffbf9Sitojun s = splsoftnet(); 642fff57c55Syamt TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry); 643fff57c55Syamt pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE); 6446adffbf9Sitojun aw->p.dyn->pfid_kif = NULL; 6456adffbf9Sitojun pfr_detach_table(aw->p.dyn->pfid_kt); 6466adffbf9Sitojun aw->p.dyn->pfid_kt = NULL; 6476adffbf9Sitojun pool_put(&pfi_addr_pl, aw->p.dyn); 6486adffbf9Sitojun aw->p.dyn = NULL; 6496adffbf9Sitojun splx(s); 6506adffbf9Sitojun } 6516adffbf9Sitojun 6526adffbf9Sitojun void 6536adffbf9Sitojun pfi_dynaddr_copyout(struct pf_addr_wrap *aw) 6546adffbf9Sitojun { 6556adffbf9Sitojun if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 6566adffbf9Sitojun aw->p.dyn->pfid_kif == NULL) 6576adffbf9Sitojun return; 6586adffbf9Sitojun aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; 6596adffbf9Sitojun } 6606adffbf9Sitojun 6616adffbf9Sitojun void 6626adffbf9Sitojun pfi_kifaddr_update(void *v) 6636adffbf9Sitojun { 6646adffbf9Sitojun int s; 665fff57c55Syamt struct pfi_kif *kif = (struct pfi_kif *)v; 6666adffbf9Sitojun 6676adffbf9Sitojun s = splsoftnet(); 6686adffbf9Sitojun pfi_update++; 669fff57c55Syamt pfi_kif_update(kif); 6706adffbf9Sitojun splx(s); 6716adffbf9Sitojun } 6726adffbf9Sitojun 6736adffbf9Sitojun int 6746adffbf9Sitojun pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) 6756adffbf9Sitojun { 6766adffbf9Sitojun return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); 6776adffbf9Sitojun } 6786adffbf9Sitojun 6796adffbf9Sitojun void 6806adffbf9Sitojun pfi_fill_oldstatus(struct pf_status *pfs) 6816adffbf9Sitojun { 682fff57c55Syamt struct pfi_kif *p; 683fff57c55Syamt struct pfi_kif_cmp key; 6846adffbf9Sitojun int i, j, k, s; 6856adffbf9Sitojun 6866adffbf9Sitojun strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name)); 6876adffbf9Sitojun s = splsoftnet(); 688fff57c55Syamt p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key); 6896adffbf9Sitojun if (p == NULL) { 6906adffbf9Sitojun splx(s); 6916adffbf9Sitojun return; 6926adffbf9Sitojun } 6936adffbf9Sitojun bzero(pfs->pcounters, sizeof(pfs->pcounters)); 6946adffbf9Sitojun bzero(pfs->bcounters, sizeof(pfs->bcounters)); 6956adffbf9Sitojun for (i = 0; i < 2; i++) 6966adffbf9Sitojun for (j = 0; j < 2; j++) 6976adffbf9Sitojun for (k = 0; k < 2; k++) { 6986adffbf9Sitojun pfs->pcounters[i][j][k] = 6996adffbf9Sitojun p->pfik_packets[i][j][k]; 7006adffbf9Sitojun pfs->bcounters[i][j] += 7016adffbf9Sitojun p->pfik_bytes[i][j][k]; 7026adffbf9Sitojun } 7036adffbf9Sitojun splx(s); 7046adffbf9Sitojun } 7056adffbf9Sitojun 7066adffbf9Sitojun int 707fff57c55Syamt pfi_clr_istats(const char *name) 7086adffbf9Sitojun { 7096adffbf9Sitojun struct pfi_kif *p; 710fff57c55Syamt int s; 7116adffbf9Sitojun 71297107414Speter s = splsoftnet(); 7136adffbf9Sitojun RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 714fff57c55Syamt if (pfi_skip_if(name, p)) 7156adffbf9Sitojun continue; 7166adffbf9Sitojun bzero(p->pfik_packets, sizeof(p->pfik_packets)); 7176adffbf9Sitojun bzero(p->pfik_bytes, sizeof(p->pfik_bytes)); 718fff57c55Syamt p->pfik_tzero = time_second; 7196adffbf9Sitojun } 7206adffbf9Sitojun splx(s); 721fff57c55Syamt 7226adffbf9Sitojun return (0); 7236adffbf9Sitojun } 7246adffbf9Sitojun 7256adffbf9Sitojun int 726fff57c55Syamt pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size) 727fff57c55Syamt { 728fff57c55Syamt struct pfi_kif *p, *nextp; 729fff57c55Syamt int s, n = 0; 730fff57c55Syamt 731fff57c55Syamt s = splsoftnet(); 732fff57c55Syamt for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) { 733fff57c55Syamt nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p); 734fff57c55Syamt if (pfi_skip_if(name, p)) 735fff57c55Syamt continue; 736fff57c55Syamt if (*size > n++) { 737fff57c55Syamt if (!p->pfik_tzero) 738fff57c55Syamt p->pfik_tzero = time_second; 739fff57c55Syamt pfi_kif_ref(p, PFI_KIF_REF_RULE); 740fff57c55Syamt if (copyout(p, buf++, sizeof(*buf))) { 741fff57c55Syamt pfi_kif_unref(p, PFI_KIF_REF_RULE); 742fff57c55Syamt splx(s); 743fff57c55Syamt return (EFAULT); 744fff57c55Syamt } 745fff57c55Syamt nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p); 746fff57c55Syamt pfi_kif_unref(p, PFI_KIF_REF_RULE); 747fff57c55Syamt } 748fff57c55Syamt } 749fff57c55Syamt splx(s); 750fff57c55Syamt *size = n; 751fff57c55Syamt return (0); 752fff57c55Syamt } 753fff57c55Syamt 754fff57c55Syamt int 755fff57c55Syamt pfi_skip_if(const char *filter, struct pfi_kif *p) 756fff57c55Syamt { 757fff57c55Syamt int n; 758fff57c55Syamt 759fff57c55Syamt if (filter == NULL || !*filter) 760fff57c55Syamt return (0); 761fff57c55Syamt if (!strcmp(p->pfik_name, filter)) 762fff57c55Syamt return (0); /* exact match */ 763fff57c55Syamt n = strlen(filter); 764fff57c55Syamt if (n < 1 || n >= IFNAMSIZ) 765fff57c55Syamt return (1); /* sanity check */ 766fff57c55Syamt if (filter[n-1] >= '0' && filter[n-1] <= '9') 767fff57c55Syamt return (1); /* only do exact match in that case */ 768fff57c55Syamt if (strncmp(p->pfik_name, filter, n)) 769fff57c55Syamt return (1); /* prefix doesn't match */ 770fff57c55Syamt return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9'); 771fff57c55Syamt } 772fff57c55Syamt 773fff57c55Syamt int 77497107414Speter pfi_set_flags(const char *name, int flags) 77597107414Speter { 77697107414Speter struct pfi_kif *p; 77797107414Speter int s; 77897107414Speter 77997107414Speter s = splsoftnet(); 78097107414Speter RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 781fff57c55Syamt if (pfi_skip_if(name, p)) 78297107414Speter continue; 78397107414Speter p->pfik_flags |= flags; 78497107414Speter } 78597107414Speter splx(s); 78697107414Speter return (0); 78797107414Speter } 78897107414Speter 78997107414Speter int 79097107414Speter pfi_clear_flags(const char *name, int flags) 79197107414Speter { 79297107414Speter struct pfi_kif *p; 79397107414Speter int s; 79497107414Speter 79597107414Speter s = splsoftnet(); 79697107414Speter RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 797fff57c55Syamt if (pfi_skip_if(name, p)) 79897107414Speter continue; 79997107414Speter p->pfik_flags &= ~flags; 80097107414Speter } 80197107414Speter splx(s); 80297107414Speter return (0); 80397107414Speter } 80497107414Speter 8056adffbf9Sitojun /* from pf_print_state.c */ 8066adffbf9Sitojun int 8076adffbf9Sitojun pfi_unmask(void *addr) 8086adffbf9Sitojun { 8096adffbf9Sitojun struct pf_addr *m = addr; 8106adffbf9Sitojun int i = 31, j = 0, b = 0; 8116adffbf9Sitojun u_int32_t tmp; 8126adffbf9Sitojun 8136adffbf9Sitojun while (j < 4 && m->addr32[j] == 0xffffffff) { 8146adffbf9Sitojun b += 32; 8156adffbf9Sitojun j++; 8166adffbf9Sitojun } 8176adffbf9Sitojun if (j < 4) { 8186adffbf9Sitojun tmp = ntohl(m->addr32[j]); 8196adffbf9Sitojun for (i = 31; tmp & (1 << i); --i) 8206adffbf9Sitojun b++; 8216adffbf9Sitojun } 8226adffbf9Sitojun return (b); 8236adffbf9Sitojun } 8246adffbf9Sitojun 825fff57c55Syamt #ifdef __NetBSD__ 826fff57c55Syamt static void 827fff57c55Syamt pfi_copy_group(char *dest, const char *src, ssize_t sz) 8286adffbf9Sitojun { 829fff57c55Syamt while (sz > 1 && *src && !(*src >= '0' && *src <= '9')) { 830fff57c55Syamt *dest++ = *src++; 831fff57c55Syamt sz--; 832fff57c55Syamt } 833fff57c55Syamt if (sz > 0) 834fff57c55Syamt *dest++ = '\0'; 835fff57c55Syamt } 836fff57c55Syamt 837fff57c55Syamt void 838fff57c55Syamt pfi_init_groups(struct ifnet *ifp) 839fff57c55Syamt { 840fff57c55Syamt char group[IFNAMSIZ]; 841fff57c55Syamt 842fff57c55Syamt if_init_groups(ifp); 843fff57c55Syamt if_addgroup(ifp, IFG_ALL); 844fff57c55Syamt 845fff57c55Syamt pfi_copy_group(group, ifp->if_xname, sizeof(group)); 846fff57c55Syamt if_addgroup(ifp, group); 847fff57c55Syamt } 848fff57c55Syamt 849fff57c55Syamt void 850fff57c55Syamt pfi_destroy_groups(struct ifnet *ifp) 851fff57c55Syamt { 852fff57c55Syamt char group[IFNAMSIZ]; 853fff57c55Syamt 854fff57c55Syamt pfi_copy_group(group, ifp->if_xname, sizeof(group)); 855fff57c55Syamt if_delgroup(ifp, group); 856fff57c55Syamt 857fff57c55Syamt if_delgroup(ifp, IFG_ALL); 858fff57c55Syamt if_destroy_groups(ifp); 8596adffbf9Sitojun } 8606adffbf9Sitojun 8616adffbf9Sitojun int 862fff57c55Syamt pfil_ifnet_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 8636adffbf9Sitojun { 864fff57c55Syamt u_long cmd = (u_long)mp; 865fff57c55Syamt 866fff57c55Syamt switch (cmd) { 867fff57c55Syamt case PFIL_IFNET_ATTACH: 868fff57c55Syamt pfi_init_groups(ifp); 869fff57c55Syamt 870fff57c55Syamt pfi_attach_ifnet(ifp); 871da186141Syamt break; 872fff57c55Syamt case PFIL_IFNET_DETACH: 873fff57c55Syamt pfi_detach_ifnet(ifp); 874fff57c55Syamt 875fff57c55Syamt pfi_destroy_groups(ifp); 876fff57c55Syamt break; 877fff57c55Syamt default: 878fff57c55Syamt panic("pfil_ifnet_wrapper: unexpected cmd %lu", cmd); 879fff57c55Syamt } 880fff57c55Syamt 881fff57c55Syamt return (0); 882fff57c55Syamt } 883fff57c55Syamt 884fff57c55Syamt int 885fff57c55Syamt pfil_ifaddr_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 886fff57c55Syamt { 887fff57c55Syamt u_long cmd = (u_long)mp; 888fff57c55Syamt 889fff57c55Syamt switch (cmd) { 890fff57c55Syamt case SIOCSIFADDR: 891fff57c55Syamt case SIOCAIFADDR: 892fff57c55Syamt case SIOCDIFADDR: 893da186141Syamt #ifdef INET6 894fff57c55Syamt case SIOCAIFADDR_IN6: 895fff57c55Syamt case SIOCDIFADDR_IN6: 896da186141Syamt #endif /* INET6 */ 897fff57c55Syamt pfi_kifaddr_update(ifp->if_pf_kif); 898fff57c55Syamt break; 899da186141Syamt default: 900fff57c55Syamt panic("pfil_ifaddr_wrapper: unexpected ioctl %lu", cmd); 901fff57c55Syamt } 902fff57c55Syamt 903da186141Syamt return (0); 9046adffbf9Sitojun } 905fff57c55Syamt #endif /* __NetBSD__ */ 906