pf_if.c revision 133872
1214571Sdim/* $FreeBSD: head/sys/contrib/pf/net/pf_if.c 133872 2004-08-16 17:58:12Z mlaier $ */ 2214571Sdim/* $OpenBSD: pf_if.c,v 1.11 2004/03/15 11:38:23 cedric Exp $ */ 3214571Sdim/* add $OpenBSD: pf_if.c,v 1.19 2004/08/11 12:06:44 henning Exp $ */ 4214571Sdim 5214571Sdim/* 6214571Sdim * Copyright (c) 2001 Daniel Hartmeier 7214571Sdim * Copyright (c) 2003 Cedric Berger 8214571Sdim * All rights reserved. 9214571Sdim * 10214571Sdim * Redistribution and use in source and binary forms, with or without 11214571Sdim * modification, are permitted provided that the following conditions 12214571Sdim * are met: 13214571Sdim * 14214571Sdim * - Redistributions of source code must retain the above copyright 15214571Sdim * notice, this list of conditions and the following disclaimer. 16214571Sdim * - Redistributions in binary form must reproduce the above 17214571Sdim * copyright notice, this list of conditions and the following 18214571Sdim * disclaimer in the documentation and/or other materials provided 19214571Sdim * with the distribution. 20214571Sdim * 21214571Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22214571Sdim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23214571Sdim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24214571Sdim * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25214571Sdim * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26214571Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27214571Sdim * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28214571Sdim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29214571Sdim * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30214571Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31214571Sdim * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32214571Sdim * POSSIBILITY OF SUCH DAMAGE. 33214571Sdim */ 34214571Sdim 35214571Sdim#if defined(__FreeBSD__) 36214571Sdim#include "opt_inet.h" 37214571Sdim#include "opt_inet6.h" 38214571Sdim#endif 39214571Sdim 40214571Sdim#include <sys/param.h> 41214571Sdim#include <sys/systm.h> 42214571Sdim#ifdef __FreeBSD__ 43214571Sdim#include <sys/malloc.h> 44214571Sdim#endif 45214571Sdim#include <sys/mbuf.h> 46214571Sdim#include <sys/filio.h> 47214571Sdim#include <sys/socket.h> 48214571Sdim#include <sys/socketvar.h> 49214571Sdim#include <sys/kernel.h> 50214571Sdim#ifndef __FreeBSD__ 51214571Sdim#include <sys/device.h> 52214571Sdim#endif 53214571Sdim#include <sys/time.h> 54214571Sdim 55214571Sdim#include <net/if.h> 56214571Sdim#include <net/if_types.h> 57214571Sdim#include <net/route.h> 58214571Sdim 59214571Sdim#include <netinet/in.h> 60214571Sdim#include <netinet/in_var.h> 61214571Sdim#include <netinet/in_systm.h> 62214571Sdim#include <netinet/ip.h> 63214571Sdim#include <netinet/ip_var.h> 64214571Sdim 65214571Sdim#include <net/pfvar.h> 66214571Sdim 67214571Sdim#ifdef INET6 68214571Sdim#include <netinet/ip6.h> 69214571Sdim#endif /* INET6 */ 70214571Sdim 71214571Sdim#define ACCEPT_FLAGS(oklist) \ 72214571Sdim do { \ 73214571Sdim if ((flags & ~(oklist)) & \ 74214571Sdim PFI_FLAG_ALLMASK) \ 75214571Sdim return (EINVAL); \ 76214571Sdim } while (0) 77214571Sdim 78214571Sdim#define senderr(e) do { rv = (e); goto _bad; } while (0) 79214571Sdim 80214571Sdimstruct pfi_kif **pfi_index2kif; 81214571Sdimstruct pfi_kif *pfi_self, *pfi_dummy; 82214571Sdimint pfi_indexlim; 83214571Sdimstruct pfi_ifhead pfi_ifs; 84214571Sdimstruct pfi_statehead pfi_statehead; 85214571Sdimint pfi_ifcnt; 86214571Sdim#ifdef __FreeBSD__ 87214571Sdimuma_zone_t pfi_addr_pl; 88214571Sdim#else 89214571Sdimstruct pool pfi_addr_pl; 90214571Sdim#endif 91214571Sdimlong pfi_update = 1; 92214571Sdimstruct pfr_addr *pfi_buffer; 93214571Sdimint pfi_buffer_cnt; 94214571Sdimint pfi_buffer_max; 95214571Sdimchar pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] = 96214571Sdim PF_RESERVED_ANCHOR; 97214571Sdimchar pfi_interface_ruleset[PF_RULESET_NAME_SIZE] = 98214571Sdim PF_INTERFACE_RULESET; 99214571Sdim#ifdef __FreeBSD__ 100214571Sdimeventhandler_tag pfi_clone_cookie = NULL; 101214571Sdimeventhandler_tag pfi_attach_cookie = NULL; 102214571Sdimeventhandler_tag pfi_detach_cookie = NULL; 103214571Sdim#endif 104214571Sdim 105214571Sdimvoid pfi_dynaddr_update(void *); 106214571Sdimvoid pfi_kifaddr_update(void *); 107214571Sdimvoid pfi_table_update(struct pfr_ktable *, struct pfi_kif *, 108214571Sdim int, int); 109214571Sdimvoid pfi_instance_add(struct ifnet *, int, int); 110214571Sdimvoid pfi_address_add(struct sockaddr *, int, int); 111214571Sdimint pfi_if_compare(struct pfi_kif *, struct pfi_kif *); 112214571Sdimstruct pfi_kif *pfi_if_create(const char *, struct pfi_kif *, int); 113214571Sdimvoid pfi_copy_group(char *, const char *, int); 114214571Sdimvoid pfi_dynamic_drivers(void); 115214571Sdimvoid pfi_newgroup(const char *, int); 116214571Sdimint pfi_skip_if(const char *, struct pfi_kif *, int); 117214571Sdimint pfi_unmask(void *); 118214571Sdimvoid pfi_dohooks(struct pfi_kif *); 119214571Sdim#ifdef __FreeBSD__ 120214571Sdimvoid pfi_kifaddr_update_event(void *, struct ifnet *); 121214571Sdimvoid pfi_attach_clone_event(void * __unused, struct if_clone *); 122214571Sdimvoid pfi_attach_ifnet_event(void * __unused, struct ifnet *); 123214571Sdimvoid pfi_detach_ifnet_event(void * __unused, struct ifnet *); 124214571Sdim#endif 125214571Sdim 126214571SdimRB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 127214571SdimRB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 128214571Sdim 129214571Sdim#define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" } 130214571Sdim#define PFI_BUFFER_MAX 0x10000 131214571Sdim#ifdef __FreeBSD__ 132214571SdimMALLOC_DEFINE(PFI_MTYPE, "pf_if", "pf interface table"); 133214571Sdim#else 134214571Sdim#define PFI_MTYPE M_IFADDR 135214571Sdim#endif 136214571Sdim 137214571Sdimvoid 138214571Sdimpfi_initialize(void) 139214571Sdim{ 140214571Sdim#ifdef __FreeBSD__ 141214571Sdim struct ifnet *ifp; 142214571Sdim#endif 143214571Sdim 144214571Sdim if (pfi_self != NULL) /* already initialized */ 145214571Sdim return; 146214571Sdim 147214571Sdim TAILQ_INIT(&pfi_statehead); 148214571Sdim#ifndef __FreeBSD__ 149214571Sdim pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 150214571Sdim "pfiaddrpl", &pool_allocator_nointr); 151214571Sdim#endif 152214571Sdim pfi_buffer_max = 64; 153214571Sdim pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer), 154214571Sdim PFI_MTYPE, M_WAITOK); 155214571Sdim pfi_self = pfi_if_create("self", NULL, PFI_IFLAG_GROUP); 156214571Sdim pfi_dynamic_drivers(); 157214571Sdim#ifdef __FreeBSD__ 158214571Sdim PF_LOCK(); 159214571Sdim IFNET_RLOCK(); 160214571Sdim TAILQ_FOREACH(ifp, &ifnet, if_link) 161214571Sdim if (ifp->if_dunit != IF_DUNIT_NONE) { 162214571Sdim IFNET_RUNLOCK(); 163214571Sdim pfi_attach_ifnet(ifp); 164214571Sdim IFNET_RLOCK(); 165214571Sdim } 166214571Sdim IFNET_RUNLOCK(); 167214571Sdim PF_UNLOCK(); 168214571Sdim pfi_dummy = pfi_if_create("notyet", pfi_self, 169214571Sdim PFI_IFLAG_GROUP | PFI_IFLAG_DYNAMIC); 170214571Sdim pfi_attach_cookie = EVENTHANDLER_REGISTER(ifnet_arrival_event, 171214571Sdim pfi_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); 172214571Sdim pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event, 173214571Sdim pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); 174214571Sdim pfi_clone_cookie = EVENTHANDLER_REGISTER(if_clone_event, 175214571Sdim pfi_attach_clone_event, NULL, EVENTHANDLER_PRI_ANY); 176214571Sdim#endif 177214571Sdim} 178214571Sdim 179214571Sdim#ifdef __FreeBSD__ 180214571Sdimvoid 181214571Sdimpfi_cleanup(void) 182214571Sdim{ 183214571Sdim struct pfi_kif *p, key; 184214571Sdim struct ifnet *ifp; 185214571Sdim 186214571Sdim PF_ASSERT(MA_OWNED); 187214571Sdim 188214571Sdim PF_UNLOCK(); 189214571Sdim EVENTHANDLER_DEREGISTER(ifnet_arrival_event, pfi_attach_cookie); 190214571Sdim EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfi_detach_cookie); 191214571Sdim EVENTHANDLER_DEREGISTER(if_clone_event, pfi_clone_cookie); 192214571Sdim PF_LOCK(); 193214571Sdim 194214571Sdim IFNET_RLOCK(); 195214571Sdim /* release PFI_IFLAG_INSTANCE */ 196214571Sdim TAILQ_FOREACH(ifp, &ifnet, if_link) { 197214571Sdim strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 198214571Sdim p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 199214571Sdim if (p != NULL) { 200214571Sdim IFNET_RUNLOCK(); 201214571Sdim pfi_detach_ifnet(ifp); 202214571Sdim IFNET_RLOCK(); 203214571Sdim } 204214571Sdim } 205214571Sdim IFNET_RUNLOCK(); 206214571Sdim 207214571Sdim /* XXX clear all other interface group */ 208214571Sdim while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) { 209214571Sdim RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 210214571Sdim 211214571Sdim free(p->pfik_ah_head, PFI_MTYPE); 212214571Sdim free(p, PFI_MTYPE); 213214571Sdim } 214214571Sdim free(pfi_index2kif, PFI_MTYPE); 215214571Sdim free(pfi_buffer, PFI_MTYPE); 216214571Sdim pfi_index2kif = NULL; 217214571Sdim pfi_buffer = NULL; 218214571Sdim pfi_self = NULL; 219214571Sdim} 220214571Sdim 221214571Sdim/* 222214571Sdim * Wrapper functions for FreeBSD eventhandler 223214571Sdim */ 224214571Sdimvoid 225214571Sdimpfi_kifaddr_update_event(void *arg, struct ifnet *ifp) 226214571Sdim{ 227214571Sdim struct pfi_kif *p = arg; 228214571Sdim 229214571Sdim PF_LOCK(); 230214571Sdim /* 231214571Sdim * Check to see if it is 'our' interface as we do not have per 232214571Sdim * interface hooks and thus get an update for every interface. 233214571Sdim */ 234214571Sdim if (p && p->pfik_ifp == ifp) 235214571Sdim pfi_kifaddr_update(p); 236214571Sdim PF_UNLOCK(); 237214571Sdim} 238214571Sdim 239214571Sdimvoid 240214571Sdimpfi_attach_clone_event(void *arg __unused, struct if_clone *ifc) 241214571Sdim{ 242214571Sdim PF_LOCK(); 243214571Sdim pfi_attach_clone(ifc); 244214571Sdim PF_UNLOCK(); 245214571Sdim} 246214571Sdim 247214571Sdimvoid 248214571Sdimpfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp) 249214571Sdim{ 250214571Sdim PF_LOCK(); 251214571Sdim if (ifp->if_dunit != IF_DUNIT_NONE) 252214571Sdim pfi_attach_ifnet(ifp); 253214571Sdim PF_UNLOCK(); 254214571Sdim} 255214571Sdim 256214571Sdimvoid 257214571Sdimpfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp) 258214571Sdim{ 259214571Sdim PF_LOCK(); 260214571Sdim pfi_detach_ifnet(ifp); 261214571Sdim PF_UNLOCK(); 262214571Sdim} 263214571Sdim#endif /* __FreeBSD__ */ 264214571Sdim 265214571Sdimvoid 266214571Sdimpfi_attach_clone(struct if_clone *ifc) 267214571Sdim{ 268214571Sdim pfi_initialize(); 269214571Sdim pfi_newgroup(ifc->ifc_name, PFI_IFLAG_CLONABLE); 270214571Sdim} 271214571Sdim 272214571Sdimvoid 273214571Sdimpfi_attach_ifnet(struct ifnet *ifp) 274214571Sdim{ 275214571Sdim struct pfi_kif *p, *q, key; 276214571Sdim int s; 277214571Sdim#ifdef __FreeBSD__ 278214571Sdim int realname; 279214571Sdim#endif 280214571Sdim 281214571Sdim pfi_initialize(); 282214571Sdim s = splsoftnet(); 283214571Sdim pfi_update++; 284214571Sdim if (ifp->if_index >= pfi_indexlim) { 285214571Sdim /* 286214571Sdim * grow pfi_index2kif, similar to ifindex2ifnet code in if.c 287214571Sdim */ 288214571Sdim size_t m, n, oldlim; 289214571Sdim struct pfi_kif **mp, **np; 290214571Sdim 291214571Sdim oldlim = pfi_indexlim; 292214571Sdim if (pfi_indexlim == 0) 293214571Sdim pfi_indexlim = 64; 294214571Sdim while (ifp->if_index >= pfi_indexlim) 295214571Sdim pfi_indexlim <<= 1; 296214571Sdim 297214571Sdim m = oldlim * sizeof(struct pfi_kif *); 298214571Sdim mp = pfi_index2kif; 299214571Sdim n = pfi_indexlim * sizeof(struct pfi_kif *); 300214571Sdim#ifdef __FreeBSD__ 301214571Sdim np = malloc(n, PFI_MTYPE, M_NOWAIT); 302214571Sdim#else 303214571Sdim np = malloc(n, PFI_MTYPE, M_DONTWAIT); 304214571Sdim#endif 305214571Sdim if (np == NULL) 306214571Sdim panic("pfi_attach_ifnet: " 307214571Sdim "cannot allocate translation table"); 308214571Sdim bzero(np, n); 309214571Sdim if (mp != NULL) 310214571Sdim bcopy(mp, np, m); 311214571Sdim pfi_index2kif = np; 312214571Sdim if (mp != NULL) 313214571Sdim free(mp, PFI_MTYPE); 314214571Sdim } 315214571Sdim 316214571Sdim strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 317214571Sdim p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 318214571Sdim#ifdef __FreeBSD__ 319214571Sdim /* some additional trickery for placeholders */ 320214571Sdim if ((p == NULL) || (p->pfik_parent == pfi_dummy)) { 321214571Sdim /* are we looking at a renamed instance or not? */ 322214571Sdim pfi_copy_group(key.pfik_name, ifp->if_xname, 323214571Sdim sizeof(key.pfik_name)); 324214571Sdim realname = (strncmp(key.pfik_name, ifp->if_dname, 325214571Sdim sizeof(key.pfik_name)) == 0); 326214571Sdim /* add group */ 327214571Sdim /* we can change if_xname, hence use if_dname as group id */ 328214571Sdim pfi_copy_group(key.pfik_name, ifp->if_dname, 329214571Sdim sizeof(key.pfik_name)); 330214571Sdim q = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 331214571Sdim if (q == NULL) 332214571Sdim q = pfi_if_create(key.pfik_name, pfi_self, 333214571Sdim PFI_IFLAG_GROUP|PFI_IFLAG_DYNAMIC); 334214571Sdim else if (q->pfik_parent == pfi_dummy) { 335214571Sdim q->pfik_parent = pfi_self; 336214571Sdim q->pfik_flags = (PFI_IFLAG_GROUP | PFI_IFLAG_DYNAMIC); 337214571Sdim } 338214571Sdim if (q == NULL) 339214571Sdim panic("pfi_attach_ifnet: " 340214571Sdim "cannot allocate '%s' group", key.pfik_name); 341214571Sdim 342214571Sdim /* add/modify interface */ 343214571Sdim if (p == NULL) 344214571Sdim p = pfi_if_create(ifp->if_xname, q, 345214571Sdim realname?PFI_IFLAG_INSTANCE:PFI_IFLAG_PLACEHOLDER); 346214571Sdim else { 347214571Sdim /* remove from the dummy group */ 348214571Sdim /* XXX: copy stats? We should not have any!!! */ 349214571Sdim pfi_dummy->pfik_delcnt++; 350214571Sdim TAILQ_REMOVE(&pfi_dummy->pfik_grouphead, p, 351214571Sdim pfik_instances); 352214571Sdim /* move to the right group */ 353214571Sdim p->pfik_parent = q; 354214571Sdim q->pfik_addcnt++; 355214571Sdim TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, 356214571Sdim pfik_instances); 357214571Sdim if (realname) { 358214571Sdim p->pfik_flags &= ~PFI_IFLAG_PLACEHOLDER; 359214571Sdim p->pfik_flags |= PFI_IFLAG_INSTANCE; 360214571Sdim } 361214571Sdim } 362214571Sdim if (p == NULL) 363214571Sdim panic("pfi_attach_ifnet: " 364214571Sdim "cannot allocate '%s' interface", ifp->if_xname); 365214571Sdim#else 366214571Sdim if (p == NULL) { 367214571Sdim /* add group */ 368214571Sdim pfi_copy_group(key.pfik_name, ifp->if_xname, 369214571Sdim sizeof(key.pfik_name)); 370214571Sdim q = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 371214571Sdim if (q == NULL) 372214571Sdim q = pfi_if_create(key.pfik_name, pfi_self, PFI_IFLAG_GROUP); 373214571Sdim else if (q->pfik_parent == pfi_dummy) { 374214571Sdim q->pfik_parent = pfi_self; 375214571Sdim q->pfik_flags = (PFI_IFLAG_GROUP | PFI_IFLAG_DYNAMIC); 376214571Sdim } 377214571Sdim if (q == NULL) 378214571Sdim panic("pfi_attach_ifnet: " 379214571Sdim "cannot allocate '%s' group", key.pfik_name); 380214571Sdim 381214571Sdim /* add interface */ 382214571Sdim p = pfi_if_create(ifp->if_xname, q, PFI_IFLAG_INSTANCE); 383214571Sdim if (p == NULL) 384214571Sdim panic("pfi_attach_ifnet: " 385214571Sdim "cannot allocate '%s' interface", ifp->if_xname); 386214571Sdim#endif 387214571Sdim } else 388214571Sdim q = p->pfik_parent; 389214571Sdim p->pfik_ifp = ifp; 390214571Sdim p->pfik_flags |= PFI_IFLAG_ATTACHED; 391214571Sdim#ifdef __FreeBSD__ 392214571Sdim PF_UNLOCK(); 393214571Sdim p->pfik_ah_cookie = EVENTHANDLER_REGISTER(ifaddr_event, 394214571Sdim pfi_kifaddr_update_event, p, EVENTHANDLER_PRI_ANY); 395214571Sdim PF_LOCK(); 396214571Sdim#else 397214571Sdim p->pfik_ah_cookie = 398214571Sdim hook_establish(ifp->if_addrhooks, 1, pfi_kifaddr_update, p); 399214571Sdim#endif 400214571Sdim pfi_index2kif[ifp->if_index] = p; 401214571Sdim pfi_dohooks(p); 402214571Sdim splx(s); 403214571Sdim} 404214571Sdim 405214571Sdimvoid 406214571Sdimpfi_detach_ifnet(struct ifnet *ifp) 407214571Sdim{ 408214571Sdim struct pfi_kif *p, *q, key; 409214571Sdim int s; 410214571Sdim 411214571Sdim strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 412214571Sdim 413214571Sdim s = splsoftnet(); 414214571Sdim pfi_update++; 415214571Sdim p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 416214571Sdim if (p == NULL) { 417214571Sdim printf("pfi_detach_ifnet: cannot find %s", ifp->if_xname); 418 splx(s); 419 return; 420 } 421#ifdef __FreeBSD__ 422 PF_UNLOCK(); 423 EVENTHANDLER_DEREGISTER(ifaddr_event, p->pfik_ah_cookie); 424 PF_LOCK(); 425#else 426 hook_disestablish(p->pfik_ifp->if_addrhooks, p->pfik_ah_cookie); 427#endif 428 q = p->pfik_parent; 429 p->pfik_ifp = NULL; 430 p->pfik_flags &= ~PFI_IFLAG_ATTACHED; 431 pfi_index2kif[ifp->if_index] = NULL; 432 pfi_dohooks(p); 433 pfi_maybe_destroy(p); 434 splx(s); 435} 436 437struct pfi_kif * 438pfi_lookup_create(const char *name) 439{ 440 struct pfi_kif *p, *q, key; 441 int s; 442 443 s = splsoftnet(); 444 p = pfi_lookup_if(name); 445 if (p == NULL) { 446 pfi_copy_group(key.pfik_name, name, sizeof(key.pfik_name)); 447 q = pfi_lookup_if(key.pfik_name); 448#ifdef __FreeBSD__ 449 if ((q != NULL) && (q->pfik_parent != pfi_dummy)) 450 p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE); 451 else { 452 if (pfi_dummy == NULL) 453 panic("no 'notyet' dummy group"); 454 p = pfi_if_create(name, pfi_dummy, 455 PFI_IFLAG_PLACEHOLDER); 456 } 457#else 458 if (q != NULL) 459 p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE); 460#endif 461 } 462 splx(s); 463 return (p); 464} 465 466struct pfi_kif * 467pfi_attach_rule(const char *name) 468{ 469 struct pfi_kif *p; 470 471 p = pfi_lookup_create(name); 472 if (p != NULL) 473 p->pfik_rules++; 474 return (p); 475} 476 477void 478pfi_detach_rule(struct pfi_kif *p) 479{ 480 if (p == NULL) 481 return; 482 if (p->pfik_rules > 0) 483 p->pfik_rules--; 484 else 485 printf("pfi_detach_rule: reference count at 0\n"); 486 pfi_maybe_destroy(p); 487} 488 489void 490pfi_attach_state(struct pfi_kif *p) 491{ 492 if (!p->pfik_states++) 493 TAILQ_INSERT_TAIL(&pfi_statehead, p, pfik_w_states); 494} 495 496void 497pfi_detach_state(struct pfi_kif *p) 498{ 499 if (p == NULL) 500 return; 501 if (p->pfik_states <= 0) { 502 printf("pfi_detach_state: reference count <= 0\n"); 503 return; 504 } 505 if (!--p->pfik_states) 506 TAILQ_REMOVE(&pfi_statehead, p, pfik_w_states); 507 pfi_maybe_destroy(p); 508} 509 510int 511pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) 512{ 513 struct pfi_dynaddr *dyn; 514 char tblname[PF_TABLE_NAME_SIZE]; 515 struct pf_ruleset *ruleset = NULL; 516 int s, rv = 0; 517 518 if (aw->type != PF_ADDR_DYNIFTL) 519 return (0); 520 dyn = pool_get(&pfi_addr_pl, PR_NOWAIT); 521 if (dyn == NULL) 522 return (1); 523 bzero(dyn, sizeof(*dyn)); 524 525 s = splsoftnet(); 526 dyn->pfid_kif = pfi_attach_rule(aw->v.ifname); 527 if (dyn->pfid_kif == NULL) 528 senderr(1); 529 530 dyn->pfid_net = pfi_unmask(&aw->v.a.mask); 531 if (af == AF_INET && dyn->pfid_net == 32) 532 dyn->pfid_net = 128; 533 strlcpy(tblname, aw->v.ifname, sizeof(tblname)); 534 if (aw->iflags & PFI_AFLAG_NETWORK) 535 strlcat(tblname, ":network", sizeof(tblname)); 536 if (aw->iflags & PFI_AFLAG_BROADCAST) 537 strlcat(tblname, ":broadcast", sizeof(tblname)); 538 if (aw->iflags & PFI_AFLAG_PEER) 539 strlcat(tblname, ":peer", sizeof(tblname)); 540 if (aw->iflags & PFI_AFLAG_NOALIAS) 541 strlcat(tblname, ":0", sizeof(tblname)); 542 if (dyn->pfid_net != 128) 543 snprintf(tblname + strlen(tblname), 544 sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); 545 ruleset = pf_find_or_create_ruleset(pfi_reserved_anchor, 546 pfi_interface_ruleset); 547 if (ruleset == NULL) 548 senderr(1); 549 550 dyn->pfid_kt = pfr_attach_table(ruleset, tblname); 551 if (dyn->pfid_kt == NULL) 552 senderr(1); 553 554 dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; 555 dyn->pfid_iflags = aw->iflags; 556 dyn->pfid_af = af; 557 dyn->pfid_hook_cookie = hook_establish(dyn->pfid_kif->pfik_ah_head, 1, 558 pfi_dynaddr_update, dyn); 559 if (dyn->pfid_hook_cookie == NULL) 560 senderr(1); 561 562 aw->p.dyn = dyn; 563 pfi_dynaddr_update(aw->p.dyn); 564 splx(s); 565 return (0); 566 567_bad: 568 if (dyn->pfid_kt != NULL) 569 pfr_detach_table(dyn->pfid_kt); 570 if (ruleset != NULL) 571 pf_remove_if_empty_ruleset(ruleset); 572 if (dyn->pfid_kif != NULL) 573 pfi_detach_rule(dyn->pfid_kif); 574 pool_put(&pfi_addr_pl, dyn); 575 splx(s); 576 return (rv); 577} 578 579void 580pfi_dynaddr_update(void *p) 581{ 582 struct pfi_dynaddr *dyn = (struct pfi_dynaddr *)p; 583 struct pfi_kif *kif = dyn->pfid_kif; 584 struct pfr_ktable *kt = dyn->pfid_kt; 585 586 if (dyn == NULL || kif == NULL || kt == NULL) 587 panic("pfi_dynaddr_update"); 588 if (kt->pfrkt_larg != pfi_update) { 589 /* this table needs to be brought up-to-date */ 590 pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); 591 kt->pfrkt_larg = pfi_update; 592 } 593 pfr_dynaddr_update(kt, dyn); 594} 595 596void 597pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) 598{ 599 int e, size2 = 0; 600 struct pfi_kif *p; 601 struct pfr_table t; 602 603 if ((kif->pfik_flags & PFI_IFLAG_INSTANCE) && kif->pfik_ifp == NULL) { 604 pfr_clr_addrs(&kt->pfrkt_t, NULL, 0); 605 return; 606 } 607 pfi_buffer_cnt = 0; 608 if ((kif->pfik_flags & PFI_IFLAG_INSTANCE)) 609 pfi_instance_add(kif->pfik_ifp, net, flags); 610 else if (strcmp(kif->pfik_name, "self")) { 611 TAILQ_FOREACH(p, &kif->pfik_grouphead, pfik_instances) 612 pfi_instance_add(p->pfik_ifp, net, flags); 613 } else { 614 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) 615 if (p->pfik_flags & PFI_IFLAG_INSTANCE) 616 pfi_instance_add(p->pfik_ifp, net, flags); 617 } 618 t = kt->pfrkt_t; 619 t.pfrt_flags = 0; 620 if ((e = pfr_set_addrs(&t, pfi_buffer, pfi_buffer_cnt, &size2, 621 NULL, NULL, NULL, 0))) 622 printf("pfi_table_update: cannot set %d new addresses " 623 "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e); 624} 625 626void 627pfi_instance_add(struct ifnet *ifp, int net, int flags) 628{ 629 struct ifaddr *ia; 630 int got4 = 0, got6 = 0; 631 int net2, af; 632 633 if (ifp == NULL) 634 return; 635 TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) { 636 if (ia->ifa_addr == NULL) 637 continue; 638 af = ia->ifa_addr->sa_family; 639 if (af != AF_INET && af != AF_INET6) 640 continue; 641#ifdef notyet 642 if (!(ia->ifa_flags & IFA_ROUTE)) 643 continue; 644#endif 645 if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) 646 continue; 647 if ((flags & PFI_AFLAG_BROADCAST) && 648 !(ifp->if_flags & IFF_BROADCAST)) 649 continue; 650 if ((flags & PFI_AFLAG_PEER) && 651 !(ifp->if_flags & IFF_POINTOPOINT)) 652 continue; 653 if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && 654 IN6_IS_ADDR_LINKLOCAL( 655 &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr)) 656 continue; 657 if (flags & PFI_AFLAG_NOALIAS) { 658 if (af == AF_INET && got4) 659 continue; 660 if (af == AF_INET6 && got6) 661 continue; 662 } 663 if (af == AF_INET) 664 got4 = 1; 665 else 666 got6 = 1; 667 net2 = net; 668 if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { 669 if (af == AF_INET) { 670 net2 = pfi_unmask(&((struct sockaddr_in *) 671 ia->ifa_netmask)->sin_addr); 672 } else { 673 net2 = pfi_unmask(&((struct sockaddr_in6 *) 674 ia->ifa_netmask)->sin6_addr); 675 } 676 } 677 if (af == AF_INET && net2 > 32) 678 net2 = 32; 679 if (flags & PFI_AFLAG_BROADCAST) 680 pfi_address_add(ia->ifa_broadaddr, af, net2); 681 else if (flags & PFI_AFLAG_PEER) 682 pfi_address_add(ia->ifa_dstaddr, af, net2); 683 else 684 pfi_address_add(ia->ifa_addr, af, net2); 685 } 686} 687 688void 689pfi_address_add(struct sockaddr *sa, int af, int net) 690{ 691 struct pfr_addr *p; 692 int i; 693 694 if (pfi_buffer_cnt >= pfi_buffer_max) { 695 int new_max = pfi_buffer_max * 2; 696 697 if (new_max > PFI_BUFFER_MAX) { 698 printf("pfi_address_add: address buffer full (%d/%d)\n", 699 pfi_buffer_cnt, PFI_BUFFER_MAX); 700 return; 701 } 702#ifdef __FreeBSD__ 703 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE, 704 M_NOWAIT); 705#else 706 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE, 707 M_DONTWAIT); 708#endif 709 if (p == NULL) { 710 printf("pfi_address_add: no memory to grow buffer " 711 "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); 712 return; 713 } 714 memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer)); 715 /* no need to zero buffer */ 716 free(pfi_buffer, PFI_MTYPE); 717 pfi_buffer = p; 718 pfi_buffer_max = new_max; 719 } 720 if (af == AF_INET && net > 32) 721 net = 128; 722 p = pfi_buffer + pfi_buffer_cnt++; 723 bzero(p, sizeof(*p)); 724 p->pfra_af = af; 725 p->pfra_net = net; 726 if (af == AF_INET) 727 p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; 728 if (af == AF_INET6) { 729 p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; 730 if (IN6_IS_ADDR_LINKLOCAL(&p->pfra_ip6addr)) 731 p->pfra_ip6addr.s6_addr16[1] = 0; 732 } 733 /* mask network address bits */ 734 if (net < 128) 735 ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); 736 for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) 737 ((caddr_t)p)[i] = 0; 738} 739 740void 741pfi_dynaddr_remove(struct pf_addr_wrap *aw) 742{ 743 int s; 744 745 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 746 aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) 747 return; 748 749 s = splsoftnet(); 750 hook_disestablish(aw->p.dyn->pfid_kif->pfik_ah_head, 751 aw->p.dyn->pfid_hook_cookie); 752 pfi_detach_rule(aw->p.dyn->pfid_kif); 753 aw->p.dyn->pfid_kif = NULL; 754 pfr_detach_table(aw->p.dyn->pfid_kt); 755 aw->p.dyn->pfid_kt = NULL; 756 pool_put(&pfi_addr_pl, aw->p.dyn); 757 aw->p.dyn = NULL; 758 splx(s); 759} 760 761void 762pfi_dynaddr_copyout(struct pf_addr_wrap *aw) 763{ 764 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 765 aw->p.dyn->pfid_kif == NULL) 766 return; 767 aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; 768} 769 770void 771pfi_kifaddr_update(void *v) 772{ 773 int s; 774 775 s = splsoftnet(); 776 pfi_update++; 777 pfi_dohooks(v); 778 splx(s); 779} 780 781int 782pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) 783{ 784 return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); 785} 786 787struct pfi_kif * 788pfi_if_create(const char *name, struct pfi_kif *q, int flags) 789{ 790 struct pfi_kif *p; 791 792#ifdef __FreeBSD__ 793 p = malloc(sizeof(*p), PFI_MTYPE, M_NOWAIT); 794#else 795 p = malloc(sizeof(*p), PFI_MTYPE, M_DONTWAIT); 796#endif 797 if (p == NULL) 798 return (NULL); 799 bzero(p, sizeof(*p)); 800#ifdef __FreeBSD__ 801 p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE, 802 M_NOWAIT); 803#else 804 p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE, 805 M_DONTWAIT); 806#endif 807 if (p->pfik_ah_head == NULL) { 808 free(p, PFI_MTYPE); 809 return (NULL); 810 } 811 bzero(p->pfik_ah_head, sizeof(*p->pfik_ah_head)); 812 TAILQ_INIT(p->pfik_ah_head); 813 TAILQ_INIT(&p->pfik_grouphead); 814 strlcpy(p->pfik_name, name, sizeof(p->pfik_name)); 815 RB_INIT(&p->pfik_lan_ext); 816 RB_INIT(&p->pfik_ext_gwy); 817 p->pfik_flags = flags; 818 p->pfik_parent = q; 819#ifdef __FreeBSD__ 820 p->pfik_tzero = time_second; 821#else 822 p->pfik_tzero = time.tv_sec; 823#endif 824 825 RB_INSERT(pfi_ifhead, &pfi_ifs, p); 826 if (q != NULL) { 827 q->pfik_addcnt++; 828 TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, pfik_instances); 829 } 830 pfi_ifcnt++; 831 return (p); 832} 833 834int 835pfi_maybe_destroy(struct pfi_kif *p) 836{ 837 int i, j, k, s; 838 struct pfi_kif *q = p->pfik_parent; 839 840 if ((p->pfik_flags & (PFI_IFLAG_ATTACHED | PFI_IFLAG_GROUP)) || 841 p->pfik_rules > 0 || p->pfik_states > 0) 842#ifdef __FreeBSD__ 843 if (!(p->pfik_flags & PFI_IFLAG_PLACEHOLDER)) 844#endif 845 return (0); 846 847 s = splsoftnet(); 848 if (q != NULL) { 849 for (i = 0; i < 2; i++) 850 for (j = 0; j < 2; j++) 851 for (k = 0; k < 2; k++) { 852 q->pfik_bytes[i][j][k] += 853 p->pfik_bytes[i][j][k]; 854 q->pfik_packets[i][j][k] += 855 p->pfik_packets[i][j][k]; 856#ifdef __FreeBSD__ 857 /* clear stats in case we return to the dummy group */ 858 p->pfik_bytes[i][j][k] = 0; 859 p->pfik_packets[i][j][k] = 0; 860#endif 861 } 862 q->pfik_delcnt++; 863 TAILQ_REMOVE(&q->pfik_grouphead, p, pfik_instances); 864 } 865#ifdef __FreeBSD__ 866 if (p->pfik_rules > 0 || p->pfik_states > 0) { 867 /* move back to the dummy group */ 868 p->pfik_parent = pfi_dummy; 869 pfi_dummy->pfik_addcnt++; 870 TAILQ_INSERT_TAIL(&pfi_dummy->pfik_grouphead, p, 871 pfik_instances); 872 return (0); 873 } 874#endif 875 pfi_ifcnt--; 876 RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 877 splx(s); 878 879 free(p->pfik_ah_head, PFI_MTYPE); 880 free(p, PFI_MTYPE); 881 return (1); 882} 883 884void 885pfi_copy_group(char *p, const char *q, int m) 886{ 887 while (m > 1 && *q && !(*q >= '0' && *q <= '9')) { 888 *p++ = *q++; 889 m--; 890 } 891 if (m > 0) 892 *p++ = '\0'; 893} 894 895void 896pfi_dynamic_drivers(void) 897{ 898#ifdef __FreeBSD__ 899 struct ifnet *ifp; 900 901/* 902 * For FreeBSD basically every interface is "dynamic" as we can unload 903 * modules e.g. 904 */ 905 906 IFNET_RLOCK(); 907 TAILQ_FOREACH(ifp, &ifnet, if_link) { 908 if (ifp->if_dunit == IF_DUNIT_NONE) 909 continue; 910 pfi_newgroup(ifp->if_dname, PFI_IFLAG_DYNAMIC); 911 } 912 IFNET_RUNLOCK(); 913#else 914 char *buses[] = PFI_DYNAMIC_BUSES; 915 int nbuses = sizeof(buses)/sizeof(buses[0]); 916 int enabled[sizeof(buses)/sizeof(buses[0])]; 917 struct device *dev; 918 struct cfdata *cf; 919 struct cfdriver *drv; 920 short *p; 921 int i; 922 923 bzero(enabled, sizeof(enabled)); 924 TAILQ_FOREACH(dev, &alldevs, dv_list) { 925 if (!(dev->dv_flags & DVF_ACTIVE)) 926 continue; 927 for (i = 0; i < nbuses; i++) 928 if (!enabled[i] && !strcmp(buses[i], 929 dev->dv_cfdata->cf_driver->cd_name)) 930 enabled[i] = 1; 931 } 932 for (cf = cfdata; cf->cf_driver; cf++) { 933 if (cf->cf_driver->cd_class != DV_IFNET) 934 continue; 935 for (p = cf->cf_parents; p && *p >= 0; p++) { 936 if ((drv = cfdata[*p].cf_driver) == NULL) 937 continue; 938 for (i = 0; i < nbuses; i++) 939 if (enabled[i] && 940 !strcmp(drv->cd_name, buses[i])) 941 break; 942 if (i < nbuses) { 943 pfi_newgroup(cf->cf_driver->cd_name, 944 PFI_IFLAG_DYNAMIC); 945 break; 946 } 947 } 948 } 949#endif 950} 951 952void 953pfi_newgroup(const char *name, int flags) 954{ 955 struct pfi_kif *p; 956 957 p = pfi_lookup_if(name); 958 if (p == NULL) 959 p = pfi_if_create(name, pfi_self, PFI_IFLAG_GROUP); 960 if (p == NULL) { 961 printf("pfi_newgroup: cannot allocate '%s' group", name); 962 return; 963 } 964 p->pfik_flags |= flags; 965} 966 967void 968pfi_fill_oldstatus(struct pf_status *pfs) 969{ 970 struct pfi_kif *p, key; 971 int i, j, k, s; 972 973 strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name)); 974 s = splsoftnet(); 975 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 976 if (p == NULL) { 977 splx(s); 978 return; 979 } 980 bzero(pfs->pcounters, sizeof(pfs->pcounters)); 981 bzero(pfs->bcounters, sizeof(pfs->bcounters)); 982 for (i = 0; i < 2; i++) 983 for (j = 0; j < 2; j++) 984 for (k = 0; k < 2; k++) { 985 pfs->pcounters[i][j][k] = 986 p->pfik_packets[i][j][k]; 987 pfs->bcounters[i][j] += 988 p->pfik_bytes[i][j][k]; 989 } 990 splx(s); 991} 992 993int 994pfi_clr_istats(const char *name, int *nzero, int flags) 995{ 996 struct pfi_kif *p; 997 int n = 0, s; 998#ifdef __FreeBSD__ 999 long tzero = time_second; 1000#else 1001 long tzero = time.tv_sec; 1002#endif 1003 1004 s = splsoftnet(); 1005 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); 1006 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 1007 if (pfi_skip_if(name, p, flags)) 1008 continue; 1009 bzero(p->pfik_packets, sizeof(p->pfik_packets)); 1010 bzero(p->pfik_bytes, sizeof(p->pfik_bytes)); 1011 p->pfik_tzero = tzero; 1012 n++; 1013 } 1014 splx(s); 1015 if (nzero != NULL) 1016 *nzero = n; 1017 return (0); 1018} 1019 1020int 1021pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags) 1022{ 1023 struct pfi_kif *p; 1024 int s, n = 0; 1025#ifdef __FreeBSD__ 1026 int ec; 1027#endif 1028 1029 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); 1030 s = splsoftnet(); 1031 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 1032 if (pfi_skip_if(name, p, flags)) 1033 continue; 1034 if (*size > n++) { 1035 if (!p->pfik_tzero) 1036 p->pfik_tzero = boottime.tv_sec; 1037#ifdef __FreeBSD__ 1038 PF_COPYOUT(p, buf++, sizeof(*buf), ec); 1039 if (ec) { 1040#else 1041 if (copyout(p, buf++, sizeof(*buf))) { 1042#endif 1043 splx(s); 1044 return (EFAULT); 1045 } 1046 } 1047 } 1048 splx(s); 1049 *size = n; 1050 return (0); 1051} 1052 1053struct pfi_kif * 1054pfi_lookup_if(const char *name) 1055{ 1056 struct pfi_kif *p, key; 1057 1058 strlcpy(key.pfik_name, name, sizeof(key.pfik_name)); 1059 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 1060 return (p); 1061} 1062 1063int 1064pfi_skip_if(const char *filter, struct pfi_kif *p, int f) 1065{ 1066 int n; 1067 1068 if ((p->pfik_flags & PFI_IFLAG_GROUP) && !(f & PFI_FLAG_GROUP)) 1069 return (1); 1070 if ((p->pfik_flags & PFI_IFLAG_INSTANCE) && !(f & PFI_FLAG_INSTANCE)) 1071 return (1); 1072 if (filter == NULL || !*filter) 1073 return (0); 1074 if (!strcmp(p->pfik_name, filter)) 1075 return (0); /* exact match */ 1076 n = strlen(filter); 1077 if (n < 1 || n >= IFNAMSIZ) 1078 return (1); /* sanity check */ 1079 if (filter[n-1] >= '0' && filter[n-1] <= '9') 1080 return (1); /* only do exact match in that case */ 1081 if (strncmp(p->pfik_name, filter, n)) 1082 return (1); /* prefix doesn't match */ 1083 return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9'); 1084} 1085 1086/* from pf_print_state.c */ 1087int 1088pfi_unmask(void *addr) 1089{ 1090 struct pf_addr *m = addr; 1091 int i = 31, j = 0, b = 0; 1092 u_int32_t tmp; 1093 1094 while (j < 4 && m->addr32[j] == 0xffffffff) { 1095 b += 32; 1096 j++; 1097 } 1098 if (j < 4) { 1099 tmp = ntohl(m->addr32[j]); 1100 for (i = 31; tmp & (1 << i); --i) 1101 b++; 1102 } 1103 return (b); 1104} 1105 1106void 1107pfi_dohooks(struct pfi_kif *p) 1108{ 1109 for (; p != NULL; p = p->pfik_parent) 1110 dohooks(p->pfik_ah_head, 0); 1111} 1112 1113int 1114pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) 1115{ 1116 if (af == AF_INET) { 1117 switch (dyn->pfid_acnt4) { 1118 case 0: 1119 return (0); 1120 case 1: 1121 return (PF_MATCHA(0, &dyn->pfid_addr4, 1122 &dyn->pfid_mask4, a, AF_INET)); 1123 default: 1124 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); 1125 } 1126 } else { 1127 switch (dyn->pfid_acnt6) { 1128 case 0: 1129 return (0); 1130 case 1: 1131 return (PF_MATCHA(0, &dyn->pfid_addr6, 1132 &dyn->pfid_mask6, a, AF_INET6)); 1133 default: 1134 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); 1135 } 1136 } 1137} 1138