66 67#include <netinet/in.h> 68#include <netinet/in_var.h> 69#include <netinet/in_systm.h> 70#include <netinet/ip.h> 71#include <netinet/ip_var.h> 72 73#include <net/pfvar.h> 74 75#ifdef INET6 76#include <netinet/ip6.h> 77#endif /* INET6 */ 78 79struct pfi_kif *pfi_all = NULL; 80struct pfi_statehead pfi_statehead; 81#ifdef __FreeBSD__ 82uma_zone_t pfi_addr_pl; 83#else 84struct pool pfi_addr_pl; 85#endif 86struct pfi_ifhead pfi_ifs; 87long pfi_update = 1; 88struct pfr_addr *pfi_buffer; 89int pfi_buffer_cnt; 90int pfi_buffer_max; 91#ifdef __FreeBSD__ 92eventhandler_tag pfi_attach_cookie = NULL; 93eventhandler_tag pfi_detach_cookie = NULL; 94eventhandler_tag pfi_attach_group_cookie = NULL; 95eventhandler_tag pfi_change_group_cookie = NULL; 96eventhandler_tag pfi_detach_group_cookie = NULL; 97eventhandler_tag pfi_ifaddr_event_cookie = NULL; 98#endif 99 100void pfi_kif_update(struct pfi_kif *); 101void pfi_dynaddr_update(struct pfi_dynaddr *dyn); 102void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, 103 int, int); 104void pfi_kifaddr_update(void *); 105void pfi_instance_add(struct ifnet *, int, int); 106void pfi_address_add(struct sockaddr *, int, int); 107int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); 108int pfi_skip_if(const char *, struct pfi_kif *); 109int pfi_unmask(void *); 110#ifdef __FreeBSD__ 111void pfi_attach_ifnet_event(void * __unused, struct ifnet *); 112void pfi_detach_ifnet_event(void * __unused, struct ifnet *); 113void pfi_attach_group_event(void * __unused, struct ifg_group *); 114void pfi_change_group_event(void * __unused, char *); 115void pfi_detach_group_event(void * __unused, struct ifg_group *); 116void pfi_ifaddr_event(void * __unused, struct ifnet *); 117 118extern struct ifgrouphead ifg_head; 119#endif 120 121RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 122RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); 123 124#define PFI_BUFFER_MAX 0x10000 125#define PFI_MTYPE M_IFADDR 126 127void 128pfi_initialize(void) 129{ 130 INIT_VNET_NET(curvnet); 131 132 if (pfi_all != NULL) /* already initialized */ 133 return; 134 135 TAILQ_INIT(&pfi_statehead); 136#ifndef __FreeBSD__ 137 pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, 138 "pfiaddrpl", &pool_allocator_nointr); 139#endif 140 pfi_buffer_max = 64; 141 pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer), 142 PFI_MTYPE, M_WAITOK); 143 144 if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL) 145 panic("pfi_kif_get for pfi_all failed"); 146 147#ifdef __FreeBSD__ 148 struct ifg_group *ifg; 149 struct ifnet *ifp; 150 151 IFNET_RLOCK(); 152 TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) 153 pfi_attach_ifgroup(ifg); 154 TAILQ_FOREACH(ifp, &V_ifnet, if_link) 155 pfi_attach_ifnet(ifp); 156 IFNET_RUNLOCK(); 157 158 pfi_attach_cookie = EVENTHANDLER_REGISTER(ifnet_arrival_event, 159 pfi_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); 160 pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event, 161 pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); 162 pfi_attach_group_cookie = EVENTHANDLER_REGISTER(group_attach_event, 163 pfi_attach_group_event, NULL, EVENTHANDLER_PRI_ANY); 164 pfi_change_group_cookie = EVENTHANDLER_REGISTER(group_change_event, 165 pfi_change_group_event, NULL, EVENTHANDLER_PRI_ANY); 166 pfi_detach_group_cookie = EVENTHANDLER_REGISTER(group_detach_event, 167 pfi_detach_group_event, NULL, EVENTHANDLER_PRI_ANY); 168 pfi_ifaddr_event_cookie = EVENTHANDLER_REGISTER(ifaddr_event, 169 pfi_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY); 170#endif 171} 172 173#ifdef __FreeBSD__ 174void 175pfi_cleanup(void) 176{ 177 struct pfi_kif *p; 178 179 PF_UNLOCK(); 180 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, pfi_attach_cookie); 181 EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfi_detach_cookie); 182 EVENTHANDLER_DEREGISTER(group_attach_event, pfi_attach_group_cookie); 183 EVENTHANDLER_DEREGISTER(group_change_event, pfi_change_group_cookie); 184 EVENTHANDLER_DEREGISTER(group_detach_event, pfi_detach_group_cookie); 185 EVENTHANDLER_DEREGISTER(ifaddr_event, pfi_ifaddr_event_cookie); 186 PF_LOCK(); 187 188 pfi_all = NULL; 189 while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) { 190 if (p->pfik_rules || p->pfik_states) { 191 printf("pfi_cleanup: dangling refs for %s\n", 192 p->pfik_name); 193 } 194 195 RB_REMOVE(pfi_ifhead, &pfi_ifs, p); 196 free(p, PFI_MTYPE); 197 } 198 199 free(pfi_buffer, PFI_MTYPE); 200} 201#endif 202 203struct pfi_kif * 204pfi_kif_get(const char *kif_name) 205{ 206 struct pfi_kif *kif; 207 struct pfi_kif_cmp s; 208 209 bzero(&s, sizeof(s)); 210 strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name)); 211 if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL) 212 return (kif); 213 214 /* create new one */ 215#ifdef __FreeBSD__ 216 if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT)) == NULL) 217#else 218 if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT)) == NULL) 219#endif 220 return (NULL); 221 222 bzero(kif, sizeof(*kif)); 223 strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name)); 224#ifdef __FreeBSD__ 225 /* 226 * It seems that the value of time_second is in unintialzied state 227 * when pf sets interface statistics clear time in boot phase if pf 228 * was statically linked to kernel. Instead of setting the bogus 229 * time value have pfi_get_ifaces handle this case. In 230 * pfi_get_ifaces it uses boottime.tv_sec if it sees the time is 0. 231 */ 232 kif->pfik_tzero = time_second > 1 ? time_second : 0; 233#else 234 kif->pfik_tzero = time_second; 235#endif 236 TAILQ_INIT(&kif->pfik_dynaddrs); 237 238 RB_INSERT(pfi_ifhead, &pfi_ifs, kif); 239 return (kif); 240} 241 242void 243pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what) 244{ 245 switch (what) { 246 case PFI_KIF_REF_RULE: 247 kif->pfik_rules++; 248 break; 249 case PFI_KIF_REF_STATE: 250 if (!kif->pfik_states++) 251 TAILQ_INSERT_TAIL(&pfi_statehead, kif, pfik_w_states); 252 break; 253 default: 254 panic("pfi_kif_ref with unknown type"); 255 } 256} 257 258void 259pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what) 260{ 261 if (kif == NULL) 262 return; 263 264 switch (what) { 265 case PFI_KIF_REF_NONE: 266 break; 267 case PFI_KIF_REF_RULE: 268 if (kif->pfik_rules <= 0) { 269 printf("pfi_kif_unref: rules refcount <= 0\n"); 270 return; 271 } 272 kif->pfik_rules--; 273 break; 274 case PFI_KIF_REF_STATE: 275 if (kif->pfik_states <= 0) { 276 printf("pfi_kif_unref: state refcount <= 0\n"); 277 return; 278 } 279 if (!--kif->pfik_states) 280 TAILQ_REMOVE(&pfi_statehead, kif, pfik_w_states); 281 break; 282 default: 283 panic("pfi_kif_unref with unknown type"); 284 } 285 286 if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all) 287 return; 288 289 if (kif->pfik_rules || kif->pfik_states) 290 return; 291 292 RB_REMOVE(pfi_ifhead, &pfi_ifs, kif); 293 free(kif, PFI_MTYPE); 294} 295 296int 297pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif) 298{ 299 struct ifg_list *p; 300 301 if (rule_kif == NULL || rule_kif == packet_kif) 302 return (1); 303 304 if (rule_kif->pfik_group != NULL) 305 TAILQ_FOREACH(p, &packet_kif->pfik_ifp->if_groups, ifgl_next) 306 if (p->ifgl_group == rule_kif->pfik_group) 307 return (1); 308 309 return (0); 310} 311 312void 313pfi_attach_ifnet(struct ifnet *ifp) 314{ 315 struct pfi_kif *kif; 316 int s; 317 318 pfi_initialize(); 319 s = splsoftnet(); 320 pfi_update++; 321 if ((kif = pfi_kif_get(ifp->if_xname)) == NULL) 322 panic("pfi_kif_get failed"); 323 324 kif->pfik_ifp = ifp; 325 ifp->if_pf_kif = (caddr_t)kif; 326 327#ifndef __FreeBSD__ 328 if ((kif->pfik_ah_cookie = hook_establish(ifp->if_addrhooks, 1, 329 pfi_kifaddr_update, kif)) == NULL) 330 panic("pfi_attach_ifnet: cannot allocate '%s' address hook", 331 ifp->if_xname); 332#endif 333 334 pfi_kif_update(kif); 335 336 splx(s); 337} 338 339void 340pfi_detach_ifnet(struct ifnet *ifp) 341{ 342 int s; 343 struct pfi_kif *kif; 344 345 if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL) 346 return; 347 348 s = splsoftnet(); 349 pfi_update++; 350#ifndef __FreeBSD__ 351 hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie); 352#endif 353 pfi_kif_update(kif); 354 355 kif->pfik_ifp = NULL; 356 ifp->if_pf_kif = NULL; 357 pfi_kif_unref(kif, PFI_KIF_REF_NONE); 358 splx(s); 359} 360 361void 362pfi_attach_ifgroup(struct ifg_group *ifg) 363{ 364 struct pfi_kif *kif; 365 int s; 366 367 pfi_initialize(); 368 s = splsoftnet(); 369 pfi_update++; 370 if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL) 371 panic("pfi_kif_get failed"); 372 373 kif->pfik_group = ifg; 374 ifg->ifg_pf_kif = (caddr_t)kif; 375 376 splx(s); 377} 378 379void 380pfi_detach_ifgroup(struct ifg_group *ifg) 381{ 382 int s; 383 struct pfi_kif *kif; 384 385 if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL) 386 return; 387 388 s = splsoftnet(); 389 pfi_update++; 390 391 kif->pfik_group = NULL; 392 ifg->ifg_pf_kif = NULL; 393 pfi_kif_unref(kif, PFI_KIF_REF_NONE); 394 splx(s); 395} 396 397void 398pfi_group_change(const char *group) 399{ 400 struct pfi_kif *kif; 401 int s; 402 403 s = splsoftnet(); 404 pfi_update++; 405 if ((kif = pfi_kif_get(group)) == NULL) 406 panic("pfi_kif_get failed"); 407 408 pfi_kif_update(kif); 409 410 splx(s); 411} 412 413int 414pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) 415{ 416 switch (af) { 417#ifdef INET 418 case AF_INET: 419 switch (dyn->pfid_acnt4) { 420 case 0: 421 return (0); 422 case 1: 423 return (PF_MATCHA(0, &dyn->pfid_addr4, 424 &dyn->pfid_mask4, a, AF_INET)); 425 default: 426 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); 427 } 428 break; 429#endif /* INET */ 430#ifdef INET6 431 case AF_INET6: 432 switch (dyn->pfid_acnt6) { 433 case 0: 434 return (0); 435 case 1: 436 return (PF_MATCHA(0, &dyn->pfid_addr6, 437 &dyn->pfid_mask6, a, AF_INET6)); 438 default: 439 return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); 440 } 441 break; 442#endif /* INET6 */ 443 default: 444 return (0); 445 } 446} 447 448int 449pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) 450{ 451 struct pfi_dynaddr *dyn; 452 char tblname[PF_TABLE_NAME_SIZE]; 453 struct pf_ruleset *ruleset = NULL; 454 int s, rv = 0; 455 456 if (aw->type != PF_ADDR_DYNIFTL) 457 return (0); 458 if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL) 459 return (1); 460 bzero(dyn, sizeof(*dyn)); 461 462 s = splsoftnet(); 463 if (!strcmp(aw->v.ifname, "self")) 464 dyn->pfid_kif = pfi_kif_get(IFG_ALL); 465 else 466 dyn->pfid_kif = pfi_kif_get(aw->v.ifname); 467 if (dyn->pfid_kif == NULL) { 468 rv = 1; 469 goto _bad; 470 } 471 pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE); 472 473 dyn->pfid_net = pfi_unmask(&aw->v.a.mask); 474 if (af == AF_INET && dyn->pfid_net == 32) 475 dyn->pfid_net = 128; 476 strlcpy(tblname, aw->v.ifname, sizeof(tblname)); 477 if (aw->iflags & PFI_AFLAG_NETWORK) 478 strlcat(tblname, ":network", sizeof(tblname)); 479 if (aw->iflags & PFI_AFLAG_BROADCAST) 480 strlcat(tblname, ":broadcast", sizeof(tblname)); 481 if (aw->iflags & PFI_AFLAG_PEER) 482 strlcat(tblname, ":peer", sizeof(tblname)); 483 if (aw->iflags & PFI_AFLAG_NOALIAS) 484 strlcat(tblname, ":0", sizeof(tblname)); 485 if (dyn->pfid_net != 128) 486 snprintf(tblname + strlen(tblname), 487 sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); 488 if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) { 489 rv = 1; 490 goto _bad; 491 } 492 493 if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) { 494 rv = 1; 495 goto _bad; 496 } 497 498 dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; 499 dyn->pfid_iflags = aw->iflags; 500 dyn->pfid_af = af; 501 502 TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry); 503 aw->p.dyn = dyn; 504 pfi_kif_update(dyn->pfid_kif); 505 splx(s); 506 return (0); 507 508_bad: 509 if (dyn->pfid_kt != NULL) 510 pfr_detach_table(dyn->pfid_kt); 511 if (ruleset != NULL) 512 pf_remove_if_empty_ruleset(ruleset); 513 if (dyn->pfid_kif != NULL) 514 pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE); 515 pool_put(&pfi_addr_pl, dyn); 516 splx(s); 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, int 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 printf("pfi_table_update: cannot set %d new addresses " 574 "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e); 575} 576 577void 578pfi_instance_add(struct ifnet *ifp, int net, int flags) 579{ 580 struct ifaddr *ia; 581 int got4 = 0, got6 = 0; 582 int net2, af; 583 584 if (ifp == NULL) 585 return; 586 TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) { 587 if (ia->ifa_addr == NULL) 588 continue; 589 af = ia->ifa_addr->sa_family; 590 if (af != AF_INET && af != AF_INET6) 591 continue; 592#ifdef __FreeBSD__ 593 /* 594 * XXX: For point-to-point interfaces, (ifname:0) and IPv4, 595 * jump over addresses without a proper route to work 596 * around a problem with ppp not fully removing the 597 * address used during IPCP. 598 */ 599 if ((ifp->if_flags & IFF_POINTOPOINT) && 600 !(ia->ifa_flags & IFA_ROUTE) && 601 (flags & PFI_AFLAG_NOALIAS) && (af == AF_INET)) 602 continue; 603#endif 604 if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) 605 continue; 606 if ((flags & PFI_AFLAG_BROADCAST) && 607 !(ifp->if_flags & IFF_BROADCAST)) 608 continue; 609 if ((flags & PFI_AFLAG_PEER) && 610 !(ifp->if_flags & IFF_POINTOPOINT)) 611 continue; 612 if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && 613 IN6_IS_ADDR_LINKLOCAL( 614 &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr)) 615 continue; 616 if (flags & PFI_AFLAG_NOALIAS) { 617 if (af == AF_INET && got4) 618 continue; 619 if (af == AF_INET6 && got6) 620 continue; 621 } 622 if (af == AF_INET) 623 got4 = 1; 624 else if (af == AF_INET6) 625 got6 = 1; 626 net2 = net; 627 if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { 628 if (af == AF_INET) 629 net2 = pfi_unmask(&((struct sockaddr_in *) 630 ia->ifa_netmask)->sin_addr); 631 else if (af == AF_INET6) 632 net2 = pfi_unmask(&((struct sockaddr_in6 *) 633 ia->ifa_netmask)->sin6_addr); 634 } 635 if (af == AF_INET && net2 > 32) 636 net2 = 32; 637 if (flags & PFI_AFLAG_BROADCAST) 638 pfi_address_add(ia->ifa_broadaddr, af, net2); 639 else if (flags & PFI_AFLAG_PEER) 640 pfi_address_add(ia->ifa_dstaddr, af, net2); 641 else 642 pfi_address_add(ia->ifa_addr, af, net2); 643 } 644} 645 646void 647pfi_address_add(struct sockaddr *sa, int af, int net) 648{ 649 struct pfr_addr *p; 650 int i; 651 652 if (pfi_buffer_cnt >= pfi_buffer_max) { 653 int new_max = pfi_buffer_max * 2; 654 655 if (new_max > PFI_BUFFER_MAX) { 656 printf("pfi_address_add: address buffer full (%d/%d)\n", 657 pfi_buffer_cnt, PFI_BUFFER_MAX); 658 return; 659 } 660 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE, 661#ifdef __FreeBSD__ 662 M_NOWAIT); 663#else 664 M_DONTWAIT); 665#endif 666 if (p == NULL) { 667 printf("pfi_address_add: no memory to grow buffer " 668 "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); 669 return; 670 } 671 memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer)); 672 /* no need to zero buffer */ 673 free(pfi_buffer, PFI_MTYPE); 674 pfi_buffer = p; 675 pfi_buffer_max = new_max; 676 } 677 if (af == AF_INET && net > 32) 678 net = 128; 679 p = pfi_buffer + pfi_buffer_cnt++; 680 bzero(p, sizeof(*p)); 681 p->pfra_af = af; 682 p->pfra_net = net; 683 if (af == AF_INET) 684 p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; 685 else if (af == AF_INET6) { 686 p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; 687 if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr)) 688 p->pfra_ip6addr.s6_addr16[1] = 0; 689 } 690 /* mask network address bits */ 691 if (net < 128) 692 ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); 693 for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) 694 ((caddr_t)p)[i] = 0; 695} 696 697void 698pfi_dynaddr_remove(struct pf_addr_wrap *aw) 699{ 700 int s; 701 702 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 703 aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) 704 return; 705 706 s = splsoftnet(); 707 TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry); 708 pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE); 709 aw->p.dyn->pfid_kif = NULL; 710 pfr_detach_table(aw->p.dyn->pfid_kt); 711 aw->p.dyn->pfid_kt = NULL; 712 pool_put(&pfi_addr_pl, aw->p.dyn); 713 aw->p.dyn = NULL; 714 splx(s); 715} 716 717void 718pfi_dynaddr_copyout(struct pf_addr_wrap *aw) 719{ 720 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || 721 aw->p.dyn->pfid_kif == NULL) 722 return; 723 aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; 724} 725 726void 727pfi_kifaddr_update(void *v) 728{ 729 int s; 730 struct pfi_kif *kif = (struct pfi_kif *)v; 731 732 s = splsoftnet(); 733 pfi_update++; 734 pfi_kif_update(kif); 735 splx(s); 736} 737 738int 739pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) 740{ 741 return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); 742} 743 744void 745pfi_fill_oldstatus(struct pf_status *pfs) 746{ 747 struct pfi_kif *p; 748 struct pfi_kif_cmp key; 749 int i, j, k, s; 750 751 strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name)); 752 s = splsoftnet(); 753 p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key); 754 if (p == NULL) { 755 splx(s); 756 return; 757 } 758 bzero(pfs->pcounters, sizeof(pfs->pcounters)); 759 bzero(pfs->bcounters, sizeof(pfs->bcounters)); 760 for (i = 0; i < 2; i++) 761 for (j = 0; j < 2; j++) 762 for (k = 0; k < 2; k++) { 763 pfs->pcounters[i][j][k] = 764 p->pfik_packets[i][j][k]; 765 pfs->bcounters[i][j] += 766 p->pfik_bytes[i][j][k]; 767 } 768 splx(s); 769} 770 771int 772pfi_clr_istats(const char *name) 773{ 774 struct pfi_kif *p; 775 int s; 776 777 s = splsoftnet(); 778 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 779 if (pfi_skip_if(name, p)) 780 continue; 781 bzero(p->pfik_packets, sizeof(p->pfik_packets)); 782 bzero(p->pfik_bytes, sizeof(p->pfik_bytes)); 783 p->pfik_tzero = time_second; 784 } 785 splx(s); 786 787 return (0); 788} 789 790int 791pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size) 792{ 793 struct pfi_kif *p, *nextp; 794 int s, n = 0; 795#ifdef __FreeBSD__ 796 int error; 797#endif 798 799 s = splsoftnet(); 800 for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) { 801 nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p); 802 if (pfi_skip_if(name, p)) 803 continue; 804 if (*size > n++) { 805 if (!p->pfik_tzero) 806 p->pfik_tzero = time_second; 807 pfi_kif_ref(p, PFI_KIF_REF_RULE); 808#ifdef __FreeBSD__ 809 PF_COPYOUT(p, buf++, sizeof(*buf), error); 810 if (error) { 811#else 812 if (copyout(p, buf++, sizeof(*buf))) { 813#endif 814 pfi_kif_unref(p, PFI_KIF_REF_RULE); 815 splx(s); 816 return (EFAULT); 817 } 818 nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p); 819 pfi_kif_unref(p, PFI_KIF_REF_RULE); 820 } 821 } 822 splx(s); 823 *size = n; 824 return (0); 825} 826 827int 828pfi_skip_if(const char *filter, struct pfi_kif *p) 829{ 830 int n; 831 832 if (filter == NULL || !*filter) 833 return (0); 834 if (!strcmp(p->pfik_name, filter)) 835 return (0); /* exact match */ 836 n = strlen(filter); 837 if (n < 1 || n >= IFNAMSIZ) 838 return (1); /* sanity check */ 839 if (filter[n-1] >= '0' && filter[n-1] <= '9') 840 return (1); /* only do exact match in that case */ 841 if (strncmp(p->pfik_name, filter, n)) 842 return (1); /* prefix doesn't match */ 843 return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9'); 844} 845 846int 847pfi_set_flags(const char *name, int flags) 848{ 849 struct pfi_kif *p; 850 int s; 851 852 s = splsoftnet(); 853 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 854 if (pfi_skip_if(name, p)) 855 continue; 856 p->pfik_flags |= flags; 857 } 858 splx(s); 859 return (0); 860} 861 862int 863pfi_clear_flags(const char *name, int flags) 864{ 865 struct pfi_kif *p; 866 int s; 867 868 s = splsoftnet(); 869 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { 870 if (pfi_skip_if(name, p)) 871 continue; 872 p->pfik_flags &= ~flags; 873 } 874 splx(s); 875 return (0); 876} 877 878/* from pf_print_state.c */ 879int 880pfi_unmask(void *addr) 881{ 882 struct pf_addr *m = addr; 883 int i = 31, j = 0, b = 0; 884 u_int32_t tmp; 885 886 while (j < 4 && m->addr32[j] == 0xffffffff) { 887 b += 32; 888 j++; 889 } 890 if (j < 4) { 891 tmp = ntohl(m->addr32[j]); 892 for (i = 31; tmp & (1 << i); --i) 893 b++; 894 } 895 return (b); 896} 897 898#ifdef __FreeBSD__ 899void 900pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp) 901{ 902 PF_LOCK(); 903 pfi_attach_ifnet(ifp); 904#ifdef ALTQ 905 pf_altq_ifnet_event(ifp, 0); 906#endif 907 PF_UNLOCK(); 908} 909 910void 911pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp) 912{ 913 PF_LOCK(); 914 pfi_detach_ifnet(ifp); 915#ifdef ALTQ 916 pf_altq_ifnet_event(ifp, 1); 917#endif 918 PF_UNLOCK(); 919} 920 921void 922pfi_attach_group_event(void *arg __unused, struct ifg_group *ifg) 923{ 924 PF_LOCK(); 925 pfi_attach_ifgroup(ifg); 926 PF_UNLOCK(); 927} 928 929void 930pfi_change_group_event(void *arg __unused, char *gname) 931{ 932 PF_LOCK(); 933 pfi_group_change(gname); 934 PF_UNLOCK(); 935} 936 937void 938pfi_detach_group_event(void *arg __unused, struct ifg_group *ifg) 939{ 940 PF_LOCK(); 941 pfi_detach_ifgroup(ifg); 942 PF_UNLOCK(); 943} 944 945void 946pfi_ifaddr_event(void *arg __unused, struct ifnet *ifp) 947{ 948 PF_LOCK(); 949 if (ifp && ifp->if_pf_kif) 950 pfi_kifaddr_update(ifp->if_pf_kif); 951 PF_UNLOCK(); 952} 953#endif /* __FreeBSD__ */
|