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