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