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