1/* $OpenBSD: pf_if.c,v 1.111 2023/06/30 09:58:30 mvs Exp $ */ 2 3/* 4 * Copyright 2005 Henning Brauer <henning@openbsd.org> 5 * Copyright 2005 Ryan McBride <mcbride@openbsd.org> 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#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/mbuf.h> 38#include <sys/filio.h> 39#include <sys/socket.h> 40#include <sys/socketvar.h> 41#include <sys/kernel.h> 42#include <sys/device.h> 43#include <sys/time.h> 44#include <sys/pool.h> 45#include <sys/syslog.h> 46 47#include <net/if.h> 48#include <net/if_var.h> 49 50#include <netinet/in.h> 51#include <netinet/ip.h> 52#include <netinet/ip_var.h> 53 54#include <net/pfvar.h> 55 56#include <netinet/ip_icmp.h> 57#include <netinet/tcp.h> 58#include <netinet/udp.h> 59 60#ifdef INET6 61#include <netinet/ip6.h> 62#include <netinet/icmp6.h> 63#endif /* INET6 */ 64 65#include <net/pfvar_priv.h> 66 67#define isupper(c) ((c) >= 'A' && (c) <= 'Z') 68#define islower(c) ((c) >= 'a' && (c) <= 'z') 69#define isalpha(c) (isupper(c)||islower(c)) 70 71struct pfi_kif *pfi_all = NULL; 72struct pool pfi_addr_pl; 73struct pfi_ifhead pfi_ifs; 74long pfi_update = 1; 75struct pfr_addr *pfi_buffer; 76int pfi_buffer_cnt; 77int pfi_buffer_max; 78 79void pfi_kif_update(struct pfi_kif *); 80void pfi_dynaddr_update(struct pfi_dynaddr *dyn); 81void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, 82 u_int8_t, int); 83void pfi_kifaddr_update(void *); 84void pfi_instance_add(struct ifnet *, u_int8_t, int); 85void pfi_address_add(struct sockaddr *, sa_family_t, u_int8_t); 86int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); 87int pfi_skip_if(const char *, struct pfi_kif *); 88int pfi_unmask(void *); 89void pfi_group_change(const char *); 90 91RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 92RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 93 94#define PFI_BUFFER_MAX 0x10000 95#define PFI_MTYPE M_PF 96 97struct pfi_kif * 98pfi_kif_alloc(const char *kif_name, int mflags) 99{ 100 struct pfi_kif *kif; 101 102 kif = malloc(sizeof(*pfi_all), PFI_MTYPE, mflags|M_ZERO); 103 if (kif == NULL) 104 return (NULL); 105 strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name)); 106 kif->pfik_tzero = gettime(); 107 TAILQ_INIT(&kif->pfik_dynaddrs); 108 109 if (!strcmp(kif->pfik_name, "any")) { 110 /* both so it works in the ioctl and the regular case */ 111 kif->pfik_flags |= PFI_IFLAG_ANY; 112 kif->pfik_flags_new |= PFI_IFLAG_ANY; 113 } 114 115 return (kif); 116} 117 118void 119pfi_kif_free(struct pfi_kif *kif) 120{ 121 if (kif == NULL) 122 return; 123 124 if (kif->pfik_rules || kif->pfik_states || kif->pfik_routes || 125 kif->pfik_srcnodes || kif->pfik_flagrefs) 126 panic("kif is still alive"); 127 128 free(kif, PFI_MTYPE, sizeof(*kif)); 129} 130 131void 132pfi_initialize(void) 133{ 134 /* 135 * The first time we arrive here is during kernel boot, 136 * when if_attachsetup() for the first time. No locking 137 * is needed in this case, because it's granted there 138 * is a single thread, which sets pfi_all global var. 139 */ 140 if (pfi_all != NULL) /* already initialized */ 141 return; 142 143 pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, IPL_SOFTNET, 0, 144 "pfiaddrpl", NULL); 145 pfi_buffer_max = 64; 146 pfi_buffer = mallocarray(pfi_buffer_max, sizeof(*pfi_buffer), 147 PFI_MTYPE, M_WAITOK); 148 149 pfi_all = pfi_kif_alloc(IFG_ALL, M_WAITOK); 150 151 if (RB_INSERT(pfi_ifhead, &pfi_ifs, pfi_all) != NULL) 152 panic("IFG_ALL kif found already"); 153} 154 155struct pfi_kif * 156pfi_kif_find(const char *kif_name) 157{ 158 struct pfi_kif_cmp s; 159 160 PF_ASSERT_LOCKED(); 161 162 memset(&s, 0, sizeof(s)); 163 strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name)); 164 return (RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)); 165} 166 167struct pfi_kif * 168pfi_kif_get(const char *kif_name, struct pfi_kif **prealloc) 169{ 170 struct pfi_kif *kif; 171 172 PF_ASSERT_LOCKED(); 173 174 if ((kif = pfi_kif_find(kif_name))) 175 return (kif); 176 177 /* create new one */ 178 if ((prealloc == NULL) || (*prealloc == NULL)) { 179 kif = pfi_kif_alloc(kif_name, M_NOWAIT); 180 if (kif == NULL) 181 return (NULL); 182 } else { 183 kif = *prealloc; 184 *prealloc = NULL; 185 } 186 187 RB_INSERT(pfi_ifhead, &pfi_ifs, kif); 188 return (kif); 189} 190 191void 192pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what) 193{ 194 PF_ASSERT_LOCKED(); 195 196 switch (what) { 197 case PFI_KIF_REF_RULE: 198 kif->pfik_rules++; 199 break; 200 case PFI_KIF_REF_STATE: 201 kif->pfik_states++; 202 break; 203 case PFI_KIF_REF_ROUTE: 204 kif->pfik_routes++; 205 break; 206 case PFI_KIF_REF_SRCNODE: 207 kif->pfik_srcnodes++; 208 break; 209 case PFI_KIF_REF_FLAG: 210 kif->pfik_flagrefs++; 211 break; 212 default: 213 panic("pfi_kif_ref with unknown type"); 214 } 215} 216 217void 218pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what) 219{ 220 if (kif == NULL) 221 return; 222 223 PF_ASSERT_LOCKED(); 224 225 switch (what) { 226 case PFI_KIF_REF_NONE: 227 break; 228 case PFI_KIF_REF_RULE: 229 if (kif->pfik_rules <= 0) { 230 DPFPRINTF(LOG_ERR, 231 "pfi_kif_unref (%s): rules refcount <= 0", 232 kif->pfik_name); 233 return; 234 } 235 kif->pfik_rules--; 236 break; 237 case PFI_KIF_REF_STATE: 238 if (kif->pfik_states <= 0) { 239 DPFPRINTF(LOG_ERR, 240 "pfi_kif_unref (%s): state refcount <= 0", 241 kif->pfik_name); 242 return; 243 } 244 kif->pfik_states--; 245 break; 246 case PFI_KIF_REF_ROUTE: 247 if (kif->pfik_routes <= 0) { 248 DPFPRINTF(LOG_ERR, 249 "pfi_kif_unref (%s): route refcount <= 0", 250 kif->pfik_name); 251 return; 252 } 253 kif->pfik_routes--; 254 break; 255 case PFI_KIF_REF_SRCNODE: 256 if (kif->pfik_srcnodes <= 0) { 257 DPFPRINTF(LOG_ERR, 258 "pfi_kif_unref (%s): src-node refcount <= 0", 259 kif->pfik_name); 260 return; 261 } 262 kif->pfik_srcnodes--; 263 break; 264 case PFI_KIF_REF_FLAG: 265 if (kif->pfik_flagrefs <= 0) { 266 DPFPRINTF(LOG_ERR, 267 "pfi_kif_unref (%s): flags refcount <= 0", 268 kif->pfik_name); 269 return; 270 } 271 kif->pfik_flagrefs--; 272 break; 273 default: 274 panic("pfi_kif_unref (%s) with unknown type", kif->pfik_name); 275 } 276 277 if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all) 278 return; 279 280 if (kif->pfik_rules || kif->pfik_states || kif->pfik_routes || 281 kif->pfik_srcnodes || kif->pfik_flagrefs) 282 return; 283 284 RB_REMOVE(pfi_ifhead, &pfi_ifs, kif); 285 free(kif, PFI_MTYPE, sizeof(*kif)); 286} 287 288int 289pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif) 290{ 291 struct ifg_list *p; 292 293 if (rule_kif == NULL || rule_kif == packet_kif) 294 return (1); 295 296 if (rule_kif->pfik_group != NULL) 297 TAILQ_FOREACH(p, &packet_kif->pfik_ifp->if_groups, ifgl_next) 298 if (p->ifgl_group == rule_kif->pfik_group) 299 return (1); 300 301 if (rule_kif->pfik_flags & PFI_IFLAG_ANY && packet_kif->pfik_ifp && 302 !(packet_kif->pfik_ifp->if_flags & IFF_LOOPBACK)) 303 return (1); 304 305 return (0); 306} 307 308void 309pfi_attach_ifnet(struct ifnet *ifp) 310{ 311 struct pfi_kif *kif; 312 struct task *t; 313 314 PF_LOCK(); 315 pfi_initialize(); 316 pfi_update++; 317 if ((kif = pfi_kif_get(ifp->if_xname, NULL)) == NULL) 318 panic("%s: pfi_kif_get failed", __func__); 319 320 kif->pfik_ifp = ifp; 321 ifp->if_pf_kif = (caddr_t)kif; 322 323 t = malloc(sizeof(*t), PFI_MTYPE, M_WAITOK); 324 task_set(t, pfi_kifaddr_update, kif); 325 if_addrhook_add(ifp, t); 326 kif->pfik_ah_cookie = t; 327 328 pfi_kif_update(kif); 329 PF_UNLOCK(); 330} 331 332void 333pfi_detach_ifnet(struct ifnet *ifp) 334{ 335 struct pfi_kif *kif; 336 struct task *t; 337 338 if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL) 339 return; 340 341 PF_LOCK(); 342 pfi_update++; 343 t = kif->pfik_ah_cookie; 344 kif->pfik_ah_cookie = NULL; 345 if_addrhook_del(ifp, t); 346 free(t, PFI_MTYPE, sizeof(*t)); 347 348 pfi_kif_update(kif); 349 350 kif->pfik_ifp = NULL; 351 ifp->if_pf_kif = NULL; 352 pfi_kif_unref(kif, PFI_KIF_REF_NONE); 353 PF_UNLOCK(); 354} 355 356void 357pfi_attach_ifgroup(struct ifg_group *ifg) 358{ 359 struct pfi_kif *kif; 360 361 PF_LOCK(); 362 pfi_initialize(); 363 pfi_update++; 364 if ((kif = pfi_kif_get(ifg->ifg_group, NULL)) == NULL) 365 panic("%s: pfi_kif_get failed", __func__); 366 367 kif->pfik_group = ifg; 368 ifg->ifg_pf_kif = (caddr_t)kif; 369 PF_UNLOCK(); 370} 371 372void 373pfi_detach_ifgroup(struct ifg_group *ifg) 374{ 375 struct pfi_kif *kif; 376 377 if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL) 378 return; 379 380 PF_LOCK(); 381 pfi_update++; 382 383 kif->pfik_group = NULL; 384 ifg->ifg_pf_kif = NULL; 385 pfi_kif_unref(kif, PFI_KIF_REF_NONE); 386 PF_UNLOCK(); 387} 388 389void 390pfi_group_change(const char *group) 391{ 392 struct pfi_kif *kif; 393 394 pfi_update++; 395 if ((kif = pfi_kif_get(group, NULL)) == NULL) 396 panic("%s: pfi_kif_get failed", __func__); 397 398 pfi_kif_update(kif); 399} 400 401void 402pfi_group_delmember(const char *group) 403{ 404 PF_LOCK(); 405 pfi_group_change(group); 406 pfi_xcommit(); 407 PF_UNLOCK(); 408} 409 410void 411pfi_group_addmember(const char *group) 412{ 413 PF_LOCK(); 414 pfi_group_change(group); 415 pfi_xcommit(); 416 PF_UNLOCK(); 417} 418 419int 420pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) 421{ 422 switch (af) { 423 case AF_INET: 424 switch (dyn->pfid_acnt4) { 425 case 0: 426 return (0); 427 case 1: 428 return (pf_match_addr(0, &dyn->pfid_addr4, 429 &dyn->pfid_mask4, a, AF_INET)); 430 default: 431 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); 432 } 433 break; 434#ifdef INET6 435 case AF_INET6: 436 switch (dyn->pfid_acnt6) { 437 case 0: 438 return (0); 439 case 1: 440 return (pf_match_addr(0, &dyn->pfid_addr6, 441 &dyn->pfid_mask6, a, AF_INET6)); 442 default: 443 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); 444 } 445 break; 446#endif /* INET6 */ 447 default: 448 return (0); 449 } 450} 451 452int 453pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af, int wait) 454{ 455 struct pfi_dynaddr *dyn; 456 char tblname[PF_TABLE_NAME_SIZE]; 457 struct pf_ruleset *ruleset = NULL; 458 int rv = 0; 459 460 if (aw->type != PF_ADDR_DYNIFTL) 461 return (0); 462 if ((dyn = pool_get(&pfi_addr_pl, wait|PR_LIMITFAIL|PR_ZERO)) == NULL) 463 return (1); 464 465 if (!strcmp(aw->v.ifname, "self")) 466 dyn->pfid_kif = pfi_kif_get(IFG_ALL, NULL); 467 else 468 dyn->pfid_kif = pfi_kif_get(aw->v.ifname, NULL); 469 if (dyn->pfid_kif == NULL) { 470 rv = 1; 471 goto _bad; 472 } 473 pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE); 474 475 dyn->pfid_net = pfi_unmask(&aw->v.a.mask); 476 if (af == AF_INET && dyn->pfid_net == 32) 477 dyn->pfid_net = 128; 478 strlcpy(tblname, aw->v.ifname, sizeof(tblname)); 479 if (aw->iflags & PFI_AFLAG_NETWORK) 480 strlcat(tblname, ":network", sizeof(tblname)); 481 if (aw->iflags & PFI_AFLAG_BROADCAST) 482 strlcat(tblname, ":broadcast", sizeof(tblname)); 483 if (aw->iflags & PFI_AFLAG_PEER) 484 strlcat(tblname, ":peer", sizeof(tblname)); 485 if (aw->iflags & PFI_AFLAG_NOALIAS) 486 strlcat(tblname, ":0", sizeof(tblname)); 487 if (dyn->pfid_net != 128) 488 snprintf(tblname + strlen(tblname), 489 sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); 490 if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) { 491 rv = 1; 492 goto _bad; 493 } 494 495 if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, wait)) == NULL) { 496 rv = 1; 497 goto _bad; 498 } 499 500 dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; 501 dyn->pfid_iflags = aw->iflags; 502 dyn->pfid_af = af; 503 504 TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry); 505 aw->p.dyn = dyn; 506 pfi_kif_update(dyn->pfid_kif); 507 return (0); 508 509_bad: 510 if (dyn->pfid_kt != NULL) 511 pfr_detach_table(dyn->pfid_kt); 512 if (ruleset != NULL) 513 pf_remove_if_empty_ruleset(ruleset); 514 if (dyn->pfid_kif != NULL) 515 pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE); 516 pool_put(&pfi_addr_pl, dyn); 517 return (rv); 518} 519 520void 521pfi_kif_update(struct pfi_kif *kif) 522{ 523 struct ifg_list *ifgl; 524 struct pfi_dynaddr *p; 525 526 /* update all dynaddr */ 527 TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry) 528 pfi_dynaddr_update(p); 529 530 /* again for all groups kif is member of */ 531 if (kif->pfik_ifp != NULL) 532 TAILQ_FOREACH(ifgl, &kif->pfik_ifp->if_groups, ifgl_next) 533 pfi_kif_update((struct pfi_kif *) 534 ifgl->ifgl_group->ifg_pf_kif); 535} 536 537void 538pfi_dynaddr_update(struct pfi_dynaddr *dyn) 539{ 540 struct pfi_kif *kif; 541 struct pfr_ktable *kt; 542 543 if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL) 544 panic("pfi_dynaddr_update"); 545 546 kif = dyn->pfid_kif; 547 kt = dyn->pfid_kt; 548 549 if (kt->pfrkt_larg != pfi_update) { 550 /* this table needs to be brought up-to-date */ 551 pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); 552 kt->pfrkt_larg = pfi_update; 553 } 554 pfr_dynaddr_update(kt, dyn); 555} 556 557void 558pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, u_int8_t net, int flags) 559{ 560 int e, size2 = 0; 561 struct ifg_member *ifgm; 562 563 pfi_buffer_cnt = 0; 564 565 if (kif->pfik_ifp != NULL) 566 pfi_instance_add(kif->pfik_ifp, net, flags); 567 else if (kif->pfik_group != NULL) 568 TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next) 569 pfi_instance_add(ifgm->ifgm_ifp, net, flags); 570 571 if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2, 572 NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK))) 573 DPFPRINTF(LOG_ERR, 574 "pfi_table_update: cannot set %d new addresses " 575 "into table %s: %d", pfi_buffer_cnt, kt->pfrkt_name, e); 576} 577 578void 579pfi_instance_add(struct ifnet *ifp, u_int8_t net, int flags) 580{ 581 struct ifaddr *ifa; 582 int got4 = 0, got6 = 0; 583 int net2, af; 584 585 if (ifp == NULL) 586 return; 587 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 588 if (ifa->ifa_addr == NULL) 589 continue; 590 af = ifa->ifa_addr->sa_family; 591 if (af != AF_INET && af != AF_INET6) 592 continue; 593 if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) 594 continue; 595 if ((flags & PFI_AFLAG_BROADCAST) && 596 !(ifp->if_flags & IFF_BROADCAST)) 597 continue; 598 if ((flags & PFI_AFLAG_PEER) && 599 !(ifp->if_flags & IFF_POINTOPOINT)) 600 continue; 601 if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && 602 IN6_IS_ADDR_LINKLOCAL( 603 &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) 604 continue; 605 if (flags & PFI_AFLAG_NOALIAS) { 606 if (af == AF_INET && got4) 607 continue; 608 if (af == AF_INET6 && got6) 609 continue; 610 } 611 if (af == AF_INET) 612 got4 = 1; 613 else if (af == AF_INET6) 614 got6 = 1; 615 net2 = net; 616 if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { 617 if (af == AF_INET) 618 net2 = pfi_unmask(&((struct sockaddr_in *) 619 ifa->ifa_netmask)->sin_addr); 620 else if (af == AF_INET6) 621 net2 = pfi_unmask(&((struct sockaddr_in6 *) 622 ifa->ifa_netmask)->sin6_addr); 623 } 624 if (af == AF_INET && net2 > 32) 625 net2 = 32; 626 if (flags & PFI_AFLAG_BROADCAST) 627 pfi_address_add(ifa->ifa_broadaddr, af, net2); 628 else if (flags & PFI_AFLAG_PEER) 629 pfi_address_add(ifa->ifa_dstaddr, af, net2); 630 else 631 pfi_address_add(ifa->ifa_addr, af, net2); 632 } 633} 634 635void 636pfi_address_add(struct sockaddr *sa, sa_family_t af, u_int8_t net) 637{ 638 struct pfr_addr *p; 639 int i; 640 641 if (pfi_buffer_cnt >= pfi_buffer_max) { 642 int new_max = pfi_buffer_max * 2; 643 644 if (new_max > PFI_BUFFER_MAX) { 645 DPFPRINTF(LOG_ERR, 646 "pfi_address_add: address buffer full (%d/%d)", 647 pfi_buffer_cnt, PFI_BUFFER_MAX); 648 return; 649 } 650 p = mallocarray(new_max, sizeof(*pfi_buffer), PFI_MTYPE, 651 M_DONTWAIT); 652 if (p == NULL) { 653 DPFPRINTF(LOG_ERR, 654 "pfi_address_add: no memory to grow buffer " 655 "(%d/%d)", pfi_buffer_cnt, PFI_BUFFER_MAX); 656 return; 657 } 658 memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer)); 659 /* no need to zero buffer */ 660 free(pfi_buffer, PFI_MTYPE, pfi_buffer_max * sizeof(*pfi_buffer)); 661 pfi_buffer = p; 662 pfi_buffer_max = new_max; 663 } 664 if (af == AF_INET && net > 32) 665 net = 128; 666 p = pfi_buffer + pfi_buffer_cnt++; 667 memset(p, 0, sizeof(*p)); 668 p->pfra_af = af; 669 p->pfra_net = net; 670 if (af == AF_INET) 671 p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; 672 else if (af == AF_INET6) { 673 p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; 674 if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr)) 675 p->pfra_ip6addr.s6_addr16[1] = 0; 676 } 677 /* mask network address bits */ 678 if (net < 128) 679 ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); 680 for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) 681 ((caddr_t)p)[i] = 0; 682} 683 684void 685pfi_dynaddr_remove(struct pf_addr_wrap *aw) 686{ 687 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 688 aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) 689 return; 690 691 TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry); 692 pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE); 693 aw->p.dyn->pfid_kif = NULL; 694 pfr_detach_table(aw->p.dyn->pfid_kt); 695 aw->p.dyn->pfid_kt = NULL; 696 pool_put(&pfi_addr_pl, aw->p.dyn); 697 aw->p.dyn = NULL; 698} 699 700void 701pfi_dynaddr_copyout(struct pf_addr_wrap *aw) 702{ 703 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 704 aw->p.dyn->pfid_kif == NULL) 705 return; 706 aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; 707} 708 709void 710pfi_kifaddr_update(void *v) 711{ 712 struct pfi_kif *kif = (struct pfi_kif *)v; 713 714 NET_ASSERT_LOCKED(); 715 716 PF_LOCK(); 717 pfi_update++; 718 pfi_kif_update(kif); 719 PF_UNLOCK(); 720} 721 722int 723pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) 724{ 725 return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); 726} 727 728void 729pfi_update_status(const char *name, struct pf_status *pfs) 730{ 731 struct pfi_kif *p; 732 struct pfi_kif_cmp key; 733 struct ifg_member p_member, *ifgm; 734 TAILQ_HEAD(, ifg_member) ifg_members; 735 int i, j, k; 736 737 if (*name == '\0' && pfs == NULL) { 738 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 739 memset(p->pfik_packets, 0, sizeof(p->pfik_packets)); 740 memset(p->pfik_bytes, 0, sizeof(p->pfik_bytes)); 741 p->pfik_tzero = gettime(); 742 } 743 return; 744 } 745 746 strlcpy(key.pfik_name, name, sizeof(key.pfik_name)); 747 p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key); 748 if (p == NULL) { 749 return; 750 } 751 if (p->pfik_group != NULL) { 752 memcpy(&ifg_members, &p->pfik_group->ifg_members, 753 sizeof(ifg_members)); 754 } else { 755 /* build a temporary list for p only */ 756 memset(&p_member, 0, sizeof(p_member)); 757 p_member.ifgm_ifp = p->pfik_ifp; 758 TAILQ_INIT(&ifg_members); 759 TAILQ_INSERT_TAIL(&ifg_members, &p_member, ifgm_next); 760 } 761 if (pfs) { 762 memset(pfs->pcounters, 0, sizeof(pfs->pcounters)); 763 memset(pfs->bcounters, 0, sizeof(pfs->bcounters)); 764 } 765 TAILQ_FOREACH(ifgm, &ifg_members, ifgm_next) { 766 if (ifgm->ifgm_ifp == NULL) 767 continue; 768 p = (struct pfi_kif *)ifgm->ifgm_ifp->if_pf_kif; 769 770 /* just clear statistics */ 771 if (pfs == NULL) { 772 memset(p->pfik_packets, 0, sizeof(p->pfik_packets)); 773 memset(p->pfik_bytes, 0, sizeof(p->pfik_bytes)); 774 p->pfik_tzero = gettime(); 775 continue; 776 } 777 for (i = 0; i < 2; i++) 778 for (j = 0; j < 2; j++) 779 for (k = 0; k < 2; k++) { 780 pfs->pcounters[i][j][k] += 781 p->pfik_packets[i][j][k]; 782 pfs->bcounters[i][j] += 783 p->pfik_bytes[i][j][k]; 784 } 785 } 786} 787 788void 789pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size) 790{ 791 struct pfi_kif *p; 792 int n = 0; 793 794 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 795 if (pfi_skip_if(name, p)) 796 continue; 797 if (*size <= ++n) 798 break; 799 if (!p->pfik_tzero) 800 p->pfik_tzero = gettime(); 801 memcpy(buf++, p, sizeof(*buf)); 802 } 803 *size = n; 804} 805 806int 807pfi_skip_if(const char *filter, struct pfi_kif *p) 808{ 809 struct ifg_list *i; 810 int n; 811 812 PF_ASSERT_LOCKED(); 813 814 if (filter == NULL || !*filter) 815 return (0); 816 if (!strcmp(p->pfik_name, filter)) 817 return (0); /* exact match */ 818 n = strlen(filter); 819 if (n < 1 || n >= IFNAMSIZ) 820 return (1); /* sanity check */ 821 if (filter[n-1] >= '0' && filter[n-1] <= '9') 822 return (1); /* group names may not end in a digit */ 823 if (p->pfik_ifp != NULL) 824 TAILQ_FOREACH(i, &p->pfik_ifp->if_groups, ifgl_next) 825 if (!strncmp(i->ifgl_group->ifg_group, filter, IFNAMSIZ)) 826 return (0); /* iface is in group "filter" */ 827 return (1); 828} 829 830int 831pfi_set_flags(const char *name, int flags) 832{ 833 struct pfi_kif *p; 834 size_t n; 835 836 PF_ASSERT_LOCKED(); 837 838 if (name != NULL && name[0] != '\0') { 839 p = pfi_kif_find(name); 840 if (p == NULL) { 841 n = strlen(name); 842 if (n < 1 || n >= IFNAMSIZ) 843 return (EINVAL); 844 845 if (!isalpha(name[0])) 846 return (EINVAL); 847 848 p = pfi_kif_get(name, NULL); 849 if (p != NULL) { 850 p->pfik_flags_new = p->pfik_flags | flags; 851 /* 852 * We use pfik_flagrefs counter as an 853 * indication whether the kif has been created 854 * on behalf of 'pfi_set_flags()' or not. 855 */ 856 KASSERT(p->pfik_flagrefs == 0); 857 if (ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP)) 858 pfi_kif_ref(p, PFI_KIF_REF_FLAG); 859 } else 860 panic("%s pfi_kif_get() returned NULL\n", 861 __func__); 862 } else 863 p->pfik_flags_new = p->pfik_flags | flags; 864 } else { 865 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) 866 p->pfik_flags_new = p->pfik_flags | flags; 867 } 868 869 return (0); 870} 871 872int 873pfi_clear_flags(const char *name, int flags) 874{ 875 struct pfi_kif *p, *w; 876 877 PF_ASSERT_LOCKED(); 878 879 if (name != NULL && name[0] != '\0') { 880 p = pfi_kif_find(name); 881 if (p != NULL) { 882 p->pfik_flags_new = p->pfik_flags & ~flags; 883 884 KASSERT((p->pfik_flagrefs == 0) || 885 (p->pfik_flagrefs == 1)); 886 887 if (!ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP) && 888 (p->pfik_flagrefs == 1)) 889 pfi_kif_unref(p, PFI_KIF_REF_FLAG); 890 } else 891 return (ESRCH); 892 893 } else 894 RB_FOREACH_SAFE(p, pfi_ifhead, &pfi_ifs, w) { 895 p->pfik_flags_new = p->pfik_flags & ~flags; 896 897 KASSERT((p->pfik_flagrefs == 0) || 898 (p->pfik_flagrefs == 1)); 899 900 if (!ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP) && 901 (p->pfik_flagrefs == 1)) 902 pfi_kif_unref(p, PFI_KIF_REF_FLAG); 903 } 904 905 return (0); 906} 907 908void 909pfi_xcommit(void) 910{ 911 struct pfi_kif *p, *gkif; 912 struct ifg_list *g; 913 struct ifnet *ifp; 914 size_t n; 915 916 PF_ASSERT_LOCKED(); 917 918 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 919 p->pfik_flags = p->pfik_flags_new; 920 n = strlen(p->pfik_name); 921 ifp = p->pfik_ifp; 922 /* 923 * if kif is backed by existing interface, then we must use 924 * skip flags found in groups. We use pfik_flags_new, otherwise 925 * we would need to do two RB_FOREACH() passes: the first to 926 * commit group changes the second to commit flag changes for 927 * interfaces. 928 */ 929 if (ifp != NULL) 930 TAILQ_FOREACH(g, &ifp->if_groups, ifgl_next) { 931 gkif = 932 (struct pfi_kif *)g->ifgl_group->ifg_pf_kif; 933 KASSERT(gkif != NULL); 934 p->pfik_flags |= gkif->pfik_flags_new; 935 } 936 } 937} 938 939/* from pf_print_state.c */ 940int 941pfi_unmask(void *addr) 942{ 943 struct pf_addr *m = addr; 944 int i = 31, j = 0, b = 0; 945 u_int32_t tmp; 946 947 while (j < 4 && m->addr32[j] == 0xffffffff) { 948 b += 32; 949 j++; 950 } 951 if (j < 4) { 952 tmp = ntohl(m->addr32[j]); 953 for (i = 31; tmp & (1 << i); --i) 954 b++; 955 } 956 return (b); 957} 958 959