if_pfsync.c revision 228814
1/* $OpenBSD: if_pfsync.c,v 1.110 2009/02/24 05:39:19 dlg Exp $ */ 2 3/* 4 * Copyright (c) 2002 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * Copyright (c) 2009 David Gwynne <dlg@openbsd.org> 31 * 32 * Permission to use, copy, modify, and distribute this software for any 33 * purpose with or without fee is hereby granted, provided that the above 34 * copyright notice and this permission notice appear in all copies. 35 * 36 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 37 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 38 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 39 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 40 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 41 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 42 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 43 */ 44 45/* 46 * Revisions picked from OpenBSD after revision 1.110 import: 47 * 1.118, 1.124, 1.148, 1.149, 1.151, 1.171 - fixes to bulk updates 48 */ 49 50#ifdef __FreeBSD__ 51#include "opt_inet.h" 52#include "opt_inet6.h" 53#include "opt_pf.h" 54 55#include <sys/cdefs.h> 56__FBSDID("$FreeBSD: head/sys/contrib/pf/net/if_pfsync.c 228814 2011-12-22 18:56:27Z glebius $"); 57 58#define NBPFILTER 1 59 60#ifdef DEV_PFSYNC 61#define NPFSYNC DEV_PFSYNC 62#else 63#define NPFSYNC 0 64#endif 65#endif /* __FreeBSD__ */ 66 67#include <sys/param.h> 68#include <sys/kernel.h> 69#ifdef __FreeBSD__ 70#include <sys/bus.h> 71#include <sys/interrupt.h> 72#include <sys/priv.h> 73#endif 74#include <sys/proc.h> 75#include <sys/systm.h> 76#include <sys/time.h> 77#include <sys/mbuf.h> 78#include <sys/socket.h> 79#ifdef __FreeBSD__ 80#include <sys/endian.h> 81#include <sys/malloc.h> 82#include <sys/module.h> 83#include <sys/sockio.h> 84#include <sys/taskqueue.h> 85#include <sys/lock.h> 86#include <sys/mutex.h> 87#else 88#include <sys/ioctl.h> 89#include <sys/timeout.h> 90#endif 91#include <sys/sysctl.h> 92#ifndef __FreeBSD__ 93#include <sys/pool.h> 94#endif 95 96#include <net/if.h> 97#ifdef __FreeBSD__ 98#include <net/if_clone.h> 99#endif 100#include <net/if_types.h> 101#include <net/route.h> 102#include <net/bpf.h> 103#include <net/netisr.h> 104#ifdef __FreeBSD__ 105#include <net/vnet.h> 106#endif 107 108#include <netinet/in.h> 109#include <netinet/if_ether.h> 110#include <netinet/tcp.h> 111#include <netinet/tcp_seq.h> 112 113#ifdef INET 114#include <netinet/in_systm.h> 115#include <netinet/in_var.h> 116#include <netinet/ip.h> 117#include <netinet/ip_var.h> 118#endif 119 120#ifdef INET6 121#include <netinet6/nd6.h> 122#endif /* INET6 */ 123 124#ifdef __FreeBSD__ 125#include <netinet/ip_carp.h> 126#else 127#include "carp.h" 128#if NCARP > 0 129#include <netinet/ip_carp.h> 130#endif 131#endif 132 133#include <net/pfvar.h> 134#include <net/if_pfsync.h> 135 136#ifndef __FreeBSD__ 137#include "bpfilter.h" 138#include "pfsync.h" 139#endif 140 141#define PFSYNC_MINPKT ( \ 142 sizeof(struct ip) + \ 143 sizeof(struct pfsync_header) + \ 144 sizeof(struct pfsync_subheader) + \ 145 sizeof(struct pfsync_eof)) 146 147struct pfsync_pkt { 148 struct ip *ip; 149 struct in_addr src; 150 u_int8_t flags; 151}; 152 153int pfsync_input_hmac(struct mbuf *, int); 154 155int pfsync_upd_tcp(struct pf_state *, struct pfsync_state_peer *, 156 struct pfsync_state_peer *); 157 158int pfsync_in_clr(struct pfsync_pkt *, struct mbuf *, int, int); 159int pfsync_in_ins(struct pfsync_pkt *, struct mbuf *, int, int); 160int pfsync_in_iack(struct pfsync_pkt *, struct mbuf *, int, int); 161int pfsync_in_upd(struct pfsync_pkt *, struct mbuf *, int, int); 162int pfsync_in_upd_c(struct pfsync_pkt *, struct mbuf *, int, int); 163int pfsync_in_ureq(struct pfsync_pkt *, struct mbuf *, int, int); 164int pfsync_in_del(struct pfsync_pkt *, struct mbuf *, int, int); 165int pfsync_in_del_c(struct pfsync_pkt *, struct mbuf *, int, int); 166int pfsync_in_bus(struct pfsync_pkt *, struct mbuf *, int, int); 167int pfsync_in_tdb(struct pfsync_pkt *, struct mbuf *, int, int); 168int pfsync_in_eof(struct pfsync_pkt *, struct mbuf *, int, int); 169 170int pfsync_in_error(struct pfsync_pkt *, struct mbuf *, int, int); 171 172int (*pfsync_acts[])(struct pfsync_pkt *, struct mbuf *, int, int) = { 173 pfsync_in_clr, /* PFSYNC_ACT_CLR */ 174 pfsync_in_ins, /* PFSYNC_ACT_INS */ 175 pfsync_in_iack, /* PFSYNC_ACT_INS_ACK */ 176 pfsync_in_upd, /* PFSYNC_ACT_UPD */ 177 pfsync_in_upd_c, /* PFSYNC_ACT_UPD_C */ 178 pfsync_in_ureq, /* PFSYNC_ACT_UPD_REQ */ 179 pfsync_in_del, /* PFSYNC_ACT_DEL */ 180 pfsync_in_del_c, /* PFSYNC_ACT_DEL_C */ 181 pfsync_in_error, /* PFSYNC_ACT_INS_F */ 182 pfsync_in_error, /* PFSYNC_ACT_DEL_F */ 183 pfsync_in_bus, /* PFSYNC_ACT_BUS */ 184 pfsync_in_tdb, /* PFSYNC_ACT_TDB */ 185 pfsync_in_eof /* PFSYNC_ACT_EOF */ 186}; 187 188struct pfsync_q { 189 int (*write)(struct pf_state *, struct mbuf *, int); 190 size_t len; 191 u_int8_t action; 192}; 193 194/* we have one of these for every PFSYNC_S_ */ 195int pfsync_out_state(struct pf_state *, struct mbuf *, int); 196int pfsync_out_iack(struct pf_state *, struct mbuf *, int); 197int pfsync_out_upd_c(struct pf_state *, struct mbuf *, int); 198int pfsync_out_del(struct pf_state *, struct mbuf *, int); 199 200struct pfsync_q pfsync_qs[] = { 201 { pfsync_out_state, sizeof(struct pfsync_state), PFSYNC_ACT_INS }, 202 { pfsync_out_iack, sizeof(struct pfsync_ins_ack), PFSYNC_ACT_INS_ACK }, 203 { pfsync_out_state, sizeof(struct pfsync_state), PFSYNC_ACT_UPD }, 204 { pfsync_out_upd_c, sizeof(struct pfsync_upd_c), PFSYNC_ACT_UPD_C }, 205 { pfsync_out_del, sizeof(struct pfsync_del_c), PFSYNC_ACT_DEL_C } 206}; 207 208void pfsync_q_ins(struct pf_state *, int); 209void pfsync_q_del(struct pf_state *); 210 211struct pfsync_upd_req_item { 212 TAILQ_ENTRY(pfsync_upd_req_item) ur_entry; 213 struct pfsync_upd_req ur_msg; 214}; 215TAILQ_HEAD(pfsync_upd_reqs, pfsync_upd_req_item); 216 217struct pfsync_deferral { 218 TAILQ_ENTRY(pfsync_deferral) pd_entry; 219 struct pf_state *pd_st; 220 struct mbuf *pd_m; 221#ifdef __FreeBSD__ 222 struct callout pd_tmo; 223#else 224 struct timeout pd_tmo; 225#endif 226}; 227TAILQ_HEAD(pfsync_deferrals, pfsync_deferral); 228 229#define PFSYNC_PLSIZE MAX(sizeof(struct pfsync_upd_req_item), \ 230 sizeof(struct pfsync_deferral)) 231 232#ifdef notyet 233int pfsync_out_tdb(struct tdb *, struct mbuf *, int); 234#endif 235 236struct pfsync_softc { 237#ifdef __FreeBSD__ 238 struct ifnet *sc_ifp; 239#else 240 struct ifnet sc_if; 241#endif 242 struct ifnet *sc_sync_if; 243 244#ifdef __FreeBSD__ 245 uma_zone_t sc_pool; 246#else 247 struct pool sc_pool; 248#endif 249 250 struct ip_moptions sc_imo; 251 252 struct in_addr sc_sync_peer; 253 u_int8_t sc_maxupdates; 254#ifdef __FreeBSD__ 255 int pfsync_sync_ok; 256#endif 257 258 struct ip sc_template; 259 260 struct pf_state_queue sc_qs[PFSYNC_S_COUNT]; 261 size_t sc_len; 262 263 struct pfsync_upd_reqs sc_upd_req_list; 264 265 struct pfsync_deferrals sc_deferrals; 266 u_int sc_deferred; 267 268 void *sc_plus; 269 size_t sc_pluslen; 270 271 u_int32_t sc_ureq_sent; 272 int sc_bulk_tries; 273#ifdef __FreeBSD__ 274 struct callout sc_bulkfail_tmo; 275#else 276 struct timeout sc_bulkfail_tmo; 277#endif 278 279 u_int32_t sc_ureq_received; 280 struct pf_state *sc_bulk_next; 281 struct pf_state *sc_bulk_last; 282#ifdef __FreeBSD__ 283 struct callout sc_bulk_tmo; 284#else 285 struct timeout sc_bulk_tmo; 286#endif 287 288 TAILQ_HEAD(, tdb) sc_tdb_q; 289 290#ifdef __FreeBSD__ 291 struct callout sc_tmo; 292#else 293 struct timeout sc_tmo; 294#endif 295#ifdef __FreeBSD__ 296 eventhandler_tag sc_detachtag; 297#endif 298 299}; 300 301#ifdef __FreeBSD__ 302static VNET_DEFINE(struct pfsync_softc *, pfsyncif) = NULL; 303#define V_pfsyncif VNET(pfsyncif) 304 305static VNET_DEFINE(struct pfsyncstats, pfsyncstats); 306#define V_pfsyncstats VNET(pfsyncstats) 307static VNET_DEFINE(int, pfsync_carp_adj) = CARP_MAXSKEW; 308#define V_pfsync_carp_adj VNET(pfsync_carp_adj) 309 310SYSCTL_NODE(_net, OID_AUTO, pfsync, CTLFLAG_RW, 0, "PFSYNC"); 311SYSCTL_VNET_STRUCT(_net_pfsync, OID_AUTO, stats, CTLFLAG_RW, 312 &VNET_NAME(pfsyncstats), pfsyncstats, 313 "PFSYNC statistics (struct pfsyncstats, net/if_pfsync.h)"); 314SYSCTL_INT(_net_pfsync, OID_AUTO, carp_demotion_factor, CTLFLAG_RW, 315 &VNET_NAME(pfsync_carp_adj), 0, "pfsync's CARP demotion factor adjustment"); 316#else 317struct pfsync_softc *pfsyncif = NULL; 318struct pfsyncstats pfsyncstats; 319#define V_pfsyncstats pfsyncstats 320#endif 321 322#ifdef __FreeBSD__ 323static void pfsyncintr(void *); 324struct pfsync_swi { 325 void * pfsync_swi_cookie; 326}; 327static struct pfsync_swi pfsync_swi; 328#define schednetisr(p) swi_sched(pfsync_swi.pfsync_swi_cookie, 0) 329#define NETISR_PFSYNC 330#endif 331 332void pfsyncattach(int); 333#ifdef __FreeBSD__ 334int pfsync_clone_create(struct if_clone *, int, caddr_t); 335void pfsync_clone_destroy(struct ifnet *); 336#else 337int pfsync_clone_create(struct if_clone *, int); 338int pfsync_clone_destroy(struct ifnet *); 339#endif 340int pfsync_alloc_scrub_memory(struct pfsync_state_peer *, 341 struct pf_state_peer *); 342void pfsync_update_net_tdb(struct pfsync_tdb *); 343int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 344#ifdef __FreeBSD__ 345 struct route *); 346#else 347 struct rtentry *); 348#endif 349int pfsyncioctl(struct ifnet *, u_long, caddr_t); 350void pfsyncstart(struct ifnet *); 351 352struct mbuf *pfsync_if_dequeue(struct ifnet *); 353struct mbuf *pfsync_get_mbuf(struct pfsync_softc *); 354 355void pfsync_deferred(struct pf_state *, int); 356void pfsync_undefer(struct pfsync_deferral *, int); 357void pfsync_defer_tmo(void *); 358 359void pfsync_request_update(u_int32_t, u_int64_t); 360void pfsync_update_state_req(struct pf_state *); 361 362void pfsync_drop(struct pfsync_softc *); 363void pfsync_sendout(void); 364void pfsync_send_plus(void *, size_t); 365int pfsync_tdb_sendout(struct pfsync_softc *); 366int pfsync_sendout_mbuf(struct pfsync_softc *, struct mbuf *); 367void pfsync_timeout(void *); 368void pfsync_tdb_timeout(void *); 369void pfsync_send_bus(struct pfsync_softc *, u_int8_t); 370 371void pfsync_bulk_start(void); 372void pfsync_bulk_status(u_int8_t); 373void pfsync_bulk_update(void *); 374void pfsync_bulk_fail(void *); 375 376#ifdef __FreeBSD__ 377void pfsync_ifdetach(void *, struct ifnet *); 378 379/* XXX: ugly */ 380#define betoh64 (unsigned long long)be64toh 381#define timeout_del callout_stop 382#endif 383 384#define PFSYNC_MAX_BULKTRIES 12 385#ifndef __FreeBSD__ 386int pfsync_sync_ok; 387#endif 388 389#ifdef __FreeBSD__ 390IFC_SIMPLE_DECLARE(pfsync, 1); 391#else 392struct if_clone pfsync_cloner = 393 IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create, pfsync_clone_destroy); 394#endif 395 396void 397pfsyncattach(int npfsync) 398{ 399 if_clone_attach(&pfsync_cloner); 400} 401int 402#ifdef __FreeBSD__ 403pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param) 404#else 405pfsync_clone_create(struct if_clone *ifc, int unit) 406#endif 407{ 408 struct pfsync_softc *sc; 409 struct ifnet *ifp; 410 int q; 411 412 if (unit != 0) 413 return (EINVAL); 414 415#ifndef __FreeBSD__ 416 pfsync_sync_ok = 1; 417#endif 418 419 sc = malloc(sizeof(struct pfsync_softc), M_DEVBUF, M_NOWAIT | M_ZERO); 420 if (sc == NULL) 421 return (ENOMEM); 422 423 for (q = 0; q < PFSYNC_S_COUNT; q++) 424 TAILQ_INIT(&sc->sc_qs[q]); 425 426#ifdef __FreeBSD__ 427 sc->pfsync_sync_ok = 1; 428 sc->sc_pool = uma_zcreate("pfsync", PFSYNC_PLSIZE, 429 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 430 if (sc->sc_pool == NULL) { 431 free(sc, M_DEVBUF); 432 return (ENOMEM); 433 } 434#else 435 pool_init(&sc->sc_pool, PFSYNC_PLSIZE, 0, 0, 0, "pfsync", NULL); 436#endif 437 TAILQ_INIT(&sc->sc_upd_req_list); 438 TAILQ_INIT(&sc->sc_deferrals); 439 sc->sc_deferred = 0; 440 441 TAILQ_INIT(&sc->sc_tdb_q); 442 443 sc->sc_len = PFSYNC_MINPKT; 444 sc->sc_maxupdates = 128; 445 446#ifdef __FreeBSD__ 447 sc->sc_imo.imo_membership = (struct in_multi **)malloc( 448 (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_DEVBUF, 449 M_NOWAIT | M_ZERO); 450 sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; 451 sc->sc_imo.imo_multicast_vif = -1; 452#else 453 sc->sc_imo.imo_membership = (struct in_multi **)malloc( 454 (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, 455 M_WAITOK | M_ZERO); 456 sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; 457#endif 458 459#ifdef __FreeBSD__ 460 ifp = sc->sc_ifp = if_alloc(IFT_PFSYNC); 461 if (ifp == NULL) { 462 free(sc->sc_imo.imo_membership, M_DEVBUF); 463 uma_zdestroy(sc->sc_pool); 464 free(sc, M_DEVBUF); 465 return (ENOSPC); 466 } 467 if_initname(ifp, ifc->ifc_name, unit); 468 469 sc->sc_detachtag = EVENTHANDLER_REGISTER(ifnet_departure_event, 470#ifdef __FreeBSD__ 471 pfsync_ifdetach, V_pfsyncif, EVENTHANDLER_PRI_ANY); 472#else 473 pfsync_ifdetach, pfsyncif, EVENTHANDLER_PRI_ANY); 474#endif 475 if (sc->sc_detachtag == NULL) { 476 if_free(ifp); 477 free(sc->sc_imo.imo_membership, M_DEVBUF); 478 uma_zdestroy(sc->sc_pool); 479 free(sc, M_DEVBUF); 480 return (ENOSPC); 481 } 482#else 483 ifp = &sc->sc_if; 484 snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit); 485#endif 486 ifp->if_softc = sc; 487 ifp->if_ioctl = pfsyncioctl; 488 ifp->if_output = pfsyncoutput; 489 ifp->if_start = pfsyncstart; 490 ifp->if_type = IFT_PFSYNC; 491 ifp->if_snd.ifq_maxlen = ifqmaxlen; 492 ifp->if_hdrlen = sizeof(struct pfsync_header); 493 ifp->if_mtu = 1500; /* XXX */ 494#ifdef __FreeBSD__ 495 callout_init(&sc->sc_tmo, CALLOUT_MPSAFE); 496 callout_init_mtx(&sc->sc_bulk_tmo, &pf_task_mtx, 0); 497 callout_init(&sc->sc_bulkfail_tmo, CALLOUT_MPSAFE); 498#else 499 ifp->if_hardmtu = MCLBYTES; /* XXX */ 500 timeout_set(&sc->sc_tmo, pfsync_timeout, sc); 501 timeout_set(&sc->sc_bulk_tmo, pfsync_bulk_update, sc); 502 timeout_set(&sc->sc_bulkfail_tmo, pfsync_bulk_fail, sc); 503#endif 504 505 if_attach(ifp); 506#ifndef __FreeBSD__ 507 if_alloc_sadl(ifp); 508 509#if NCARP > 0 510 if_addgroup(ifp, "carp"); 511#endif 512#endif 513 514#if NBPFILTER > 0 515#ifdef __FreeBSD__ 516 bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 517#else 518 bpfattach(&sc->sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 519#endif 520#endif 521 522#ifdef __FreeBSD__ 523 V_pfsyncif = sc; 524#else 525 pfsyncif = sc; 526#endif 527 528 return (0); 529} 530 531#ifdef __FreeBSD__ 532void 533#else 534int 535#endif 536pfsync_clone_destroy(struct ifnet *ifp) 537{ 538 struct pfsync_softc *sc = ifp->if_softc; 539 540#ifdef __FreeBSD__ 541 EVENTHANDLER_DEREGISTER(ifnet_departure_event, sc->sc_detachtag); 542 PF_LOCK(); 543#endif 544 timeout_del(&sc->sc_bulkfail_tmo); 545 timeout_del(&sc->sc_bulk_tmo); 546 timeout_del(&sc->sc_tmo); 547#ifdef __FreeBSD__ 548 PF_UNLOCK(); 549 if (!sc->pfsync_sync_ok && carp_demote_adj_p) 550 (*carp_demote_adj_p)(-V_pfsync_carp_adj, "pfsync destroy"); 551#else 552#if NCARP > 0 553 if (!pfsync_sync_ok) 554 carp_group_demote_adj(&sc->sc_if, -1); 555#endif 556#endif 557#if NBPFILTER > 0 558 bpfdetach(ifp); 559#endif 560 if_detach(ifp); 561 562 pfsync_drop(sc); 563 564 while (sc->sc_deferred > 0) 565 pfsync_undefer(TAILQ_FIRST(&sc->sc_deferrals), 0); 566 567#ifdef __FreeBSD__ 568 UMA_DESTROY(sc->sc_pool); 569#else 570 pool_destroy(&sc->sc_pool); 571#endif 572#ifdef __FreeBSD__ 573 if_free(ifp); 574 free(sc->sc_imo.imo_membership, M_DEVBUF); 575#else 576 free(sc->sc_imo.imo_membership, M_IPMOPTS); 577#endif 578 free(sc, M_DEVBUF); 579 580#ifdef __FreeBSD__ 581 V_pfsyncif = NULL; 582#else 583 pfsyncif = NULL; 584#endif 585 586#ifndef __FreeBSD__ 587 return (0); 588#endif 589} 590 591struct mbuf * 592pfsync_if_dequeue(struct ifnet *ifp) 593{ 594 struct mbuf *m; 595#ifndef __FreeBSD__ 596 int s; 597#endif 598 599#ifdef __FreeBSD__ 600 IF_LOCK(&ifp->if_snd); 601 _IF_DROP(&ifp->if_snd); 602 _IF_DEQUEUE(&ifp->if_snd, m); 603 IF_UNLOCK(&ifp->if_snd); 604#else 605 s = splnet(); 606 IF_DEQUEUE(&ifp->if_snd, m); 607 splx(s); 608#endif 609 610 return (m); 611} 612 613/* 614 * Start output on the pfsync interface. 615 */ 616void 617pfsyncstart(struct ifnet *ifp) 618{ 619 struct mbuf *m; 620 621 while ((m = pfsync_if_dequeue(ifp)) != NULL) { 622#ifndef __FreeBSD__ 623 IF_DROP(&ifp->if_snd); 624#endif 625 m_freem(m); 626 } 627} 628 629int 630pfsync_alloc_scrub_memory(struct pfsync_state_peer *s, 631 struct pf_state_peer *d) 632{ 633 if (s->scrub.scrub_flag && d->scrub == NULL) { 634#ifdef __FreeBSD__ 635 d->scrub = pool_get(&V_pf_state_scrub_pl, PR_NOWAIT | PR_ZERO); 636#else 637 d->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT | PR_ZERO); 638#endif 639 if (d->scrub == NULL) 640 return (ENOMEM); 641 } 642 643 return (0); 644} 645 646#ifndef __FreeBSD__ 647void 648pfsync_state_export(struct pfsync_state *sp, struct pf_state *st) 649{ 650 bzero(sp, sizeof(struct pfsync_state)); 651 652 /* copy from state key */ 653 sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0]; 654 sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1]; 655 sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0]; 656 sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1]; 657 sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0]; 658 sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1]; 659 sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0]; 660 sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1]; 661 sp->proto = st->key[PF_SK_WIRE]->proto; 662 sp->af = st->key[PF_SK_WIRE]->af; 663 664 /* copy from state */ 665 strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname)); 666 bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); 667 sp->creation = htonl(time_second - st->creation); 668 sp->expire = pf_state_expires(st); 669 if (sp->expire <= time_second) 670 sp->expire = htonl(0); 671 else 672 sp->expire = htonl(sp->expire - time_second); 673 674 sp->direction = st->direction; 675 sp->log = st->log; 676 sp->timeout = st->timeout; 677 sp->state_flags = st->state_flags; 678 if (st->src_node) 679 sp->sync_flags |= PFSYNC_FLAG_SRCNODE; 680 if (st->nat_src_node) 681 sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE; 682 683 bcopy(&st->id, &sp->id, sizeof(sp->id)); 684 sp->creatorid = st->creatorid; 685 pf_state_peer_hton(&st->src, &sp->src); 686 pf_state_peer_hton(&st->dst, &sp->dst); 687 688 if (st->rule.ptr == NULL) 689 sp->rule = htonl(-1); 690 else 691 sp->rule = htonl(st->rule.ptr->nr); 692 if (st->anchor.ptr == NULL) 693 sp->anchor = htonl(-1); 694 else 695 sp->anchor = htonl(st->anchor.ptr->nr); 696 if (st->nat_rule.ptr == NULL) 697 sp->nat_rule = htonl(-1); 698 else 699 sp->nat_rule = htonl(st->nat_rule.ptr->nr); 700 701 pf_state_counter_hton(st->packets[0], sp->packets[0]); 702 pf_state_counter_hton(st->packets[1], sp->packets[1]); 703 pf_state_counter_hton(st->bytes[0], sp->bytes[0]); 704 pf_state_counter_hton(st->bytes[1], sp->bytes[1]); 705 706} 707#endif 708 709int 710pfsync_state_import(struct pfsync_state *sp, u_int8_t flags) 711{ 712 struct pf_state *st = NULL; 713 struct pf_state_key *skw = NULL, *sks = NULL; 714 struct pf_rule *r = NULL; 715 struct pfi_kif *kif; 716 int pool_flags; 717 int error; 718 719 PF_LOCK_ASSERT(); 720 721#ifdef __FreeBSD__ 722 if (sp->creatorid == 0 && V_pf_status.debug >= PF_DEBUG_MISC) { 723#else 724 if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) { 725#endif 726 printf("pfsync_state_import: invalid creator id:" 727 " %08x\n", ntohl(sp->creatorid)); 728 return (EINVAL); 729 } 730 731 if ((kif = pfi_kif_get(sp->ifname)) == NULL) { 732#ifdef __FreeBSD__ 733 if (V_pf_status.debug >= PF_DEBUG_MISC) 734#else 735 if (pf_status.debug >= PF_DEBUG_MISC) 736#endif 737 printf("pfsync_state_import: " 738 "unknown interface: %s\n", sp->ifname); 739 if (flags & PFSYNC_SI_IOCTL) 740 return (EINVAL); 741 return (0); /* skip this state */ 742 } 743 744 /* 745 * If the ruleset checksums match or the state is coming from the ioctl, 746 * it's safe to associate the state with the rule of that number. 747 */ 748 if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && 749 (flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->rule) < 750 pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount) 751 r = pf_main_ruleset.rules[ 752 PF_RULESET_FILTER].active.ptr_array[ntohl(sp->rule)]; 753 else 754#ifdef __FreeBSD__ 755 r = &V_pf_default_rule; 756#else 757 r = &pf_default_rule; 758#endif 759 760 if ((r->max_states && r->states_cur >= r->max_states)) 761 goto cleanup; 762 763#ifdef __FreeBSD__ 764 if (flags & PFSYNC_SI_IOCTL) 765 pool_flags = PR_WAITOK | PR_ZERO; 766 else 767 pool_flags = PR_NOWAIT | PR_ZERO; 768 769 if ((st = pool_get(&V_pf_state_pl, pool_flags)) == NULL) 770 goto cleanup; 771#else 772 if (flags & PFSYNC_SI_IOCTL) 773 pool_flags = PR_WAITOK | PR_LIMITFAIL | PR_ZERO; 774 else 775 pool_flags = PR_LIMITFAIL | PR_ZERO; 776 777 if ((st = pool_get(&pf_state_pl, pool_flags)) == NULL) 778 goto cleanup; 779#endif 780 781 if ((skw = pf_alloc_state_key(pool_flags)) == NULL) 782 goto cleanup; 783 784 if (PF_ANEQ(&sp->key[PF_SK_WIRE].addr[0], 785 &sp->key[PF_SK_STACK].addr[0], sp->af) || 786 PF_ANEQ(&sp->key[PF_SK_WIRE].addr[1], 787 &sp->key[PF_SK_STACK].addr[1], sp->af) || 788 sp->key[PF_SK_WIRE].port[0] != sp->key[PF_SK_STACK].port[0] || 789 sp->key[PF_SK_WIRE].port[1] != sp->key[PF_SK_STACK].port[1]) { 790 if ((sks = pf_alloc_state_key(pool_flags)) == NULL) 791 goto cleanup; 792 } else 793 sks = skw; 794 795 /* allocate memory for scrub info */ 796 if (pfsync_alloc_scrub_memory(&sp->src, &st->src) || 797 pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) 798 goto cleanup; 799 800 /* copy to state key(s) */ 801 skw->addr[0] = sp->key[PF_SK_WIRE].addr[0]; 802 skw->addr[1] = sp->key[PF_SK_WIRE].addr[1]; 803 skw->port[0] = sp->key[PF_SK_WIRE].port[0]; 804 skw->port[1] = sp->key[PF_SK_WIRE].port[1]; 805 skw->proto = sp->proto; 806 skw->af = sp->af; 807 if (sks != skw) { 808 sks->addr[0] = sp->key[PF_SK_STACK].addr[0]; 809 sks->addr[1] = sp->key[PF_SK_STACK].addr[1]; 810 sks->port[0] = sp->key[PF_SK_STACK].port[0]; 811 sks->port[1] = sp->key[PF_SK_STACK].port[1]; 812 sks->proto = sp->proto; 813 sks->af = sp->af; 814 } 815 816 /* copy to state */ 817 bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr)); 818 st->creation = time_second - ntohl(sp->creation); 819 st->expire = time_second; 820 if (sp->expire) { 821 /* XXX No adaptive scaling. */ 822 st->expire -= r->timeout[sp->timeout] - ntohl(sp->expire); 823 } 824 825 st->expire = ntohl(sp->expire) + time_second; 826 st->direction = sp->direction; 827 st->log = sp->log; 828 st->timeout = sp->timeout; 829 st->state_flags = sp->state_flags; 830 831 bcopy(sp->id, &st->id, sizeof(st->id)); 832 st->creatorid = sp->creatorid; 833 pf_state_peer_ntoh(&sp->src, &st->src); 834 pf_state_peer_ntoh(&sp->dst, &st->dst); 835 836 st->rule.ptr = r; 837 st->nat_rule.ptr = NULL; 838 st->anchor.ptr = NULL; 839 st->rt_kif = NULL; 840 841 st->pfsync_time = time_second; 842 st->sync_state = PFSYNC_S_NONE; 843 844 /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */ 845 r->states_cur++; 846 r->states_tot++; 847 848 if (!ISSET(flags, PFSYNC_SI_IOCTL)) 849 SET(st->state_flags, PFSTATE_NOSYNC); 850 851 if ((error = pf_state_insert(kif, skw, sks, st)) != 0) { 852 /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */ 853 r->states_cur--; 854 goto cleanup_state; 855 } 856 857 if (!ISSET(flags, PFSYNC_SI_IOCTL)) { 858 CLR(st->state_flags, PFSTATE_NOSYNC); 859 if (ISSET(st->state_flags, PFSTATE_ACK)) { 860 pfsync_q_ins(st, PFSYNC_S_IACK); 861#ifdef __FreeBSD__ 862 pfsync_sendout(); 863#else 864 schednetisr(NETISR_PFSYNC); 865#endif 866 } 867 } 868 CLR(st->state_flags, PFSTATE_ACK); 869 870 return (0); 871 872cleanup: 873 error = ENOMEM; 874 if (skw == sks) 875 sks = NULL; 876#ifdef __FreeBSD__ 877 if (skw != NULL) 878 pool_put(&V_pf_state_key_pl, skw); 879 if (sks != NULL) 880 pool_put(&V_pf_state_key_pl, sks); 881#else 882 if (skw != NULL) 883 pool_put(&pf_state_key_pl, skw); 884 if (sks != NULL) 885 pool_put(&pf_state_key_pl, sks); 886#endif 887 888cleanup_state: /* pf_state_insert frees the state keys */ 889 if (st) { 890#ifdef __FreeBSD__ 891 if (st->dst.scrub) 892 pool_put(&V_pf_state_scrub_pl, st->dst.scrub); 893 if (st->src.scrub) 894 pool_put(&V_pf_state_scrub_pl, st->src.scrub); 895 pool_put(&V_pf_state_pl, st); 896#else 897 if (st->dst.scrub) 898 pool_put(&pf_state_scrub_pl, st->dst.scrub); 899 if (st->src.scrub) 900 pool_put(&pf_state_scrub_pl, st->src.scrub); 901 pool_put(&pf_state_pl, st); 902#endif 903 } 904 return (error); 905} 906 907void 908#ifdef __FreeBSD__ 909pfsync_input(struct mbuf *m, __unused int off) 910#else 911pfsync_input(struct mbuf *m, ...) 912#endif 913{ 914#ifdef __FreeBSD__ 915 struct pfsync_softc *sc = V_pfsyncif; 916#else 917 struct pfsync_softc *sc = pfsyncif; 918#endif 919 struct pfsync_pkt pkt; 920 struct ip *ip = mtod(m, struct ip *); 921 struct pfsync_header *ph; 922 struct pfsync_subheader subh; 923 924 int offset; 925 int rv; 926 927 V_pfsyncstats.pfsyncs_ipackets++; 928 929 /* verify that we have a sync interface configured */ 930#ifdef __FreeBSD__ 931 if (!sc || !sc->sc_sync_if || !V_pf_status.running) 932#else 933 if (!sc || !sc->sc_sync_if || !pf_status.running) 934#endif 935 goto done; 936 937 /* verify that the packet came in on the right interface */ 938 if (sc->sc_sync_if != m->m_pkthdr.rcvif) { 939 V_pfsyncstats.pfsyncs_badif++; 940 goto done; 941 } 942 943#ifdef __FreeBSD__ 944 sc->sc_ifp->if_ipackets++; 945 sc->sc_ifp->if_ibytes += m->m_pkthdr.len; 946#else 947 sc->sc_if.if_ipackets++; 948 sc->sc_if.if_ibytes += m->m_pkthdr.len; 949#endif 950 /* verify that the IP TTL is 255. */ 951 if (ip->ip_ttl != PFSYNC_DFLTTL) { 952 V_pfsyncstats.pfsyncs_badttl++; 953 goto done; 954 } 955 956 offset = ip->ip_hl << 2; 957 if (m->m_pkthdr.len < offset + sizeof(*ph)) { 958 V_pfsyncstats.pfsyncs_hdrops++; 959 goto done; 960 } 961 962 if (offset + sizeof(*ph) > m->m_len) { 963 if (m_pullup(m, offset + sizeof(*ph)) == NULL) { 964 V_pfsyncstats.pfsyncs_hdrops++; 965 return; 966 } 967 ip = mtod(m, struct ip *); 968 } 969 ph = (struct pfsync_header *)((char *)ip + offset); 970 971 /* verify the version */ 972 if (ph->version != PFSYNC_VERSION) { 973 V_pfsyncstats.pfsyncs_badver++; 974 goto done; 975 } 976 977#if 0 978 if (pfsync_input_hmac(m, offset) != 0) { 979 /* XXX stats */ 980 goto done; 981 } 982#endif 983 984 /* Cheaper to grab this now than having to mess with mbufs later */ 985 pkt.ip = ip; 986 pkt.src = ip->ip_src; 987 pkt.flags = 0; 988 989#ifdef __FreeBSD__ 990 if (!bcmp(&ph->pfcksum, &V_pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH)) 991#else 992 if (!bcmp(&ph->pfcksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH)) 993#endif 994 pkt.flags |= PFSYNC_SI_CKSUM; 995 996 offset += sizeof(*ph); 997 for (;;) { 998 m_copydata(m, offset, sizeof(subh), (caddr_t)&subh); 999 offset += sizeof(subh); 1000 1001 if (subh.action >= PFSYNC_ACT_MAX) { 1002 V_pfsyncstats.pfsyncs_badact++; 1003 goto done; 1004 } 1005 1006 rv = (*pfsync_acts[subh.action])(&pkt, m, offset, 1007 ntohs(subh.count)); 1008 if (rv == -1) 1009 return; 1010 1011 offset += rv; 1012 } 1013 1014done: 1015 m_freem(m); 1016} 1017 1018int 1019pfsync_in_clr(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1020{ 1021 struct pfsync_clr *clr; 1022 struct mbuf *mp; 1023 int len = sizeof(*clr) * count; 1024 int i, offp; 1025 1026 struct pf_state *st, *nexts; 1027 struct pf_state_key *sk, *nextsk; 1028 struct pf_state_item *si; 1029 u_int32_t creatorid; 1030 int s; 1031 1032 mp = m_pulldown(m, offset, len, &offp); 1033 if (mp == NULL) { 1034 V_pfsyncstats.pfsyncs_badlen++; 1035 return (-1); 1036 } 1037 clr = (struct pfsync_clr *)(mp->m_data + offp); 1038 1039 s = splsoftnet(); 1040#ifdef __FreeBSD__ 1041 PF_LOCK(); 1042#endif 1043 for (i = 0; i < count; i++) { 1044 creatorid = clr[i].creatorid; 1045 1046 if (clr[i].ifname[0] == '\0') { 1047#ifdef __FreeBSD__ 1048 for (st = RB_MIN(pf_state_tree_id, &V_tree_id); 1049 st; st = nexts) { 1050 nexts = RB_NEXT(pf_state_tree_id, &V_tree_id, st); 1051#else 1052 for (st = RB_MIN(pf_state_tree_id, &tree_id); 1053 st; st = nexts) { 1054 nexts = RB_NEXT(pf_state_tree_id, &tree_id, st); 1055#endif 1056 if (st->creatorid == creatorid) { 1057 SET(st->state_flags, PFSTATE_NOSYNC); 1058 pf_unlink_state(st); 1059 } 1060 } 1061 } else { 1062 if (pfi_kif_get(clr[i].ifname) == NULL) 1063 continue; 1064 1065 /* XXX correct? */ 1066#ifdef __FreeBSD__ 1067 for (sk = RB_MIN(pf_state_tree, &V_pf_statetbl); 1068#else 1069 for (sk = RB_MIN(pf_state_tree, &pf_statetbl); 1070#endif 1071 sk; sk = nextsk) { 1072 nextsk = RB_NEXT(pf_state_tree, 1073#ifdef __FreeBSD__ 1074 &V_pf_statetbl, sk); 1075#else 1076 &pf_statetbl, sk); 1077#endif 1078 TAILQ_FOREACH(si, &sk->states, entry) { 1079 if (si->s->creatorid == creatorid) { 1080 SET(si->s->state_flags, 1081 PFSTATE_NOSYNC); 1082 pf_unlink_state(si->s); 1083 } 1084 } 1085 } 1086 } 1087 } 1088#ifdef __FreeBSD__ 1089 PF_UNLOCK(); 1090#endif 1091 splx(s); 1092 1093 return (len); 1094} 1095 1096int 1097pfsync_in_ins(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1098{ 1099 struct mbuf *mp; 1100 struct pfsync_state *sa, *sp; 1101 int len = sizeof(*sp) * count; 1102 int i, offp; 1103 1104 int s; 1105 1106 mp = m_pulldown(m, offset, len, &offp); 1107 if (mp == NULL) { 1108 V_pfsyncstats.pfsyncs_badlen++; 1109 return (-1); 1110 } 1111 sa = (struct pfsync_state *)(mp->m_data + offp); 1112 1113 s = splsoftnet(); 1114#ifdef __FreeBSD__ 1115 PF_LOCK(); 1116#endif 1117 for (i = 0; i < count; i++) { 1118 sp = &sa[i]; 1119 1120 /* check for invalid values */ 1121 if (sp->timeout >= PFTM_MAX || 1122 sp->src.state > PF_TCPS_PROXY_DST || 1123 sp->dst.state > PF_TCPS_PROXY_DST || 1124 sp->direction > PF_OUT || 1125 (sp->af != AF_INET && sp->af != AF_INET6)) { 1126#ifdef __FreeBSD__ 1127 if (V_pf_status.debug >= PF_DEBUG_MISC) { 1128#else 1129 if (pf_status.debug >= PF_DEBUG_MISC) { 1130#endif 1131 printf("pfsync_input: PFSYNC5_ACT_INS: " 1132 "invalid value\n"); 1133 } 1134 V_pfsyncstats.pfsyncs_badval++; 1135 continue; 1136 } 1137 1138 if (pfsync_state_import(sp, pkt->flags) == ENOMEM) { 1139 /* drop out, but process the rest of the actions */ 1140 break; 1141 } 1142 } 1143#ifdef __FreeBSD__ 1144 PF_UNLOCK(); 1145#endif 1146 splx(s); 1147 1148 return (len); 1149} 1150 1151int 1152pfsync_in_iack(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1153{ 1154 struct pfsync_ins_ack *ia, *iaa; 1155 struct pf_state_cmp id_key; 1156 struct pf_state *st; 1157 1158 struct mbuf *mp; 1159 int len = count * sizeof(*ia); 1160 int offp, i; 1161 int s; 1162 1163 mp = m_pulldown(m, offset, len, &offp); 1164 if (mp == NULL) { 1165 V_pfsyncstats.pfsyncs_badlen++; 1166 return (-1); 1167 } 1168 iaa = (struct pfsync_ins_ack *)(mp->m_data + offp); 1169 1170 s = splsoftnet(); 1171#ifdef __FreeBSD__ 1172 PF_LOCK(); 1173#endif 1174 for (i = 0; i < count; i++) { 1175 ia = &iaa[i]; 1176 1177 bcopy(&ia->id, &id_key.id, sizeof(id_key.id)); 1178 id_key.creatorid = ia->creatorid; 1179 1180 st = pf_find_state_byid(&id_key); 1181 if (st == NULL) 1182 continue; 1183 1184 if (ISSET(st->state_flags, PFSTATE_ACK)) 1185 pfsync_deferred(st, 0); 1186 } 1187#ifdef __FreeBSD__ 1188 PF_UNLOCK(); 1189#endif 1190 splx(s); 1191 /* 1192 * XXX this is not yet implemented, but we know the size of the 1193 * message so we can skip it. 1194 */ 1195 1196 return (count * sizeof(struct pfsync_ins_ack)); 1197} 1198 1199int 1200pfsync_upd_tcp(struct pf_state *st, struct pfsync_state_peer *src, 1201 struct pfsync_state_peer *dst) 1202{ 1203 int sfail = 0; 1204 1205 /* 1206 * The state should never go backwards except 1207 * for syn-proxy states. Neither should the 1208 * sequence window slide backwards. 1209 */ 1210 if (st->src.state > src->state && 1211 (st->src.state < PF_TCPS_PROXY_SRC || 1212 src->state >= PF_TCPS_PROXY_SRC)) 1213 sfail = 1; 1214 else if (SEQ_GT(st->src.seqlo, ntohl(src->seqlo))) 1215 sfail = 3; 1216 else if (st->dst.state > dst->state) { 1217 /* There might still be useful 1218 * information about the src state here, 1219 * so import that part of the update, 1220 * then "fail" so we send the updated 1221 * state back to the peer who is missing 1222 * our what we know. */ 1223 pf_state_peer_ntoh(src, &st->src); 1224 /* XXX do anything with timeouts? */ 1225 sfail = 7; 1226 } else if (st->dst.state >= TCPS_SYN_SENT && 1227 SEQ_GT(st->dst.seqlo, ntohl(dst->seqlo))) 1228 sfail = 4; 1229 1230 return (sfail); 1231} 1232 1233int 1234pfsync_in_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1235{ 1236 struct pfsync_state *sa, *sp; 1237 struct pf_state_cmp id_key; 1238 struct pf_state_key *sk; 1239 struct pf_state *st; 1240 int sfail; 1241 1242 struct mbuf *mp; 1243 int len = count * sizeof(*sp); 1244 int offp, i; 1245 int s; 1246 1247 mp = m_pulldown(m, offset, len, &offp); 1248 if (mp == NULL) { 1249 V_pfsyncstats.pfsyncs_badlen++; 1250 return (-1); 1251 } 1252 sa = (struct pfsync_state *)(mp->m_data + offp); 1253 1254 s = splsoftnet(); 1255#ifdef __FreeBSD__ 1256 PF_LOCK(); 1257#endif 1258 for (i = 0; i < count; i++) { 1259 sp = &sa[i]; 1260 1261 /* check for invalid values */ 1262 if (sp->timeout >= PFTM_MAX || 1263 sp->src.state > PF_TCPS_PROXY_DST || 1264 sp->dst.state > PF_TCPS_PROXY_DST) { 1265#ifdef __FreeBSD__ 1266 if (V_pf_status.debug >= PF_DEBUG_MISC) { 1267#else 1268 if (pf_status.debug >= PF_DEBUG_MISC) { 1269#endif 1270 printf("pfsync_input: PFSYNC_ACT_UPD: " 1271 "invalid value\n"); 1272 } 1273 V_pfsyncstats.pfsyncs_badval++; 1274 continue; 1275 } 1276 1277 bcopy(sp->id, &id_key.id, sizeof(id_key.id)); 1278 id_key.creatorid = sp->creatorid; 1279 1280 st = pf_find_state_byid(&id_key); 1281 if (st == NULL) { 1282 /* insert the update */ 1283 if (pfsync_state_import(sp, 0)) 1284 V_pfsyncstats.pfsyncs_badstate++; 1285 continue; 1286 } 1287 1288 if (ISSET(st->state_flags, PFSTATE_ACK)) 1289 pfsync_deferred(st, 1); 1290 1291 sk = st->key[PF_SK_WIRE]; /* XXX right one? */ 1292 sfail = 0; 1293 if (sk->proto == IPPROTO_TCP) 1294 sfail = pfsync_upd_tcp(st, &sp->src, &sp->dst); 1295 else { 1296 /* 1297 * Non-TCP protocol state machine always go 1298 * forwards 1299 */ 1300 if (st->src.state > sp->src.state) 1301 sfail = 5; 1302 else if (st->dst.state > sp->dst.state) 1303 sfail = 6; 1304 } 1305 1306 if (sfail) { 1307#ifdef __FreeBSD__ 1308 if (V_pf_status.debug >= PF_DEBUG_MISC) { 1309#else 1310 if (pf_status.debug >= PF_DEBUG_MISC) { 1311#endif 1312 printf("pfsync: %s stale update (%d)" 1313 " id: %016llx creatorid: %08x\n", 1314 (sfail < 7 ? "ignoring" : "partial"), 1315 sfail, betoh64(st->id), 1316 ntohl(st->creatorid)); 1317 } 1318 V_pfsyncstats.pfsyncs_stale++; 1319 1320 pfsync_update_state(st); 1321#ifdef __FreeBSD__ 1322 pfsync_sendout(); 1323#else 1324 schednetisr(NETISR_PFSYNC); 1325#endif 1326 continue; 1327 } 1328 pfsync_alloc_scrub_memory(&sp->dst, &st->dst); 1329 pf_state_peer_ntoh(&sp->src, &st->src); 1330 pf_state_peer_ntoh(&sp->dst, &st->dst); 1331 st->expire = ntohl(sp->expire) + time_second; 1332 st->timeout = sp->timeout; 1333 st->pfsync_time = time_second; 1334 } 1335#ifdef __FreeBSD__ 1336 PF_UNLOCK(); 1337#endif 1338 splx(s); 1339 1340 return (len); 1341} 1342 1343int 1344pfsync_in_upd_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1345{ 1346 struct pfsync_upd_c *ua, *up; 1347 struct pf_state_key *sk; 1348 struct pf_state_cmp id_key; 1349 struct pf_state *st; 1350 1351 int len = count * sizeof(*up); 1352 int sfail; 1353 1354 struct mbuf *mp; 1355 int offp, i; 1356 int s; 1357 1358 mp = m_pulldown(m, offset, len, &offp); 1359 if (mp == NULL) { 1360 V_pfsyncstats.pfsyncs_badlen++; 1361 return (-1); 1362 } 1363 ua = (struct pfsync_upd_c *)(mp->m_data + offp); 1364 1365 s = splsoftnet(); 1366#ifdef __FreeBSD__ 1367 PF_LOCK(); 1368#endif 1369 for (i = 0; i < count; i++) { 1370 up = &ua[i]; 1371 1372 /* check for invalid values */ 1373 if (up->timeout >= PFTM_MAX || 1374 up->src.state > PF_TCPS_PROXY_DST || 1375 up->dst.state > PF_TCPS_PROXY_DST) { 1376#ifdef __FreeBSD__ 1377 if (V_pf_status.debug >= PF_DEBUG_MISC) { 1378#else 1379 if (pf_status.debug >= PF_DEBUG_MISC) { 1380#endif 1381 printf("pfsync_input: " 1382 "PFSYNC_ACT_UPD_C: " 1383 "invalid value\n"); 1384 } 1385 V_pfsyncstats.pfsyncs_badval++; 1386 continue; 1387 } 1388 1389 bcopy(&up->id, &id_key.id, sizeof(id_key.id)); 1390 id_key.creatorid = up->creatorid; 1391 1392 st = pf_find_state_byid(&id_key); 1393 if (st == NULL) { 1394 /* We don't have this state. Ask for it. */ 1395 pfsync_request_update(id_key.creatorid, id_key.id); 1396 continue; 1397 } 1398 1399 if (ISSET(st->state_flags, PFSTATE_ACK)) 1400 pfsync_deferred(st, 1); 1401 1402 sk = st->key[PF_SK_WIRE]; /* XXX right one? */ 1403 sfail = 0; 1404 if (sk->proto == IPPROTO_TCP) 1405 sfail = pfsync_upd_tcp(st, &up->src, &up->dst); 1406 else { 1407 /* 1408 * Non-TCP protocol state machine always go forwards 1409 */ 1410 if (st->src.state > up->src.state) 1411 sfail = 5; 1412 else if (st->dst.state > up->dst.state) 1413 sfail = 6; 1414 } 1415 1416 if (sfail) { 1417#ifdef __FreeBSD__ 1418 if (V_pf_status.debug >= PF_DEBUG_MISC) { 1419#else 1420 if (pf_status.debug >= PF_DEBUG_MISC) { 1421#endif 1422 printf("pfsync: ignoring stale update " 1423 "(%d) id: %016llx " 1424 "creatorid: %08x\n", sfail, 1425 betoh64(st->id), 1426 ntohl(st->creatorid)); 1427 } 1428 V_pfsyncstats.pfsyncs_stale++; 1429 1430 pfsync_update_state(st); 1431#ifdef __FreeBSD__ 1432 pfsync_sendout(); 1433#else 1434 schednetisr(NETISR_PFSYNC); 1435#endif 1436 continue; 1437 } 1438 pfsync_alloc_scrub_memory(&up->dst, &st->dst); 1439 pf_state_peer_ntoh(&up->src, &st->src); 1440 pf_state_peer_ntoh(&up->dst, &st->dst); 1441 st->expire = ntohl(up->expire) + time_second; 1442 st->timeout = up->timeout; 1443 st->pfsync_time = time_second; 1444 } 1445#ifdef __FreeBSD__ 1446 PF_UNLOCK(); 1447#endif 1448 splx(s); 1449 1450 return (len); 1451} 1452 1453int 1454pfsync_in_ureq(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1455{ 1456 struct pfsync_upd_req *ur, *ura; 1457 struct mbuf *mp; 1458 int len = count * sizeof(*ur); 1459 int i, offp; 1460 1461 struct pf_state_cmp id_key; 1462 struct pf_state *st; 1463 1464 mp = m_pulldown(m, offset, len, &offp); 1465 if (mp == NULL) { 1466 V_pfsyncstats.pfsyncs_badlen++; 1467 return (-1); 1468 } 1469 ura = (struct pfsync_upd_req *)(mp->m_data + offp); 1470 1471 for (i = 0; i < count; i++) { 1472 ur = &ura[i]; 1473 1474 bcopy(&ur->id, &id_key.id, sizeof(id_key.id)); 1475 id_key.creatorid = ur->creatorid; 1476 1477 if (id_key.id == 0 && id_key.creatorid == 0) 1478 pfsync_bulk_start(); 1479 else { 1480 st = pf_find_state_byid(&id_key); 1481 if (st == NULL) { 1482 V_pfsyncstats.pfsyncs_badstate++; 1483 continue; 1484 } 1485 if (ISSET(st->state_flags, PFSTATE_NOSYNC)) 1486 continue; 1487 1488 PF_LOCK(); 1489 pfsync_update_state_req(st); 1490 PF_UNLOCK(); 1491 } 1492 } 1493 1494 return (len); 1495} 1496 1497int 1498pfsync_in_del(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1499{ 1500 struct mbuf *mp; 1501 struct pfsync_state *sa, *sp; 1502 struct pf_state_cmp id_key; 1503 struct pf_state *st; 1504 int len = count * sizeof(*sp); 1505 int offp, i; 1506 int s; 1507 1508 mp = m_pulldown(m, offset, len, &offp); 1509 if (mp == NULL) { 1510 V_pfsyncstats.pfsyncs_badlen++; 1511 return (-1); 1512 } 1513 sa = (struct pfsync_state *)(mp->m_data + offp); 1514 1515 s = splsoftnet(); 1516#ifdef __FreeBSD__ 1517 PF_LOCK(); 1518#endif 1519 for (i = 0; i < count; i++) { 1520 sp = &sa[i]; 1521 1522 bcopy(sp->id, &id_key.id, sizeof(id_key.id)); 1523 id_key.creatorid = sp->creatorid; 1524 1525 st = pf_find_state_byid(&id_key); 1526 if (st == NULL) { 1527 V_pfsyncstats.pfsyncs_badstate++; 1528 continue; 1529 } 1530 SET(st->state_flags, PFSTATE_NOSYNC); 1531 pf_unlink_state(st); 1532 } 1533#ifdef __FreeBSD__ 1534 PF_UNLOCK(); 1535#endif 1536 splx(s); 1537 1538 return (len); 1539} 1540 1541int 1542pfsync_in_del_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1543{ 1544 struct mbuf *mp; 1545 struct pfsync_del_c *sa, *sp; 1546 struct pf_state_cmp id_key; 1547 struct pf_state *st; 1548 int len = count * sizeof(*sp); 1549 int offp, i; 1550 int s; 1551 1552 mp = m_pulldown(m, offset, len, &offp); 1553 if (mp == NULL) { 1554 V_pfsyncstats.pfsyncs_badlen++; 1555 return (-1); 1556 } 1557 sa = (struct pfsync_del_c *)(mp->m_data + offp); 1558 1559 s = splsoftnet(); 1560#ifdef __FreeBSD__ 1561 PF_LOCK(); 1562#endif 1563 for (i = 0; i < count; i++) { 1564 sp = &sa[i]; 1565 1566 bcopy(&sp->id, &id_key.id, sizeof(id_key.id)); 1567 id_key.creatorid = sp->creatorid; 1568 1569 st = pf_find_state_byid(&id_key); 1570 if (st == NULL) { 1571 V_pfsyncstats.pfsyncs_badstate++; 1572 continue; 1573 } 1574 1575 SET(st->state_flags, PFSTATE_NOSYNC); 1576 pf_unlink_state(st); 1577 } 1578#ifdef __FreeBSD__ 1579 PF_UNLOCK(); 1580#endif 1581 splx(s); 1582 1583 return (len); 1584} 1585 1586int 1587pfsync_in_bus(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1588{ 1589#ifdef __FreeBSD__ 1590 struct pfsync_softc *sc = V_pfsyncif; 1591#else 1592 struct pfsync_softc *sc = pfsyncif; 1593#endif 1594 struct pfsync_bus *bus; 1595 struct mbuf *mp; 1596 int len = count * sizeof(*bus); 1597 int offp; 1598 1599 /* If we're not waiting for a bulk update, who cares. */ 1600 if (sc->sc_ureq_sent == 0) 1601 return (len); 1602 1603 mp = m_pulldown(m, offset, len, &offp); 1604 if (mp == NULL) { 1605 V_pfsyncstats.pfsyncs_badlen++; 1606 return (-1); 1607 } 1608 bus = (struct pfsync_bus *)(mp->m_data + offp); 1609 1610 switch (bus->status) { 1611 case PFSYNC_BUS_START: 1612#ifdef __FreeBSD__ 1613 callout_reset(&sc->sc_bulkfail_tmo, 4 * hz + 1614 pf_pool_limits[PF_LIMIT_STATES].limit / 1615 ((sc->sc_sync_if->if_mtu - PFSYNC_MINPKT) / 1616 sizeof(struct pfsync_state)), 1617 pfsync_bulk_fail, V_pfsyncif); 1618#else 1619 timeout_add(&sc->sc_bulkfail_tmo, 4 * hz + 1620 pf_pool_limits[PF_LIMIT_STATES].limit / 1621 ((sc->sc_if.if_mtu - PFSYNC_MINPKT) / 1622 sizeof(struct pfsync_state))); 1623#endif 1624#ifdef __FreeBSD__ 1625 if (V_pf_status.debug >= PF_DEBUG_MISC) 1626#else 1627 if (pf_status.debug >= PF_DEBUG_MISC) 1628#endif 1629 printf("pfsync: received bulk update start\n"); 1630 break; 1631 1632 case PFSYNC_BUS_END: 1633 if (time_uptime - ntohl(bus->endtime) >= 1634 sc->sc_ureq_sent) { 1635 /* that's it, we're happy */ 1636 sc->sc_ureq_sent = 0; 1637 sc->sc_bulk_tries = 0; 1638 timeout_del(&sc->sc_bulkfail_tmo); 1639#ifdef __FreeBSD__ 1640 if (!sc->pfsync_sync_ok && carp_demote_adj_p) 1641 (*carp_demote_adj_p)(-V_pfsync_carp_adj, 1642 "pfsync bulk done"); 1643 sc->pfsync_sync_ok = 1; 1644#else 1645#if NCARP > 0 1646 if (!pfsync_sync_ok) 1647 carp_group_demote_adj(&sc->sc_if, -1); 1648#endif 1649 pfsync_sync_ok = 1; 1650#endif 1651#ifdef __FreeBSD__ 1652 if (V_pf_status.debug >= PF_DEBUG_MISC) 1653#else 1654 if (pf_status.debug >= PF_DEBUG_MISC) 1655#endif 1656 printf("pfsync: received valid " 1657 "bulk update end\n"); 1658 } else { 1659#ifdef __FreeBSD__ 1660 if (V_pf_status.debug >= PF_DEBUG_MISC) 1661#else 1662 if (pf_status.debug >= PF_DEBUG_MISC) 1663#endif 1664 printf("pfsync: received invalid " 1665 "bulk update end: bad timestamp\n"); 1666 } 1667 break; 1668 } 1669 1670 return (len); 1671} 1672 1673int 1674pfsync_in_tdb(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1675{ 1676 int len = count * sizeof(struct pfsync_tdb); 1677 1678#if defined(IPSEC) 1679 struct pfsync_tdb *tp; 1680 struct mbuf *mp; 1681 int offp; 1682 int i; 1683 int s; 1684 1685 mp = m_pulldown(m, offset, len, &offp); 1686 if (mp == NULL) { 1687 V_pfsyncstats.pfsyncs_badlen++; 1688 return (-1); 1689 } 1690 tp = (struct pfsync_tdb *)(mp->m_data + offp); 1691 1692 s = splsoftnet(); 1693#ifdef __FreeBSD__ 1694 PF_LOCK(); 1695#endif 1696 for (i = 0; i < count; i++) 1697 pfsync_update_net_tdb(&tp[i]); 1698#ifdef __FreeBSD__ 1699 PF_UNLOCK(); 1700#endif 1701 splx(s); 1702#endif 1703 1704 return (len); 1705} 1706 1707#if defined(IPSEC) 1708/* Update an in-kernel tdb. Silently fail if no tdb is found. */ 1709void 1710pfsync_update_net_tdb(struct pfsync_tdb *pt) 1711{ 1712 struct tdb *tdb; 1713 int s; 1714 1715 /* check for invalid values */ 1716 if (ntohl(pt->spi) <= SPI_RESERVED_MAX || 1717 (pt->dst.sa.sa_family != AF_INET && 1718 pt->dst.sa.sa_family != AF_INET6)) 1719 goto bad; 1720 1721 s = spltdb(); 1722 tdb = gettdb(pt->spi, &pt->dst, pt->sproto); 1723 if (tdb) { 1724 pt->rpl = ntohl(pt->rpl); 1725 pt->cur_bytes = betoh64(pt->cur_bytes); 1726 1727 /* Neither replay nor byte counter should ever decrease. */ 1728 if (pt->rpl < tdb->tdb_rpl || 1729 pt->cur_bytes < tdb->tdb_cur_bytes) { 1730 splx(s); 1731 goto bad; 1732 } 1733 1734 tdb->tdb_rpl = pt->rpl; 1735 tdb->tdb_cur_bytes = pt->cur_bytes; 1736 } 1737 splx(s); 1738 return; 1739 1740bad: 1741#ifdef __FreeBSD__ 1742 if (V_pf_status.debug >= PF_DEBUG_MISC) 1743#else 1744 if (pf_status.debug >= PF_DEBUG_MISC) 1745#endif 1746 printf("pfsync_insert: PFSYNC_ACT_TDB_UPD: " 1747 "invalid value\n"); 1748 V_pfsyncstats.pfsyncs_badstate++; 1749 return; 1750} 1751#endif 1752 1753 1754int 1755pfsync_in_eof(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1756{ 1757 /* check if we are at the right place in the packet */ 1758 if (offset != m->m_pkthdr.len - sizeof(struct pfsync_eof)) 1759 V_pfsyncstats.pfsyncs_badact++; 1760 1761 /* we're done. free and let the caller return */ 1762 m_freem(m); 1763 return (-1); 1764} 1765 1766int 1767pfsync_in_error(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) 1768{ 1769 V_pfsyncstats.pfsyncs_badact++; 1770 1771 m_freem(m); 1772 return (-1); 1773} 1774 1775int 1776pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 1777#ifdef __FreeBSD__ 1778 struct route *rt) 1779#else 1780 struct rtentry *rt) 1781#endif 1782{ 1783 m_freem(m); 1784 return (0); 1785} 1786 1787/* ARGSUSED */ 1788int 1789pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1790{ 1791#ifndef __FreeBSD__ 1792 struct proc *p = curproc; 1793#endif 1794 struct pfsync_softc *sc = ifp->if_softc; 1795 struct ifreq *ifr = (struct ifreq *)data; 1796 struct ip_moptions *imo = &sc->sc_imo; 1797 struct pfsyncreq pfsyncr; 1798 struct ifnet *sifp; 1799 struct ip *ip; 1800 int s, error; 1801 1802 switch (cmd) { 1803#if 0 1804 case SIOCSIFADDR: 1805 case SIOCAIFADDR: 1806 case SIOCSIFDSTADDR: 1807#endif 1808 case SIOCSIFFLAGS: 1809#ifdef __FreeBSD__ 1810 if (ifp->if_flags & IFF_UP) 1811 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1812 else 1813 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1814#else 1815 if (ifp->if_flags & IFF_UP) 1816 ifp->if_flags |= IFF_RUNNING; 1817 else 1818 ifp->if_flags &= ~IFF_RUNNING; 1819#endif 1820 break; 1821 case SIOCSIFMTU: 1822 if (ifr->ifr_mtu <= PFSYNC_MINPKT) 1823 return (EINVAL); 1824 if (ifr->ifr_mtu > MCLBYTES) /* XXX could be bigger */ 1825 ifr->ifr_mtu = MCLBYTES; 1826 if (ifr->ifr_mtu < ifp->if_mtu) { 1827 s = splnet(); 1828#ifdef __FreeBSD__ 1829 PF_LOCK(); 1830#endif 1831 pfsync_sendout(); 1832#ifdef __FreeBSD__ 1833 PF_UNLOCK(); 1834#endif 1835 splx(s); 1836 } 1837 ifp->if_mtu = ifr->ifr_mtu; 1838 break; 1839 case SIOCGETPFSYNC: 1840 bzero(&pfsyncr, sizeof(pfsyncr)); 1841 if (sc->sc_sync_if) { 1842 strlcpy(pfsyncr.pfsyncr_syncdev, 1843 sc->sc_sync_if->if_xname, IFNAMSIZ); 1844 } 1845 pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer; 1846 pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates; 1847 return (copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))); 1848 1849 case SIOCSETPFSYNC: 1850#ifdef __FreeBSD__ 1851 if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0) 1852#else 1853 if ((error = suser(p, p->p_acflag)) != 0) 1854#endif 1855 return (error); 1856 if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr)))) 1857 return (error); 1858 1859#ifdef __FreeBSD__ 1860 PF_LOCK(); 1861#endif 1862 if (pfsyncr.pfsyncr_syncpeer.s_addr == 0) 1863#ifdef __FreeBSD__ 1864 sc->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP); 1865#else 1866 sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP; 1867#endif 1868 else 1869 sc->sc_sync_peer.s_addr = 1870 pfsyncr.pfsyncr_syncpeer.s_addr; 1871 1872 if (pfsyncr.pfsyncr_maxupdates > 255) 1873#ifdef __FreeBSD__ 1874 { 1875 PF_UNLOCK(); 1876#endif 1877 return (EINVAL); 1878#ifdef __FreeBSD__ 1879 } 1880#endif 1881 sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; 1882 1883 if (pfsyncr.pfsyncr_syncdev[0] == 0) { 1884 sc->sc_sync_if = NULL; 1885#ifdef __FreeBSD__ 1886 PF_UNLOCK(); 1887#endif 1888 if (imo->imo_num_memberships > 0) { 1889 in_delmulti(imo->imo_membership[ 1890 --imo->imo_num_memberships]); 1891 imo->imo_multicast_ifp = NULL; 1892 } 1893 break; 1894 } 1895 1896#ifdef __FreeBSD__ 1897 PF_UNLOCK(); 1898#endif 1899 if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) 1900 return (EINVAL); 1901 1902#ifdef __FreeBSD__ 1903 PF_LOCK(); 1904#endif 1905 s = splnet(); 1906#ifdef __FreeBSD__ 1907 if (sifp->if_mtu < sc->sc_ifp->if_mtu || 1908#else 1909 if (sifp->if_mtu < sc->sc_if.if_mtu || 1910#endif 1911 (sc->sc_sync_if != NULL && 1912 sifp->if_mtu < sc->sc_sync_if->if_mtu) || 1913 sifp->if_mtu < MCLBYTES - sizeof(struct ip)) 1914 pfsync_sendout(); 1915 sc->sc_sync_if = sifp; 1916 1917 if (imo->imo_num_memberships > 0) { 1918#ifdef __FreeBSD__ 1919 PF_UNLOCK(); 1920#endif 1921 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1922#ifdef __FreeBSD__ 1923 PF_LOCK(); 1924#endif 1925 imo->imo_multicast_ifp = NULL; 1926 } 1927 1928 if (sc->sc_sync_if && 1929#ifdef __FreeBSD__ 1930 sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) { 1931#else 1932 sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) { 1933#endif 1934 struct in_addr addr; 1935 1936 if (!(sc->sc_sync_if->if_flags & IFF_MULTICAST)) { 1937 sc->sc_sync_if = NULL; 1938#ifdef __FreeBSD__ 1939 PF_UNLOCK(); 1940#endif 1941 splx(s); 1942 return (EADDRNOTAVAIL); 1943 } 1944 1945#ifdef __FreeBSD__ 1946 addr.s_addr = htonl(INADDR_PFSYNC_GROUP); 1947#else 1948 addr.s_addr = INADDR_PFSYNC_GROUP; 1949#endif 1950 1951#ifdef __FreeBSD__ 1952 PF_UNLOCK(); 1953#endif 1954 if ((imo->imo_membership[0] = 1955 in_addmulti(&addr, sc->sc_sync_if)) == NULL) { 1956 sc->sc_sync_if = NULL; 1957 splx(s); 1958 return (ENOBUFS); 1959 } 1960#ifdef __FreeBSD__ 1961 PF_LOCK(); 1962#endif 1963 imo->imo_num_memberships++; 1964 imo->imo_multicast_ifp = sc->sc_sync_if; 1965 imo->imo_multicast_ttl = PFSYNC_DFLTTL; 1966 imo->imo_multicast_loop = 0; 1967 } 1968 1969 ip = &sc->sc_template; 1970 bzero(ip, sizeof(*ip)); 1971 ip->ip_v = IPVERSION; 1972 ip->ip_hl = sizeof(sc->sc_template) >> 2; 1973 ip->ip_tos = IPTOS_LOWDELAY; 1974 /* len and id are set later */ 1975#ifdef __FreeBSD__ 1976 ip->ip_off = IP_DF; 1977#else 1978 ip->ip_off = htons(IP_DF); 1979#endif 1980 ip->ip_ttl = PFSYNC_DFLTTL; 1981 ip->ip_p = IPPROTO_PFSYNC; 1982 ip->ip_src.s_addr = INADDR_ANY; 1983 ip->ip_dst.s_addr = sc->sc_sync_peer.s_addr; 1984 1985 if (sc->sc_sync_if) { 1986 /* Request a full state table update. */ 1987 sc->sc_ureq_sent = time_uptime; 1988#ifdef __FreeBSD__ 1989 if (sc->pfsync_sync_ok && carp_demote_adj_p) 1990 (*carp_demote_adj_p)(V_pfsync_carp_adj, 1991 "pfsync bulk start"); 1992 sc->pfsync_sync_ok = 0; 1993#else 1994#if NCARP > 0 1995 if (pfsync_sync_ok) 1996 carp_group_demote_adj(&sc->sc_if, 1); 1997#endif 1998 pfsync_sync_ok = 0; 1999#endif 2000#ifdef __FreeBSD__ 2001 if (V_pf_status.debug >= PF_DEBUG_MISC) 2002#else 2003 if (pf_status.debug >= PF_DEBUG_MISC) 2004#endif 2005 printf("pfsync: requesting bulk update\n"); 2006#ifdef __FreeBSD__ 2007 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, 2008 pfsync_bulk_fail, V_pfsyncif); 2009#else 2010 timeout_add_sec(&sc->sc_bulkfail_tmo, 5); 2011#endif 2012 pfsync_request_update(0, 0); 2013 } 2014#ifdef __FreeBSD__ 2015 PF_UNLOCK(); 2016#endif 2017 splx(s); 2018 2019 break; 2020 2021 default: 2022 return (ENOTTY); 2023 } 2024 2025 return (0); 2026} 2027 2028int 2029pfsync_out_state(struct pf_state *st, struct mbuf *m, int offset) 2030{ 2031 struct pfsync_state *sp = (struct pfsync_state *)(m->m_data + offset); 2032 2033 pfsync_state_export(sp, st); 2034 2035 return (sizeof(*sp)); 2036} 2037 2038int 2039pfsync_out_iack(struct pf_state *st, struct mbuf *m, int offset) 2040{ 2041 struct pfsync_ins_ack *iack = 2042 (struct pfsync_ins_ack *)(m->m_data + offset); 2043 2044 iack->id = st->id; 2045 iack->creatorid = st->creatorid; 2046 2047 return (sizeof(*iack)); 2048} 2049 2050int 2051pfsync_out_upd_c(struct pf_state *st, struct mbuf *m, int offset) 2052{ 2053 struct pfsync_upd_c *up = (struct pfsync_upd_c *)(m->m_data + offset); 2054 2055 up->id = st->id; 2056 pf_state_peer_hton(&st->src, &up->src); 2057 pf_state_peer_hton(&st->dst, &up->dst); 2058 up->creatorid = st->creatorid; 2059 2060 up->expire = pf_state_expires(st); 2061 if (up->expire <= time_second) 2062 up->expire = htonl(0); 2063 else 2064 up->expire = htonl(up->expire - time_second); 2065 up->timeout = st->timeout; 2066 2067 bzero(up->_pad, sizeof(up->_pad)); /* XXX */ 2068 2069 return (sizeof(*up)); 2070} 2071 2072int 2073pfsync_out_del(struct pf_state *st, struct mbuf *m, int offset) 2074{ 2075 struct pfsync_del_c *dp = (struct pfsync_del_c *)(m->m_data + offset); 2076 2077 dp->id = st->id; 2078 dp->creatorid = st->creatorid; 2079 2080 SET(st->state_flags, PFSTATE_NOSYNC); 2081 2082 return (sizeof(*dp)); 2083} 2084 2085void 2086pfsync_drop(struct pfsync_softc *sc) 2087{ 2088 struct pf_state *st; 2089 struct pfsync_upd_req_item *ur; 2090#ifdef notyet 2091 struct tdb *t; 2092#endif 2093 int q; 2094 2095 for (q = 0; q < PFSYNC_S_COUNT; q++) { 2096 if (TAILQ_EMPTY(&sc->sc_qs[q])) 2097 continue; 2098 2099 TAILQ_FOREACH(st, &sc->sc_qs[q], sync_list) { 2100#ifdef PFSYNC_DEBUG 2101#ifdef __FreeBSD__ 2102 KASSERT(st->sync_state == q, 2103 ("%s: st->sync_state == q", 2104 __FUNCTION__)); 2105#else 2106 KASSERT(st->sync_state == q); 2107#endif 2108#endif 2109 st->sync_state = PFSYNC_S_NONE; 2110 } 2111 TAILQ_INIT(&sc->sc_qs[q]); 2112 } 2113 2114 while ((ur = TAILQ_FIRST(&sc->sc_upd_req_list)) != NULL) { 2115 TAILQ_REMOVE(&sc->sc_upd_req_list, ur, ur_entry); 2116 pool_put(&sc->sc_pool, ur); 2117 } 2118 2119 sc->sc_plus = NULL; 2120 2121#ifdef notyet 2122 if (!TAILQ_EMPTY(&sc->sc_tdb_q)) { 2123 TAILQ_FOREACH(t, &sc->sc_tdb_q, tdb_sync_entry) 2124 CLR(t->tdb_flags, TDBF_PFSYNC); 2125 2126 TAILQ_INIT(&sc->sc_tdb_q); 2127 } 2128#endif 2129 2130 sc->sc_len = PFSYNC_MINPKT; 2131} 2132 2133void 2134pfsync_sendout(void) 2135{ 2136#ifdef __FreeBSD__ 2137 struct pfsync_softc *sc = V_pfsyncif; 2138#else 2139 struct pfsync_softc *sc = pfsyncif; 2140#endif 2141#if NBPFILTER > 0 2142#ifdef __FreeBSD__ 2143 struct ifnet *ifp = sc->sc_ifp; 2144#else 2145 struct ifnet *ifp = &sc->sc_if; 2146#endif 2147#endif 2148 struct mbuf *m; 2149 struct ip *ip; 2150 struct pfsync_header *ph; 2151 struct pfsync_subheader *subh; 2152 struct pf_state *st; 2153 struct pfsync_upd_req_item *ur; 2154#ifdef notyet 2155 struct tdb *t; 2156#endif 2157#ifdef __FreeBSD__ 2158 size_t pktlen; 2159 int dummy_error; 2160#endif 2161 int offset; 2162 int q, count = 0; 2163 2164#ifdef __FreeBSD__ 2165 PF_LOCK_ASSERT(); 2166#else 2167 splassert(IPL_NET); 2168#endif 2169 2170 if (sc == NULL || sc->sc_len == PFSYNC_MINPKT) 2171 return; 2172 2173#if NBPFILTER > 0 2174 if (ifp->if_bpf == NULL && sc->sc_sync_if == NULL) { 2175#else 2176 if (sc->sc_sync_if == NULL) { 2177#endif 2178 pfsync_drop(sc); 2179 return; 2180 } 2181 2182 MGETHDR(m, M_DONTWAIT, MT_DATA); 2183 if (m == NULL) { 2184#ifdef __FreeBSD__ 2185 sc->sc_ifp->if_oerrors++; 2186#else 2187 sc->sc_if.if_oerrors++; 2188#endif 2189 V_pfsyncstats.pfsyncs_onomem++; 2190 pfsync_drop(sc); 2191 return; 2192 } 2193 2194#ifdef __FreeBSD__ 2195 pktlen = max_linkhdr + sc->sc_len; 2196 if (pktlen > MHLEN) { 2197 /* Find the right pool to allocate from. */ 2198 /* XXX: This is ugly. */ 2199 m_cljget(m, M_DONTWAIT, pktlen <= MSIZE ? MSIZE : 2200 pktlen <= MCLBYTES ? MCLBYTES : 2201#if MJUMPAGESIZE != MCLBYTES 2202 pktlen <= MJUMPAGESIZE ? MJUMPAGESIZE : 2203#endif 2204 pktlen <= MJUM9BYTES ? MJUM9BYTES : MJUM16BYTES); 2205#else 2206 if (max_linkhdr + sc->sc_len > MHLEN) { 2207 MCLGETI(m, M_DONTWAIT, NULL, max_linkhdr + sc->sc_len); 2208#endif 2209 if (!ISSET(m->m_flags, M_EXT)) { 2210 m_free(m); 2211#ifdef __FreeBSD__ 2212 sc->sc_ifp->if_oerrors++; 2213#else 2214 sc->sc_if.if_oerrors++; 2215#endif 2216 V_pfsyncstats.pfsyncs_onomem++; 2217 pfsync_drop(sc); 2218 return; 2219 } 2220 } 2221 m->m_data += max_linkhdr; 2222 m->m_len = m->m_pkthdr.len = sc->sc_len; 2223 2224 /* build the ip header */ 2225 ip = (struct ip *)m->m_data; 2226 bcopy(&sc->sc_template, ip, sizeof(*ip)); 2227 offset = sizeof(*ip); 2228 2229#ifdef __FreeBSD__ 2230 ip->ip_len = m->m_pkthdr.len; 2231#else 2232 ip->ip_len = htons(m->m_pkthdr.len); 2233#endif 2234 ip->ip_id = htons(ip_randomid()); 2235 2236 /* build the pfsync header */ 2237 ph = (struct pfsync_header *)(m->m_data + offset); 2238 bzero(ph, sizeof(*ph)); 2239 offset += sizeof(*ph); 2240 2241 ph->version = PFSYNC_VERSION; 2242 ph->len = htons(sc->sc_len - sizeof(*ip)); 2243#ifdef __FreeBSD__ 2244 bcopy(V_pf_status.pf_chksum, ph->pfcksum, PF_MD5_DIGEST_LENGTH); 2245#else 2246 bcopy(pf_status.pf_chksum, ph->pfcksum, PF_MD5_DIGEST_LENGTH); 2247#endif 2248 2249 /* walk the queues */ 2250 for (q = 0; q < PFSYNC_S_COUNT; q++) { 2251 if (TAILQ_EMPTY(&sc->sc_qs[q])) 2252 continue; 2253 2254 subh = (struct pfsync_subheader *)(m->m_data + offset); 2255 offset += sizeof(*subh); 2256 2257 count = 0; 2258 TAILQ_FOREACH(st, &sc->sc_qs[q], sync_list) { 2259#ifdef PFSYNC_DEBUG 2260#ifdef __FreeBSD__ 2261 KASSERT(st->sync_state == q, 2262 ("%s: st->sync_state == q", 2263 __FUNCTION__)); 2264#else 2265 KASSERT(st->sync_state == q); 2266#endif 2267#endif 2268 2269 offset += pfsync_qs[q].write(st, m, offset); 2270 st->sync_state = PFSYNC_S_NONE; 2271 count++; 2272 } 2273 TAILQ_INIT(&sc->sc_qs[q]); 2274 2275 bzero(subh, sizeof(*subh)); 2276 subh->action = pfsync_qs[q].action; 2277 subh->count = htons(count); 2278 } 2279 2280 if (!TAILQ_EMPTY(&sc->sc_upd_req_list)) { 2281 subh = (struct pfsync_subheader *)(m->m_data + offset); 2282 offset += sizeof(*subh); 2283 2284 count = 0; 2285 while ((ur = TAILQ_FIRST(&sc->sc_upd_req_list)) != NULL) { 2286 TAILQ_REMOVE(&sc->sc_upd_req_list, ur, ur_entry); 2287 2288 bcopy(&ur->ur_msg, m->m_data + offset, 2289 sizeof(ur->ur_msg)); 2290 offset += sizeof(ur->ur_msg); 2291 2292 pool_put(&sc->sc_pool, ur); 2293 2294 count++; 2295 } 2296 2297 bzero(subh, sizeof(*subh)); 2298 subh->action = PFSYNC_ACT_UPD_REQ; 2299 subh->count = htons(count); 2300 } 2301 2302 /* has someone built a custom region for us to add? */ 2303 if (sc->sc_plus != NULL) { 2304 bcopy(sc->sc_plus, m->m_data + offset, sc->sc_pluslen); 2305 offset += sc->sc_pluslen; 2306 2307 sc->sc_plus = NULL; 2308 } 2309 2310#ifdef notyet 2311 if (!TAILQ_EMPTY(&sc->sc_tdb_q)) { 2312 subh = (struct pfsync_subheader *)(m->m_data + offset); 2313 offset += sizeof(*subh); 2314 2315 count = 0; 2316 TAILQ_FOREACH(t, &sc->sc_tdb_q, tdb_sync_entry) { 2317 offset += pfsync_out_tdb(t, m, offset); 2318 CLR(t->tdb_flags, TDBF_PFSYNC); 2319 2320 count++; 2321 } 2322 TAILQ_INIT(&sc->sc_tdb_q); 2323 2324 bzero(subh, sizeof(*subh)); 2325 subh->action = PFSYNC_ACT_TDB; 2326 subh->count = htons(count); 2327 } 2328#endif 2329 2330 subh = (struct pfsync_subheader *)(m->m_data + offset); 2331 offset += sizeof(*subh); 2332 2333 bzero(subh, sizeof(*subh)); 2334 subh->action = PFSYNC_ACT_EOF; 2335 subh->count = htons(1); 2336 2337 /* XXX write checksum in EOF here */ 2338 2339 /* we're done, let's put it on the wire */ 2340#if NBPFILTER > 0 2341 if (ifp->if_bpf) { 2342 m->m_data += sizeof(*ip); 2343 m->m_len = m->m_pkthdr.len = sc->sc_len - sizeof(*ip); 2344#ifdef __FreeBSD__ 2345 BPF_MTAP(ifp, m); 2346#else 2347 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 2348#endif 2349 m->m_data -= sizeof(*ip); 2350 m->m_len = m->m_pkthdr.len = sc->sc_len; 2351 } 2352 2353 if (sc->sc_sync_if == NULL) { 2354 sc->sc_len = PFSYNC_MINPKT; 2355 m_freem(m); 2356 return; 2357 } 2358#endif 2359 2360#ifdef __FreeBSD__ 2361 sc->sc_ifp->if_opackets++; 2362 sc->sc_ifp->if_obytes += m->m_pkthdr.len; 2363 sc->sc_len = PFSYNC_MINPKT; 2364 2365 IFQ_ENQUEUE(&sc->sc_ifp->if_snd, m, dummy_error); 2366 schednetisr(NETISR_PFSYNC); 2367#else 2368 sc->sc_if.if_opackets++; 2369 sc->sc_if.if_obytes += m->m_pkthdr.len; 2370 2371 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL) == 0) 2372 pfsyncstats.pfsyncs_opackets++; 2373 else 2374 pfsyncstats.pfsyncs_oerrors++; 2375 2376 /* start again */ 2377 sc->sc_len = PFSYNC_MINPKT; 2378#endif 2379} 2380 2381void 2382pfsync_insert_state(struct pf_state *st) 2383{ 2384#ifdef __FreeBSD__ 2385 struct pfsync_softc *sc = V_pfsyncif; 2386#else 2387 struct pfsync_softc *sc = pfsyncif; 2388#endif 2389 2390#ifdef __FreeBSD__ 2391 PF_LOCK_ASSERT(); 2392#else 2393 splassert(IPL_SOFTNET); 2394#endif 2395 2396 if (ISSET(st->rule.ptr->rule_flag, PFRULE_NOSYNC) || 2397 st->key[PF_SK_WIRE]->proto == IPPROTO_PFSYNC) { 2398 SET(st->state_flags, PFSTATE_NOSYNC); 2399 return; 2400 } 2401 2402 if (sc == NULL || ISSET(st->state_flags, PFSTATE_NOSYNC)) 2403 return; 2404 2405#ifdef PFSYNC_DEBUG 2406#ifdef __FreeBSD__ 2407 KASSERT(st->sync_state == PFSYNC_S_NONE, 2408 ("%s: st->sync_state == PFSYNC_S_NONE", __FUNCTION__)); 2409#else 2410 KASSERT(st->sync_state == PFSYNC_S_NONE); 2411#endif 2412#endif 2413 2414 if (sc->sc_len == PFSYNC_MINPKT) 2415#ifdef __FreeBSD__ 2416 callout_reset(&sc->sc_tmo, 1 * hz, pfsync_timeout, 2417 V_pfsyncif); 2418#else 2419 timeout_add_sec(&sc->sc_tmo, 1); 2420#endif 2421 2422 pfsync_q_ins(st, PFSYNC_S_INS); 2423 2424 if (ISSET(st->state_flags, PFSTATE_ACK)) 2425#ifdef __FreeBSD__ 2426 pfsync_sendout(); 2427#else 2428 schednetisr(NETISR_PFSYNC); 2429#endif 2430 else 2431 st->sync_updates = 0; 2432} 2433 2434int defer = 10; 2435 2436int 2437pfsync_defer(struct pf_state *st, struct mbuf *m) 2438{ 2439#ifdef __FreeBSD__ 2440 struct pfsync_softc *sc = V_pfsyncif; 2441#else 2442 struct pfsync_softc *sc = pfsyncif; 2443#endif 2444 struct pfsync_deferral *pd; 2445 2446#ifdef __FreeBSD__ 2447 PF_LOCK_ASSERT(); 2448#else 2449 splassert(IPL_SOFTNET); 2450#endif 2451 2452 if (sc->sc_deferred >= 128) 2453 pfsync_undefer(TAILQ_FIRST(&sc->sc_deferrals), 0); 2454 2455 pd = pool_get(&sc->sc_pool, M_NOWAIT); 2456 if (pd == NULL) 2457 return (0); 2458 sc->sc_deferred++; 2459 2460#ifdef __FreeBSD__ 2461 m->m_flags |= M_SKIP_FIREWALL; 2462#else 2463 m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; 2464#endif 2465 SET(st->state_flags, PFSTATE_ACK); 2466 2467 pd->pd_st = st; 2468 pd->pd_m = m; 2469 2470 TAILQ_INSERT_TAIL(&sc->sc_deferrals, pd, pd_entry); 2471#ifdef __FreeBSD__ 2472 callout_init(&pd->pd_tmo, CALLOUT_MPSAFE); 2473 callout_reset(&pd->pd_tmo, defer, pfsync_defer_tmo, 2474 pd); 2475#else 2476 timeout_set(&pd->pd_tmo, pfsync_defer_tmo, pd); 2477 timeout_add(&pd->pd_tmo, defer); 2478#endif 2479 2480 return (1); 2481} 2482 2483void 2484pfsync_undefer(struct pfsync_deferral *pd, int drop) 2485{ 2486#ifdef __FreeBSD__ 2487 struct pfsync_softc *sc = V_pfsyncif; 2488#else 2489 struct pfsync_softc *sc = pfsyncif; 2490#endif 2491 int s; 2492 2493#ifdef __FreeBSD__ 2494 PF_LOCK_ASSERT(); 2495#else 2496 splassert(IPL_SOFTNET); 2497#endif 2498 2499 TAILQ_REMOVE(&sc->sc_deferrals, pd, pd_entry); 2500 sc->sc_deferred--; 2501 2502 CLR(pd->pd_st->state_flags, PFSTATE_ACK); 2503 timeout_del(&pd->pd_tmo); /* bah */ 2504 if (drop) 2505 m_freem(pd->pd_m); 2506 else { 2507 s = splnet(); 2508#ifdef __FreeBSD__ 2509 /* XXX: use pf_defered?! */ 2510 PF_UNLOCK(); 2511#endif 2512 ip_output(pd->pd_m, (void *)NULL, (void *)NULL, 0, 2513 (void *)NULL, (void *)NULL); 2514#ifdef __FreeBSD__ 2515 PF_LOCK(); 2516#endif 2517 splx(s); 2518 } 2519 2520 pool_put(&sc->sc_pool, pd); 2521} 2522 2523void 2524pfsync_defer_tmo(void *arg) 2525{ 2526#if defined(__FreeBSD__) && defined(VIMAGE) 2527 struct pfsync_deferral *pd = arg; 2528#endif 2529 int s; 2530 2531 s = splsoftnet(); 2532#ifdef __FreeBSD__ 2533 CURVNET_SET(pd->pd_m->m_pkthdr.rcvif->if_vnet); /* XXX */ 2534 PF_LOCK(); 2535#endif 2536 pfsync_undefer(arg, 0); 2537#ifdef __FreeBSD__ 2538 PF_UNLOCK(); 2539 CURVNET_RESTORE(); 2540#endif 2541 splx(s); 2542} 2543 2544void 2545pfsync_deferred(struct pf_state *st, int drop) 2546{ 2547#ifdef __FreeBSD__ 2548 struct pfsync_softc *sc = V_pfsyncif; 2549#else 2550 struct pfsync_softc *sc = pfsyncif; 2551#endif 2552 struct pfsync_deferral *pd; 2553 2554 TAILQ_FOREACH(pd, &sc->sc_deferrals, pd_entry) { 2555 if (pd->pd_st == st) { 2556 pfsync_undefer(pd, drop); 2557 return; 2558 } 2559 } 2560 2561 panic("pfsync_send_deferred: unable to find deferred state"); 2562} 2563 2564u_int pfsync_upds = 0; 2565 2566void 2567pfsync_update_state(struct pf_state *st) 2568{ 2569#ifdef __FreeBSD__ 2570 struct pfsync_softc *sc = V_pfsyncif; 2571#else 2572 struct pfsync_softc *sc = pfsyncif; 2573#endif 2574 int sync = 0; 2575 2576#ifdef __FreeBSD__ 2577 PF_LOCK_ASSERT(); 2578#else 2579 splassert(IPL_SOFTNET); 2580#endif 2581 2582 if (sc == NULL) 2583 return; 2584 2585 if (ISSET(st->state_flags, PFSTATE_ACK)) 2586 pfsync_deferred(st, 0); 2587 if (ISSET(st->state_flags, PFSTATE_NOSYNC)) { 2588 if (st->sync_state != PFSYNC_S_NONE) 2589 pfsync_q_del(st); 2590 return; 2591 } 2592 2593 if (sc->sc_len == PFSYNC_MINPKT) 2594#ifdef __FreeBSD__ 2595 callout_reset(&sc->sc_tmo, 1 * hz, pfsync_timeout, 2596 V_pfsyncif); 2597#else 2598 timeout_add_sec(&sc->sc_tmo, 1); 2599#endif 2600 2601 switch (st->sync_state) { 2602 case PFSYNC_S_UPD_C: 2603 case PFSYNC_S_UPD: 2604 case PFSYNC_S_INS: 2605 /* we're already handling it */ 2606 2607 st->sync_updates++; 2608 if (st->sync_updates >= sc->sc_maxupdates) 2609 sync = 1; 2610 break; 2611 2612 case PFSYNC_S_IACK: 2613 pfsync_q_del(st); 2614 case PFSYNC_S_NONE: 2615 pfsync_q_ins(st, PFSYNC_S_UPD_C); 2616 st->sync_updates = 0; 2617 break; 2618 2619 default: 2620 panic("pfsync_update_state: unexpected sync state %d", 2621 st->sync_state); 2622 } 2623 2624 if (sync || (time_second - st->pfsync_time) < 2) { 2625 pfsync_upds++; 2626#ifdef __FreeBSD__ 2627 pfsync_sendout(); 2628#else 2629 schednetisr(NETISR_PFSYNC); 2630#endif 2631 } 2632} 2633 2634void 2635pfsync_request_update(u_int32_t creatorid, u_int64_t id) 2636{ 2637#ifdef __FreeBSD__ 2638 struct pfsync_softc *sc = V_pfsyncif; 2639#else 2640 struct pfsync_softc *sc = pfsyncif; 2641#endif 2642 struct pfsync_upd_req_item *item; 2643 size_t nlen = sizeof(struct pfsync_upd_req); 2644 int s; 2645 2646 PF_LOCK_ASSERT(); 2647 2648 /* 2649 * this code does nothing to prevent multiple update requests for the 2650 * same state being generated. 2651 */ 2652 2653 item = pool_get(&sc->sc_pool, PR_NOWAIT); 2654 if (item == NULL) { 2655 /* XXX stats */ 2656 return; 2657 } 2658 2659 item->ur_msg.id = id; 2660 item->ur_msg.creatorid = creatorid; 2661 2662 if (TAILQ_EMPTY(&sc->sc_upd_req_list)) 2663 nlen += sizeof(struct pfsync_subheader); 2664 2665#ifdef __FreeBSD__ 2666 if (sc->sc_len + nlen > sc->sc_sync_if->if_mtu) { 2667#else 2668 if (sc->sc_len + nlen > sc->sc_if.if_mtu) { 2669#endif 2670 s = splnet(); 2671 pfsync_sendout(); 2672 splx(s); 2673 2674 nlen = sizeof(struct pfsync_subheader) + 2675 sizeof(struct pfsync_upd_req); 2676 } 2677 2678 TAILQ_INSERT_TAIL(&sc->sc_upd_req_list, item, ur_entry); 2679 sc->sc_len += nlen; 2680 2681#ifdef __FreeBSD__ 2682 pfsync_sendout(); 2683#else 2684 schednetisr(NETISR_PFSYNC); 2685#endif 2686} 2687 2688void 2689pfsync_update_state_req(struct pf_state *st) 2690{ 2691#ifdef __FreeBSD__ 2692 struct pfsync_softc *sc = V_pfsyncif; 2693#else 2694 struct pfsync_softc *sc = pfsyncif; 2695#endif 2696 2697 PF_LOCK_ASSERT(); 2698 2699 if (sc == NULL) 2700 panic("pfsync_update_state_req: nonexistant instance"); 2701 2702 if (ISSET(st->state_flags, PFSTATE_NOSYNC)) { 2703 if (st->sync_state != PFSYNC_S_NONE) 2704 pfsync_q_del(st); 2705 return; 2706 } 2707 2708 switch (st->sync_state) { 2709 case PFSYNC_S_UPD_C: 2710 case PFSYNC_S_IACK: 2711 pfsync_q_del(st); 2712 case PFSYNC_S_NONE: 2713 pfsync_q_ins(st, PFSYNC_S_UPD); 2714#ifdef __FreeBSD__ 2715 pfsync_sendout(); 2716#else 2717 schednetisr(NETISR_PFSYNC); 2718#endif 2719 return; 2720 2721 case PFSYNC_S_INS: 2722 case PFSYNC_S_UPD: 2723 case PFSYNC_S_DEL: 2724 /* we're already handling it */ 2725 return; 2726 2727 default: 2728 panic("pfsync_update_state_req: unexpected sync state %d", 2729 st->sync_state); 2730 } 2731} 2732 2733void 2734pfsync_delete_state(struct pf_state *st) 2735{ 2736#ifdef __FreeBSD__ 2737 struct pfsync_softc *sc = V_pfsyncif; 2738#else 2739 struct pfsync_softc *sc = pfsyncif; 2740#endif 2741 2742#ifdef __FreeBSD__ 2743 PF_LOCK_ASSERT(); 2744#else 2745 splassert(IPL_SOFTNET); 2746#endif 2747 2748 if (sc == NULL) 2749 return; 2750 2751 if (ISSET(st->state_flags, PFSTATE_ACK)) 2752 pfsync_deferred(st, 1); 2753 if (ISSET(st->state_flags, PFSTATE_NOSYNC)) { 2754 if (st->sync_state != PFSYNC_S_NONE) 2755 pfsync_q_del(st); 2756 return; 2757 } 2758 2759 if (sc->sc_len == PFSYNC_MINPKT) 2760#ifdef __FreeBSD__ 2761 callout_reset(&sc->sc_tmo, 1 * hz, pfsync_timeout, 2762 V_pfsyncif); 2763#else 2764 timeout_add_sec(&sc->sc_tmo, 1); 2765#endif 2766 2767 switch (st->sync_state) { 2768 case PFSYNC_S_INS: 2769 /* we never got to tell the world so just forget about it */ 2770 pfsync_q_del(st); 2771 return; 2772 2773 case PFSYNC_S_UPD_C: 2774 case PFSYNC_S_UPD: 2775 case PFSYNC_S_IACK: 2776 pfsync_q_del(st); 2777 /* FALLTHROUGH to putting it on the del list */ 2778 2779 case PFSYNC_S_NONE: 2780 pfsync_q_ins(st, PFSYNC_S_DEL); 2781 return; 2782 2783 default: 2784 panic("pfsync_delete_state: unexpected sync state %d", 2785 st->sync_state); 2786 } 2787} 2788 2789void 2790pfsync_clear_states(u_int32_t creatorid, const char *ifname) 2791{ 2792 struct { 2793 struct pfsync_subheader subh; 2794 struct pfsync_clr clr; 2795 } __packed r; 2796 2797#ifdef __FreeBSD__ 2798 struct pfsync_softc *sc = V_pfsyncif; 2799#else 2800 struct pfsync_softc *sc = pfsyncif; 2801#endif 2802 2803#ifdef __FreeBSD__ 2804 PF_LOCK_ASSERT(); 2805#else 2806 splassert(IPL_SOFTNET); 2807#endif 2808 2809 if (sc == NULL) 2810 return; 2811 2812 bzero(&r, sizeof(r)); 2813 2814 r.subh.action = PFSYNC_ACT_CLR; 2815 r.subh.count = htons(1); 2816 2817 strlcpy(r.clr.ifname, ifname, sizeof(r.clr.ifname)); 2818 r.clr.creatorid = creatorid; 2819 2820 pfsync_send_plus(&r, sizeof(r)); 2821} 2822 2823void 2824pfsync_q_ins(struct pf_state *st, int q) 2825{ 2826#ifdef __FreeBSD__ 2827 struct pfsync_softc *sc = V_pfsyncif; 2828#else 2829 struct pfsync_softc *sc = pfsyncif; 2830#endif 2831 size_t nlen = pfsync_qs[q].len; 2832 int s; 2833 2834 PF_LOCK_ASSERT(); 2835 2836#ifdef __FreeBSD__ 2837 KASSERT(st->sync_state == PFSYNC_S_NONE, 2838 ("%s: st->sync_state == PFSYNC_S_NONE", __FUNCTION__)); 2839#else 2840 KASSERT(st->sync_state == PFSYNC_S_NONE); 2841#endif 2842 2843#if 1 || defined(PFSYNC_DEBUG) 2844 if (sc->sc_len < PFSYNC_MINPKT) 2845#ifdef __FreeBSD__ 2846 panic("pfsync pkt len is too low %zu", sc->sc_len); 2847#else 2848 panic("pfsync pkt len is too low %d", sc->sc_len); 2849#endif 2850#endif 2851 if (TAILQ_EMPTY(&sc->sc_qs[q])) 2852 nlen += sizeof(struct pfsync_subheader); 2853 2854#ifdef __FreeBSD__ 2855 if (sc->sc_len + nlen > sc->sc_ifp->if_mtu) { 2856#else 2857 if (sc->sc_len + nlen > sc->sc_if.if_mtu) { 2858#endif 2859 s = splnet(); 2860 pfsync_sendout(); 2861 splx(s); 2862 2863 nlen = sizeof(struct pfsync_subheader) + pfsync_qs[q].len; 2864 } 2865 2866 sc->sc_len += nlen; 2867 TAILQ_INSERT_TAIL(&sc->sc_qs[q], st, sync_list); 2868 st->sync_state = q; 2869} 2870 2871void 2872pfsync_q_del(struct pf_state *st) 2873{ 2874#ifdef __FreeBSD__ 2875 struct pfsync_softc *sc = V_pfsyncif; 2876#else 2877 struct pfsync_softc *sc = pfsyncif; 2878#endif 2879 int q = st->sync_state; 2880 2881#ifdef __FreeBSD__ 2882 KASSERT(st->sync_state != PFSYNC_S_NONE, 2883 ("%s: st->sync_state != PFSYNC_S_NONE", __FUNCTION__)); 2884#else 2885 KASSERT(st->sync_state != PFSYNC_S_NONE); 2886#endif 2887 2888 sc->sc_len -= pfsync_qs[q].len; 2889 TAILQ_REMOVE(&sc->sc_qs[q], st, sync_list); 2890 st->sync_state = PFSYNC_S_NONE; 2891 2892 if (TAILQ_EMPTY(&sc->sc_qs[q])) 2893 sc->sc_len -= sizeof(struct pfsync_subheader); 2894} 2895 2896#ifdef notyet 2897void 2898pfsync_update_tdb(struct tdb *t, int output) 2899{ 2900#ifdef __FreeBSD__ 2901 struct pfsync_softc *sc = V_pfsyncif; 2902#else 2903 struct pfsync_softc *sc = pfsyncif; 2904#endif 2905 size_t nlen = sizeof(struct pfsync_tdb); 2906 int s; 2907 2908 if (sc == NULL) 2909 return; 2910 2911 if (!ISSET(t->tdb_flags, TDBF_PFSYNC)) { 2912 if (TAILQ_EMPTY(&sc->sc_tdb_q)) 2913 nlen += sizeof(struct pfsync_subheader); 2914 2915 if (sc->sc_len + nlen > sc->sc_if.if_mtu) { 2916 s = splnet(); 2917 PF_LOCK(); 2918 pfsync_sendout(); 2919 PF_UNLOCK(); 2920 splx(s); 2921 2922 nlen = sizeof(struct pfsync_subheader) + 2923 sizeof(struct pfsync_tdb); 2924 } 2925 2926 sc->sc_len += nlen; 2927 TAILQ_INSERT_TAIL(&sc->sc_tdb_q, t, tdb_sync_entry); 2928 SET(t->tdb_flags, TDBF_PFSYNC); 2929 t->tdb_updates = 0; 2930 } else { 2931 if (++t->tdb_updates >= sc->sc_maxupdates) 2932 schednetisr(NETISR_PFSYNC); 2933 } 2934 2935 if (output) 2936 SET(t->tdb_flags, TDBF_PFSYNC_RPL); 2937 else 2938 CLR(t->tdb_flags, TDBF_PFSYNC_RPL); 2939} 2940 2941void 2942pfsync_delete_tdb(struct tdb *t) 2943{ 2944#ifdef __FreeBSD__ 2945 struct pfsync_softc *sc = V_pfsyncif; 2946#else 2947 struct pfsync_softc *sc = pfsyncif; 2948#endif 2949 2950 if (sc == NULL || !ISSET(t->tdb_flags, TDBF_PFSYNC)) 2951 return; 2952 2953 sc->sc_len -= sizeof(struct pfsync_tdb); 2954 TAILQ_REMOVE(&sc->sc_tdb_q, t, tdb_sync_entry); 2955 CLR(t->tdb_flags, TDBF_PFSYNC); 2956 2957 if (TAILQ_EMPTY(&sc->sc_tdb_q)) 2958 sc->sc_len -= sizeof(struct pfsync_subheader); 2959} 2960 2961int 2962pfsync_out_tdb(struct tdb *t, struct mbuf *m, int offset) 2963{ 2964 struct pfsync_tdb *ut = (struct pfsync_tdb *)(m->m_data + offset); 2965 2966 bzero(ut, sizeof(*ut)); 2967 ut->spi = t->tdb_spi; 2968 bcopy(&t->tdb_dst, &ut->dst, sizeof(ut->dst)); 2969 /* 2970 * When a failover happens, the master's rpl is probably above 2971 * what we see here (we may be up to a second late), so 2972 * increase it a bit for outbound tdbs to manage most such 2973 * situations. 2974 * 2975 * For now, just add an offset that is likely to be larger 2976 * than the number of packets we can see in one second. The RFC 2977 * just says the next packet must have a higher seq value. 2978 * 2979 * XXX What is a good algorithm for this? We could use 2980 * a rate-determined increase, but to know it, we would have 2981 * to extend struct tdb. 2982 * XXX pt->rpl can wrap over MAXINT, but if so the real tdb 2983 * will soon be replaced anyway. For now, just don't handle 2984 * this edge case. 2985 */ 2986#define RPL_INCR 16384 2987 ut->rpl = htonl(t->tdb_rpl + (ISSET(t->tdb_flags, TDBF_PFSYNC_RPL) ? 2988 RPL_INCR : 0)); 2989 ut->cur_bytes = htobe64(t->tdb_cur_bytes); 2990 ut->sproto = t->tdb_sproto; 2991 2992 return (sizeof(*ut)); 2993} 2994#endif 2995 2996void 2997pfsync_bulk_start(void) 2998{ 2999#ifdef __FreeBSD__ 3000 struct pfsync_softc *sc = V_pfsyncif; 3001#else 3002 struct pfsync_softc *sc = pfsyncif; 3003#endif 3004 3005#ifdef __FreeBSD__ 3006 if (V_pf_status.debug >= PF_DEBUG_MISC) 3007#else 3008 if (pf_status.debug >= PF_DEBUG_MISC) 3009#endif 3010 printf("pfsync: received bulk update request\n"); 3011 3012#ifdef __FreeBSD__ 3013 PF_LOCK(); 3014 if (TAILQ_EMPTY(&V_state_list)) 3015#else 3016 if (TAILQ_EMPTY(&state_list)) 3017#endif 3018 pfsync_bulk_status(PFSYNC_BUS_END); 3019 else { 3020 sc->sc_ureq_received = time_uptime; 3021 if (sc->sc_bulk_next == NULL) 3022#ifdef __FreeBSD__ 3023 sc->sc_bulk_next = TAILQ_FIRST(&V_state_list); 3024#else 3025 sc->sc_bulk_next = TAILQ_FIRST(&state_list); 3026#endif 3027 sc->sc_bulk_last = sc->sc_bulk_next; 3028 3029 pfsync_bulk_status(PFSYNC_BUS_START); 3030 callout_reset(&sc->sc_bulk_tmo, 1, 3031 pfsync_bulk_update, sc); 3032 } 3033#ifdef __FreeBSD__ 3034 PF_UNLOCK(); 3035#endif 3036} 3037 3038void 3039pfsync_bulk_update(void *arg) 3040{ 3041 struct pfsync_softc *sc = arg; 3042 struct pf_state *st = sc->sc_bulk_next; 3043 int i = 0; 3044 int s; 3045 3046 PF_LOCK_ASSERT(); 3047 3048 s = splsoftnet(); 3049#ifdef __FreeBSD__ 3050 CURVNET_SET(sc->sc_ifp->if_vnet); 3051#endif 3052 for (;;) { 3053 if (st->sync_state == PFSYNC_S_NONE && 3054 st->timeout < PFTM_MAX && 3055 st->pfsync_time <= sc->sc_ureq_received) { 3056 pfsync_update_state_req(st); 3057 i++; 3058 } 3059 3060 st = TAILQ_NEXT(st, entry_list); 3061 if (st == NULL) 3062#ifdef __FreeBSD__ 3063 st = TAILQ_FIRST(&V_state_list); 3064#else 3065 st = TAILQ_FIRST(&state_list); 3066#endif 3067 3068 if (st == sc->sc_bulk_last) { 3069 /* we're done */ 3070 sc->sc_bulk_next = NULL; 3071 sc->sc_bulk_last = NULL; 3072 pfsync_bulk_status(PFSYNC_BUS_END); 3073 break; 3074 } 3075 3076#ifdef __FreeBSD__ 3077 if (i > 1 && (sc->sc_ifp->if_mtu - sc->sc_len) < 3078#else 3079 if (i > 1 && (sc->sc_if.if_mtu - sc->sc_len) < 3080#endif 3081 sizeof(struct pfsync_state)) { 3082 /* we've filled a packet */ 3083 sc->sc_bulk_next = st; 3084#ifdef __FreeBSD__ 3085 callout_reset(&sc->sc_bulk_tmo, 1, 3086 pfsync_bulk_update, sc); 3087#else 3088 timeout_add(&sc->sc_bulk_tmo, 1); 3089#endif 3090 break; 3091 } 3092 } 3093 3094#ifdef __FreeBSD__ 3095 CURVNET_RESTORE(); 3096#endif 3097 splx(s); 3098} 3099 3100void 3101pfsync_bulk_status(u_int8_t status) 3102{ 3103 struct { 3104 struct pfsync_subheader subh; 3105 struct pfsync_bus bus; 3106 } __packed r; 3107 3108#ifdef __FreeBSD__ 3109 struct pfsync_softc *sc = V_pfsyncif; 3110#else 3111 struct pfsync_softc *sc = pfsyncif; 3112#endif 3113 3114 PF_LOCK_ASSERT(); 3115 3116 bzero(&r, sizeof(r)); 3117 3118 r.subh.action = PFSYNC_ACT_BUS; 3119 r.subh.count = htons(1); 3120 3121#ifdef __FreeBSD__ 3122 r.bus.creatorid = V_pf_status.hostid; 3123#else 3124 r.bus.creatorid = pf_status.hostid; 3125#endif 3126 r.bus.endtime = htonl(time_uptime - sc->sc_ureq_received); 3127 r.bus.status = status; 3128 3129 pfsync_send_plus(&r, sizeof(r)); 3130} 3131 3132void 3133pfsync_bulk_fail(void *arg) 3134{ 3135 struct pfsync_softc *sc = arg; 3136 3137#ifdef __FreeBSD__ 3138 CURVNET_SET(sc->sc_ifp->if_vnet); 3139#endif 3140 3141 if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) { 3142 /* Try again */ 3143#ifdef __FreeBSD__ 3144 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, 3145 pfsync_bulk_fail, V_pfsyncif); 3146#else 3147 timeout_add_sec(&sc->sc_bulkfail_tmo, 5); 3148#endif 3149 PF_LOCK(); 3150 pfsync_request_update(0, 0); 3151 PF_UNLOCK(); 3152 } else { 3153 /* Pretend like the transfer was ok */ 3154 sc->sc_ureq_sent = 0; 3155 sc->sc_bulk_tries = 0; 3156#ifdef __FreeBSD__ 3157 if (!sc->pfsync_sync_ok && carp_demote_adj_p) 3158 (*carp_demote_adj_p)(-V_pfsync_carp_adj, 3159 "pfsync bulk fail"); 3160 sc->pfsync_sync_ok = 1; 3161#else 3162#if NCARP > 0 3163 if (!pfsync_sync_ok) 3164 carp_group_demote_adj(&sc->sc_if, -1); 3165#endif 3166 pfsync_sync_ok = 1; 3167#endif 3168#ifdef __FreeBSD__ 3169 if (V_pf_status.debug >= PF_DEBUG_MISC) 3170#else 3171 if (pf_status.debug >= PF_DEBUG_MISC) 3172#endif 3173 printf("pfsync: failed to receive bulk update\n"); 3174 } 3175 3176#ifdef __FreeBSD__ 3177 CURVNET_RESTORE(); 3178#endif 3179} 3180 3181void 3182pfsync_send_plus(void *plus, size_t pluslen) 3183{ 3184#ifdef __FreeBSD__ 3185 struct pfsync_softc *sc = V_pfsyncif; 3186#else 3187 struct pfsync_softc *sc = pfsyncif; 3188#endif 3189 int s; 3190 3191 PF_LOCK_ASSERT(); 3192 3193#ifdef __FreeBSD__ 3194 if (sc->sc_len + pluslen > sc->sc_ifp->if_mtu) { 3195#else 3196 if (sc->sc_len + pluslen > sc->sc_if.if_mtu) { 3197#endif 3198 s = splnet(); 3199 pfsync_sendout(); 3200 splx(s); 3201 } 3202 3203 sc->sc_plus = plus; 3204 sc->sc_len += (sc->sc_pluslen = pluslen); 3205 3206 s = splnet(); 3207 pfsync_sendout(); 3208 splx(s); 3209} 3210 3211int 3212pfsync_up(void) 3213{ 3214#ifdef __FreeBSD__ 3215 struct pfsync_softc *sc = V_pfsyncif; 3216#else 3217 struct pfsync_softc *sc = pfsyncif; 3218#endif 3219 3220#ifdef __FreeBSD__ 3221 if (sc == NULL || !ISSET(sc->sc_ifp->if_flags, IFF_DRV_RUNNING)) 3222#else 3223 if (sc == NULL || !ISSET(sc->sc_if.if_flags, IFF_RUNNING)) 3224#endif 3225 return (0); 3226 3227 return (1); 3228} 3229 3230int 3231pfsync_state_in_use(struct pf_state *st) 3232{ 3233#ifdef __FreeBSD__ 3234 struct pfsync_softc *sc = V_pfsyncif; 3235#else 3236 struct pfsync_softc *sc = pfsyncif; 3237#endif 3238 3239 if (sc == NULL) 3240 return (0); 3241 3242 if (st->sync_state != PFSYNC_S_NONE || 3243 st == sc->sc_bulk_next || 3244 st == sc->sc_bulk_last) 3245 return (1); 3246 3247 return (0); 3248} 3249 3250u_int pfsync_ints; 3251u_int pfsync_tmos; 3252 3253void 3254pfsync_timeout(void *arg) 3255{ 3256#if defined(__FreeBSD__) && defined(VIMAGE) 3257 struct pfsync_softc *sc = arg; 3258#endif 3259 int s; 3260 3261#ifdef __FreeBSD__ 3262 CURVNET_SET(sc->sc_ifp->if_vnet); 3263#endif 3264 3265 pfsync_tmos++; 3266 3267 s = splnet(); 3268#ifdef __FreeBSD__ 3269 PF_LOCK(); 3270#endif 3271 pfsync_sendout(); 3272#ifdef __FreeBSD__ 3273 PF_UNLOCK(); 3274#endif 3275 splx(s); 3276 3277#ifdef __FreeBSD__ 3278 CURVNET_RESTORE(); 3279#endif 3280} 3281 3282/* this is a softnet/netisr handler */ 3283void 3284#ifdef __FreeBSD__ 3285pfsyncintr(void *arg) 3286{ 3287 struct pfsync_softc *sc = arg; 3288 struct mbuf *m, *n; 3289 3290 CURVNET_SET(sc->sc_ifp->if_vnet); 3291 pfsync_ints++; 3292 3293 IF_DEQUEUE_ALL(&sc->sc_ifp->if_snd, m); 3294 3295 for (; m != NULL; m = n) { 3296 3297 n = m->m_nextpkt; 3298 m->m_nextpkt = NULL; 3299 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL) 3300 == 0) 3301 V_pfsyncstats.pfsyncs_opackets++; 3302 else 3303 V_pfsyncstats.pfsyncs_oerrors++; 3304 } 3305 CURVNET_RESTORE(); 3306} 3307#else 3308pfsyncintr(void) 3309{ 3310 int s; 3311 3312 pfsync_ints++; 3313 3314 s = splnet(); 3315 pfsync_sendout(); 3316 splx(s); 3317} 3318#endif 3319 3320int 3321pfsync_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 3322 size_t newlen) 3323{ 3324 3325#ifdef notyet 3326 /* All sysctl names at this level are terminal. */ 3327 if (namelen != 1) 3328 return (ENOTDIR); 3329 3330 switch (name[0]) { 3331 case PFSYNCCTL_STATS: 3332 if (newp != NULL) 3333 return (EPERM); 3334 return (sysctl_struct(oldp, oldlenp, newp, newlen, 3335 &V_pfsyncstats, sizeof(V_pfsyncstats))); 3336 } 3337#endif 3338 return (ENOPROTOOPT); 3339} 3340 3341#ifdef __FreeBSD__ 3342void 3343pfsync_ifdetach(void *arg, struct ifnet *ifp) 3344{ 3345 struct pfsync_softc *sc = (struct pfsync_softc *)arg; 3346 struct ip_moptions *imo; 3347 3348 if (sc == NULL || sc->sc_sync_if != ifp) 3349 return; /* not for us; unlocked read */ 3350 3351 CURVNET_SET(sc->sc_ifp->if_vnet); 3352 3353 PF_LOCK(); 3354 3355 /* Deal with a member interface going away from under us. */ 3356 sc->sc_sync_if = NULL; 3357 imo = &sc->sc_imo; 3358 if (imo->imo_num_memberships > 0) { 3359 KASSERT(imo->imo_num_memberships == 1, 3360 ("%s: imo_num_memberships != 1", __func__)); 3361 /* 3362 * Our event handler is always called after protocol 3363 * domains have been detached from the underlying ifnet. 3364 * Do not call in_delmulti(); we held a single reference 3365 * which the protocol domain has purged in in_purgemaddrs(). 3366 */ 3367 PF_UNLOCK(); 3368 imo->imo_membership[--imo->imo_num_memberships] = NULL; 3369 PF_LOCK(); 3370 imo->imo_multicast_ifp = NULL; 3371 } 3372 3373 PF_UNLOCK(); 3374 3375 CURVNET_RESTORE(); 3376} 3377 3378static int 3379vnet_pfsync_init(const void *unused) 3380{ 3381 int error = 0; 3382 3383 pfsyncattach(0); 3384 3385 error = swi_add(NULL, "pfsync", pfsyncintr, V_pfsyncif, 3386 SWI_NET, INTR_MPSAFE, &pfsync_swi.pfsync_swi_cookie); 3387 if (error) 3388 panic("%s: swi_add %d", __func__, error); 3389 3390 PF_LOCK(); 3391 pfsync_state_import_ptr = pfsync_state_import; 3392 pfsync_up_ptr = pfsync_up; 3393 pfsync_insert_state_ptr = pfsync_insert_state; 3394 pfsync_update_state_ptr = pfsync_update_state; 3395 pfsync_delete_state_ptr = pfsync_delete_state; 3396 pfsync_clear_states_ptr = pfsync_clear_states; 3397 pfsync_state_in_use_ptr = pfsync_state_in_use; 3398 pfsync_defer_ptr = pfsync_defer; 3399 PF_UNLOCK(); 3400 3401 return (0); 3402} 3403 3404static int 3405vnet_pfsync_uninit(const void *unused) 3406{ 3407 3408 swi_remove(pfsync_swi.pfsync_swi_cookie); 3409 3410 PF_LOCK(); 3411 pfsync_state_import_ptr = NULL; 3412 pfsync_up_ptr = NULL; 3413 pfsync_insert_state_ptr = NULL; 3414 pfsync_update_state_ptr = NULL; 3415 pfsync_delete_state_ptr = NULL; 3416 pfsync_clear_states_ptr = NULL; 3417 pfsync_state_in_use_ptr = NULL; 3418 pfsync_defer_ptr = NULL; 3419 PF_UNLOCK(); 3420 3421 if_clone_detach(&pfsync_cloner); 3422 3423 return (0); 3424} 3425 3426/* Define startup order. */ 3427#define PFSYNC_SYSINIT_ORDER SI_SUB_PROTO_IF 3428#define PFSYNC_MODEVENT_ORDER (SI_ORDER_FIRST) /* On boot slot in here. */ 3429#define PFSYNC_VNET_ORDER (PFSYNC_MODEVENT_ORDER + 2) /* Later still. */ 3430 3431/* 3432 * Starting up. 3433 * VNET_SYSINIT is called for each existing vnet and each new vnet. 3434 */ 3435VNET_SYSINIT(vnet_pfsync_init, PFSYNC_SYSINIT_ORDER, PFSYNC_VNET_ORDER, 3436 vnet_pfsync_init, NULL); 3437 3438/* 3439 * Closing up shop. These are done in REVERSE ORDER, 3440 * Not called on reboot. 3441 * VNET_SYSUNINIT is called for each exiting vnet as it exits. 3442 */ 3443VNET_SYSUNINIT(vnet_pfsync_uninit, PFSYNC_SYSINIT_ORDER, PFSYNC_VNET_ORDER, 3444 vnet_pfsync_uninit, NULL); 3445static int 3446pfsync_modevent(module_t mod, int type, void *data) 3447{ 3448 int error = 0; 3449 3450 switch (type) { 3451 case MOD_LOAD: 3452#ifndef __FreeBSD__ 3453 pfsyncattach(0); 3454#endif 3455 break; 3456 case MOD_UNLOAD: 3457#ifndef __FreeBSD__ 3458 if_clone_detach(&pfsync_cloner); 3459#endif 3460 break; 3461 default: 3462 error = EINVAL; 3463 break; 3464 } 3465 3466 return error; 3467} 3468 3469static moduledata_t pfsync_mod = { 3470 "pfsync", 3471 pfsync_modevent, 3472 0 3473}; 3474 3475#define PFSYNC_MODVER 1 3476 3477DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 3478MODULE_VERSION(pfsync, PFSYNC_MODVER); 3479MODULE_DEPEND(pfsync, pf, PF_MODVER, PF_MODVER, PF_MODVER); 3480#endif /* __FreeBSD__ */ 3481