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