227 mtx_init(&sc->sc_ifq.ifq_mtx, ifp->if_xname, "pfsync send queue", 228 MTX_DEF); 229 if_attach(ifp); 230 231 LIST_INSERT_HEAD(&pfsync_list, sc, sc_next); 232#if NBPFILTER > 0 233 bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 234#endif 235 236 return (0); 237} 238#else /* !__FreeBSD__ */ 239void 240pfsyncattach(int npfsync) 241{ 242 struct ifnet *ifp; 243 244 pfsync_sync_ok = 1; 245 bzero(&pfsyncif, sizeof(pfsyncif)); 246 pfsyncif.sc_mbuf = NULL; 247 pfsyncif.sc_mbuf_net = NULL; 248 pfsyncif.sc_statep.s = NULL; 249 pfsyncif.sc_statep_net.s = NULL; 250 pfsyncif.sc_maxupdates = 128; 251 pfsyncif.sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP; 252 pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP; 253 pfsyncif.sc_ureq_received = 0; 254 pfsyncif.sc_ureq_sent = 0; 255 ifp = &pfsyncif.sc_if; 256 strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname); 257 ifp->if_softc = &pfsyncif; 258 ifp->if_ioctl = pfsyncioctl; 259 ifp->if_output = pfsyncoutput; 260 ifp->if_start = pfsyncstart; 261 ifp->if_type = IFT_PFSYNC; 262 ifp->if_snd.ifq_maxlen = ifqmaxlen; 263 ifp->if_hdrlen = PFSYNC_HDRLEN; 264 pfsync_setmtu(&pfsyncif, MCLBYTES); 265 timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif); 266 timeout_set(&pfsyncif.sc_bulk_tmo, pfsync_bulk_update, &pfsyncif); 267 timeout_set(&pfsyncif.sc_bulkfail_tmo, pfsync_bulkfail, &pfsyncif); 268 if_attach(ifp); 269 if_alloc_sadl(ifp); 270 271#if NBPFILTER > 0 272 bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 273#endif 274} 275#endif 276 277/* 278 * Start output on the pfsync interface. 279 */ 280void 281pfsyncstart(struct ifnet *ifp) 282{ 283#ifdef __FreeBSD__ 284 IF_LOCK(&ifp->if_snd); 285 _IF_DROP(&ifp->if_snd); 286 _IF_DRAIN(&ifp->if_snd); 287 IF_UNLOCK(&ifp->if_snd); 288#else 289 struct mbuf *m; 290 int s; 291 292 for (;;) { 293 s = splimp(); 294 IF_DROP(&ifp->if_snd); 295 IF_DEQUEUE(&ifp->if_snd, m); 296 splx(s); 297 298 if (m == NULL) 299 return; 300 else 301 m_freem(m); 302 } 303#endif 304} 305 306int 307pfsync_insert_net_state(struct pfsync_state *sp) 308{ 309 struct pf_state *st = NULL; 310 struct pf_rule *r = NULL; 311 struct pfi_kif *kif; 312 313#ifdef __FreeBSD__ 314 PF_ASSERT(MA_OWNED); 315#endif 316 if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) { 317 printf("pfsync_insert_net_state: invalid creator id:" 318 " %08x\n", ntohl(sp->creatorid)); 319 return (EINVAL); 320 } 321 322 kif = pfi_lookup_create(sp->ifname); 323 if (kif == NULL) { 324 if (pf_status.debug >= PF_DEBUG_MISC) 325 printf("pfsync_insert_net_state: " 326 "unknown interface: %s\n", sp->ifname); 327 /* skip this state */ 328 return (0); 329 } 330 331 /* 332 * Just use the default rule until we have infrastructure to find the 333 * best matching rule. 334 */ 335 r = &pf_default_rule; 336 337 if (!r->max_states || r->states < r->max_states) 338 st = pool_get(&pf_state_pl, PR_NOWAIT); 339 if (st == NULL) { 340 pfi_maybe_destroy(kif); 341 return (ENOMEM); 342 } 343 bzero(st, sizeof(*st)); 344 345 st->rule.ptr = r; 346 /* XXX get pointers to nat_rule and anchor */ 347 348 /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */ 349 r->states++; 350 351 /* fill in the rest of the state entry */ 352 pf_state_host_ntoh(&sp->lan, &st->lan); 353 pf_state_host_ntoh(&sp->gwy, &st->gwy); 354 pf_state_host_ntoh(&sp->ext, &st->ext); 355 356 pf_state_peer_ntoh(&sp->src, &st->src); 357 pf_state_peer_ntoh(&sp->dst, &st->dst); 358 359 bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr)); 360 st->creation = time_second - ntohl(sp->creation); 361 st->expire = ntohl(sp->expire) + time_second; 362 363 st->af = sp->af; 364 st->proto = sp->proto; 365 st->direction = sp->direction; 366 st->log = sp->log; 367 st->timeout = sp->timeout; 368 st->allow_opts = sp->allow_opts; 369 370 bcopy(sp->id, &st->id, sizeof(st->id)); 371 st->creatorid = sp->creatorid; 372 st->sync_flags = PFSTATE_FROMSYNC; 373 374 375 if (pf_insert_state(kif, st)) { 376 pfi_maybe_destroy(kif); 377 /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */ 378 r->states--; 379 pool_put(&pf_state_pl, st); 380 return (EINVAL); 381 } 382 383 return (0); 384} 385 386void 387#ifdef __FreeBSD__ 388pfsync_input(struct mbuf *m, __unused int off) 389#else 390pfsync_input(struct mbuf *m, ...) 391#endif 392{ 393 struct ip *ip = mtod(m, struct ip *); 394 struct pfsync_header *ph; 395#ifdef __FreeBSD__ 396 struct pfsync_softc *sc = LIST_FIRST(&pfsync_list); 397#else 398 struct pfsync_softc *sc = &pfsyncif; 399#endif 400 struct pf_state *st, key; 401 struct pfsync_state *sp; 402 struct pfsync_state_upd *up; 403 struct pfsync_state_del *dp; 404 struct pfsync_state_clr *cp; 405 struct pfsync_state_upd_req *rup; 406 struct pfsync_state_bus *bus; 407 struct in_addr src; 408 struct mbuf *mp; 409 int iplen, action, error, i, s, count, offp, sfail, stale = 0; 410 411 pfsyncstats.pfsyncs_ipackets++; 412 413 /* verify that we have a sync interface configured */ 414 if (!sc->sc_sync_ifp || !pf_status.running) /* XXX PF_LOCK? */ 415 goto done; 416 417 /* verify that the packet came in on the right interface */ 418 if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) { 419 pfsyncstats.pfsyncs_badif++; 420 goto done; 421 } 422 423 /* verify that the IP TTL is 255. */ 424 if (ip->ip_ttl != PFSYNC_DFLTTL) { 425 pfsyncstats.pfsyncs_badttl++; 426 goto done; 427 } 428 429 iplen = ip->ip_hl << 2; 430 431 if (m->m_pkthdr.len < iplen + sizeof(*ph)) { 432 pfsyncstats.pfsyncs_hdrops++; 433 goto done; 434 } 435 436 if (iplen + sizeof(*ph) > m->m_len) { 437 if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) { 438 pfsyncstats.pfsyncs_hdrops++; 439 goto done; 440 } 441 ip = mtod(m, struct ip *); 442 } 443 ph = (struct pfsync_header *)((char *)ip + iplen); 444 445 /* verify the version */ 446 if (ph->version != PFSYNC_VERSION) { 447 pfsyncstats.pfsyncs_badver++; 448 goto done; 449 } 450 451 action = ph->action; 452 count = ph->count; 453 454 /* make sure it's a valid action code */ 455 if (action >= PFSYNC_ACT_MAX) { 456 pfsyncstats.pfsyncs_badact++; 457 goto done; 458 } 459 460 /* Cheaper to grab this now than having to mess with mbufs later */ 461 src = ip->ip_src; 462 463 switch (action) { 464 case PFSYNC_ACT_CLR: { 465 struct pf_state *nexts; 466 struct pfi_kif *kif; 467 u_int32_t creatorid; 468 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 469 sizeof(*cp), &offp)) == NULL) { 470 pfsyncstats.pfsyncs_badlen++; 471 return; 472 } 473 cp = (struct pfsync_state_clr *)(mp->m_data + offp); 474 creatorid = cp->creatorid; 475 476 s = splsoftnet(); 477#ifdef __FreeBSD__ 478 PF_LOCK(); 479#endif 480 if (cp->ifname[0] == '\0') { 481 for (st = RB_MIN(pf_state_tree_id, &tree_id); 482 st; st = nexts) { 483 nexts = RB_NEXT(pf_state_tree_id, &tree_id, st); 484 if (st->creatorid == creatorid) { 485 st->timeout = PFTM_PURGE; 486 pf_purge_expired_state(st); 487 } 488 } 489 } else { 490 kif = pfi_lookup_if(cp->ifname); 491 if (kif == NULL) { 492 if (pf_status.debug >= PF_DEBUG_MISC) 493 printf("pfsync_input: PFSYNC_ACT_CLR " 494 "bad interface: %s\n", cp->ifname); 495 splx(s); 496#ifdef __FreeBSD__ 497 PF_UNLOCK(); 498#endif 499 goto done; 500 } 501 for (st = RB_MIN(pf_state_tree_lan_ext, 502 &kif->pfik_lan_ext); st; st = nexts) { 503 nexts = RB_NEXT(pf_state_tree_lan_ext, 504 &kif->pfik_lan_ext, st); 505 if (st->creatorid == creatorid) { 506 st->timeout = PFTM_PURGE; 507 pf_purge_expired_state(st); 508 } 509 } 510 } 511#ifdef __FreeBSD__ 512 PF_UNLOCK(); 513#endif 514 splx(s); 515 516 break; 517 } 518 case PFSYNC_ACT_INS: 519 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 520 count * sizeof(*sp), &offp)) == NULL) { 521 pfsyncstats.pfsyncs_badlen++; 522 return; 523 } 524 525 s = splsoftnet(); 526#ifdef __FreeBSD__ 527 PF_LOCK(); 528#endif 529 for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 530 i < count; i++, sp++) { 531 /* check for invalid values */ 532 if (sp->timeout >= PFTM_MAX || 533 sp->src.state > PF_TCPS_PROXY_DST || 534 sp->dst.state > PF_TCPS_PROXY_DST || 535 sp->direction > PF_OUT || 536 (sp->af != AF_INET && sp->af != AF_INET6)) { 537 if (pf_status.debug >= PF_DEBUG_MISC) 538 printf("pfsync_insert: PFSYNC_ACT_INS: " 539 "invalid value\n"); 540 pfsyncstats.pfsyncs_badstate++; 541 continue; 542 } 543 544 if ((error = pfsync_insert_net_state(sp))) { 545 if (error == ENOMEM) { 546 splx(s); 547#ifdef __FreeBSD__ 548 PF_UNLOCK(); 549#endif 550 goto done; 551 } 552 continue; 553 } 554 } 555#ifdef __FreeBSD__ 556 PF_UNLOCK(); 557#endif 558 splx(s); 559 break; 560 case PFSYNC_ACT_UPD: 561 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 562 count * sizeof(*sp), &offp)) == NULL) { 563 pfsyncstats.pfsyncs_badlen++; 564 return; 565 } 566 567 s = splsoftnet(); 568#ifdef __FreeBSD__ 569 PF_LOCK(); 570#endif 571 for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 572 i < count; i++, sp++) { 573 int flags = PFSYNC_FLAG_STALE; 574 575 /* check for invalid values */ 576 if (sp->timeout >= PFTM_MAX || 577 sp->src.state > PF_TCPS_PROXY_DST || 578 sp->dst.state > PF_TCPS_PROXY_DST) { 579 if (pf_status.debug >= PF_DEBUG_MISC) 580 printf("pfsync_insert: PFSYNC_ACT_UPD: " 581 "invalid value\n"); 582 pfsyncstats.pfsyncs_badstate++; 583 continue; 584 } 585 586 bcopy(sp->id, &key.id, sizeof(key.id)); 587 key.creatorid = sp->creatorid; 588 589 st = pf_find_state_byid(&key); 590 if (st == NULL) { 591 /* insert the update */ 592 if (pfsync_insert_net_state(sp)) 593 pfsyncstats.pfsyncs_badstate++; 594 continue; 595 } 596 sfail = 0; 597 if (st->proto == IPPROTO_TCP) { 598 /* 599 * The state should never go backwards except 600 * for syn-proxy states. Neither should the 601 * sequence window slide backwards. 602 */ 603 if (st->src.state > sp->src.state && 604 (st->src.state < PF_TCPS_PROXY_SRC || 605 sp->src.state >= PF_TCPS_PROXY_SRC)) 606 sfail = 1; 607 else if (SEQ_GT(st->src.seqlo, 608 ntohl(sp->src.seqlo))) 609 sfail = 3; 610 else if (st->dst.state > sp->dst.state) { 611 /* There might still be useful 612 * information about the src state here, 613 * so import that part of the update, 614 * then "fail" so we send the updated 615 * state back to the peer who is missing 616 * our what we know. */ 617 pf_state_peer_ntoh(&sp->src, &st->src); 618 /* XXX do anything with timeouts? */ 619 sfail = 7; 620 flags = 0; 621 } else if (st->dst.state >= TCPS_SYN_SENT && 622 SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo))) 623 sfail = 4; 624 } else { 625 /* 626 * Non-TCP protocol state machine always go 627 * forwards 628 */ 629 if (st->src.state > sp->src.state) 630 sfail = 5; 631 else if ( st->dst.state > sp->dst.state) 632 sfail = 6; 633 } 634 if (sfail) { 635 if (pf_status.debug >= PF_DEBUG_MISC) 636 printf("pfsync: %s stale update " 637 "(%d) id: %016llx " 638 "creatorid: %08x\n", 639 (sfail < 7 ? "ignoring" 640 : "partial"), sfail, 641#ifdef __FreeBSD__ 642 (unsigned long long)be64toh(st->id), 643#else 644 betoh64(st->id), 645#endif 646 ntohl(st->creatorid)); 647 pfsyncstats.pfsyncs_badstate++; 648 649 if (!(sp->sync_flags & PFSTATE_STALE)) { 650 /* we have a better state, send it */ 651 if (sc->sc_mbuf != NULL && !stale) 652 pfsync_sendout(sc); 653 stale++; 654 if (!st->sync_flags) 655 pfsync_pack_state( 656 PFSYNC_ACT_UPD, st, flags); 657 } 658 continue; 659 } 660 pf_state_peer_ntoh(&sp->src, &st->src); 661 pf_state_peer_ntoh(&sp->dst, &st->dst); 662 st->expire = ntohl(sp->expire) + time_second; 663 st->timeout = sp->timeout; 664 } 665 if (stale && sc->sc_mbuf != NULL) 666 pfsync_sendout(sc); 667#ifdef __FreeBSD__ 668 PF_UNLOCK(); 669#endif 670 splx(s); 671 break; 672 /* 673 * It's not strictly necessary for us to support the "uncompressed" 674 * delete action, but it's relatively simple and maintains consistency. 675 */ 676 case PFSYNC_ACT_DEL: 677 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 678 count * sizeof(*sp), &offp)) == NULL) { 679 pfsyncstats.pfsyncs_badlen++; 680 return; 681 } 682 683 s = splsoftnet(); 684#ifdef __FreeBSD__ 685 PF_LOCK(); 686#endif 687 for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 688 i < count; i++, sp++) { 689 bcopy(sp->id, &key.id, sizeof(key.id)); 690 key.creatorid = sp->creatorid; 691 692 st = pf_find_state_byid(&key); 693 if (st == NULL) { 694 pfsyncstats.pfsyncs_badstate++; 695 continue; 696 } 697 st->timeout = PFTM_PURGE; 698 st->sync_flags |= PFSTATE_FROMSYNC; 699 pf_purge_expired_state(st); 700 } 701#ifdef __FreeBSD__ 702 PF_UNLOCK(); 703#endif 704 splx(s); 705 break; 706 case PFSYNC_ACT_UPD_C: { 707 int update_requested = 0; 708 709 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 710 count * sizeof(*up), &offp)) == NULL) { 711 pfsyncstats.pfsyncs_badlen++; 712 return; 713 } 714 715 s = splsoftnet(); 716#ifdef __FreeBSD__ 717 PF_LOCK(); 718#endif 719 for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp); 720 i < count; i++, up++) { 721 /* check for invalid values */ 722 if (up->timeout >= PFTM_MAX || 723 up->src.state > PF_TCPS_PROXY_DST || 724 up->dst.state > PF_TCPS_PROXY_DST) { 725 if (pf_status.debug >= PF_DEBUG_MISC) 726 printf("pfsync_insert: " 727 "PFSYNC_ACT_UPD_C: " 728 "invalid value\n"); 729 pfsyncstats.pfsyncs_badstate++; 730 continue; 731 } 732 733 bcopy(up->id, &key.id, sizeof(key.id)); 734 key.creatorid = up->creatorid; 735 736 st = pf_find_state_byid(&key); 737 if (st == NULL) { 738 /* We don't have this state. Ask for it. */ 739 error = pfsync_request_update(up, &src); 740 if (error == ENOMEM) { 741 splx(s); 742 goto done; 743 } 744 update_requested = 1; 745 pfsyncstats.pfsyncs_badstate++; 746 continue; 747 } 748 sfail = 0; 749 if (st->proto == IPPROTO_TCP) { 750 /* 751 * The state should never go backwards except 752 * for syn-proxy states. Neither should the 753 * sequence window slide backwards. 754 */ 755 if (st->src.state > up->src.state && 756 (st->src.state < PF_TCPS_PROXY_SRC || 757 up->src.state >= PF_TCPS_PROXY_SRC)) 758 sfail = 1; 759 else if (st->dst.state > up->dst.state) 760 sfail = 2; 761 else if (SEQ_GT(st->src.seqlo, 762 ntohl(up->src.seqlo))) 763 sfail = 3; 764 else if (st->dst.state >= TCPS_SYN_SENT && 765 SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo))) 766 sfail = 4; 767 } else { 768 /* 769 * Non-TCP protocol state machine always go 770 * forwards 771 */ 772 if (st->src.state > up->src.state) 773 sfail = 5; 774 else if (st->dst.state > up->dst.state) 775 sfail = 6; 776 } 777 if (sfail) { 778 if (pf_status.debug >= PF_DEBUG_MISC) 779 printf("pfsync: ignoring stale update " 780 "(%d) id: %016llx " 781 "creatorid: %08x\n", sfail, 782#ifdef __FreeBSD__ 783 (unsigned long long)be64toh(st->id), 784#else 785 betoh64(st->id), 786#endif 787 ntohl(st->creatorid)); 788 pfsyncstats.pfsyncs_badstate++; 789 790 /* we have a better state, send it out */ 791 if ((!stale || update_requested) && 792 sc->sc_mbuf != NULL) { 793 pfsync_sendout(sc); 794 update_requested = 0; 795 } 796 stale++; 797 if (!st->sync_flags) 798 pfsync_pack_state(PFSYNC_ACT_UPD, st, 799 PFSYNC_FLAG_STALE); 800 continue; 801 } 802 pf_state_peer_ntoh(&up->src, &st->src); 803 pf_state_peer_ntoh(&up->dst, &st->dst); 804 st->expire = ntohl(up->expire) + time_second; 805 st->timeout = up->timeout; 806 } 807 if ((update_requested || stale) && sc->sc_mbuf) 808 pfsync_sendout(sc); 809#ifdef __FreeBSD__ 810 PF_UNLOCK(); 811#endif 812 splx(s); 813 break; 814 } 815 case PFSYNC_ACT_DEL_C: 816 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 817 count * sizeof(*dp), &offp)) == NULL) { 818 pfsyncstats.pfsyncs_badlen++; 819 return; 820 } 821 822 s = splsoftnet(); 823#ifdef __FreeBSD__ 824 PF_LOCK(); 825#endif 826 for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp); 827 i < count; i++, dp++) { 828 bcopy(dp->id, &key.id, sizeof(key.id)); 829 key.creatorid = dp->creatorid; 830 831 st = pf_find_state_byid(&key); 832 if (st == NULL) { 833 pfsyncstats.pfsyncs_badstate++; 834 continue; 835 } 836 st->timeout = PFTM_PURGE; 837 st->sync_flags |= PFSTATE_FROMSYNC; 838 pf_purge_expired_state(st); 839 } 840#ifdef __FreeBSD__ 841 PF_UNLOCK(); 842#endif 843 splx(s); 844 break; 845 case PFSYNC_ACT_INS_F: 846 case PFSYNC_ACT_DEL_F: 847 /* not implemented */ 848 break; 849 case PFSYNC_ACT_UREQ: 850 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 851 count * sizeof(*rup), &offp)) == NULL) { 852 pfsyncstats.pfsyncs_badlen++; 853 return; 854 } 855 856 s = splsoftnet(); 857#ifdef __FreeBSD__ 858 PF_LOCK(); 859#endif 860 if (sc->sc_mbuf != NULL) 861 pfsync_sendout(sc); 862 for (i = 0, 863 rup = (struct pfsync_state_upd_req *)(mp->m_data + offp); 864 i < count; i++, rup++) { 865 bcopy(rup->id, &key.id, sizeof(key.id)); 866 key.creatorid = rup->creatorid; 867 868 if (key.id == 0 && key.creatorid == 0) { 869 sc->sc_ureq_received = time_uptime; 870 if (pf_status.debug >= PF_DEBUG_MISC) 871 printf("pfsync: received " 872 "bulk update request\n"); 873 pfsync_send_bus(sc, PFSYNC_BUS_START); 874#ifdef __FreeBSD__ 875 callout_reset(&sc->sc_bulk_tmo, 1 * hz, 876 pfsync_bulk_update, 877 LIST_FIRST(&pfsync_list)); 878#else 879 timeout_add(&sc->sc_bulk_tmo, 1 * hz); 880#endif 881 } else { 882 st = pf_find_state_byid(&key); 883 if (st == NULL) { 884 pfsyncstats.pfsyncs_badstate++; 885 continue; 886 } 887 if (!st->sync_flags) 888 pfsync_pack_state(PFSYNC_ACT_UPD, 889 st, 0); 890 } 891 } 892 if (sc->sc_mbuf != NULL) 893 pfsync_sendout(sc); 894#ifdef __FreeBSD__ 895 PF_UNLOCK(); 896#endif 897 splx(s); 898 break; 899 case PFSYNC_ACT_BUS: 900 /* If we're not waiting for a bulk update, who cares. */ 901 if (sc->sc_ureq_sent == 0) 902 break; 903 904 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 905 sizeof(*bus), &offp)) == NULL) { 906 pfsyncstats.pfsyncs_badlen++; 907 return; 908 } 909 bus = (struct pfsync_state_bus *)(mp->m_data + offp); 910 switch (bus->status) { 911 case PFSYNC_BUS_START: 912#ifdef __FreeBSD__ 913 callout_reset(&sc->sc_bulkfail_tmo, 914 pf_pool_limits[PF_LIMIT_STATES].limit / 915 (PFSYNC_BULKPACKETS * sc->sc_maxcount), 916 pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 917#else 918 timeout_add(&sc->sc_bulkfail_tmo, 919 pf_pool_limits[PF_LIMIT_STATES].limit / 920 (PFSYNC_BULKPACKETS * sc->sc_maxcount)); 921#endif 922 if (pf_status.debug >= PF_DEBUG_MISC) 923 printf("pfsync: received bulk " 924 "update start\n"); 925 break; 926 case PFSYNC_BUS_END: 927 if (time_uptime - ntohl(bus->endtime) >= 928 sc->sc_ureq_sent) { 929 /* that's it, we're happy */ 930 sc->sc_ureq_sent = 0; 931 sc->sc_bulk_tries = 0; 932#ifdef __FreeBSD__ 933 callout_stop(&sc->sc_bulkfail_tmo); 934#else 935 timeout_del(&sc->sc_bulkfail_tmo); 936#endif 937#if NCARP > 0 /* XXX_IMPORT */ 938 if (!pfsync_sync_ok) 939 carp_suppress_preempt--; 940#endif 941 pfsync_sync_ok = 1; 942 if (pf_status.debug >= PF_DEBUG_MISC) 943 printf("pfsync: received valid " 944 "bulk update end\n"); 945 } else { 946 if (pf_status.debug >= PF_DEBUG_MISC) 947 printf("pfsync: received invalid " 948 "bulk update end: bad timestamp\n"); 949 } 950 break; 951 } 952 break; 953 } 954 955done: 956 if (m) 957 m_freem(m); 958} 959 960int 961pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 962 struct rtentry *rt) 963{ 964 m_freem(m); 965 return (0); 966} 967 968/* ARGSUSED */ 969int 970pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 971{ 972#ifndef __FreeBSD__ 973 struct proc *p = curproc; 974#endif 975 struct pfsync_softc *sc = ifp->if_softc; 976 struct ifreq *ifr = (struct ifreq *)data; 977 struct ip_moptions *imo = &sc->sc_imo; 978 struct pfsyncreq pfsyncr; 979 struct ifnet *sifp; 980 int s, error; 981 982 switch (cmd) { 983 case SIOCSIFADDR: 984 case SIOCAIFADDR: 985 case SIOCSIFDSTADDR: 986 case SIOCSIFFLAGS: 987 if (ifp->if_flags & IFF_UP) 988 ifp->if_flags |= IFF_RUNNING; 989 else 990 ifp->if_flags &= ~IFF_RUNNING; 991 break; 992 case SIOCSIFMTU: 993 if (ifr->ifr_mtu < PFSYNC_MINMTU) 994 return (EINVAL); 995 if (ifr->ifr_mtu > MCLBYTES) 996 ifr->ifr_mtu = MCLBYTES; 997 s = splnet(); 998#ifdef __FreeBSD__ 999 PF_LOCK(); 1000#endif 1001 if (ifr->ifr_mtu < ifp->if_mtu) { 1002 pfsync_sendout(sc); 1003 } 1004 pfsync_setmtu(sc, ifr->ifr_mtu); 1005#ifdef __FreeBSD__ 1006 PF_UNLOCK(); 1007#endif 1008 splx(s); 1009 break; 1010 case SIOCGETPFSYNC: 1011#ifdef __FreeBSD__ 1012 /* XXX: read unlocked */ 1013#endif 1014 bzero(&pfsyncr, sizeof(pfsyncr)); 1015 if (sc->sc_sync_ifp) 1016 strlcpy(pfsyncr.pfsyncr_syncdev, 1017 sc->sc_sync_ifp->if_xname, IFNAMSIZ); 1018 pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer; 1019 pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates; 1020 if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr)))) 1021 return (error); 1022 break; 1023 case SIOCSETPFSYNC: 1024#ifdef __FreeBSD__ 1025 if ((error = suser(curthread)) != 0) 1026#else 1027 if ((error = suser(p, p->p_acflag)) != 0) 1028#endif 1029 return (error); 1030 if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr)))) 1031 return (error); 1032 1033 if (pfsyncr.pfsyncr_syncpeer.s_addr == 0) 1034 sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP; 1035 else 1036 sc->sc_sync_peer.s_addr = 1037 pfsyncr.pfsyncr_syncpeer.s_addr; 1038 1039 if (pfsyncr.pfsyncr_maxupdates > 255) 1040 return (EINVAL); 1041#ifdef __FreeBSD__ 1042 callout_drain(&sc->sc_send_tmo); 1043 PF_LOCK(); 1044#endif 1045 sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; 1046 1047 if (pfsyncr.pfsyncr_syncdev[0] == 0) { 1048 sc->sc_sync_ifp = NULL; 1049 if (sc->sc_mbuf_net != NULL) { 1050 /* Don't keep stale pfsync packets around. */ 1051 s = splnet(); 1052 m_freem(sc->sc_mbuf_net); 1053 sc->sc_mbuf_net = NULL; 1054 sc->sc_statep_net.s = NULL; 1055 splx(s); 1056 } 1057 if (imo->imo_num_memberships > 0) { 1058 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1059 imo->imo_multicast_ifp = NULL; 1060 } 1061#ifdef __FreeBSD__ 1062 PF_UNLOCK(); 1063#endif 1064 break; 1065 } 1066 1067 if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) { 1068#ifdef __FreeBSD__ 1069 PF_UNLOCK(); 1070#endif 1071 return (EINVAL); 1072 } 1073 1074 s = splnet(); 1075#ifdef __FreeBSD__ 1076 if (sifp->if_mtu < SCP2IFP(sc)->if_mtu || 1077#else 1078 if (sifp->if_mtu < sc->sc_if.if_mtu || 1079#endif 1080 (sc->sc_sync_ifp != NULL && 1081 sifp->if_mtu < sc->sc_sync_ifp->if_mtu) || 1082 sifp->if_mtu < MCLBYTES - sizeof(struct ip)) 1083 pfsync_sendout(sc); 1084 sc->sc_sync_ifp = sifp; 1085 1086#ifdef __FreeBSD__ 1087 pfsync_setmtu(sc, SCP2IFP(sc)->if_mtu); 1088#else 1089 pfsync_setmtu(sc, sc->sc_if.if_mtu); 1090#endif 1091 1092 if (imo->imo_num_memberships > 0) { 1093 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1094 imo->imo_multicast_ifp = NULL; 1095 } 1096 1097 if (sc->sc_sync_ifp && 1098 sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) { 1099 struct in_addr addr; 1100 1101 if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) { 1102 sc->sc_sync_ifp = NULL; 1103#ifdef __FreeBSD__ 1104 PF_UNLOCK(); 1105#endif 1106 splx(s); 1107 return (EADDRNOTAVAIL); 1108 } 1109#ifdef __FreeBSD__ 1110 PF_UNLOCK(); /* addmulti mallocs w/ WAITOK */ 1111 addr.s_addr = htonl(INADDR_PFSYNC_GROUP); 1112#else 1113 addr.s_addr = INADDR_PFSYNC_GROUP; 1114#endif 1115 1116 if ((imo->imo_membership[0] = 1117 in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) { 1118 sc->sc_sync_ifp = NULL; 1119 splx(s); 1120 return (ENOBUFS); 1121 } 1122 imo->imo_num_memberships++; 1123 imo->imo_multicast_ifp = sc->sc_sync_ifp; 1124 imo->imo_multicast_ttl = PFSYNC_DFLTTL; 1125 imo->imo_multicast_loop = 0; 1126 } 1127 1128 if (sc->sc_sync_ifp || 1129 sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) { 1130 /* Request a full state table update. */ 1131#ifdef __FreeBSD__ 1132 PF_LOCK(); 1133#endif 1134 sc->sc_ureq_sent = time_uptime; 1135#if NCARP > 0 1136 if (pfsync_sync_ok) 1137 carp_suppress_preempt++; 1138#endif 1139 pfsync_sync_ok = 0; 1140 if (pf_status.debug >= PF_DEBUG_MISC) 1141 printf("pfsync: requesting bulk update\n"); 1142#ifdef __FreeBSD__ 1143 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, 1144 pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 1145#else 1146 timeout_add(&sc->sc_bulkfail_tmo, 5 * hz); 1147#endif 1148 error = pfsync_request_update(NULL, NULL); 1149 if (error == ENOMEM) { 1150#ifdef __FreeBSD__ 1151 PF_UNLOCK(); 1152#endif 1153 splx(s); 1154 return (ENOMEM); 1155 } 1156 pfsync_sendout(sc); 1157 } 1158#ifdef __FreeBSD__ 1159 PF_UNLOCK(); 1160#endif 1161 splx(s); 1162 1163 break; 1164 1165 default: 1166 return (ENOTTY); 1167 } 1168 1169 return (0); 1170} 1171 1172void 1173pfsync_setmtu(struct pfsync_softc *sc, int mtu_req) 1174{ 1175 int mtu; 1176 1177 if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req) 1178 mtu = sc->sc_sync_ifp->if_mtu; 1179 else 1180 mtu = mtu_req; 1181 1182 sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) / 1183 sizeof(struct pfsync_state); 1184 if (sc->sc_maxcount > 254) 1185 sc->sc_maxcount = 254; 1186#ifdef __FreeBSD__ 1187 SCP2IFP(sc)->if_mtu = sizeof(struct pfsync_header) + 1188 sc->sc_maxcount * sizeof(struct pfsync_state); 1189#else 1190 sc->sc_if.if_mtu = sizeof(struct pfsync_header) + 1191 sc->sc_maxcount * sizeof(struct pfsync_state); 1192#endif 1193} 1194 1195struct mbuf * 1196pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp) 1197{ 1198 struct pfsync_header *h; 1199 struct mbuf *m; 1200 int len; 1201 1202#ifdef __FreeBSD__ 1203 PF_ASSERT(MA_OWNED); 1204#endif 1205 MGETHDR(m, M_DONTWAIT, MT_DATA); 1206 if (m == NULL) { 1207#ifdef __FreeBSD__ 1208 SCP2IFP(sc)->if_oerrors++; 1209#else 1210 sc->sc_if.if_oerrors++; 1211#endif 1212 return (NULL); 1213 } 1214 1215 switch (action) { 1216 case PFSYNC_ACT_CLR: 1217 len = sizeof(struct pfsync_header) + 1218 sizeof(struct pfsync_state_clr); 1219 break; 1220 case PFSYNC_ACT_UPD_C: 1221 len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) + 1222 sizeof(struct pfsync_header); 1223 break; 1224 case PFSYNC_ACT_DEL_C: 1225 len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) + 1226 sizeof(struct pfsync_header); 1227 break; 1228 case PFSYNC_ACT_UREQ: 1229 len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) + 1230 sizeof(struct pfsync_header); 1231 break; 1232 case PFSYNC_ACT_BUS: 1233 len = sizeof(struct pfsync_header) + 1234 sizeof(struct pfsync_state_bus); 1235 break; 1236 default: 1237 len = (sc->sc_maxcount * sizeof(struct pfsync_state)) + 1238 sizeof(struct pfsync_header); 1239 break; 1240 } 1241 1242 if (len > MHLEN) { 1243 MCLGET(m, M_DONTWAIT); 1244 if ((m->m_flags & M_EXT) == 0) { 1245 m_free(m); 1246#ifdef __FreeBSD__ 1247 SCP2IFP(sc)->if_oerrors++; 1248#else 1249 sc->sc_if.if_oerrors++; 1250#endif 1251 return (NULL); 1252 } 1253 m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1); 1254 } else 1255 MH_ALIGN(m, len); 1256 1257 m->m_pkthdr.rcvif = NULL; 1258 m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header); 1259 h = mtod(m, struct pfsync_header *); 1260 h->version = PFSYNC_VERSION; 1261 h->af = 0; 1262 h->count = 0; 1263 h->action = action; 1264 1265 *sp = (void *)((char *)h + PFSYNC_HDRLEN); 1266#ifdef __FreeBSD__ 1267 callout_reset(&sc->sc_tmo, hz, pfsync_timeout, 1268 LIST_FIRST(&pfsync_list)); 1269#else 1270 timeout_add(&sc->sc_tmo, hz); 1271#endif 1272 return (m); 1273} 1274 1275int 1276pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags) 1277{ 1278#ifdef __FreeBSD__ 1279 struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1280#else 1281 struct ifnet *ifp = &pfsyncif.sc_if; 1282#endif 1283 struct pfsync_softc *sc = ifp->if_softc; 1284 struct pfsync_header *h, *h_net; 1285 struct pfsync_state *sp = NULL; 1286 struct pfsync_state_upd *up = NULL; 1287 struct pfsync_state_del *dp = NULL; 1288 struct pf_rule *r; 1289 u_long secs; 1290 int s, ret = 0; 1291 u_int8_t i = 255, newaction = 0; 1292 1293#ifdef __FreeBSD__ 1294 PF_ASSERT(MA_OWNED); 1295#endif 1296 /* 1297 * If a packet falls in the forest and there's nobody around to 1298 * hear, does it make a sound? 1299 */ 1300 if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL && 1301 sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) { 1302 /* Don't leave any stale pfsync packets hanging around. */ 1303 if (sc->sc_mbuf != NULL) { 1304 m_freem(sc->sc_mbuf); 1305 sc->sc_mbuf = NULL; 1306 sc->sc_statep.s = NULL; 1307 } 1308 return (0); 1309 } 1310 1311 if (action >= PFSYNC_ACT_MAX) 1312 return (EINVAL); 1313 1314 s = splnet(); 1315 if (sc->sc_mbuf == NULL) { 1316 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 1317 (void *)&sc->sc_statep.s)) == NULL) { 1318 splx(s); 1319 return (ENOMEM); 1320 } 1321 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1322 } else { 1323 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1324 if (h->action != action) { 1325 pfsync_sendout(sc); 1326 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 1327 (void *)&sc->sc_statep.s)) == NULL) { 1328 splx(s); 1329 return (ENOMEM); 1330 } 1331 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1332 } else { 1333 /* 1334 * If it's an update, look in the packet to see if 1335 * we already have an update for the state. 1336 */ 1337 if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) { 1338 struct pfsync_state *usp = 1339 (void *)((char *)h + PFSYNC_HDRLEN); 1340 1341 for (i = 0; i < h->count; i++) { 1342 if (!memcmp(usp->id, &st->id, 1343 PFSYNC_ID_LEN) && 1344 usp->creatorid == st->creatorid) { 1345 sp = usp; 1346 sp->updates++; 1347 break; 1348 } 1349 usp++; 1350 } 1351 } 1352 } 1353 } 1354 1355 secs = time_second; 1356 1357 st->pfsync_time = time_uptime; 1358 TAILQ_REMOVE(&state_updates, st, u.s.entry_updates); 1359 TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates); 1360 1361 if (sp == NULL) { 1362 /* not a "duplicate" update */ 1363 i = 255; 1364 sp = sc->sc_statep.s++; 1365 sc->sc_mbuf->m_pkthdr.len = 1366 sc->sc_mbuf->m_len += sizeof(struct pfsync_state); 1367 h->count++; 1368 bzero(sp, sizeof(*sp)); 1369 1370 bcopy(&st->id, sp->id, sizeof(sp->id)); 1371 sp->creatorid = st->creatorid; 1372 1373 strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname)); 1374 pf_state_host_hton(&st->lan, &sp->lan); 1375 pf_state_host_hton(&st->gwy, &sp->gwy); 1376 pf_state_host_hton(&st->ext, &sp->ext); 1377 1378 bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); 1379 1380 sp->creation = htonl(secs - st->creation); 1381 sp->packets[0] = htonl(st->packets[0]); 1382 sp->packets[1] = htonl(st->packets[1]); 1383 sp->bytes[0] = htonl(st->bytes[0]); 1384 sp->bytes[1] = htonl(st->bytes[1]); 1385 if ((r = st->rule.ptr) == NULL) 1386 sp->rule = htonl(-1); 1387 else 1388 sp->rule = htonl(r->nr); 1389 if ((r = st->anchor.ptr) == NULL) 1390 sp->anchor = htonl(-1); 1391 else 1392 sp->anchor = htonl(r->nr); 1393 sp->af = st->af; 1394 sp->proto = st->proto; 1395 sp->direction = st->direction; 1396 sp->log = st->log; 1397 sp->allow_opts = st->allow_opts; 1398 sp->timeout = st->timeout; 1399 1400 if (flags & PFSYNC_FLAG_STALE) 1401 sp->sync_flags |= PFSTATE_STALE; 1402 } 1403 1404 pf_state_peer_hton(&st->src, &sp->src); 1405 pf_state_peer_hton(&st->dst, &sp->dst); 1406 1407 if (st->expire <= secs) 1408 sp->expire = htonl(0); 1409 else 1410 sp->expire = htonl(st->expire - secs); 1411 1412 /* do we need to build "compressed" actions for network transfer? */ 1413 if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) { 1414 switch (action) { 1415 case PFSYNC_ACT_UPD: 1416 newaction = PFSYNC_ACT_UPD_C; 1417 break; 1418 case PFSYNC_ACT_DEL: 1419 newaction = PFSYNC_ACT_DEL_C; 1420 break; 1421 default: 1422 /* by default we just send the uncompressed states */ 1423 break; 1424 } 1425 } 1426 1427 if (newaction) { 1428 if (sc->sc_mbuf_net == NULL) { 1429 if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction, 1430 (void *)&sc->sc_statep_net.s)) == NULL) { 1431 splx(s); 1432 return (ENOMEM); 1433 } 1434 } 1435 h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *); 1436 1437 switch (newaction) { 1438 case PFSYNC_ACT_UPD_C: 1439 if (i != 255) { 1440 up = (void *)((char *)h_net + 1441 PFSYNC_HDRLEN + (i * sizeof(*up))); 1442 up->updates++; 1443 } else { 1444 h_net->count++; 1445 sc->sc_mbuf_net->m_pkthdr.len = 1446 sc->sc_mbuf_net->m_len += sizeof(*up); 1447 up = sc->sc_statep_net.u++; 1448 1449 bzero(up, sizeof(*up)); 1450 bcopy(&st->id, up->id, sizeof(up->id)); 1451 up->creatorid = st->creatorid; 1452 } 1453 up->timeout = st->timeout; 1454 up->expire = sp->expire; 1455 up->src = sp->src; 1456 up->dst = sp->dst; 1457 break; 1458 case PFSYNC_ACT_DEL_C: 1459 sc->sc_mbuf_net->m_pkthdr.len = 1460 sc->sc_mbuf_net->m_len += sizeof(*dp); 1461 dp = sc->sc_statep_net.d++; 1462 h_net->count++; 1463 1464 bzero(dp, sizeof(*dp)); 1465 bcopy(&st->id, dp->id, sizeof(dp->id)); 1466 dp->creatorid = st->creatorid; 1467 break; 1468 } 1469 } 1470 1471 if (h->count == sc->sc_maxcount || 1472 (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates))) 1473 ret = pfsync_sendout(sc); 1474 1475 splx(s); 1476 return (ret); 1477} 1478 1479/* This must be called in splnet() */ 1480int 1481pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src) 1482{ 1483#ifdef __FreeBSD__ 1484 struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1485#else 1486 struct ifnet *ifp = &pfsyncif.sc_if; 1487#endif 1488 struct pfsync_header *h; 1489 struct pfsync_softc *sc = ifp->if_softc; 1490 struct pfsync_state_upd_req *rup; 1491 int ret = 0; 1492 1493#ifdef __FreeBSD__ 1494 PF_ASSERT(MA_OWNED); 1495#endif 1496 if (sc->sc_mbuf == NULL) { 1497 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1498 (void *)&sc->sc_statep.s)) == NULL) 1499 return (ENOMEM); 1500 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1501 } else { 1502 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1503 if (h->action != PFSYNC_ACT_UREQ) { 1504 pfsync_sendout(sc); 1505 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1506 (void *)&sc->sc_statep.s)) == NULL) 1507 return (ENOMEM); 1508 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1509 } 1510 } 1511 1512 if (src != NULL) 1513 sc->sc_sendaddr = *src; 1514 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup); 1515 h->count++; 1516 rup = sc->sc_statep.r++; 1517 bzero(rup, sizeof(*rup)); 1518 if (up != NULL) { 1519 bcopy(up->id, rup->id, sizeof(rup->id)); 1520 rup->creatorid = up->creatorid; 1521 } 1522 1523 if (h->count == sc->sc_maxcount) 1524 ret = pfsync_sendout(sc); 1525 1526 return (ret); 1527} 1528 1529int 1530pfsync_clear_states(u_int32_t creatorid, char *ifname) 1531{ 1532#ifdef __FreeBSD__ 1533 struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1534#else 1535 struct ifnet *ifp = &pfsyncif.sc_if; 1536#endif 1537 struct pfsync_softc *sc = ifp->if_softc; 1538 struct pfsync_state_clr *cp; 1539 int s, ret; 1540 1541 s = splnet(); 1542#ifdef __FreeBSD__ 1543 PF_ASSERT(MA_OWNED); 1544#endif 1545 if (sc->sc_mbuf != NULL) 1546 pfsync_sendout(sc); 1547 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR, 1548 (void *)&sc->sc_statep.c)) == NULL) { 1549 splx(s); 1550 return (ENOMEM); 1551 } 1552 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp); 1553 cp = sc->sc_statep.c; 1554 cp->creatorid = creatorid; 1555 if (ifname != NULL) 1556 strlcpy(cp->ifname, ifname, IFNAMSIZ); 1557 1558 ret = (pfsync_sendout(sc)); 1559 splx(s); 1560 return (ret); 1561} 1562 1563void 1564pfsync_timeout(void *v) 1565{ 1566 struct pfsync_softc *sc = v; 1567 int s; 1568 1569 s = splnet(); 1570#ifdef __FreeBSD__ 1571 PF_LOCK(); 1572#endif 1573 pfsync_sendout(sc); 1574#ifdef __FreeBSD__ 1575 PF_UNLOCK(); 1576#endif 1577 splx(s); 1578} 1579 1580/* This must be called in splnet() */ 1581void 1582pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status) 1583{ 1584 struct pfsync_state_bus *bus; 1585 1586#ifdef __FreeBSD__ 1587 PF_ASSERT(MA_OWNED); 1588#endif 1589 if (sc->sc_mbuf != NULL) 1590 pfsync_sendout(sc); 1591 1592 if (pfsync_sync_ok && 1593 (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS, 1594 (void *)&sc->sc_statep.b)) != NULL) { 1595 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus); 1596 bus = sc->sc_statep.b; 1597 bus->creatorid = pf_status.hostid; 1598 bus->status = status; 1599 bus->endtime = htonl(time_uptime - sc->sc_ureq_received); 1600 pfsync_sendout(sc); 1601 } 1602} 1603 1604void 1605pfsync_bulk_update(void *v) 1606{ 1607 struct pfsync_softc *sc = v; 1608 int s, i = 0; 1609 struct pf_state *state; 1610 1611#ifdef __FreeBSD__ 1612 PF_LOCK(); 1613#endif 1614 s = splnet(); 1615 if (sc->sc_mbuf != NULL) 1616 pfsync_sendout(sc); 1617 1618 /* 1619 * Grab at most PFSYNC_BULKPACKETS worth of states which have not 1620 * been sent since the latest request was made. 1621 */ 1622 while ((state = TAILQ_FIRST(&state_updates)) != NULL && 1623 ++i < (sc->sc_maxcount * PFSYNC_BULKPACKETS)) { 1624 if (state->pfsync_time > sc->sc_ureq_received) { 1625 /* we're done */ 1626 pfsync_send_bus(sc, PFSYNC_BUS_END); 1627 sc->sc_ureq_received = 0; 1628#ifdef __FreeBSD__ 1629 callout_stop(&sc->sc_bulk_tmo); 1630#else 1631 timeout_del(&sc->sc_bulk_tmo); 1632#endif 1633 if (pf_status.debug >= PF_DEBUG_MISC) 1634 printf("pfsync: bulk update complete\n"); 1635 break; 1636 } else { 1637 /* send an update and move to end of list */ 1638 if (!state->sync_flags) 1639 pfsync_pack_state(PFSYNC_ACT_UPD, state, 0); 1640 state->pfsync_time = time_uptime; 1641 TAILQ_REMOVE(&state_updates, state, u.s.entry_updates); 1642 TAILQ_INSERT_TAIL(&state_updates, state, 1643 u.s.entry_updates); 1644 1645 /* look again for more in a bit */ 1646#ifdef __FreeBSD__ 1647 callout_reset(&sc->sc_bulk_tmo, 1, pfsync_timeout, 1648 LIST_FIRST(&pfsync_list)); 1649#else 1650 timeout_add(&sc->sc_bulk_tmo, 1); 1651#endif 1652 } 1653 } 1654 if (sc->sc_mbuf != NULL) 1655 pfsync_sendout(sc); 1656 splx(s); 1657#ifdef __FreeBSD__ 1658 PF_UNLOCK(); 1659#endif 1660} 1661 1662void 1663pfsync_bulkfail(void *v) 1664{ 1665 struct pfsync_softc *sc = v; 1666 int s, error; 1667 1668#ifdef __FreeBSD__ 1669 PF_LOCK(); 1670#endif 1671 if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) { 1672 /* Try again in a bit */ 1673#ifdef __FreeBSD__ 1674 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail, 1675 LIST_FIRST(&pfsync_list)); 1676#else 1677 timeout_add(&sc->sc_bulkfail_tmo, 5 * hz); 1678#endif 1679 s = splnet(); 1680 error = pfsync_request_update(NULL, NULL); 1681 if (error == ENOMEM) { 1682 if (pf_status.debug >= PF_DEBUG_MISC) 1683 printf("pfsync: cannot allocate mbufs for " 1684 "bulk update\n"); 1685 } else 1686 pfsync_sendout(sc); 1687 splx(s); 1688 } else { 1689 /* Pretend like the transfer was ok */ 1690 sc->sc_ureq_sent = 0; 1691 sc->sc_bulk_tries = 0; 1692#if NCARP > 0 1693 if (!pfsync_sync_ok) 1694 carp_suppress_preempt--; 1695#endif 1696 pfsync_sync_ok = 1; 1697 if (pf_status.debug >= PF_DEBUG_MISC) 1698 printf("pfsync: failed to receive " 1699 "bulk update status\n"); 1700#ifdef __FreeBSD__ 1701 callout_stop(&sc->sc_bulkfail_tmo); 1702#else 1703 timeout_del(&sc->sc_bulkfail_tmo); 1704#endif 1705 } 1706#ifdef __FreeBSD__ 1707 PF_UNLOCK(); 1708#endif 1709} 1710 1711/* This must be called in splnet() */ 1712int 1713pfsync_sendout(sc) 1714 struct pfsync_softc *sc; 1715{ 1716#if NBPFILTER > 0 1717# ifdef __FreeBSD__ 1718 struct ifnet *ifp = SCP2IFP(sc); 1719# else 1720 struct ifnet *ifp = &sc->if_sc; 1721# endif 1722#endif 1723 struct mbuf *m; 1724 1725#ifdef __FreeBSD__ 1726 PF_ASSERT(MA_OWNED); 1727 callout_stop(&sc->sc_tmo); 1728#else 1729 timeout_del(&sc->sc_tmo); 1730#endif 1731 1732 if (sc->sc_mbuf == NULL) 1733 return (0); 1734 m = sc->sc_mbuf; 1735 sc->sc_mbuf = NULL; 1736 sc->sc_statep.s = NULL; 1737 1738#ifdef __FreeBSD__ 1739 KASSERT(m != NULL, ("pfsync_sendout: null mbuf")); 1740#endif 1741#if NBPFILTER > 0 1742 if (ifp->if_bpf) 1743 bpf_mtap(ifp->if_bpf, m); 1744#endif 1745 1746 if (sc->sc_mbuf_net) { 1747 m_freem(m); 1748 m = sc->sc_mbuf_net; 1749 sc->sc_mbuf_net = NULL; 1750 sc->sc_statep_net.s = NULL; 1751 } 1752 1753 if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) { 1754 struct ip *ip; 1755 struct sockaddr sa; 1756 1757 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 1758 if (m == NULL) { 1759 pfsyncstats.pfsyncs_onomem++; 1760 return (0); 1761 } 1762 ip = mtod(m, struct ip *); 1763 ip->ip_v = IPVERSION; 1764 ip->ip_hl = sizeof(*ip) >> 2; 1765 ip->ip_tos = IPTOS_LOWDELAY; 1766#ifdef __FreeBSD__ 1767 ip->ip_len = m->m_pkthdr.len; 1768#else 1769 ip->ip_len = htons(m->m_pkthdr.len); 1770#endif 1771 ip->ip_id = htons(ip_randomid()); 1772#ifdef __FreeBSD__ 1773 ip->ip_off = IP_DF; 1774#else 1775 ip->ip_off = htons(IP_DF); 1776#endif 1777 ip->ip_ttl = PFSYNC_DFLTTL; 1778 ip->ip_p = IPPROTO_PFSYNC; 1779 ip->ip_sum = 0; 1780 1781 bzero(&sa, sizeof(sa)); 1782 ip->ip_src.s_addr = INADDR_ANY; 1783 1784#ifdef __FreeBSD__ 1785 if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP)) 1786#else 1787 if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP) 1788#endif 1789 m->m_flags |= M_MCAST; 1790 ip->ip_dst = sc->sc_sendaddr; 1791#ifdef __FreeBSD__ 1792 /* XXX_IMPORT */ 1793 sc->sc_sendaddr.s_addr = htonl(sc->sc_sync_peer.s_addr); 1794#else 1795 sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr; 1796#endif 1797 1798 pfsyncstats.pfsyncs_opackets++; 1799#ifdef __FreeBSD__ 1800 if (IF_HANDOFF(&sc->sc_ifq, m, NULL)) 1801 pfsyncstats.pfsyncs_oerrors++; 1802 callout_reset(&sc->sc_send_tmo, 1, pfsync_senddef, sc); 1803#else 1804 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 1805 pfsyncstats.pfsyncs_oerrors++; 1806#endif 1807 } else 1808 m_freem(m); 1809 1810 return (0); 1811} 1812 1813#ifdef __FreeBSD__ 1814static void 1815pfsync_senddef(void *arg) 1816{ 1817 struct pfsync_softc *sc = (struct pfsync_softc *)arg; 1818 struct mbuf *m; 1819 1820 for(;;) { 1821 IF_DEQUEUE(&sc->sc_ifq, m); 1822 if (m == NULL) 1823 break; 1824 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 1825 pfsyncstats.pfsyncs_oerrors++; 1826 } 1827} 1828 1829static int 1830pfsync_modevent(module_t mod, int type, void *data) 1831{ 1832 int error = 0; 1833 1834 switch (type) { 1835 case MOD_LOAD: 1836 LIST_INIT(&pfsync_list); 1837 if_clone_attach(&pfsync_cloner); 1838 break; 1839 1840 case MOD_UNLOAD: 1841 if_clone_detach(&pfsync_cloner); 1842 while (!LIST_EMPTY(&pfsync_list)) 1843 pfsync_clone_destroy( 1844 SCP2IFP(LIST_FIRST(&pfsync_list))); 1845 break; 1846 1847 default: 1848 error = EINVAL; 1849 break; 1850 } 1851 1852 return error; 1853} 1854 1855static moduledata_t pfsync_mod = { 1856 "pfsync", 1857 pfsync_modevent, 1858 0 1859}; 1860 1861#define PFSYNC_MODVER 1 1862 1863DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 1864MODULE_VERSION(pfsync, PFSYNC_MODVER); 1865#endif /* __FreeBSD__ */
|