1 1.33 ozaki /* $NetBSD: pf_if.c,v 1.33 2017/03/14 09:03:08 ozaki-r Exp $ */ 2 1.16 yamt /* $OpenBSD: pf_if.c,v 1.47 2007/07/13 09:17:48 markus Exp $ */ 3 1.1 itojun 4 1.1 itojun /* 5 1.16 yamt * Copyright 2005 Henning Brauer <henning (at) openbsd.org> 6 1.16 yamt * Copyright 2005 Ryan McBride <mcbride (at) openbsd.org> 7 1.1 itojun * Copyright (c) 2001 Daniel Hartmeier 8 1.1 itojun * Copyright (c) 2003 Cedric Berger 9 1.1 itojun * All rights reserved. 10 1.1 itojun * 11 1.1 itojun * Redistribution and use in source and binary forms, with or without 12 1.1 itojun * modification, are permitted provided that the following conditions 13 1.1 itojun * are met: 14 1.1 itojun * 15 1.1 itojun * - Redistributions of source code must retain the above copyright 16 1.1 itojun * notice, this list of conditions and the following disclaimer. 17 1.1 itojun * - Redistributions in binary form must reproduce the above 18 1.1 itojun * copyright notice, this list of conditions and the following 19 1.1 itojun * disclaimer in the documentation and/or other materials provided 20 1.1 itojun * with the distribution. 21 1.1 itojun * 22 1.1 itojun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 1.1 itojun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 1.1 itojun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 1.1 itojun * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 1.1 itojun * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 1.1 itojun * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 1.1 itojun * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 1.1 itojun * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 1.1 itojun * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.1 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 1.1 itojun * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 1.1 itojun * POSSIBILITY OF SUCH DAMAGE. 34 1.1 itojun */ 35 1.1 itojun 36 1.14 lukem #include <sys/cdefs.h> 37 1.33 ozaki __KERNEL_RCSID(0, "$NetBSD: pf_if.c,v 1.33 2017/03/14 09:03:08 ozaki-r Exp $"); 38 1.14 lukem 39 1.2 itojun #ifdef _KERNEL_OPT 40 1.2 itojun #include "opt_inet.h" 41 1.2 itojun #endif 42 1.2 itojun 43 1.1 itojun #include <sys/param.h> 44 1.1 itojun #include <sys/systm.h> 45 1.1 itojun #include <sys/mbuf.h> 46 1.1 itojun #include <sys/filio.h> 47 1.1 itojun #include <sys/socket.h> 48 1.1 itojun #include <sys/socketvar.h> 49 1.1 itojun #include <sys/kernel.h> 50 1.1 itojun #include <sys/device.h> 51 1.1 itojun #include <sys/time.h> 52 1.1 itojun 53 1.1 itojun #include <net/if.h> 54 1.1 itojun #include <net/if_types.h> 55 1.1 itojun 56 1.1 itojun #include <netinet/in.h> 57 1.1 itojun #include <netinet/in_var.h> 58 1.1 itojun #include <netinet/in_systm.h> 59 1.1 itojun #include <netinet/ip.h> 60 1.1 itojun #include <netinet/ip_var.h> 61 1.1 itojun 62 1.1 itojun #include <net/pfvar.h> 63 1.1 itojun 64 1.1 itojun #ifdef INET6 65 1.1 itojun #include <netinet/ip6.h> 66 1.1 itojun #endif /* INET6 */ 67 1.1 itojun 68 1.16 yamt struct pfi_kif *pfi_all = NULL; 69 1.16 yamt struct pool pfi_addr_pl; 70 1.1 itojun struct pfi_ifhead pfi_ifs; 71 1.1 itojun long pfi_update = 1; 72 1.1 itojun struct pfr_addr *pfi_buffer; 73 1.1 itojun int pfi_buffer_cnt; 74 1.1 itojun int pfi_buffer_max; 75 1.1 itojun 76 1.16 yamt void pfi_kif_update(struct pfi_kif *); 77 1.16 yamt void pfi_dynaddr_update(struct pfi_dynaddr *dyn); 78 1.1 itojun void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, 79 1.1 itojun int, int); 80 1.16 yamt void pfi_kifaddr_update(void *); 81 1.1 itojun void pfi_instance_add(struct ifnet *, int, int); 82 1.1 itojun void pfi_address_add(struct sockaddr *, int, int); 83 1.1 itojun int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); 84 1.16 yamt int pfi_skip_if(const char *, struct pfi_kif *); 85 1.1 itojun int pfi_unmask(void *); 86 1.16 yamt #ifdef __NetBSD__ 87 1.16 yamt void pfi_init_groups(struct ifnet *); 88 1.16 yamt void pfi_destroy_groups(struct ifnet *); 89 1.16 yamt 90 1.32 christos void pfil_ifnet_wrapper(void *, u_long, void *); 91 1.32 christos void pfil_ifaddr_wrapper(void *, u_long, void *); 92 1.16 yamt #endif 93 1.1 itojun 94 1.1 itojun RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 95 1.1 itojun RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 96 1.1 itojun 97 1.1 itojun #define PFI_BUFFER_MAX 0x10000 98 1.1 itojun #define PFI_MTYPE M_IFADDR 99 1.1 itojun 100 1.1 itojun void 101 1.1 itojun pfi_initialize(void) 102 1.1 itojun { 103 1.27 ozaki int s; 104 1.28 ozaki int bound; 105 1.27 ozaki 106 1.16 yamt if (pfi_all != NULL) /* already initialized */ 107 1.1 itojun return; 108 1.1 itojun 109 1.12 ad #ifdef __NetBSD__ 110 1.12 ad pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 111 1.12 ad "pfiaddrpl", &pool_allocator_nointr, IPL_NONE); 112 1.12 ad #else 113 1.1 itojun pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 114 1.1 itojun "pfiaddrpl", &pool_allocator_nointr); 115 1.16 yamt #endif /* !__NetBSD__ */ 116 1.1 itojun pfi_buffer_max = 64; 117 1.1 itojun pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer), 118 1.1 itojun PFI_MTYPE, M_WAITOK); 119 1.16 yamt 120 1.16 yamt if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL) 121 1.16 yamt panic("pfi_kif_get for pfi_all failed"); 122 1.16 yamt 123 1.16 yamt #ifdef __NetBSD__ 124 1.25 rmind ifnet_t *ifp; 125 1.28 ozaki bound = curlwp_bind(); 126 1.27 ozaki s = pserialize_read_enter(); 127 1.27 ozaki IFNET_READER_FOREACH(ifp) { 128 1.27 ozaki struct psref psref; 129 1.33 ozaki if_acquire(ifp, &psref); 130 1.27 ozaki pserialize_read_exit(s); 131 1.27 ozaki 132 1.25 rmind pfi_init_groups(ifp); 133 1.25 rmind pfi_attach_ifnet(ifp); 134 1.27 ozaki 135 1.27 ozaki s = pserialize_read_enter(); 136 1.33 ozaki if_release(ifp, &psref); 137 1.16 yamt } 138 1.27 ozaki pserialize_read_exit(s); 139 1.28 ozaki curlwp_bindx(bound); 140 1.16 yamt 141 1.32 christos pfil_add_ihook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, if_pfil); 142 1.32 christos pfil_add_ihook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, if_pfil); 143 1.16 yamt #endif /* __NetBSD__ */ 144 1.1 itojun } 145 1.1 itojun 146 1.21 ahoka #ifdef _MODULE 147 1.21 ahoka void 148 1.21 ahoka pfi_destroy(void) 149 1.21 ahoka { 150 1.21 ahoka struct pfi_kif *p; 151 1.26 rmind ifnet_t *ifp; 152 1.27 ozaki int s; 153 1.28 ozaki int bound; 154 1.21 ahoka 155 1.32 christos pfil_remove_ihook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, if_pfil); 156 1.32 christos pfil_remove_ihook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, if_pfil); 157 1.21 ahoka 158 1.28 ozaki bound = curlwp_bind(); 159 1.27 ozaki s = pserialize_read_enter(); 160 1.27 ozaki IFNET_READER_FOREACH(ifp) { 161 1.27 ozaki struct psref psref; 162 1.33 ozaki if_acquire(ifp, &psref); 163 1.27 ozaki pserialize_read_exit(s); 164 1.27 ozaki 165 1.26 rmind pfi_detach_ifnet(ifp); 166 1.26 rmind pfi_destroy_groups(ifp); 167 1.27 ozaki 168 1.27 ozaki s = pserialize_read_enter(); 169 1.33 ozaki if_release(ifp, &psref); 170 1.21 ahoka } 171 1.27 ozaki pserialize_read_exit(s); 172 1.28 ozaki curlwp_bindx(bound); 173 1.21 ahoka 174 1.21 ahoka while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) { 175 1.21 ahoka RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 176 1.21 ahoka free(p, PFI_MTYPE); 177 1.21 ahoka } 178 1.21 ahoka 179 1.21 ahoka pool_destroy(&pfi_addr_pl); 180 1.21 ahoka 181 1.21 ahoka free(pfi_buffer, PFI_MTYPE); 182 1.21 ahoka } 183 1.21 ahoka #endif /* _MODULE */ 184 1.21 ahoka 185 1.16 yamt struct pfi_kif * 186 1.16 yamt pfi_kif_get(const char *kif_name) 187 1.16 yamt { 188 1.16 yamt struct pfi_kif *kif; 189 1.16 yamt struct pfi_kif_cmp s; 190 1.16 yamt 191 1.16 yamt bzero(&s, sizeof(s)); 192 1.16 yamt strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name)); 193 1.16 yamt if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL) 194 1.16 yamt return (kif); 195 1.16 yamt 196 1.16 yamt /* create new one */ 197 1.18 cegger if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT|M_ZERO)) == NULL) 198 1.16 yamt return (NULL); 199 1.16 yamt 200 1.16 yamt strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name)); 201 1.16 yamt #ifdef __NetBSD__ 202 1.16 yamt /* time_second is not valid yet */ 203 1.16 yamt kif->pfik_tzero = (time_second > 7200) ? time_second : 0; 204 1.16 yamt #else 205 1.16 yamt kif->pfik_tzero = time_second; 206 1.16 yamt #endif /* !__NetBSD__ */ 207 1.16 yamt TAILQ_INIT(&kif->pfik_dynaddrs); 208 1.16 yamt 209 1.16 yamt RB_INSERT(pfi_ifhead, &pfi_ifs, kif); 210 1.16 yamt return (kif); 211 1.16 yamt } 212 1.16 yamt 213 1.16 yamt void 214 1.16 yamt pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what) 215 1.16 yamt { 216 1.16 yamt switch (what) { 217 1.16 yamt case PFI_KIF_REF_RULE: 218 1.16 yamt kif->pfik_rules++; 219 1.16 yamt break; 220 1.16 yamt case PFI_KIF_REF_STATE: 221 1.16 yamt kif->pfik_states++; 222 1.16 yamt break; 223 1.16 yamt default: 224 1.16 yamt panic("pfi_kif_ref with unknown type"); 225 1.16 yamt } 226 1.16 yamt } 227 1.3 itojun 228 1.1 itojun void 229 1.16 yamt pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what) 230 1.16 yamt { 231 1.16 yamt if (kif == NULL) 232 1.16 yamt return; 233 1.16 yamt 234 1.16 yamt switch (what) { 235 1.16 yamt case PFI_KIF_REF_NONE: 236 1.16 yamt break; 237 1.16 yamt case PFI_KIF_REF_RULE: 238 1.16 yamt if (kif->pfik_rules <= 0) { 239 1.16 yamt printf("pfi_kif_unref: rules refcount <= 0\n"); 240 1.16 yamt return; 241 1.16 yamt } 242 1.16 yamt kif->pfik_rules--; 243 1.16 yamt break; 244 1.16 yamt case PFI_KIF_REF_STATE: 245 1.16 yamt if (kif->pfik_states <= 0) { 246 1.16 yamt printf("pfi_kif_unref: state refcount <= 0\n"); 247 1.16 yamt return; 248 1.16 yamt } 249 1.16 yamt kif->pfik_states--; 250 1.16 yamt break; 251 1.16 yamt default: 252 1.16 yamt panic("pfi_kif_unref with unknown type"); 253 1.16 yamt } 254 1.16 yamt 255 1.16 yamt if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all) 256 1.16 yamt return; 257 1.16 yamt 258 1.16 yamt if (kif->pfik_rules || kif->pfik_states) 259 1.16 yamt return; 260 1.16 yamt 261 1.16 yamt RB_REMOVE(pfi_ifhead, &pfi_ifs, kif); 262 1.16 yamt free(kif, PFI_MTYPE); 263 1.16 yamt } 264 1.16 yamt 265 1.16 yamt int 266 1.16 yamt pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif) 267 1.1 itojun { 268 1.16 yamt struct ifg_list *p; 269 1.16 yamt 270 1.16 yamt if (rule_kif == NULL || rule_kif == packet_kif) 271 1.16 yamt return (1); 272 1.16 yamt 273 1.16 yamt if (rule_kif->pfik_group != NULL) { 274 1.16 yamt struct ifg_list_head *ifgh = 275 1.16 yamt if_get_groups(packet_kif->pfik_ifp); 276 1.16 yamt 277 1.16 yamt TAILQ_FOREACH(p, ifgh, ifgl_next) 278 1.16 yamt if (p->ifgl_group == rule_kif->pfik_group) 279 1.16 yamt return (1); 280 1.16 yamt } 281 1.16 yamt 282 1.16 yamt return (0); 283 1.1 itojun } 284 1.1 itojun 285 1.1 itojun void 286 1.1 itojun pfi_attach_ifnet(struct ifnet *ifp) 287 1.1 itojun { 288 1.16 yamt struct pfi_kif *kif; 289 1.16 yamt int s; 290 1.1 itojun 291 1.1 itojun pfi_initialize(); 292 1.1 itojun s = splsoftnet(); 293 1.1 itojun pfi_update++; 294 1.16 yamt if ((kif = pfi_kif_get(ifp->if_xname)) == NULL) 295 1.16 yamt panic("pfi_kif_get failed"); 296 1.16 yamt 297 1.16 yamt kif->pfik_ifp = ifp; 298 1.16 yamt ifp->if_pf_kif = kif; 299 1.16 yamt 300 1.16 yamt #ifndef __NetBSD__ 301 1.16 yamt if ((kif->pfik_ah_cookie = hook_establish(ifp->if_addrhooks, 1, 302 1.16 yamt pfi_kifaddr_update, kif)) == NULL) 303 1.16 yamt panic("pfi_attach_ifnet: cannot allocate '%s' address hook", 304 1.16 yamt ifp->if_xname); 305 1.16 yamt #endif /* !__NetBSD__ */ 306 1.16 yamt 307 1.16 yamt pfi_kif_update(kif); 308 1.1 itojun 309 1.1 itojun splx(s); 310 1.1 itojun } 311 1.1 itojun 312 1.1 itojun void 313 1.1 itojun pfi_detach_ifnet(struct ifnet *ifp) 314 1.1 itojun { 315 1.16 yamt int s; 316 1.16 yamt struct pfi_kif *kif; 317 1.1 itojun 318 1.16 yamt if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL) 319 1.16 yamt return; 320 1.1 itojun 321 1.1 itojun s = splsoftnet(); 322 1.1 itojun pfi_update++; 323 1.16 yamt #ifndef __NetBSD__ 324 1.16 yamt hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie); 325 1.16 yamt #endif /* !__NetBSD__ */ 326 1.16 yamt pfi_kif_update(kif); 327 1.16 yamt 328 1.16 yamt kif->pfik_ifp = NULL; 329 1.16 yamt ifp->if_pf_kif = NULL; 330 1.16 yamt pfi_kif_unref(kif, PFI_KIF_REF_NONE); 331 1.1 itojun splx(s); 332 1.1 itojun } 333 1.1 itojun 334 1.16 yamt void 335 1.16 yamt pfi_attach_ifgroup(struct ifg_group *ifg) 336 1.1 itojun { 337 1.16 yamt struct pfi_kif *kif; 338 1.1 itojun int s; 339 1.1 itojun 340 1.16 yamt pfi_initialize(); 341 1.1 itojun s = splsoftnet(); 342 1.16 yamt pfi_update++; 343 1.16 yamt if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL) 344 1.16 yamt panic("pfi_kif_get failed"); 345 1.1 itojun 346 1.16 yamt kif->pfik_group = ifg; 347 1.16 yamt ifg->ifg_pf_kif = kif; 348 1.1 itojun 349 1.16 yamt splx(s); 350 1.1 itojun } 351 1.1 itojun 352 1.1 itojun void 353 1.16 yamt pfi_detach_ifgroup(struct ifg_group *ifg) 354 1.1 itojun { 355 1.16 yamt int s; 356 1.16 yamt struct pfi_kif *kif; 357 1.16 yamt 358 1.16 yamt if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL) 359 1.1 itojun return; 360 1.16 yamt 361 1.16 yamt s = splsoftnet(); 362 1.16 yamt pfi_update++; 363 1.16 yamt 364 1.16 yamt kif->pfik_group = NULL; 365 1.16 yamt ifg->ifg_pf_kif = NULL; 366 1.16 yamt pfi_kif_unref(kif, PFI_KIF_REF_NONE); 367 1.16 yamt splx(s); 368 1.1 itojun } 369 1.1 itojun 370 1.1 itojun void 371 1.16 yamt pfi_group_change(const char *group) 372 1.1 itojun { 373 1.16 yamt struct pfi_kif *kif; 374 1.16 yamt int s; 375 1.16 yamt 376 1.16 yamt s = splsoftnet(); 377 1.16 yamt pfi_update++; 378 1.16 yamt if ((kif = pfi_kif_get(group)) == NULL) 379 1.16 yamt panic("pfi_kif_get failed"); 380 1.16 yamt 381 1.16 yamt pfi_kif_update(kif); 382 1.16 yamt 383 1.16 yamt splx(s); 384 1.1 itojun } 385 1.1 itojun 386 1.16 yamt int 387 1.16 yamt pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) 388 1.1 itojun { 389 1.16 yamt switch (af) { 390 1.16 yamt #ifdef INET 391 1.16 yamt case AF_INET: 392 1.16 yamt switch (dyn->pfid_acnt4) { 393 1.16 yamt case 0: 394 1.16 yamt return (0); 395 1.16 yamt case 1: 396 1.16 yamt return (PF_MATCHA(0, &dyn->pfid_addr4, 397 1.16 yamt &dyn->pfid_mask4, a, AF_INET)); 398 1.16 yamt default: 399 1.16 yamt return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); 400 1.16 yamt } 401 1.16 yamt break; 402 1.16 yamt #endif /* INET */ 403 1.16 yamt #ifdef INET6 404 1.16 yamt case AF_INET6: 405 1.16 yamt switch (dyn->pfid_acnt6) { 406 1.16 yamt case 0: 407 1.16 yamt return (0); 408 1.16 yamt case 1: 409 1.16 yamt return (PF_MATCHA(0, &dyn->pfid_addr6, 410 1.16 yamt &dyn->pfid_mask6, a, AF_INET6)); 411 1.16 yamt default: 412 1.16 yamt return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); 413 1.16 yamt } 414 1.16 yamt break; 415 1.16 yamt #endif /* INET6 */ 416 1.16 yamt default: 417 1.16 yamt return (0); 418 1.1 itojun } 419 1.1 itojun } 420 1.1 itojun 421 1.1 itojun int 422 1.1 itojun pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) 423 1.1 itojun { 424 1.1 itojun struct pfi_dynaddr *dyn; 425 1.1 itojun char tblname[PF_TABLE_NAME_SIZE]; 426 1.1 itojun struct pf_ruleset *ruleset = NULL; 427 1.1 itojun int s, rv = 0; 428 1.1 itojun 429 1.1 itojun if (aw->type != PF_ADDR_DYNIFTL) 430 1.1 itojun return (0); 431 1.16 yamt if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL) 432 1.1 itojun return (1); 433 1.1 itojun bzero(dyn, sizeof(*dyn)); 434 1.1 itojun 435 1.1 itojun s = splsoftnet(); 436 1.16 yamt if (!strcmp(aw->v.ifname, "self")) 437 1.16 yamt dyn->pfid_kif = pfi_kif_get(IFG_ALL); 438 1.16 yamt else 439 1.16 yamt dyn->pfid_kif = pfi_kif_get(aw->v.ifname); 440 1.16 yamt if (dyn->pfid_kif == NULL) { 441 1.16 yamt rv = 1; 442 1.16 yamt goto _bad; 443 1.16 yamt } 444 1.16 yamt pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE); 445 1.1 itojun 446 1.1 itojun dyn->pfid_net = pfi_unmask(&aw->v.a.mask); 447 1.1 itojun if (af == AF_INET && dyn->pfid_net == 32) 448 1.1 itojun dyn->pfid_net = 128; 449 1.1 itojun strlcpy(tblname, aw->v.ifname, sizeof(tblname)); 450 1.1 itojun if (aw->iflags & PFI_AFLAG_NETWORK) 451 1.1 itojun strlcat(tblname, ":network", sizeof(tblname)); 452 1.1 itojun if (aw->iflags & PFI_AFLAG_BROADCAST) 453 1.1 itojun strlcat(tblname, ":broadcast", sizeof(tblname)); 454 1.1 itojun if (aw->iflags & PFI_AFLAG_PEER) 455 1.1 itojun strlcat(tblname, ":peer", sizeof(tblname)); 456 1.1 itojun if (aw->iflags & PFI_AFLAG_NOALIAS) 457 1.1 itojun strlcat(tblname, ":0", sizeof(tblname)); 458 1.1 itojun if (dyn->pfid_net != 128) 459 1.1 itojun snprintf(tblname + strlen(tblname), 460 1.1 itojun sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); 461 1.16 yamt if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) { 462 1.16 yamt rv = 1; 463 1.16 yamt goto _bad; 464 1.16 yamt } 465 1.16 yamt 466 1.16 yamt if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) { 467 1.16 yamt rv = 1; 468 1.16 yamt goto _bad; 469 1.16 yamt } 470 1.1 itojun 471 1.1 itojun dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; 472 1.1 itojun dyn->pfid_iflags = aw->iflags; 473 1.1 itojun dyn->pfid_af = af; 474 1.1 itojun 475 1.16 yamt TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry); 476 1.1 itojun aw->p.dyn = dyn; 477 1.16 yamt pfi_kif_update(dyn->pfid_kif); 478 1.1 itojun splx(s); 479 1.1 itojun return (0); 480 1.1 itojun 481 1.1 itojun _bad: 482 1.1 itojun if (dyn->pfid_kt != NULL) 483 1.1 itojun pfr_detach_table(dyn->pfid_kt); 484 1.1 itojun if (ruleset != NULL) 485 1.1 itojun pf_remove_if_empty_ruleset(ruleset); 486 1.1 itojun if (dyn->pfid_kif != NULL) 487 1.16 yamt pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE); 488 1.1 itojun pool_put(&pfi_addr_pl, dyn); 489 1.1 itojun splx(s); 490 1.1 itojun return (rv); 491 1.1 itojun } 492 1.1 itojun 493 1.1 itojun void 494 1.16 yamt pfi_kif_update(struct pfi_kif *kif) 495 1.16 yamt { 496 1.16 yamt struct ifg_list *ifgl; 497 1.16 yamt struct pfi_dynaddr *p; 498 1.16 yamt 499 1.16 yamt /* update all dynaddr */ 500 1.16 yamt TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry) 501 1.16 yamt pfi_dynaddr_update(p); 502 1.16 yamt 503 1.16 yamt /* again for all groups kif is member of */ 504 1.16 yamt if (kif->pfik_ifp != NULL) { 505 1.16 yamt struct ifg_list_head *ifgh = if_get_groups(kif->pfik_ifp); 506 1.16 yamt 507 1.16 yamt TAILQ_FOREACH(ifgl, ifgh, ifgl_next) 508 1.16 yamt pfi_kif_update((struct pfi_kif *) 509 1.16 yamt ifgl->ifgl_group->ifg_pf_kif); 510 1.16 yamt } 511 1.16 yamt } 512 1.16 yamt 513 1.16 yamt void 514 1.16 yamt pfi_dynaddr_update(struct pfi_dynaddr *dyn) 515 1.1 itojun { 516 1.9 peter struct pfi_kif *kif; 517 1.9 peter struct pfr_ktable *kt; 518 1.1 itojun 519 1.9 peter if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL) 520 1.1 itojun panic("pfi_dynaddr_update"); 521 1.9 peter 522 1.9 peter kif = dyn->pfid_kif; 523 1.9 peter kt = dyn->pfid_kt; 524 1.16 yamt 525 1.1 itojun if (kt->pfrkt_larg != pfi_update) { 526 1.1 itojun /* this table needs to be brought up-to-date */ 527 1.1 itojun pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); 528 1.1 itojun kt->pfrkt_larg = pfi_update; 529 1.1 itojun } 530 1.1 itojun pfr_dynaddr_update(kt, dyn); 531 1.1 itojun } 532 1.1 itojun 533 1.1 itojun void 534 1.1 itojun pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) 535 1.1 itojun { 536 1.1 itojun int e, size2 = 0; 537 1.16 yamt struct ifg_member *ifgm; 538 1.1 itojun 539 1.1 itojun pfi_buffer_cnt = 0; 540 1.16 yamt 541 1.16 yamt if (kif->pfik_ifp != NULL) 542 1.1 itojun pfi_instance_add(kif->pfik_ifp, net, flags); 543 1.16 yamt else if (kif->pfik_group != NULL) 544 1.16 yamt TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next) 545 1.16 yamt pfi_instance_add(ifgm->ifgm_ifp, net, flags); 546 1.16 yamt 547 1.16 yamt if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2, 548 1.16 yamt NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK))) 549 1.1 itojun printf("pfi_table_update: cannot set %d new addresses " 550 1.1 itojun "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e); 551 1.1 itojun } 552 1.1 itojun 553 1.1 itojun void 554 1.1 itojun pfi_instance_add(struct ifnet *ifp, int net, int flags) 555 1.1 itojun { 556 1.1 itojun struct ifaddr *ia; 557 1.1 itojun int got4 = 0, got6 = 0; 558 1.1 itojun int net2, af; 559 1.31 ozaki int s; 560 1.1 itojun 561 1.1 itojun if (ifp == NULL) 562 1.1 itojun return; 563 1.31 ozaki 564 1.31 ozaki /* Depends on pfi_address_add doesn't sleep */ 565 1.31 ozaki s = pserialize_read_enter(); 566 1.30 ozaki IFADDR_READER_FOREACH(ia, ifp) { 567 1.1 itojun af = ia->ifa_addr->sa_family; 568 1.1 itojun if (af != AF_INET && af != AF_INET6) 569 1.1 itojun continue; 570 1.1 itojun if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) 571 1.1 itojun continue; 572 1.1 itojun if ((flags & PFI_AFLAG_BROADCAST) && 573 1.1 itojun !(ifp->if_flags & IFF_BROADCAST)) 574 1.1 itojun continue; 575 1.1 itojun if ((flags & PFI_AFLAG_PEER) && 576 1.1 itojun !(ifp->if_flags & IFF_POINTOPOINT)) 577 1.1 itojun continue; 578 1.1 itojun if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && 579 1.1 itojun IN6_IS_ADDR_LINKLOCAL( 580 1.1 itojun &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr)) 581 1.1 itojun continue; 582 1.1 itojun if (flags & PFI_AFLAG_NOALIAS) { 583 1.1 itojun if (af == AF_INET && got4) 584 1.1 itojun continue; 585 1.1 itojun if (af == AF_INET6 && got6) 586 1.1 itojun continue; 587 1.1 itojun } 588 1.1 itojun if (af == AF_INET) 589 1.1 itojun got4 = 1; 590 1.6 yamt else if (af == AF_INET6) 591 1.1 itojun got6 = 1; 592 1.1 itojun net2 = net; 593 1.1 itojun if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { 594 1.16 yamt if (af == AF_INET) 595 1.1 itojun net2 = pfi_unmask(&((struct sockaddr_in *) 596 1.1 itojun ia->ifa_netmask)->sin_addr); 597 1.16 yamt else if (af == AF_INET6) 598 1.1 itojun net2 = pfi_unmask(&((struct sockaddr_in6 *) 599 1.1 itojun ia->ifa_netmask)->sin6_addr); 600 1.1 itojun } 601 1.1 itojun if (af == AF_INET && net2 > 32) 602 1.1 itojun net2 = 32; 603 1.1 itojun if (flags & PFI_AFLAG_BROADCAST) 604 1.1 itojun pfi_address_add(ia->ifa_broadaddr, af, net2); 605 1.1 itojun else if (flags & PFI_AFLAG_PEER) 606 1.1 itojun pfi_address_add(ia->ifa_dstaddr, af, net2); 607 1.1 itojun else 608 1.1 itojun pfi_address_add(ia->ifa_addr, af, net2); 609 1.1 itojun } 610 1.31 ozaki pserialize_read_exit(s); 611 1.1 itojun } 612 1.1 itojun 613 1.1 itojun void 614 1.1 itojun pfi_address_add(struct sockaddr *sa, int af, int net) 615 1.1 itojun { 616 1.1 itojun struct pfr_addr *p; 617 1.1 itojun int i; 618 1.1 itojun 619 1.1 itojun if (pfi_buffer_cnt >= pfi_buffer_max) { 620 1.1 itojun int new_max = pfi_buffer_max * 2; 621 1.1 itojun 622 1.1 itojun if (new_max > PFI_BUFFER_MAX) { 623 1.1 itojun printf("pfi_address_add: address buffer full (%d/%d)\n", 624 1.1 itojun pfi_buffer_cnt, PFI_BUFFER_MAX); 625 1.1 itojun return; 626 1.1 itojun } 627 1.17 cegger p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE, M_NOWAIT); 628 1.1 itojun if (p == NULL) { 629 1.1 itojun printf("pfi_address_add: no memory to grow buffer " 630 1.1 itojun "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); 631 1.1 itojun return; 632 1.1 itojun } 633 1.20 dsl memcpy(p, pfi_buffer, pfi_buffer_cnt * sizeof(*pfi_buffer)); 634 1.1 itojun /* no need to zero buffer */ 635 1.1 itojun free(pfi_buffer, PFI_MTYPE); 636 1.1 itojun pfi_buffer = p; 637 1.1 itojun pfi_buffer_max = new_max; 638 1.1 itojun } 639 1.1 itojun if (af == AF_INET && net > 32) 640 1.1 itojun net = 128; 641 1.1 itojun p = pfi_buffer + pfi_buffer_cnt++; 642 1.1 itojun bzero(p, sizeof(*p)); 643 1.1 itojun p->pfra_af = af; 644 1.1 itojun p->pfra_net = net; 645 1.1 itojun if (af == AF_INET) 646 1.1 itojun p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; 647 1.16 yamt else if (af == AF_INET6) { 648 1.1 itojun p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; 649 1.16 yamt if (IN6_IS_SCOPE_EMBEDDABLE(&p->pfra_ip6addr)) 650 1.1 itojun p->pfra_ip6addr.s6_addr16[1] = 0; 651 1.1 itojun } 652 1.1 itojun /* mask network address bits */ 653 1.1 itojun if (net < 128) 654 1.11 christos ((char *)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); 655 1.1 itojun for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) 656 1.11 christos ((char *)p)[i] = 0; 657 1.1 itojun } 658 1.1 itojun 659 1.1 itojun void 660 1.1 itojun pfi_dynaddr_remove(struct pf_addr_wrap *aw) 661 1.1 itojun { 662 1.1 itojun int s; 663 1.1 itojun 664 1.1 itojun if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 665 1.1 itojun aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) 666 1.1 itojun return; 667 1.1 itojun 668 1.1 itojun s = splsoftnet(); 669 1.16 yamt TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry); 670 1.16 yamt pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE); 671 1.1 itojun aw->p.dyn->pfid_kif = NULL; 672 1.1 itojun pfr_detach_table(aw->p.dyn->pfid_kt); 673 1.1 itojun aw->p.dyn->pfid_kt = NULL; 674 1.1 itojun pool_put(&pfi_addr_pl, aw->p.dyn); 675 1.1 itojun aw->p.dyn = NULL; 676 1.1 itojun splx(s); 677 1.1 itojun } 678 1.1 itojun 679 1.1 itojun void 680 1.1 itojun pfi_dynaddr_copyout(struct pf_addr_wrap *aw) 681 1.1 itojun { 682 1.1 itojun if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 683 1.1 itojun aw->p.dyn->pfid_kif == NULL) 684 1.1 itojun return; 685 1.1 itojun aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; 686 1.1 itojun } 687 1.1 itojun 688 1.1 itojun void 689 1.1 itojun pfi_kifaddr_update(void *v) 690 1.1 itojun { 691 1.16 yamt int s; 692 1.16 yamt struct pfi_kif *kif = (struct pfi_kif *)v; 693 1.1 itojun 694 1.1 itojun s = splsoftnet(); 695 1.1 itojun pfi_update++; 696 1.16 yamt pfi_kif_update(kif); 697 1.1 itojun splx(s); 698 1.1 itojun } 699 1.1 itojun 700 1.1 itojun int 701 1.1 itojun pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) 702 1.1 itojun { 703 1.1 itojun return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); 704 1.1 itojun } 705 1.1 itojun 706 1.1 itojun void 707 1.1 itojun pfi_fill_oldstatus(struct pf_status *pfs) 708 1.1 itojun { 709 1.16 yamt struct pfi_kif *p; 710 1.16 yamt struct pfi_kif_cmp key; 711 1.16 yamt int i, j, k, s; 712 1.1 itojun 713 1.1 itojun strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name)); 714 1.1 itojun s = splsoftnet(); 715 1.16 yamt p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key); 716 1.1 itojun if (p == NULL) { 717 1.1 itojun splx(s); 718 1.1 itojun return; 719 1.1 itojun } 720 1.1 itojun bzero(pfs->pcounters, sizeof(pfs->pcounters)); 721 1.1 itojun bzero(pfs->bcounters, sizeof(pfs->bcounters)); 722 1.1 itojun for (i = 0; i < 2; i++) 723 1.1 itojun for (j = 0; j < 2; j++) 724 1.1 itojun for (k = 0; k < 2; k++) { 725 1.1 itojun pfs->pcounters[i][j][k] = 726 1.1 itojun p->pfik_packets[i][j][k]; 727 1.1 itojun pfs->bcounters[i][j] += 728 1.1 itojun p->pfik_bytes[i][j][k]; 729 1.1 itojun } 730 1.1 itojun splx(s); 731 1.1 itojun } 732 1.1 itojun 733 1.1 itojun int 734 1.16 yamt pfi_clr_istats(const char *name) 735 1.1 itojun { 736 1.1 itojun struct pfi_kif *p; 737 1.16 yamt int s; 738 1.1 itojun 739 1.1 itojun s = splsoftnet(); 740 1.1 itojun RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 741 1.16 yamt if (pfi_skip_if(name, p)) 742 1.1 itojun continue; 743 1.1 itojun bzero(p->pfik_packets, sizeof(p->pfik_packets)); 744 1.1 itojun bzero(p->pfik_bytes, sizeof(p->pfik_bytes)); 745 1.16 yamt p->pfik_tzero = time_second; 746 1.1 itojun } 747 1.1 itojun splx(s); 748 1.9 peter 749 1.9 peter return (0); 750 1.9 peter } 751 1.9 peter 752 1.9 peter int 753 1.16 yamt pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size) 754 1.1 itojun { 755 1.16 yamt struct pfi_kif *p, *nextp; 756 1.1 itojun int s, n = 0; 757 1.1 itojun 758 1.1 itojun s = splsoftnet(); 759 1.16 yamt for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) { 760 1.16 yamt nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p); 761 1.16 yamt if (pfi_skip_if(name, p)) 762 1.1 itojun continue; 763 1.1 itojun if (*size > n++) { 764 1.1 itojun if (!p->pfik_tzero) 765 1.6 yamt p->pfik_tzero = time_second; 766 1.16 yamt pfi_kif_ref(p, PFI_KIF_REF_RULE); 767 1.1 itojun if (copyout(p, buf++, sizeof(*buf))) { 768 1.16 yamt pfi_kif_unref(p, PFI_KIF_REF_RULE); 769 1.1 itojun splx(s); 770 1.1 itojun return (EFAULT); 771 1.1 itojun } 772 1.16 yamt nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p); 773 1.16 yamt pfi_kif_unref(p, PFI_KIF_REF_RULE); 774 1.1 itojun } 775 1.1 itojun } 776 1.1 itojun splx(s); 777 1.1 itojun *size = n; 778 1.1 itojun return (0); 779 1.1 itojun } 780 1.1 itojun 781 1.1 itojun int 782 1.16 yamt pfi_skip_if(const char *filter, struct pfi_kif *p) 783 1.1 itojun { 784 1.1 itojun int n; 785 1.1 itojun 786 1.1 itojun if (filter == NULL || !*filter) 787 1.1 itojun return (0); 788 1.1 itojun if (!strcmp(p->pfik_name, filter)) 789 1.1 itojun return (0); /* exact match */ 790 1.1 itojun n = strlen(filter); 791 1.1 itojun if (n < 1 || n >= IFNAMSIZ) 792 1.1 itojun return (1); /* sanity check */ 793 1.1 itojun if (filter[n-1] >= '0' && filter[n-1] <= '9') 794 1.1 itojun return (1); /* only do exact match in that case */ 795 1.1 itojun if (strncmp(p->pfik_name, filter, n)) 796 1.1 itojun return (1); /* prefix doesn't match */ 797 1.1 itojun return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9'); 798 1.1 itojun } 799 1.1 itojun 800 1.16 yamt int 801 1.16 yamt pfi_set_flags(const char *name, int flags) 802 1.16 yamt { 803 1.16 yamt struct pfi_kif *p; 804 1.16 yamt int s; 805 1.16 yamt 806 1.16 yamt s = splsoftnet(); 807 1.16 yamt RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 808 1.16 yamt if (pfi_skip_if(name, p)) 809 1.16 yamt continue; 810 1.16 yamt p->pfik_flags |= flags; 811 1.16 yamt } 812 1.16 yamt splx(s); 813 1.16 yamt return (0); 814 1.16 yamt } 815 1.16 yamt 816 1.16 yamt int 817 1.16 yamt pfi_clear_flags(const char *name, int flags) 818 1.16 yamt { 819 1.16 yamt struct pfi_kif *p; 820 1.16 yamt int s; 821 1.16 yamt 822 1.16 yamt s = splsoftnet(); 823 1.16 yamt RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 824 1.16 yamt if (pfi_skip_if(name, p)) 825 1.16 yamt continue; 826 1.16 yamt p->pfik_flags &= ~flags; 827 1.16 yamt } 828 1.16 yamt splx(s); 829 1.16 yamt return (0); 830 1.16 yamt } 831 1.16 yamt 832 1.1 itojun /* from pf_print_state.c */ 833 1.1 itojun int 834 1.1 itojun pfi_unmask(void *addr) 835 1.1 itojun { 836 1.1 itojun struct pf_addr *m = addr; 837 1.1 itojun int i = 31, j = 0, b = 0; 838 1.1 itojun u_int32_t tmp; 839 1.1 itojun 840 1.1 itojun while (j < 4 && m->addr32[j] == 0xffffffff) { 841 1.1 itojun b += 32; 842 1.1 itojun j++; 843 1.1 itojun } 844 1.1 itojun if (j < 4) { 845 1.1 itojun tmp = ntohl(m->addr32[j]); 846 1.1 itojun for (i = 31; tmp & (1 << i); --i) 847 1.1 itojun b++; 848 1.1 itojun } 849 1.1 itojun return (b); 850 1.1 itojun } 851 1.1 itojun 852 1.16 yamt #ifdef __NetBSD__ 853 1.16 yamt static void 854 1.16 yamt pfi_copy_group(char *dest, const char *src, ssize_t sz) 855 1.1 itojun { 856 1.16 yamt while (sz > 1 && *src && !(*src >= '0' && *src <= '9')) { 857 1.16 yamt *dest++ = *src++; 858 1.16 yamt sz--; 859 1.16 yamt } 860 1.16 yamt if (sz > 0) 861 1.16 yamt *dest++ = '\0'; 862 1.1 itojun } 863 1.1 itojun 864 1.16 yamt void 865 1.16 yamt pfi_init_groups(struct ifnet *ifp) 866 1.1 itojun { 867 1.16 yamt char group[IFNAMSIZ]; 868 1.16 yamt 869 1.16 yamt if_init_groups(ifp); 870 1.16 yamt if_addgroup(ifp, IFG_ALL); 871 1.16 yamt 872 1.16 yamt pfi_copy_group(group, ifp->if_xname, sizeof(group)); 873 1.16 yamt if_addgroup(ifp, group); 874 1.1 itojun } 875 1.2 itojun 876 1.16 yamt void 877 1.16 yamt pfi_destroy_groups(struct ifnet *ifp) 878 1.2 itojun { 879 1.16 yamt char group[IFNAMSIZ]; 880 1.2 itojun 881 1.16 yamt pfi_copy_group(group, ifp->if_xname, sizeof(group)); 882 1.16 yamt if_delgroup(ifp, group); 883 1.2 itojun 884 1.16 yamt if_delgroup(ifp, IFG_ALL); 885 1.16 yamt if_destroy_groups(ifp); 886 1.2 itojun } 887 1.2 itojun 888 1.32 christos void 889 1.32 christos pfil_ifnet_wrapper(void *arg, u_long cmd, void *arg2) 890 1.2 itojun { 891 1.32 christos ifnet_t *ifp = arg2; 892 1.16 yamt 893 1.16 yamt switch (cmd) { 894 1.16 yamt case PFIL_IFNET_ATTACH: 895 1.16 yamt pfi_init_groups(ifp); 896 1.16 yamt 897 1.16 yamt pfi_attach_ifnet(ifp); 898 1.16 yamt break; 899 1.16 yamt case PFIL_IFNET_DETACH: 900 1.16 yamt pfi_detach_ifnet(ifp); 901 1.16 yamt 902 1.16 yamt pfi_destroy_groups(ifp); 903 1.16 yamt break; 904 1.16 yamt default: 905 1.16 yamt panic("pfil_ifnet_wrapper: unexpected cmd %lu", cmd); 906 1.16 yamt } 907 1.2 itojun } 908 1.5 yamt 909 1.32 christos void 910 1.32 christos pfil_ifaddr_wrapper(void *arg, u_long cmd, void *arg2) 911 1.5 yamt { 912 1.32 christos struct ifaddr *ifa = arg2; 913 1.5 yamt 914 1.16 yamt switch (cmd) { 915 1.16 yamt case SIOCSIFADDR: 916 1.16 yamt case SIOCAIFADDR: 917 1.16 yamt case SIOCDIFADDR: 918 1.16 yamt #ifdef INET6 919 1.16 yamt case SIOCAIFADDR_IN6: 920 1.16 yamt case SIOCDIFADDR_IN6: 921 1.16 yamt #endif /* INET6 */ 922 1.32 christos pfi_kifaddr_update(ifa->ifa_ifp->if_pf_kif); 923 1.16 yamt break; 924 1.16 yamt default: 925 1.16 yamt panic("pfil_ifaddr_wrapper: unexpected ioctl %lu", cmd); 926 1.5 yamt } 927 1.5 yamt } 928 1.16 yamt #endif /* __NetBSD__ */ 929