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