| 1/* $FreeBSD: head/sys/contrib/pf/net/pf_if.c 130613 2004-06-16 23:24:02Z mlaier $ */
|
1/* $OpenBSD: pf_if.c,v 1.11 2004/03/15 11:38:23 cedric Exp $ */ 2 3/* 4 * Copyright (c) 2001 Daniel Hartmeier 5 * Copyright (c) 2003 Cedric Berger 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * - Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * - Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32
| 2/* $OpenBSD: pf_if.c,v 1.11 2004/03/15 11:38:23 cedric Exp $ */ 3 4/* 5 * Copyright (c) 2001 Daniel Hartmeier 6 * Copyright (c) 2003 Cedric Berger 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * - Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * - Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided 18 * with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33
|
| 34#if defined(__FreeBSD__) 35#include "opt_inet.h" 36#include "opt_inet6.h" 37#endif 38
|
33#include <sys/param.h> 34#include <sys/systm.h>
| 39#include <sys/param.h> 40#include <sys/systm.h>
|
| 41#ifdef __FreeBSD__ 42#include <sys/malloc.h> 43#endif
|
35#include <sys/mbuf.h> 36#include <sys/filio.h> 37#include <sys/socket.h> 38#include <sys/socketvar.h> 39#include <sys/kernel.h>
| 44#include <sys/mbuf.h> 45#include <sys/filio.h> 46#include <sys/socket.h> 47#include <sys/socketvar.h> 48#include <sys/kernel.h>
|
| 49#ifndef __FreeBSD__
|
40#include <sys/device.h>
| 50#include <sys/device.h>
|
| 51#endif
|
41#include <sys/time.h> 42 43#include <net/if.h> 44#include <net/if_types.h> 45 46#include <netinet/in.h> 47#include <netinet/in_var.h> 48#include <netinet/in_systm.h> 49#include <netinet/ip.h> 50#include <netinet/ip_var.h> 51 52#include <net/pfvar.h> 53 54#ifdef INET6 55#include <netinet/ip6.h> 56#endif /* INET6 */ 57 58#define ACCEPT_FLAGS(oklist) \ 59 do { \ 60 if ((flags & ~(oklist)) & \ 61 PFI_FLAG_ALLMASK) \ 62 return (EINVAL); \ 63 } while (0) 64 65#define senderr(e) do { rv = (e); goto _bad; } while (0) 66 67struct pfi_kif **pfi_index2kif;
| 52#include <sys/time.h> 53 54#include <net/if.h> 55#include <net/if_types.h> 56 57#include <netinet/in.h> 58#include <netinet/in_var.h> 59#include <netinet/in_systm.h> 60#include <netinet/ip.h> 61#include <netinet/ip_var.h> 62 63#include <net/pfvar.h> 64 65#ifdef INET6 66#include <netinet/ip6.h> 67#endif /* INET6 */ 68 69#define ACCEPT_FLAGS(oklist) \ 70 do { \ 71 if ((flags & ~(oklist)) & \ 72 PFI_FLAG_ALLMASK) \ 73 return (EINVAL); \ 74 } while (0) 75 76#define senderr(e) do { rv = (e); goto _bad; } while (0) 77 78struct pfi_kif **pfi_index2kif;
|
68struct pfi_kif *pfi_self;
| 79struct pfi_kif *pfi_self, *pfi_dummy;
|
69int pfi_indexlim; 70struct pfi_ifhead pfi_ifs; 71struct pfi_statehead pfi_statehead; 72int pfi_ifcnt;
| 80int pfi_indexlim; 81struct pfi_ifhead pfi_ifs; 82struct pfi_statehead pfi_statehead; 83int pfi_ifcnt;
|
| 84#ifdef __FreeBSD__ 85uma_zone_t pfi_addr_pl; 86#else
|
73struct pool pfi_addr_pl;
| 87struct pool pfi_addr_pl;
|
| 88#endif
|
74long pfi_update = 1; 75struct pfr_addr *pfi_buffer; 76int pfi_buffer_cnt; 77int pfi_buffer_max; 78char pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] = 79 PF_RESERVED_ANCHOR; 80char pfi_interface_ruleset[PF_RULESET_NAME_SIZE] = 81 PF_INTERFACE_RULESET;
| 89long pfi_update = 1; 90struct pfr_addr *pfi_buffer; 91int pfi_buffer_cnt; 92int pfi_buffer_max; 93char pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] = 94 PF_RESERVED_ANCHOR; 95char pfi_interface_ruleset[PF_RULESET_NAME_SIZE] = 96 PF_INTERFACE_RULESET;
|
| 97#ifdef __FreeBSD__ 98eventhandler_tag pfi_clone_cookie = NULL; 99eventhandler_tag pfi_attach_cookie = NULL; 100eventhandler_tag pfi_detach_cookie = NULL; 101#endif
|
82 83void pfi_dynaddr_update(void *); 84void pfi_kifaddr_update(void *); 85void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, 86 int, int); 87void pfi_instance_add(struct ifnet *, int, int); 88void pfi_address_add(struct sockaddr *, int, int); 89int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); 90struct pfi_kif *pfi_if_create(const char *, struct pfi_kif *, int); 91void pfi_copy_group(char *, const char *, int); 92void pfi_dynamic_drivers(void); 93void pfi_newgroup(const char *, int); 94int pfi_skip_if(const char *, struct pfi_kif *, int); 95int pfi_unmask(void *); 96void pfi_dohooks(struct pfi_kif *);
| 102 103void pfi_dynaddr_update(void *); 104void pfi_kifaddr_update(void *); 105void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, 106 int, int); 107void pfi_instance_add(struct ifnet *, int, int); 108void pfi_address_add(struct sockaddr *, int, int); 109int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); 110struct pfi_kif *pfi_if_create(const char *, struct pfi_kif *, int); 111void pfi_copy_group(char *, const char *, int); 112void pfi_dynamic_drivers(void); 113void pfi_newgroup(const char *, int); 114int pfi_skip_if(const char *, struct pfi_kif *, int); 115int pfi_unmask(void *); 116void pfi_dohooks(struct pfi_kif *);
|
| 117#ifdef __FreeBSD__ 118void pfi_kifaddr_update_event(void *, struct ifnet *); 119void pfi_attach_clone_event(void * __unused, struct if_clone *); 120void pfi_attach_ifnet_event(void * __unused, struct ifnet *); 121void pfi_detach_ifnet_event(void * __unused, struct ifnet *); 122#endif
|
97 98RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 99RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 100 101#define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" } 102#define PFI_BUFFER_MAX 0x10000
| 123 124RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 125RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 126 127#define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" } 128#define PFI_BUFFER_MAX 0x10000
|
| 129#ifdef __FreeBSD__ 130MALLOC_DEFINE(PFI_MTYPE, "pf_if", "pf interface table"); 131#else
|
103#define PFI_MTYPE M_IFADDR
| 132#define PFI_MTYPE M_IFADDR
|
| 133#endif
|
104 105void 106pfi_initialize(void) 107{
| 134 135void 136pfi_initialize(void) 137{
|
| 138#ifdef __FreeBSD__ 139 struct ifnet *ifp; 140#endif 141
|
108 if (pfi_self != NULL) /* already initialized */ 109 return; 110 111 TAILQ_INIT(&pfi_statehead);
| 142 if (pfi_self != NULL) /* already initialized */ 143 return; 144 145 TAILQ_INIT(&pfi_statehead);
|
| 146#ifndef __FreeBSD__
|
112 pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 113 "pfiaddrpl", &pool_allocator_nointr);
| 147 pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 148 "pfiaddrpl", &pool_allocator_nointr);
|
| 149#endif
|
114 pfi_buffer_max = 64; 115 pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer), 116 PFI_MTYPE, M_WAITOK); 117 pfi_self = pfi_if_create("self", NULL, PFI_IFLAG_GROUP); 118 pfi_dynamic_drivers();
| 150 pfi_buffer_max = 64; 151 pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer), 152 PFI_MTYPE, M_WAITOK); 153 pfi_self = pfi_if_create("self", NULL, PFI_IFLAG_GROUP); 154 pfi_dynamic_drivers();
|
| 155#ifdef __FreeBSD__ 156 PF_LOCK(); 157 IFNET_RLOCK(); 158 TAILQ_FOREACH(ifp, &ifnet, if_link) 159 if (ifp->if_dunit != IF_DUNIT_NONE) { 160 IFNET_RUNLOCK(); 161 pfi_attach_ifnet(ifp); 162 IFNET_RLOCK(); 163 } 164 IFNET_RUNLOCK(); 165 PF_UNLOCK(); 166 pfi_dummy = pfi_if_create("notyet", pfi_self, 167 PFI_IFLAG_GROUP | PFI_IFLAG_DYNAMIC); 168 pfi_attach_cookie = EVENTHANDLER_REGISTER(ifnet_arrival_event, 169 pfi_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); 170 pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event, 171 pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); 172 pfi_clone_cookie = EVENTHANDLER_REGISTER(if_clone_event, 173 pfi_attach_clone_event, NULL, EVENTHANDLER_PRI_ANY); 174#endif
|
119} 120
| 175} 176
|
| 177#ifdef __FreeBSD__
|
121void
| 178void
|
| 179pfi_cleanup(void) 180{ 181 struct pfi_kif *p, key; 182 struct ifnet *ifp; 183 184 PF_ASSERT(MA_OWNED); 185 PF_UNLOCK(); 186 187 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, pfi_attach_cookie); 188 EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfi_detach_cookie); 189 EVENTHANDLER_DEREGISTER(if_clone_event, pfi_clone_cookie); 190 191 IFNET_RLOCK(); 192 /* release PFI_IFLAG_INSTANCE */ 193 TAILQ_FOREACH(ifp, &ifnet, if_link) { 194 strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 195 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 196 if (p != NULL) { 197 PF_LOCK(); 198 pfi_detach_ifnet(ifp); 199 PF_UNLOCK(); 200 } 201 } 202 IFNET_RUNLOCK(); 203 204 PF_LOCK(); 205 /* XXX clear all other interface group */ 206 while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) { 207 RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 208 209 free(p->pfik_ah_head, PFI_MTYPE); 210 free(p, PFI_MTYPE); 211 } 212 free(pfi_index2kif, PFI_MTYPE); 213 free(pfi_buffer, PFI_MTYPE); 214 pfi_index2kif = NULL; 215 pfi_buffer = NULL; 216 pfi_self = NULL; 217} 218 219/* 220 * Wrapper functions for FreeBSD eventhandler 221 */ 222void 223pfi_kifaddr_update_event(void *arg, struct ifnet *ifp) 224{ 225 struct pfi_kif *p = arg; 226 227 PF_LOCK(); 228 /* 229 * Check to see if it is 'our' interface as we do not have per 230 * interface hooks and thus get an update for every interface. 231 */ 232 if (p && p->pfik_ifp == ifp) 233 pfi_kifaddr_update(p); 234 PF_UNLOCK(); 235} 236 237void 238pfi_attach_clone_event(void *arg __unused, struct if_clone *ifc) 239{ 240 PF_LOCK(); 241 pfi_attach_clone(ifc); 242 PF_UNLOCK(); 243} 244 245void 246pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp) 247{ 248 PF_LOCK(); 249 if (ifp->if_dunit != IF_DUNIT_NONE) 250 pfi_attach_ifnet(ifp); 251 PF_UNLOCK(); 252} 253 254void 255pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp) 256{ 257 PF_LOCK(); 258 pfi_detach_ifnet(ifp); 259 PF_UNLOCK(); 260} 261#endif /* __FreeBSD__ */ 262 263void
|
122pfi_attach_clone(struct if_clone *ifc) 123{ 124 pfi_initialize(); 125 pfi_newgroup(ifc->ifc_name, PFI_IFLAG_CLONABLE); 126} 127 128void 129pfi_attach_ifnet(struct ifnet *ifp) 130{ 131 struct pfi_kif *p, *q, key; 132 int s;
| 264pfi_attach_clone(struct if_clone *ifc) 265{ 266 pfi_initialize(); 267 pfi_newgroup(ifc->ifc_name, PFI_IFLAG_CLONABLE); 268} 269 270void 271pfi_attach_ifnet(struct ifnet *ifp) 272{ 273 struct pfi_kif *p, *q, key; 274 int s;
|
| 275#ifdef __FreeBSD__ 276 int realname; 277#endif
|
133 134 pfi_initialize(); 135 s = splsoftnet(); 136 pfi_update++; 137 if (ifp->if_index >= pfi_indexlim) { 138 /* 139 * grow pfi_index2kif, similar to ifindex2ifnet code in if.c 140 */ 141 size_t m, n, oldlim; 142 struct pfi_kif **mp, **np; 143 144 oldlim = pfi_indexlim; 145 if (pfi_indexlim == 0) 146 pfi_indexlim = 64; 147 while (ifp->if_index >= pfi_indexlim) 148 pfi_indexlim <<= 1; 149 150 m = oldlim * sizeof(struct pfi_kif *); 151 mp = pfi_index2kif; 152 n = pfi_indexlim * sizeof(struct pfi_kif *);
| 278 279 pfi_initialize(); 280 s = splsoftnet(); 281 pfi_update++; 282 if (ifp->if_index >= pfi_indexlim) { 283 /* 284 * grow pfi_index2kif, similar to ifindex2ifnet code in if.c 285 */ 286 size_t m, n, oldlim; 287 struct pfi_kif **mp, **np; 288 289 oldlim = pfi_indexlim; 290 if (pfi_indexlim == 0) 291 pfi_indexlim = 64; 292 while (ifp->if_index >= pfi_indexlim) 293 pfi_indexlim <<= 1; 294 295 m = oldlim * sizeof(struct pfi_kif *); 296 mp = pfi_index2kif; 297 n = pfi_indexlim * sizeof(struct pfi_kif *);
|
| 298#ifdef __FreeBSD__ 299 np = malloc(n, PFI_MTYPE, M_NOWAIT); 300#else
|
153 np = malloc(n, PFI_MTYPE, M_DONTWAIT);
| 301 np = malloc(n, PFI_MTYPE, M_DONTWAIT);
|
| 302#endif
|
154 if (np == NULL) 155 panic("pfi_attach_ifnet: " 156 "cannot allocate translation table"); 157 bzero(np, n); 158 if (mp != NULL) 159 bcopy(mp, np, m); 160 pfi_index2kif = np; 161 if (mp != NULL) 162 free(mp, PFI_MTYPE); 163 } 164 165 strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 166 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
| 303 if (np == NULL) 304 panic("pfi_attach_ifnet: " 305 "cannot allocate translation table"); 306 bzero(np, n); 307 if (mp != NULL) 308 bcopy(mp, np, m); 309 pfi_index2kif = np; 310 if (mp != NULL) 311 free(mp, PFI_MTYPE); 312 } 313 314 strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 315 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
|
| 316#ifdef __FreeBSD__ 317 /* some additional trickery for placeholders */ 318 if ((p == NULL) || (p->pfik_parent == pfi_dummy)) { 319 /* are we looking at a renamed instance or not? */ 320 pfi_copy_group(key.pfik_name, ifp->if_xname, 321 sizeof(key.pfik_name)); 322 realname = (strncmp(key.pfik_name, ifp->if_dname, 323 sizeof(key.pfik_name)) == 0); 324 /* add group */ 325 /* we can change if_xname, hence use if_dname as group id */ 326 pfi_copy_group(key.pfik_name, ifp->if_dname, 327 sizeof(key.pfik_name)); 328 q = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 329 if (q == NULL) 330 q = pfi_if_create(key.pfik_name, pfi_self, 331 PFI_IFLAG_GROUP|PFI_IFLAG_DYNAMIC); 332 else if (q->pfik_parent == pfi_dummy) { 333 q->pfik_parent = pfi_self; 334 q->pfik_flags = (PFI_IFLAG_GROUP | PFI_IFLAG_DYNAMIC); 335 } 336 if (q == NULL) 337 panic("pfi_attach_ifnet: " 338 "cannot allocate '%s' group", key.pfik_name); 339 340 /* add/modify interface */ 341 if (p == NULL) 342 p = pfi_if_create(ifp->if_xname, q, 343 realname?PFI_IFLAG_INSTANCE:PFI_IFLAG_PLACEHOLDER); 344 else { 345 /* remove from the dummy group */ 346 /* XXX: copy stats? We should not have any!!! */ 347 pfi_dummy->pfik_delcnt++; 348 TAILQ_REMOVE(&pfi_dummy->pfik_grouphead, p, 349 pfik_instances); 350 /* move to the right group */ 351 p->pfik_parent = q; 352 q->pfik_addcnt++; 353 TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, 354 pfik_instances); 355 if (realname) { 356 p->pfik_flags &= ~PFI_IFLAG_PLACEHOLDER; 357 p->pfik_flags |= PFI_IFLAG_INSTANCE; 358 } 359 } 360 if (p == NULL) 361 panic("pfi_attach_ifnet: " 362 "cannot allocate '%s' interface", ifp->if_xname); 363#else
|
167 if (p == NULL) { 168 /* add group */ 169 pfi_copy_group(key.pfik_name, ifp->if_xname, 170 sizeof(key.pfik_name)); 171 q = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 172 if (q == NULL) 173 q = pfi_if_create(key.pfik_name, pfi_self, PFI_IFLAG_GROUP);
| 364 if (p == NULL) { 365 /* add group */ 366 pfi_copy_group(key.pfik_name, ifp->if_xname, 367 sizeof(key.pfik_name)); 368 q = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 369 if (q == NULL) 370 q = pfi_if_create(key.pfik_name, pfi_self, PFI_IFLAG_GROUP);
|
| 371 else if (q->pfik_parent == pfi_dummy) { 372 q->pfik_parent = pfi_self; 373 q->pfik_flags = (PFI_IFLAG_GROUP | PFI_IFLAG_DYNAMIC); 374 }
|
174 if (q == NULL) 175 panic("pfi_attach_ifnet: " 176 "cannot allocate '%s' group", key.pfik_name); 177 178 /* add interface */ 179 p = pfi_if_create(ifp->if_xname, q, PFI_IFLAG_INSTANCE); 180 if (p == NULL) 181 panic("pfi_attach_ifnet: " 182 "cannot allocate '%s' interface", ifp->if_xname);
| 375 if (q == NULL) 376 panic("pfi_attach_ifnet: " 377 "cannot allocate '%s' group", key.pfik_name); 378 379 /* add interface */ 380 p = pfi_if_create(ifp->if_xname, q, PFI_IFLAG_INSTANCE); 381 if (p == NULL) 382 panic("pfi_attach_ifnet: " 383 "cannot allocate '%s' interface", ifp->if_xname);
|
| 384#endif
|
183 } else 184 q = p->pfik_parent; 185 p->pfik_ifp = ifp; 186 p->pfik_flags |= PFI_IFLAG_ATTACHED;
| 385 } else 386 q = p->pfik_parent; 387 p->pfik_ifp = ifp; 388 p->pfik_flags |= PFI_IFLAG_ATTACHED;
|
| 389#ifdef __FreeBSD__ 390 PF_UNLOCK(); 391 p->pfik_ah_cookie = EVENTHANDLER_REGISTER(ifaddr_event, 392 pfi_kifaddr_update_event, p, EVENTHANDLER_PRI_ANY); 393 PF_LOCK(); 394#else
|
187 p->pfik_ah_cookie = 188 hook_establish(ifp->if_addrhooks, 1, pfi_kifaddr_update, p);
| 395 p->pfik_ah_cookie = 396 hook_establish(ifp->if_addrhooks, 1, pfi_kifaddr_update, p);
|
| 397#endif
|
189 pfi_index2kif[ifp->if_index] = p; 190 pfi_dohooks(p); 191 splx(s); 192} 193 194void 195pfi_detach_ifnet(struct ifnet *ifp) 196{ 197 struct pfi_kif *p, *q, key; 198 int s; 199 200 strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 201 202 s = splsoftnet(); 203 pfi_update++; 204 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 205 if (p == NULL) { 206 printf("pfi_detach_ifnet: cannot find %s", ifp->if_xname); 207 splx(s); 208 return; 209 }
| 398 pfi_index2kif[ifp->if_index] = p; 399 pfi_dohooks(p); 400 splx(s); 401} 402 403void 404pfi_detach_ifnet(struct ifnet *ifp) 405{ 406 struct pfi_kif *p, *q, key; 407 int s; 408 409 strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); 410 411 s = splsoftnet(); 412 pfi_update++; 413 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 414 if (p == NULL) { 415 printf("pfi_detach_ifnet: cannot find %s", ifp->if_xname); 416 splx(s); 417 return; 418 }
|
| 419#ifdef __FreeBSD__ 420 PF_UNLOCK(); 421 EVENTHANDLER_DEREGISTER(ifaddr_event, p->pfik_ah_cookie); 422 PF_LOCK(); 423#else
|
210 hook_disestablish(p->pfik_ifp->if_addrhooks, p->pfik_ah_cookie);
| 424 hook_disestablish(p->pfik_ifp->if_addrhooks, p->pfik_ah_cookie);
|
| 425#endif
|
211 q = p->pfik_parent; 212 p->pfik_ifp = NULL; 213 p->pfik_flags &= ~PFI_IFLAG_ATTACHED; 214 pfi_index2kif[ifp->if_index] = NULL; 215 pfi_dohooks(p); 216 pfi_maybe_destroy(p); 217 splx(s); 218} 219 220struct pfi_kif * 221pfi_lookup_create(const char *name) 222{ 223 struct pfi_kif *p, *q, key; 224 int s; 225 226 s = splsoftnet(); 227 p = pfi_lookup_if(name); 228 if (p == NULL) { 229 pfi_copy_group(key.pfik_name, name, sizeof(key.pfik_name)); 230 q = pfi_lookup_if(key.pfik_name);
| 426 q = p->pfik_parent; 427 p->pfik_ifp = NULL; 428 p->pfik_flags &= ~PFI_IFLAG_ATTACHED; 429 pfi_index2kif[ifp->if_index] = NULL; 430 pfi_dohooks(p); 431 pfi_maybe_destroy(p); 432 splx(s); 433} 434 435struct pfi_kif * 436pfi_lookup_create(const char *name) 437{ 438 struct pfi_kif *p, *q, key; 439 int s; 440 441 s = splsoftnet(); 442 p = pfi_lookup_if(name); 443 if (p == NULL) { 444 pfi_copy_group(key.pfik_name, name, sizeof(key.pfik_name)); 445 q = pfi_lookup_if(key.pfik_name);
|
| 446#ifdef __FreeBSD__ 447 if ((q != NULL) && (q->pfik_parent != pfi_dummy)) 448 p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE); 449 else { 450 if (pfi_dummy == NULL) 451 panic("no 'notyet' dummy group"); 452 p = pfi_if_create(name, pfi_dummy, 453 PFI_IFLAG_PLACEHOLDER); 454 } 455#else
|
231 if (q != NULL) 232 p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE);
| 456 if (q != NULL) 457 p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE);
|
| 458#endif
|
233 } 234 splx(s); 235 return (p); 236} 237 238struct pfi_kif * 239pfi_attach_rule(const char *name) 240{ 241 struct pfi_kif *p; 242 243 p = pfi_lookup_create(name); 244 if (p != NULL) 245 p->pfik_rules++; 246 return (p); 247} 248 249void 250pfi_detach_rule(struct pfi_kif *p) 251{ 252 if (p == NULL) 253 return; 254 if (p->pfik_rules > 0) 255 p->pfik_rules--; 256 else 257 printf("pfi_detach_rule: reference count at 0\n"); 258 pfi_maybe_destroy(p); 259} 260 261void 262pfi_attach_state(struct pfi_kif *p) 263{ 264 if (!p->pfik_states++) 265 TAILQ_INSERT_TAIL(&pfi_statehead, p, pfik_w_states); 266} 267 268void 269pfi_detach_state(struct pfi_kif *p) 270{ 271 if (p == NULL) 272 return; 273 if (p->pfik_states <= 0) { 274 printf("pfi_detach_state: reference count <= 0\n"); 275 return; 276 } 277 if (!--p->pfik_states) 278 TAILQ_REMOVE(&pfi_statehead, p, pfik_w_states); 279 pfi_maybe_destroy(p); 280} 281 282int 283pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) 284{ 285 struct pfi_dynaddr *dyn; 286 char tblname[PF_TABLE_NAME_SIZE]; 287 struct pf_ruleset *ruleset = NULL; 288 int s, rv = 0; 289 290 if (aw->type != PF_ADDR_DYNIFTL) 291 return (0); 292 dyn = pool_get(&pfi_addr_pl, PR_NOWAIT); 293 if (dyn == NULL) 294 return (1); 295 bzero(dyn, sizeof(*dyn)); 296 297 s = splsoftnet(); 298 dyn->pfid_kif = pfi_attach_rule(aw->v.ifname); 299 if (dyn->pfid_kif == NULL) 300 senderr(1); 301 302 dyn->pfid_net = pfi_unmask(&aw->v.a.mask); 303 if (af == AF_INET && dyn->pfid_net == 32) 304 dyn->pfid_net = 128; 305 strlcpy(tblname, aw->v.ifname, sizeof(tblname)); 306 if (aw->iflags & PFI_AFLAG_NETWORK) 307 strlcat(tblname, ":network", sizeof(tblname)); 308 if (aw->iflags & PFI_AFLAG_BROADCAST) 309 strlcat(tblname, ":broadcast", sizeof(tblname)); 310 if (aw->iflags & PFI_AFLAG_PEER) 311 strlcat(tblname, ":peer", sizeof(tblname)); 312 if (aw->iflags & PFI_AFLAG_NOALIAS) 313 strlcat(tblname, ":0", sizeof(tblname)); 314 if (dyn->pfid_net != 128) 315 snprintf(tblname + strlen(tblname), 316 sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); 317 ruleset = pf_find_or_create_ruleset(pfi_reserved_anchor, 318 pfi_interface_ruleset); 319 if (ruleset == NULL) 320 senderr(1); 321 322 dyn->pfid_kt = pfr_attach_table(ruleset, tblname); 323 if (dyn->pfid_kt == NULL) 324 senderr(1); 325 326 dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; 327 dyn->pfid_iflags = aw->iflags; 328 dyn->pfid_af = af; 329 dyn->pfid_hook_cookie = hook_establish(dyn->pfid_kif->pfik_ah_head, 1, 330 pfi_dynaddr_update, dyn); 331 if (dyn->pfid_hook_cookie == NULL) 332 senderr(1); 333 334 aw->p.dyn = dyn; 335 pfi_dynaddr_update(aw->p.dyn); 336 splx(s); 337 return (0); 338 339_bad: 340 if (dyn->pfid_kt != NULL) 341 pfr_detach_table(dyn->pfid_kt); 342 if (ruleset != NULL) 343 pf_remove_if_empty_ruleset(ruleset); 344 if (dyn->pfid_kif != NULL) 345 pfi_detach_rule(dyn->pfid_kif); 346 pool_put(&pfi_addr_pl, dyn); 347 splx(s); 348 return (rv); 349} 350 351void 352pfi_dynaddr_update(void *p) 353{ 354 struct pfi_dynaddr *dyn = (struct pfi_dynaddr *)p; 355 struct pfi_kif *kif = dyn->pfid_kif; 356 struct pfr_ktable *kt = dyn->pfid_kt; 357 358 if (dyn == NULL || kif == NULL || kt == NULL) 359 panic("pfi_dynaddr_update"); 360 if (kt->pfrkt_larg != pfi_update) { 361 /* this table needs to be brought up-to-date */ 362 pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); 363 kt->pfrkt_larg = pfi_update; 364 } 365 pfr_dynaddr_update(kt, dyn); 366} 367 368void 369pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) 370{ 371 int e, size2 = 0; 372 struct pfi_kif *p; 373 struct pfr_table t; 374 375 if ((kif->pfik_flags & PFI_IFLAG_INSTANCE) && kif->pfik_ifp == NULL) { 376 pfr_clr_addrs(&kt->pfrkt_t, NULL, 0); 377 return; 378 } 379 pfi_buffer_cnt = 0; 380 if ((kif->pfik_flags & PFI_IFLAG_INSTANCE)) 381 pfi_instance_add(kif->pfik_ifp, net, flags); 382 else if (strcmp(kif->pfik_name, "self")) { 383 TAILQ_FOREACH(p, &kif->pfik_grouphead, pfik_instances) 384 pfi_instance_add(p->pfik_ifp, net, flags); 385 } else { 386 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) 387 if (p->pfik_flags & PFI_IFLAG_INSTANCE) 388 pfi_instance_add(p->pfik_ifp, net, flags); 389 } 390 t = kt->pfrkt_t; 391 t.pfrt_flags = 0; 392 if ((e = pfr_set_addrs(&t, pfi_buffer, pfi_buffer_cnt, &size2, 393 NULL, NULL, NULL, 0))) 394 printf("pfi_table_update: cannot set %d new addresses " 395 "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e); 396} 397 398void 399pfi_instance_add(struct ifnet *ifp, int net, int flags) 400{ 401 struct ifaddr *ia; 402 int got4 = 0, got6 = 0; 403 int net2, af; 404 405 if (ifp == NULL) 406 return; 407 TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) { 408 if (ia->ifa_addr == NULL) 409 continue; 410 af = ia->ifa_addr->sa_family; 411 if (af != AF_INET && af != AF_INET6) 412 continue; 413 if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) 414 continue; 415 if ((flags & PFI_AFLAG_BROADCAST) && 416 !(ifp->if_flags & IFF_BROADCAST)) 417 continue; 418 if ((flags & PFI_AFLAG_PEER) && 419 !(ifp->if_flags & IFF_POINTOPOINT)) 420 continue; 421 if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && 422 IN6_IS_ADDR_LINKLOCAL( 423 &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr)) 424 continue; 425 if (flags & PFI_AFLAG_NOALIAS) { 426 if (af == AF_INET && got4) 427 continue; 428 if (af == AF_INET6 && got6) 429 continue; 430 } 431 if (af == AF_INET) 432 got4 = 1; 433 else 434 got6 = 1; 435 net2 = net; 436 if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { 437 if (af == AF_INET) { 438 net2 = pfi_unmask(&((struct sockaddr_in *) 439 ia->ifa_netmask)->sin_addr); 440 } else { 441 net2 = pfi_unmask(&((struct sockaddr_in6 *) 442 ia->ifa_netmask)->sin6_addr); 443 } 444 } 445 if (af == AF_INET && net2 > 32) 446 net2 = 32; 447 if (flags & PFI_AFLAG_BROADCAST) 448 pfi_address_add(ia->ifa_broadaddr, af, net2); 449 else if (flags & PFI_AFLAG_PEER) 450 pfi_address_add(ia->ifa_dstaddr, af, net2); 451 else 452 pfi_address_add(ia->ifa_addr, af, net2); 453 } 454} 455 456void 457pfi_address_add(struct sockaddr *sa, int af, int net) 458{ 459 struct pfr_addr *p; 460 int i; 461 462 if (pfi_buffer_cnt >= pfi_buffer_max) { 463 int new_max = pfi_buffer_max * 2; 464 465 if (new_max > PFI_BUFFER_MAX) { 466 printf("pfi_address_add: address buffer full (%d/%d)\n", 467 pfi_buffer_cnt, PFI_BUFFER_MAX); 468 return; 469 }
| 459 } 460 splx(s); 461 return (p); 462} 463 464struct pfi_kif * 465pfi_attach_rule(const char *name) 466{ 467 struct pfi_kif *p; 468 469 p = pfi_lookup_create(name); 470 if (p != NULL) 471 p->pfik_rules++; 472 return (p); 473} 474 475void 476pfi_detach_rule(struct pfi_kif *p) 477{ 478 if (p == NULL) 479 return; 480 if (p->pfik_rules > 0) 481 p->pfik_rules--; 482 else 483 printf("pfi_detach_rule: reference count at 0\n"); 484 pfi_maybe_destroy(p); 485} 486 487void 488pfi_attach_state(struct pfi_kif *p) 489{ 490 if (!p->pfik_states++) 491 TAILQ_INSERT_TAIL(&pfi_statehead, p, pfik_w_states); 492} 493 494void 495pfi_detach_state(struct pfi_kif *p) 496{ 497 if (p == NULL) 498 return; 499 if (p->pfik_states <= 0) { 500 printf("pfi_detach_state: reference count <= 0\n"); 501 return; 502 } 503 if (!--p->pfik_states) 504 TAILQ_REMOVE(&pfi_statehead, p, pfik_w_states); 505 pfi_maybe_destroy(p); 506} 507 508int 509pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) 510{ 511 struct pfi_dynaddr *dyn; 512 char tblname[PF_TABLE_NAME_SIZE]; 513 struct pf_ruleset *ruleset = NULL; 514 int s, rv = 0; 515 516 if (aw->type != PF_ADDR_DYNIFTL) 517 return (0); 518 dyn = pool_get(&pfi_addr_pl, PR_NOWAIT); 519 if (dyn == NULL) 520 return (1); 521 bzero(dyn, sizeof(*dyn)); 522 523 s = splsoftnet(); 524 dyn->pfid_kif = pfi_attach_rule(aw->v.ifname); 525 if (dyn->pfid_kif == NULL) 526 senderr(1); 527 528 dyn->pfid_net = pfi_unmask(&aw->v.a.mask); 529 if (af == AF_INET && dyn->pfid_net == 32) 530 dyn->pfid_net = 128; 531 strlcpy(tblname, aw->v.ifname, sizeof(tblname)); 532 if (aw->iflags & PFI_AFLAG_NETWORK) 533 strlcat(tblname, ":network", sizeof(tblname)); 534 if (aw->iflags & PFI_AFLAG_BROADCAST) 535 strlcat(tblname, ":broadcast", sizeof(tblname)); 536 if (aw->iflags & PFI_AFLAG_PEER) 537 strlcat(tblname, ":peer", sizeof(tblname)); 538 if (aw->iflags & PFI_AFLAG_NOALIAS) 539 strlcat(tblname, ":0", sizeof(tblname)); 540 if (dyn->pfid_net != 128) 541 snprintf(tblname + strlen(tblname), 542 sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); 543 ruleset = pf_find_or_create_ruleset(pfi_reserved_anchor, 544 pfi_interface_ruleset); 545 if (ruleset == NULL) 546 senderr(1); 547 548 dyn->pfid_kt = pfr_attach_table(ruleset, tblname); 549 if (dyn->pfid_kt == NULL) 550 senderr(1); 551 552 dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; 553 dyn->pfid_iflags = aw->iflags; 554 dyn->pfid_af = af; 555 dyn->pfid_hook_cookie = hook_establish(dyn->pfid_kif->pfik_ah_head, 1, 556 pfi_dynaddr_update, dyn); 557 if (dyn->pfid_hook_cookie == NULL) 558 senderr(1); 559 560 aw->p.dyn = dyn; 561 pfi_dynaddr_update(aw->p.dyn); 562 splx(s); 563 return (0); 564 565_bad: 566 if (dyn->pfid_kt != NULL) 567 pfr_detach_table(dyn->pfid_kt); 568 if (ruleset != NULL) 569 pf_remove_if_empty_ruleset(ruleset); 570 if (dyn->pfid_kif != NULL) 571 pfi_detach_rule(dyn->pfid_kif); 572 pool_put(&pfi_addr_pl, dyn); 573 splx(s); 574 return (rv); 575} 576 577void 578pfi_dynaddr_update(void *p) 579{ 580 struct pfi_dynaddr *dyn = (struct pfi_dynaddr *)p; 581 struct pfi_kif *kif = dyn->pfid_kif; 582 struct pfr_ktable *kt = dyn->pfid_kt; 583 584 if (dyn == NULL || kif == NULL || kt == NULL) 585 panic("pfi_dynaddr_update"); 586 if (kt->pfrkt_larg != pfi_update) { 587 /* this table needs to be brought up-to-date */ 588 pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); 589 kt->pfrkt_larg = pfi_update; 590 } 591 pfr_dynaddr_update(kt, dyn); 592} 593 594void 595pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) 596{ 597 int e, size2 = 0; 598 struct pfi_kif *p; 599 struct pfr_table t; 600 601 if ((kif->pfik_flags & PFI_IFLAG_INSTANCE) && kif->pfik_ifp == NULL) { 602 pfr_clr_addrs(&kt->pfrkt_t, NULL, 0); 603 return; 604 } 605 pfi_buffer_cnt = 0; 606 if ((kif->pfik_flags & PFI_IFLAG_INSTANCE)) 607 pfi_instance_add(kif->pfik_ifp, net, flags); 608 else if (strcmp(kif->pfik_name, "self")) { 609 TAILQ_FOREACH(p, &kif->pfik_grouphead, pfik_instances) 610 pfi_instance_add(p->pfik_ifp, net, flags); 611 } else { 612 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) 613 if (p->pfik_flags & PFI_IFLAG_INSTANCE) 614 pfi_instance_add(p->pfik_ifp, net, flags); 615 } 616 t = kt->pfrkt_t; 617 t.pfrt_flags = 0; 618 if ((e = pfr_set_addrs(&t, pfi_buffer, pfi_buffer_cnt, &size2, 619 NULL, NULL, NULL, 0))) 620 printf("pfi_table_update: cannot set %d new addresses " 621 "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e); 622} 623 624void 625pfi_instance_add(struct ifnet *ifp, int net, int flags) 626{ 627 struct ifaddr *ia; 628 int got4 = 0, got6 = 0; 629 int net2, af; 630 631 if (ifp == NULL) 632 return; 633 TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) { 634 if (ia->ifa_addr == NULL) 635 continue; 636 af = ia->ifa_addr->sa_family; 637 if (af != AF_INET && af != AF_INET6) 638 continue; 639 if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) 640 continue; 641 if ((flags & PFI_AFLAG_BROADCAST) && 642 !(ifp->if_flags & IFF_BROADCAST)) 643 continue; 644 if ((flags & PFI_AFLAG_PEER) && 645 !(ifp->if_flags & IFF_POINTOPOINT)) 646 continue; 647 if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && 648 IN6_IS_ADDR_LINKLOCAL( 649 &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr)) 650 continue; 651 if (flags & PFI_AFLAG_NOALIAS) { 652 if (af == AF_INET && got4) 653 continue; 654 if (af == AF_INET6 && got6) 655 continue; 656 } 657 if (af == AF_INET) 658 got4 = 1; 659 else 660 got6 = 1; 661 net2 = net; 662 if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { 663 if (af == AF_INET) { 664 net2 = pfi_unmask(&((struct sockaddr_in *) 665 ia->ifa_netmask)->sin_addr); 666 } else { 667 net2 = pfi_unmask(&((struct sockaddr_in6 *) 668 ia->ifa_netmask)->sin6_addr); 669 } 670 } 671 if (af == AF_INET && net2 > 32) 672 net2 = 32; 673 if (flags & PFI_AFLAG_BROADCAST) 674 pfi_address_add(ia->ifa_broadaddr, af, net2); 675 else if (flags & PFI_AFLAG_PEER) 676 pfi_address_add(ia->ifa_dstaddr, af, net2); 677 else 678 pfi_address_add(ia->ifa_addr, af, net2); 679 } 680} 681 682void 683pfi_address_add(struct sockaddr *sa, int af, int net) 684{ 685 struct pfr_addr *p; 686 int i; 687 688 if (pfi_buffer_cnt >= pfi_buffer_max) { 689 int new_max = pfi_buffer_max * 2; 690 691 if (new_max > PFI_BUFFER_MAX) { 692 printf("pfi_address_add: address buffer full (%d/%d)\n", 693 pfi_buffer_cnt, PFI_BUFFER_MAX); 694 return; 695 }
|
| 696#ifdef __FreeBSD__
|
470 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
| 697 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
|
| 698 M_NOWAIT); 699#else 700 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
|
471 M_DONTWAIT);
| 701 M_DONTWAIT);
|
| 702#endif
|
472 if (p == NULL) { 473 printf("pfi_address_add: no memory to grow buffer " 474 "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); 475 return; 476 } 477 memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer)); 478 /* no need to zero buffer */ 479 free(pfi_buffer, PFI_MTYPE); 480 pfi_buffer = p; 481 pfi_buffer_max = new_max; 482 } 483 if (af == AF_INET && net > 32) 484 net = 128; 485 p = pfi_buffer + pfi_buffer_cnt++; 486 bzero(p, sizeof(*p)); 487 p->pfra_af = af; 488 p->pfra_net = net; 489 if (af == AF_INET) 490 p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; 491 if (af == AF_INET6) { 492 p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; 493 if (IN6_IS_ADDR_LINKLOCAL(&p->pfra_ip6addr)) 494 p->pfra_ip6addr.s6_addr16[1] = 0; 495 } 496 /* mask network address bits */ 497 if (net < 128) 498 ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); 499 for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) 500 ((caddr_t)p)[i] = 0; 501} 502 503void 504pfi_dynaddr_remove(struct pf_addr_wrap *aw) 505{ 506 int s; 507 508 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 509 aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) 510 return; 511 512 s = splsoftnet(); 513 hook_disestablish(aw->p.dyn->pfid_kif->pfik_ah_head, 514 aw->p.dyn->pfid_hook_cookie); 515 pfi_detach_rule(aw->p.dyn->pfid_kif); 516 aw->p.dyn->pfid_kif = NULL; 517 pfr_detach_table(aw->p.dyn->pfid_kt); 518 aw->p.dyn->pfid_kt = NULL; 519 pool_put(&pfi_addr_pl, aw->p.dyn); 520 aw->p.dyn = NULL; 521 splx(s); 522} 523 524void 525pfi_dynaddr_copyout(struct pf_addr_wrap *aw) 526{ 527 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 528 aw->p.dyn->pfid_kif == NULL) 529 return; 530 aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; 531} 532 533void 534pfi_kifaddr_update(void *v) 535{ 536 int s; 537 538 s = splsoftnet(); 539 pfi_update++; 540 pfi_dohooks(v); 541 splx(s); 542} 543 544int 545pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) 546{ 547 return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); 548} 549 550struct pfi_kif * 551pfi_if_create(const char *name, struct pfi_kif *q, int flags) 552{ 553 struct pfi_kif *p; 554
| 703 if (p == NULL) { 704 printf("pfi_address_add: no memory to grow buffer " 705 "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); 706 return; 707 } 708 memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer)); 709 /* no need to zero buffer */ 710 free(pfi_buffer, PFI_MTYPE); 711 pfi_buffer = p; 712 pfi_buffer_max = new_max; 713 } 714 if (af == AF_INET && net > 32) 715 net = 128; 716 p = pfi_buffer + pfi_buffer_cnt++; 717 bzero(p, sizeof(*p)); 718 p->pfra_af = af; 719 p->pfra_net = net; 720 if (af == AF_INET) 721 p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; 722 if (af == AF_INET6) { 723 p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; 724 if (IN6_IS_ADDR_LINKLOCAL(&p->pfra_ip6addr)) 725 p->pfra_ip6addr.s6_addr16[1] = 0; 726 } 727 /* mask network address bits */ 728 if (net < 128) 729 ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); 730 for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) 731 ((caddr_t)p)[i] = 0; 732} 733 734void 735pfi_dynaddr_remove(struct pf_addr_wrap *aw) 736{ 737 int s; 738 739 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 740 aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) 741 return; 742 743 s = splsoftnet(); 744 hook_disestablish(aw->p.dyn->pfid_kif->pfik_ah_head, 745 aw->p.dyn->pfid_hook_cookie); 746 pfi_detach_rule(aw->p.dyn->pfid_kif); 747 aw->p.dyn->pfid_kif = NULL; 748 pfr_detach_table(aw->p.dyn->pfid_kt); 749 aw->p.dyn->pfid_kt = NULL; 750 pool_put(&pfi_addr_pl, aw->p.dyn); 751 aw->p.dyn = NULL; 752 splx(s); 753} 754 755void 756pfi_dynaddr_copyout(struct pf_addr_wrap *aw) 757{ 758 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 759 aw->p.dyn->pfid_kif == NULL) 760 return; 761 aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; 762} 763 764void 765pfi_kifaddr_update(void *v) 766{ 767 int s; 768 769 s = splsoftnet(); 770 pfi_update++; 771 pfi_dohooks(v); 772 splx(s); 773} 774 775int 776pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) 777{ 778 return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); 779} 780 781struct pfi_kif * 782pfi_if_create(const char *name, struct pfi_kif *q, int flags) 783{ 784 struct pfi_kif *p; 785
|
| 786#ifdef __FreeBSD__ 787 p = malloc(sizeof(*p), PFI_MTYPE, M_NOWAIT); 788#else
|
555 p = malloc(sizeof(*p), PFI_MTYPE, M_DONTWAIT);
| 789 p = malloc(sizeof(*p), PFI_MTYPE, M_DONTWAIT);
|
| 790#endif
|
556 if (p == NULL) 557 return (NULL); 558 bzero(p, sizeof(*p));
| 791 if (p == NULL) 792 return (NULL); 793 bzero(p, sizeof(*p));
|
| 794#ifdef __FreeBSD__
|
559 p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE,
| 795 p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE,
|
| 796 M_NOWAIT); 797#else 798 p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE,
|
560 M_DONTWAIT);
| 799 M_DONTWAIT);
|
| 800#endif
|
561 if (p->pfik_ah_head == NULL) { 562 free(p, PFI_MTYPE); 563 return (NULL); 564 } 565 bzero(p->pfik_ah_head, sizeof(*p->pfik_ah_head)); 566 TAILQ_INIT(p->pfik_ah_head); 567 TAILQ_INIT(&p->pfik_grouphead); 568 strlcpy(p->pfik_name, name, sizeof(p->pfik_name)); 569 RB_INIT(&p->pfik_lan_ext); 570 RB_INIT(&p->pfik_ext_gwy); 571 p->pfik_flags = flags; 572 p->pfik_parent = q;
| 801 if (p->pfik_ah_head == NULL) { 802 free(p, PFI_MTYPE); 803 return (NULL); 804 } 805 bzero(p->pfik_ah_head, sizeof(*p->pfik_ah_head)); 806 TAILQ_INIT(p->pfik_ah_head); 807 TAILQ_INIT(&p->pfik_grouphead); 808 strlcpy(p->pfik_name, name, sizeof(p->pfik_name)); 809 RB_INIT(&p->pfik_lan_ext); 810 RB_INIT(&p->pfik_ext_gwy); 811 p->pfik_flags = flags; 812 p->pfik_parent = q;
|
| 813#ifdef __FreeBSD__ 814 p->pfik_tzero = time_second; 815#else
|
573 p->pfik_tzero = time.tv_sec;
| 816 p->pfik_tzero = time.tv_sec;
|
| 817#endif
|
574 575 RB_INSERT(pfi_ifhead, &pfi_ifs, p); 576 if (q != NULL) { 577 q->pfik_addcnt++; 578 TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, pfik_instances); 579 } 580 pfi_ifcnt++; 581 return (p); 582} 583 584int 585pfi_maybe_destroy(struct pfi_kif *p) 586{ 587 int i, j, k, s; 588 struct pfi_kif *q = p->pfik_parent; 589 590 if ((p->pfik_flags & (PFI_IFLAG_ATTACHED | PFI_IFLAG_GROUP)) || 591 p->pfik_rules > 0 || p->pfik_states > 0)
| 818 819 RB_INSERT(pfi_ifhead, &pfi_ifs, p); 820 if (q != NULL) { 821 q->pfik_addcnt++; 822 TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, pfik_instances); 823 } 824 pfi_ifcnt++; 825 return (p); 826} 827 828int 829pfi_maybe_destroy(struct pfi_kif *p) 830{ 831 int i, j, k, s; 832 struct pfi_kif *q = p->pfik_parent; 833 834 if ((p->pfik_flags & (PFI_IFLAG_ATTACHED | PFI_IFLAG_GROUP)) || 835 p->pfik_rules > 0 || p->pfik_states > 0)
|
| 836#ifdef __FreeBSD__ 837 if (!(p->pfik_flags & PFI_IFLAG_PLACEHOLDER)) 838#endif
|
592 return (0); 593 594 s = splsoftnet(); 595 if (q != NULL) { 596 for (i = 0; i < 2; i++) 597 for (j = 0; j < 2; j++) 598 for (k = 0; k < 2; k++) { 599 q->pfik_bytes[i][j][k] += 600 p->pfik_bytes[i][j][k]; 601 q->pfik_packets[i][j][k] += 602 p->pfik_packets[i][j][k];
| 839 return (0); 840 841 s = splsoftnet(); 842 if (q != NULL) { 843 for (i = 0; i < 2; i++) 844 for (j = 0; j < 2; j++) 845 for (k = 0; k < 2; k++) { 846 q->pfik_bytes[i][j][k] += 847 p->pfik_bytes[i][j][k]; 848 q->pfik_packets[i][j][k] += 849 p->pfik_packets[i][j][k];
|
| 850#ifdef __FreeBSD__ 851 /* clear stats in case we return to the dummy group */ 852 p->pfik_bytes[i][j][k] = 0; 853 p->pfik_packets[i][j][k] = 0; 854#endif
|
603 } 604 q->pfik_delcnt++; 605 TAILQ_REMOVE(&q->pfik_grouphead, p, pfik_instances); 606 }
| 855 } 856 q->pfik_delcnt++; 857 TAILQ_REMOVE(&q->pfik_grouphead, p, pfik_instances); 858 }
|
| 859#ifdef __FreeBSD__ 860 if (p->pfik_rules > 0 || p->pfik_states > 0) { 861 /* move back to the dummy group */ 862 p->pfik_parent = pfi_dummy; 863 pfi_dummy->pfik_addcnt++; 864 TAILQ_INSERT_TAIL(&pfi_dummy->pfik_grouphead, p, 865 pfik_instances); 866 return (0); 867 } 868#endif
|
607 pfi_ifcnt--; 608 RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 609 splx(s); 610 611 free(p->pfik_ah_head, PFI_MTYPE); 612 free(p, PFI_MTYPE); 613 return (1); 614} 615 616void 617pfi_copy_group(char *p, const char *q, int m) 618{ 619 while (m > 1 && *q && !(*q >= '0' && *q <= '9')) { 620 *p++ = *q++; 621 m--; 622 } 623 if (m > 0) 624 *p++ = '\0'; 625} 626 627void 628pfi_dynamic_drivers(void) 629{
| 869 pfi_ifcnt--; 870 RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 871 splx(s); 872 873 free(p->pfik_ah_head, PFI_MTYPE); 874 free(p, PFI_MTYPE); 875 return (1); 876} 877 878void 879pfi_copy_group(char *p, const char *q, int m) 880{ 881 while (m > 1 && *q && !(*q >= '0' && *q <= '9')) { 882 *p++ = *q++; 883 m--; 884 } 885 if (m > 0) 886 *p++ = '\0'; 887} 888 889void 890pfi_dynamic_drivers(void) 891{
|
| 892#ifdef __FreeBSD__ 893 struct ifnet *ifp; 894 895/* 896 * For FreeBSD basically every interface is "dynamic" as we can unload 897 * modules e.g. 898 */ 899 900 IFNET_RLOCK(); 901 TAILQ_FOREACH(ifp, &ifnet, if_link) { 902 if (ifp->if_dunit == IF_DUNIT_NONE) 903 continue; 904 pfi_newgroup(ifp->if_dname, PFI_IFLAG_DYNAMIC); 905 } 906 IFNET_RUNLOCK(); 907#else
|
630 char *buses[] = PFI_DYNAMIC_BUSES; 631 int nbuses = sizeof(buses)/sizeof(buses[0]); 632 int enabled[sizeof(buses)/sizeof(buses[0])]; 633 struct device *dev; 634 struct cfdata *cf; 635 struct cfdriver *drv; 636 short *p; 637 int i; 638 639 bzero(enabled, sizeof(enabled)); 640 TAILQ_FOREACH(dev, &alldevs, dv_list) { 641 if (!(dev->dv_flags & DVF_ACTIVE)) 642 continue; 643 for (i = 0; i < nbuses; i++) 644 if (!enabled[i] && !strcmp(buses[i], 645 dev->dv_cfdata->cf_driver->cd_name)) 646 enabled[i] = 1; 647 } 648 for (cf = cfdata; cf->cf_driver; cf++) { 649 if (cf->cf_driver->cd_class != DV_IFNET) 650 continue; 651 for (p = cf->cf_parents; p && *p >= 0; p++) { 652 if ((drv = cfdata[*p].cf_driver) == NULL) 653 continue; 654 for (i = 0; i < nbuses; i++) 655 if (enabled[i] && 656 !strcmp(drv->cd_name, buses[i])) 657 break; 658 if (i < nbuses) { 659 pfi_newgroup(cf->cf_driver->cd_name, 660 PFI_IFLAG_DYNAMIC); 661 break; 662 } 663 } 664 }
| 908 char *buses[] = PFI_DYNAMIC_BUSES; 909 int nbuses = sizeof(buses)/sizeof(buses[0]); 910 int enabled[sizeof(buses)/sizeof(buses[0])]; 911 struct device *dev; 912 struct cfdata *cf; 913 struct cfdriver *drv; 914 short *p; 915 int i; 916 917 bzero(enabled, sizeof(enabled)); 918 TAILQ_FOREACH(dev, &alldevs, dv_list) { 919 if (!(dev->dv_flags & DVF_ACTIVE)) 920 continue; 921 for (i = 0; i < nbuses; i++) 922 if (!enabled[i] && !strcmp(buses[i], 923 dev->dv_cfdata->cf_driver->cd_name)) 924 enabled[i] = 1; 925 } 926 for (cf = cfdata; cf->cf_driver; cf++) { 927 if (cf->cf_driver->cd_class != DV_IFNET) 928 continue; 929 for (p = cf->cf_parents; p && *p >= 0; p++) { 930 if ((drv = cfdata[*p].cf_driver) == NULL) 931 continue; 932 for (i = 0; i < nbuses; i++) 933 if (enabled[i] && 934 !strcmp(drv->cd_name, buses[i])) 935 break; 936 if (i < nbuses) { 937 pfi_newgroup(cf->cf_driver->cd_name, 938 PFI_IFLAG_DYNAMIC); 939 break; 940 } 941 } 942 }
|
| 943#endif
|
665} 666 667void 668pfi_newgroup(const char *name, int flags) 669{ 670 struct pfi_kif *p; 671 672 p = pfi_lookup_if(name); 673 if (p == NULL) 674 p = pfi_if_create(name, pfi_self, PFI_IFLAG_GROUP); 675 if (p == NULL) { 676 printf("pfi_newgroup: cannot allocate '%s' group", name); 677 return; 678 } 679 p->pfik_flags |= flags; 680} 681 682void 683pfi_fill_oldstatus(struct pf_status *pfs) 684{ 685 struct pfi_kif *p, key; 686 int i, j, k, s; 687 688 strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name)); 689 s = splsoftnet(); 690 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 691 if (p == NULL) { 692 splx(s); 693 return; 694 } 695 bzero(pfs->pcounters, sizeof(pfs->pcounters)); 696 bzero(pfs->bcounters, sizeof(pfs->bcounters)); 697 for (i = 0; i < 2; i++) 698 for (j = 0; j < 2; j++) 699 for (k = 0; k < 2; k++) { 700 pfs->pcounters[i][j][k] = 701 p->pfik_packets[i][j][k]; 702 pfs->bcounters[i][j] += 703 p->pfik_bytes[i][j][k]; 704 } 705 splx(s); 706} 707 708int 709pfi_clr_istats(const char *name, int *nzero, int flags) 710{ 711 struct pfi_kif *p; 712 int n = 0, s;
| 944} 945 946void 947pfi_newgroup(const char *name, int flags) 948{ 949 struct pfi_kif *p; 950 951 p = pfi_lookup_if(name); 952 if (p == NULL) 953 p = pfi_if_create(name, pfi_self, PFI_IFLAG_GROUP); 954 if (p == NULL) { 955 printf("pfi_newgroup: cannot allocate '%s' group", name); 956 return; 957 } 958 p->pfik_flags |= flags; 959} 960 961void 962pfi_fill_oldstatus(struct pf_status *pfs) 963{ 964 struct pfi_kif *p, key; 965 int i, j, k, s; 966 967 strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name)); 968 s = splsoftnet(); 969 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 970 if (p == NULL) { 971 splx(s); 972 return; 973 } 974 bzero(pfs->pcounters, sizeof(pfs->pcounters)); 975 bzero(pfs->bcounters, sizeof(pfs->bcounters)); 976 for (i = 0; i < 2; i++) 977 for (j = 0; j < 2; j++) 978 for (k = 0; k < 2; k++) { 979 pfs->pcounters[i][j][k] = 980 p->pfik_packets[i][j][k]; 981 pfs->bcounters[i][j] += 982 p->pfik_bytes[i][j][k]; 983 } 984 splx(s); 985} 986 987int 988pfi_clr_istats(const char *name, int *nzero, int flags) 989{ 990 struct pfi_kif *p; 991 int n = 0, s;
|
| 992#ifdef __FreeBSD__ 993 long tzero = time_second; 994#else
|
713 long tzero = time.tv_sec;
| 995 long tzero = time.tv_sec;
|
| 996#endif
|
714 715 s = splsoftnet(); 716 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); 717 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 718 if (pfi_skip_if(name, p, flags)) 719 continue; 720 bzero(p->pfik_packets, sizeof(p->pfik_packets)); 721 bzero(p->pfik_bytes, sizeof(p->pfik_bytes)); 722 p->pfik_tzero = tzero; 723 n++; 724 } 725 splx(s); 726 if (nzero != NULL) 727 *nzero = n; 728 return (0); 729} 730 731int 732pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags) 733{ 734 struct pfi_kif *p; 735 int s, n = 0;
| 997 998 s = splsoftnet(); 999 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); 1000 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 1001 if (pfi_skip_if(name, p, flags)) 1002 continue; 1003 bzero(p->pfik_packets, sizeof(p->pfik_packets)); 1004 bzero(p->pfik_bytes, sizeof(p->pfik_bytes)); 1005 p->pfik_tzero = tzero; 1006 n++; 1007 } 1008 splx(s); 1009 if (nzero != NULL) 1010 *nzero = n; 1011 return (0); 1012} 1013 1014int 1015pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags) 1016{ 1017 struct pfi_kif *p; 1018 int s, n = 0;
|
| 1019#ifdef __FreeBSD__ 1020 int ec; 1021#endif
|
736 737 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); 738 s = splsoftnet(); 739 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 740 if (pfi_skip_if(name, p, flags)) 741 continue; 742 if (*size > n++) { 743 if (!p->pfik_tzero) 744 p->pfik_tzero = boottime.tv_sec;
| 1022 1023 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); 1024 s = splsoftnet(); 1025 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 1026 if (pfi_skip_if(name, p, flags)) 1027 continue; 1028 if (*size > n++) { 1029 if (!p->pfik_tzero) 1030 p->pfik_tzero = boottime.tv_sec;
|
| 1031#ifdef __FreeBSD__ 1032 PF_COPYOUT(p, buf++, sizeof(*buf), ec); 1033 if (ec) { 1034#else
|
745 if (copyout(p, buf++, sizeof(*buf))) {
| 1035 if (copyout(p, buf++, sizeof(*buf))) {
|
| 1036#endif
|
746 splx(s); 747 return (EFAULT); 748 } 749 } 750 } 751 splx(s); 752 *size = n; 753 return (0); 754} 755 756struct pfi_kif * 757pfi_lookup_if(const char *name) 758{ 759 struct pfi_kif *p, key; 760 761 strlcpy(key.pfik_name, name, sizeof(key.pfik_name)); 762 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 763 return (p); 764} 765 766int 767pfi_skip_if(const char *filter, struct pfi_kif *p, int f) 768{ 769 int n; 770 771 if ((p->pfik_flags & PFI_IFLAG_GROUP) && !(f & PFI_FLAG_GROUP)) 772 return (1); 773 if ((p->pfik_flags & PFI_IFLAG_INSTANCE) && !(f & PFI_FLAG_INSTANCE)) 774 return (1); 775 if (filter == NULL || !*filter) 776 return (0); 777 if (!strcmp(p->pfik_name, filter)) 778 return (0); /* exact match */ 779 n = strlen(filter); 780 if (n < 1 || n >= IFNAMSIZ) 781 return (1); /* sanity check */ 782 if (filter[n-1] >= '0' && filter[n-1] <= '9') 783 return (1); /* only do exact match in that case */ 784 if (strncmp(p->pfik_name, filter, n)) 785 return (1); /* prefix doesn't match */ 786 return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9'); 787} 788 789/* from pf_print_state.c */ 790int 791pfi_unmask(void *addr) 792{ 793 struct pf_addr *m = addr; 794 int i = 31, j = 0, b = 0; 795 u_int32_t tmp; 796 797 while (j < 4 && m->addr32[j] == 0xffffffff) { 798 b += 32; 799 j++; 800 } 801 if (j < 4) { 802 tmp = ntohl(m->addr32[j]); 803 for (i = 31; tmp & (1 << i); --i) 804 b++; 805 } 806 return (b); 807} 808 809void 810pfi_dohooks(struct pfi_kif *p) 811{ 812 for (; p != NULL; p = p->pfik_parent) 813 dohooks(p->pfik_ah_head, 0); 814} 815 816int 817pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) 818{ 819 if (af == AF_INET) { 820 switch (dyn->pfid_acnt4) { 821 case 0: 822 return (0); 823 case 1: 824 return (PF_MATCHA(0, &dyn->pfid_addr4, 825 &dyn->pfid_mask4, a, AF_INET)); 826 default: 827 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); 828 } 829 } else { 830 switch (dyn->pfid_acnt6) { 831 case 0: 832 return (0); 833 case 1: 834 return (PF_MATCHA(0, &dyn->pfid_addr6, 835 &dyn->pfid_mask6, a, AF_INET6)); 836 default: 837 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); 838 } 839 } 840}
| 1037 splx(s); 1038 return (EFAULT); 1039 } 1040 } 1041 } 1042 splx(s); 1043 *size = n; 1044 return (0); 1045} 1046 1047struct pfi_kif * 1048pfi_lookup_if(const char *name) 1049{ 1050 struct pfi_kif *p, key; 1051 1052 strlcpy(key.pfik_name, name, sizeof(key.pfik_name)); 1053 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); 1054 return (p); 1055} 1056 1057int 1058pfi_skip_if(const char *filter, struct pfi_kif *p, int f) 1059{ 1060 int n; 1061 1062 if ((p->pfik_flags & PFI_IFLAG_GROUP) && !(f & PFI_FLAG_GROUP)) 1063 return (1); 1064 if ((p->pfik_flags & PFI_IFLAG_INSTANCE) && !(f & PFI_FLAG_INSTANCE)) 1065 return (1); 1066 if (filter == NULL || !*filter) 1067 return (0); 1068 if (!strcmp(p->pfik_name, filter)) 1069 return (0); /* exact match */ 1070 n = strlen(filter); 1071 if (n < 1 || n >= IFNAMSIZ) 1072 return (1); /* sanity check */ 1073 if (filter[n-1] >= '0' && filter[n-1] <= '9') 1074 return (1); /* only do exact match in that case */ 1075 if (strncmp(p->pfik_name, filter, n)) 1076 return (1); /* prefix doesn't match */ 1077 return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9'); 1078} 1079 1080/* from pf_print_state.c */ 1081int 1082pfi_unmask(void *addr) 1083{ 1084 struct pf_addr *m = addr; 1085 int i = 31, j = 0, b = 0; 1086 u_int32_t tmp; 1087 1088 while (j < 4 && m->addr32[j] == 0xffffffff) { 1089 b += 32; 1090 j++; 1091 } 1092 if (j < 4) { 1093 tmp = ntohl(m->addr32[j]); 1094 for (i = 31; tmp & (1 << i); --i) 1095 b++; 1096 } 1097 return (b); 1098} 1099 1100void 1101pfi_dohooks(struct pfi_kif *p) 1102{ 1103 for (; p != NULL; p = p->pfik_parent) 1104 dohooks(p->pfik_ah_head, 0); 1105} 1106 1107int 1108pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) 1109{ 1110 if (af == AF_INET) { 1111 switch (dyn->pfid_acnt4) { 1112 case 0: 1113 return (0); 1114 case 1: 1115 return (PF_MATCHA(0, &dyn->pfid_addr4, 1116 &dyn->pfid_mask4, a, AF_INET)); 1117 default: 1118 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); 1119 } 1120 } else { 1121 switch (dyn->pfid_acnt6) { 1122 case 0: 1123 return (0); 1124 case 1: 1125 return (PF_MATCHA(0, &dyn->pfid_addr6, 1126 &dyn->pfid_mask6, a, AF_INET6)); 1127 default: 1128 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); 1129 } 1130 } 1131}
|