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