if_pfsync.c revision 148015
1126261Smlaier/* $FreeBSD: head/sys/contrib/pf/net/if_pfsync.c 148015 2005-07-14 22:22:51Z mlaier $ */ 2145836Smlaier/* $OpenBSD: if_pfsync.c,v 1.46 2005/02/20 15:58:38 mcbride Exp $ */ 3126258Smlaier 4126258Smlaier/* 5126258Smlaier * Copyright (c) 2002 Michael Shalayeff 6126258Smlaier * All rights reserved. 7126258Smlaier * 8126258Smlaier * Redistribution and use in source and binary forms, with or without 9126258Smlaier * modification, are permitted provided that the following conditions 10126258Smlaier * are met: 11126258Smlaier * 1. Redistributions of source code must retain the above copyright 12126258Smlaier * notice, this list of conditions and the following disclaimer. 13126258Smlaier * 2. Redistributions in binary form must reproduce the above copyright 14126258Smlaier * notice, this list of conditions and the following disclaimer in the 15126258Smlaier * documentation and/or other materials provided with the distribution. 16126258Smlaier * 17126258Smlaier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18126258Smlaier * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19126258Smlaier * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20126258Smlaier * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 21126258Smlaier * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22126258Smlaier * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23126258Smlaier * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24126258Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25126258Smlaier * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26126258Smlaier * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27126258Smlaier * THE POSSIBILITY OF SUCH DAMAGE. 28126258Smlaier */ 29126258Smlaier 30127145Smlaier#ifdef __FreeBSD__ 31126261Smlaier#include "opt_inet.h" 32126261Smlaier#include "opt_inet6.h" 33126261Smlaier#endif 34126261Smlaier 35127145Smlaier#ifndef __FreeBSD__ 36126258Smlaier#include "bpfilter.h" 37126258Smlaier#include "pfsync.h" 38126261Smlaier#elif __FreeBSD__ >= 5 39126261Smlaier#include "opt_bpf.h" 40126261Smlaier#include "opt_pf.h" 41127145Smlaier#define NBPFILTER DEV_BPF 42127145Smlaier#define NPFSYNC DEV_PFSYNC 43126261Smlaier#endif 44126258Smlaier 45126258Smlaier#include <sys/param.h> 46130613Smlaier#include <sys/proc.h> 47126258Smlaier#include <sys/systm.h> 48126258Smlaier#include <sys/time.h> 49126258Smlaier#include <sys/mbuf.h> 50126258Smlaier#include <sys/socket.h> 51145836Smlaier#include <sys/kernel.h> 52127145Smlaier#ifdef __FreeBSD__ 53145836Smlaier#include <sys/endian.h> 54126261Smlaier#include <sys/malloc.h> 55129907Smlaier#include <sys/module.h> 56126261Smlaier#include <sys/sockio.h> 57130613Smlaier#include <sys/lock.h> 58130613Smlaier#include <sys/mutex.h> 59148015Smlaier#include <sys/sysctl.h> 60126261Smlaier#else 61126258Smlaier#include <sys/ioctl.h> 62126258Smlaier#include <sys/timeout.h> 63126261Smlaier#endif 64126258Smlaier 65126258Smlaier#include <net/if.h> 66130933Sbrooks#if defined(__FreeBSD__) 67130933Sbrooks#include <net/if_clone.h> 68130933Sbrooks#endif 69126258Smlaier#include <net/if_types.h> 70126258Smlaier#include <net/route.h> 71126258Smlaier#include <net/bpf.h> 72145836Smlaier#include <netinet/tcp.h> 73145836Smlaier#include <netinet/tcp_seq.h> 74126258Smlaier 75126258Smlaier#ifdef INET 76126258Smlaier#include <netinet/in.h> 77130613Smlaier#include <netinet/in_systm.h> 78126258Smlaier#include <netinet/in_var.h> 79130613Smlaier#include <netinet/ip.h> 80130613Smlaier#include <netinet/ip_var.h> 81126258Smlaier#endif 82126258Smlaier 83126258Smlaier#ifdef INET6 84126258Smlaier#ifndef INET 85126258Smlaier#include <netinet/in.h> 86126258Smlaier#endif 87126258Smlaier#include <netinet6/nd6.h> 88126258Smlaier#endif /* INET6 */ 89126258Smlaier 90145836Smlaier#ifdef __FreeBSD__ 91145836Smlaier#include "opt_carp.h" 92145836Smlaier#ifdef DEV_CARP 93145836Smlaier#define NCARP 1 94145836Smlaier#endif 95145836Smlaier#else 96145836Smlaier#include "carp.h" 97145836Smlaier#endif 98145836Smlaier#if NCARP > 0 99145836Smlaierextern int carp_suppress_preempt; 100145836Smlaier#endif 101145836Smlaier 102126258Smlaier#include <net/pfvar.h> 103126258Smlaier#include <net/if_pfsync.h> 104126258Smlaier 105127145Smlaier#ifdef __FreeBSD__ 106127145Smlaier#define PFSYNCNAME "pfsync" 107126261Smlaier#endif 108126261Smlaier 109126258Smlaier#define PFSYNC_MINMTU \ 110126258Smlaier (sizeof(struct pfsync_header) + sizeof(struct pf_state)) 111126258Smlaier 112126258Smlaier#ifdef PFSYNCDEBUG 113126258Smlaier#define DPRINTF(x) do { if (pfsyncdebug) printf x ; } while (0) 114126258Smlaierint pfsyncdebug; 115126258Smlaier#else 116126258Smlaier#define DPRINTF(x) 117126258Smlaier#endif 118126258Smlaier 119127145Smlaier#ifndef __FreeBSD__ 120130613Smlaierstruct pfsync_softc pfsyncif; 121126261Smlaier#endif 122130613Smlaierstruct pfsyncstats pfsyncstats; 123127145Smlaier#ifdef __FreeBSD__ 124148015SmlaierSYSCTL_DECL(_net_inet_pfsync); 125148015SmlaierSYSCTL_STRUCT(_net_inet_pfsync, 0, stats, CTLFLAG_RW, 126148015Smlaier &pfsyncstats, pfsyncstats, 127148015Smlaier "PFSYNC statistics (struct pfsyncstats, net/if_pfsync.h)"); 128130613Smlaier 129130613Smlaier/* 130130613Smlaier * Locking notes: 131130613Smlaier * Whenever we really touch/look at the state table we have to hold the 132130613Smlaier * PF_LOCK. Functions that do just the interface handling, grab the per 133130613Smlaier * softc lock instead. 134130613Smlaier * 135130613Smlaier */ 136130613Smlaier 137128209Sbrooksstatic void pfsync_clone_destroy(struct ifnet *); 138128209Sbrooksstatic int pfsync_clone_create(struct if_clone *, int); 139147261Smlaierstatic void pfsync_senddef(void *); 140126261Smlaier#else 141126258Smlaiervoid pfsyncattach(int); 142126261Smlaier#endif 143130613Smlaiervoid pfsync_setmtu(struct pfsync_softc *, int); 144130613Smlaierint pfsync_insert_net_state(struct pfsync_state *); 145126258Smlaierint pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 146130613Smlaier struct rtentry *); 147126258Smlaierint pfsyncioctl(struct ifnet *, u_long, caddr_t); 148126258Smlaiervoid pfsyncstart(struct ifnet *); 149126258Smlaier 150130613Smlaierstruct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **); 151130613Smlaierint pfsync_request_update(struct pfsync_state_upd *, struct in_addr *); 152130613Smlaierint pfsync_sendout(struct pfsync_softc *); 153130613Smlaiervoid pfsync_timeout(void *); 154130613Smlaiervoid pfsync_send_bus(struct pfsync_softc *, u_int8_t); 155130613Smlaiervoid pfsync_bulk_update(void *); 156130613Smlaiervoid pfsync_bulkfail(void *); 157126258Smlaier 158145836Smlaierint pfsync_sync_ok; 159127145Smlaier#ifndef __FreeBSD__ 160126258Smlaierextern int ifqmaxlen; 161130613Smlaierextern struct timeval time; 162130613Smlaierextern struct timeval mono_time; 163130613Smlaierextern int hz; 164126261Smlaier#endif 165126258Smlaier 166127145Smlaier#ifdef __FreeBSD__ 167126261Smlaierstatic MALLOC_DEFINE(M_PFSYNC, PFSYNCNAME, "Packet Filter State Sync. Interface"); 168126261Smlaierstatic LIST_HEAD(pfsync_list, pfsync_softc) pfsync_list; 169147256Sbrooks#define SCP2IFP(sc) ((sc)->sc_ifp) 170130933SbrooksIFC_SIMPLE_DECLARE(pfsync, 1); 171126261Smlaier 172128209Sbrooksstatic void 173126261Smlaierpfsync_clone_destroy(struct ifnet *ifp) 174126261Smlaier{ 175126261Smlaier struct pfsync_softc *sc; 176126261Smlaier 177130613Smlaier sc = ifp->if_softc; 178126261Smlaier callout_stop(&sc->sc_tmo); 179130613Smlaier callout_stop(&sc->sc_bulk_tmo); 180130613Smlaier callout_stop(&sc->sc_bulkfail_tmo); 181126261Smlaier 182147261Smlaier callout_stop(&sc->sc_send_tmo); 183147261Smlaier 184126261Smlaier#if NBPFILTER > 0 185126261Smlaier bpfdetach(ifp); 186126261Smlaier#endif 187126261Smlaier if_detach(ifp); 188147256Sbrooks if_free(ifp); 189126261Smlaier LIST_REMOVE(sc, sc_next); 190126261Smlaier free(sc, M_PFSYNC); 191126261Smlaier} 192126261Smlaier 193128209Sbrooksstatic int 194126261Smlaierpfsync_clone_create(struct if_clone *ifc, int unit) 195126261Smlaier{ 196126261Smlaier struct pfsync_softc *sc; 197130613Smlaier struct ifnet *ifp; 198126261Smlaier 199126261Smlaier MALLOC(sc, struct pfsync_softc *, sizeof(*sc), M_PFSYNC, 200130613Smlaier M_WAITOK|M_ZERO); 201147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_PFSYNC); 202147256Sbrooks if (ifp == NULL) { 203147256Sbrooks free(sc, M_PFSYNC); 204147256Sbrooks return (ENOSPC); 205147256Sbrooks } 206126261Smlaier 207130613Smlaier pfsync_sync_ok = 1; 208130613Smlaier sc->sc_mbuf = NULL; 209130613Smlaier sc->sc_mbuf_net = NULL; 210130613Smlaier sc->sc_statep.s = NULL; 211130613Smlaier sc->sc_statep_net.s = NULL; 212130613Smlaier sc->sc_maxupdates = 128; 213130613Smlaier sc->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP); 214130613Smlaier sc->sc_ureq_received = 0; 215130613Smlaier sc->sc_ureq_sent = 0; 216130613Smlaier 217141584Smlaier ifp = SCP2IFP(sc); 218130613Smlaier if_initname(ifp, ifc->ifc_name, unit); 219130613Smlaier ifp->if_ioctl = pfsyncioctl; 220130613Smlaier ifp->if_output = pfsyncoutput; 221130613Smlaier ifp->if_start = pfsyncstart; 222130613Smlaier ifp->if_snd.ifq_maxlen = ifqmaxlen; 223130613Smlaier ifp->if_hdrlen = PFSYNC_HDRLEN; 224130613Smlaier ifp->if_baudrate = IF_Mbps(100); 225130613Smlaier ifp->if_softc = sc; 226126261Smlaier pfsync_setmtu(sc, MCLBYTES); 227147321Smlaier callout_init(&sc->sc_tmo, NET_CALLOUT_MPSAFE); 228147321Smlaier callout_init(&sc->sc_bulk_tmo, NET_CALLOUT_MPSAFE); 229147321Smlaier callout_init(&sc->sc_bulkfail_tmo, NET_CALLOUT_MPSAFE); 230147321Smlaier callout_init(&sc->sc_send_tmo, NET_CALLOUT_MPSAFE); 231147614Smlaier sc->sc_ifq.ifq_maxlen = ifqmaxlen; 232147261Smlaier mtx_init(&sc->sc_ifq.ifq_mtx, ifp->if_xname, "pfsync send queue", 233147261Smlaier MTX_DEF); 234141584Smlaier if_attach(ifp); 235126261Smlaier 236126261Smlaier LIST_INSERT_HEAD(&pfsync_list, sc, sc_next); 237126261Smlaier#if NBPFILTER > 0 238141584Smlaier bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 239126261Smlaier#endif 240126261Smlaier 241126261Smlaier return (0); 242126261Smlaier} 243126261Smlaier#else /* !__FreeBSD__ */ 244126261Smlaiervoid 245126258Smlaierpfsyncattach(int npfsync) 246126258Smlaier{ 247126258Smlaier struct ifnet *ifp; 248126258Smlaier 249130613Smlaier pfsync_sync_ok = 1; 250130613Smlaier bzero(&pfsyncif, sizeof(pfsyncif)); 251126258Smlaier pfsyncif.sc_mbuf = NULL; 252130613Smlaier pfsyncif.sc_mbuf_net = NULL; 253130613Smlaier pfsyncif.sc_statep.s = NULL; 254130613Smlaier pfsyncif.sc_statep_net.s = NULL; 255130613Smlaier pfsyncif.sc_maxupdates = 128; 256145836Smlaier pfsyncif.sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP; 257130613Smlaier pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP; 258130613Smlaier pfsyncif.sc_ureq_received = 0; 259130613Smlaier pfsyncif.sc_ureq_sent = 0; 260126258Smlaier ifp = &pfsyncif.sc_if; 261126258Smlaier strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname); 262126258Smlaier ifp->if_softc = &pfsyncif; 263126258Smlaier ifp->if_ioctl = pfsyncioctl; 264126258Smlaier ifp->if_output = pfsyncoutput; 265126258Smlaier ifp->if_start = pfsyncstart; 266126258Smlaier ifp->if_type = IFT_PFSYNC; 267126258Smlaier ifp->if_snd.ifq_maxlen = ifqmaxlen; 268126258Smlaier ifp->if_hdrlen = PFSYNC_HDRLEN; 269126258Smlaier pfsync_setmtu(&pfsyncif, MCLBYTES); 270126258Smlaier timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif); 271130613Smlaier timeout_set(&pfsyncif.sc_bulk_tmo, pfsync_bulk_update, &pfsyncif); 272130613Smlaier timeout_set(&pfsyncif.sc_bulkfail_tmo, pfsync_bulkfail, &pfsyncif); 273126258Smlaier if_attach(ifp); 274126258Smlaier if_alloc_sadl(ifp); 275126258Smlaier 276126258Smlaier#if NBPFILTER > 0 277126258Smlaier bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 278126258Smlaier#endif 279126258Smlaier} 280126261Smlaier#endif 281126258Smlaier 282126258Smlaier/* 283126258Smlaier * Start output on the pfsync interface. 284126258Smlaier */ 285126258Smlaiervoid 286126258Smlaierpfsyncstart(struct ifnet *ifp) 287126258Smlaier{ 288130613Smlaier#ifdef __FreeBSD__ 289130613Smlaier IF_LOCK(&ifp->if_snd); 290130613Smlaier _IF_DROP(&ifp->if_snd); 291130613Smlaier _IF_DRAIN(&ifp->if_snd); 292130613Smlaier IF_UNLOCK(&ifp->if_snd); 293130613Smlaier#else 294126258Smlaier struct mbuf *m; 295126258Smlaier int s; 296126258Smlaier 297126258Smlaier for (;;) { 298126258Smlaier s = splimp(); 299126258Smlaier IF_DROP(&ifp->if_snd); 300126258Smlaier IF_DEQUEUE(&ifp->if_snd, m); 301126258Smlaier splx(s); 302126258Smlaier 303126258Smlaier if (m == NULL) 304126258Smlaier return; 305126258Smlaier else 306126258Smlaier m_freem(m); 307126258Smlaier } 308130613Smlaier#endif 309126258Smlaier} 310126258Smlaier 311126258Smlaierint 312130613Smlaierpfsync_insert_net_state(struct pfsync_state *sp) 313130613Smlaier{ 314130613Smlaier struct pf_state *st = NULL; 315130613Smlaier struct pf_rule *r = NULL; 316130613Smlaier struct pfi_kif *kif; 317130613Smlaier 318130613Smlaier#ifdef __FreeBSD__ 319130613Smlaier PF_ASSERT(MA_OWNED); 320130613Smlaier#endif 321130613Smlaier if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) { 322130613Smlaier printf("pfsync_insert_net_state: invalid creator id:" 323130613Smlaier " %08x\n", ntohl(sp->creatorid)); 324130613Smlaier return (EINVAL); 325130613Smlaier } 326130613Smlaier 327130613Smlaier kif = pfi_lookup_create(sp->ifname); 328130613Smlaier if (kif == NULL) { 329130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 330130613Smlaier printf("pfsync_insert_net_state: " 331130613Smlaier "unknown interface: %s\n", sp->ifname); 332130613Smlaier /* skip this state */ 333130613Smlaier return (0); 334130613Smlaier } 335130613Smlaier 336130613Smlaier /* 337130613Smlaier * Just use the default rule until we have infrastructure to find the 338130613Smlaier * best matching rule. 339130613Smlaier */ 340130613Smlaier r = &pf_default_rule; 341130613Smlaier 342130613Smlaier if (!r->max_states || r->states < r->max_states) 343130613Smlaier st = pool_get(&pf_state_pl, PR_NOWAIT); 344130613Smlaier if (st == NULL) { 345130613Smlaier pfi_maybe_destroy(kif); 346130613Smlaier return (ENOMEM); 347130613Smlaier } 348130613Smlaier bzero(st, sizeof(*st)); 349130613Smlaier 350130613Smlaier st->rule.ptr = r; 351130613Smlaier /* XXX get pointers to nat_rule and anchor */ 352130613Smlaier 353145836Smlaier /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */ 354145836Smlaier r->states++; 355145836Smlaier 356130613Smlaier /* fill in the rest of the state entry */ 357130613Smlaier pf_state_host_ntoh(&sp->lan, &st->lan); 358130613Smlaier pf_state_host_ntoh(&sp->gwy, &st->gwy); 359130613Smlaier pf_state_host_ntoh(&sp->ext, &st->ext); 360130613Smlaier 361130613Smlaier pf_state_peer_ntoh(&sp->src, &st->src); 362130613Smlaier pf_state_peer_ntoh(&sp->dst, &st->dst); 363130613Smlaier 364130613Smlaier bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr)); 365145836Smlaier st->creation = time_second - ntohl(sp->creation); 366130613Smlaier st->expire = ntohl(sp->expire) + time_second; 367130613Smlaier 368130613Smlaier st->af = sp->af; 369130613Smlaier st->proto = sp->proto; 370130613Smlaier st->direction = sp->direction; 371130613Smlaier st->log = sp->log; 372130613Smlaier st->timeout = sp->timeout; 373130613Smlaier st->allow_opts = sp->allow_opts; 374130613Smlaier 375130613Smlaier bcopy(sp->id, &st->id, sizeof(st->id)); 376130613Smlaier st->creatorid = sp->creatorid; 377145836Smlaier st->sync_flags = PFSTATE_FROMSYNC; 378130613Smlaier 379130613Smlaier 380130613Smlaier if (pf_insert_state(kif, st)) { 381130613Smlaier pfi_maybe_destroy(kif); 382145836Smlaier /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */ 383145836Smlaier r->states--; 384130613Smlaier pool_put(&pf_state_pl, st); 385130613Smlaier return (EINVAL); 386130613Smlaier } 387130613Smlaier 388130613Smlaier return (0); 389130613Smlaier} 390130613Smlaier 391130613Smlaiervoid 392130613Smlaier#ifdef __FreeBSD__ 393130613Smlaierpfsync_input(struct mbuf *m, __unused int off) 394130613Smlaier#else 395130613Smlaierpfsync_input(struct mbuf *m, ...) 396130613Smlaier#endif 397130613Smlaier{ 398130613Smlaier struct ip *ip = mtod(m, struct ip *); 399130613Smlaier struct pfsync_header *ph; 400130613Smlaier#ifdef __FreeBSD__ 401130613Smlaier struct pfsync_softc *sc = LIST_FIRST(&pfsync_list); 402130613Smlaier#else 403130613Smlaier struct pfsync_softc *sc = &pfsyncif; 404130613Smlaier#endif 405130613Smlaier struct pf_state *st, key; 406130613Smlaier struct pfsync_state *sp; 407130613Smlaier struct pfsync_state_upd *up; 408130613Smlaier struct pfsync_state_del *dp; 409130613Smlaier struct pfsync_state_clr *cp; 410130613Smlaier struct pfsync_state_upd_req *rup; 411130613Smlaier struct pfsync_state_bus *bus; 412130613Smlaier struct in_addr src; 413130613Smlaier struct mbuf *mp; 414145836Smlaier int iplen, action, error, i, s, count, offp, sfail, stale = 0; 415130613Smlaier 416130613Smlaier pfsyncstats.pfsyncs_ipackets++; 417130613Smlaier 418130613Smlaier /* verify that we have a sync interface configured */ 419130613Smlaier if (!sc->sc_sync_ifp || !pf_status.running) /* XXX PF_LOCK? */ 420130613Smlaier goto done; 421130613Smlaier 422130613Smlaier /* verify that the packet came in on the right interface */ 423130613Smlaier if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) { 424130613Smlaier pfsyncstats.pfsyncs_badif++; 425130613Smlaier goto done; 426130613Smlaier } 427130613Smlaier 428130613Smlaier /* verify that the IP TTL is 255. */ 429130613Smlaier if (ip->ip_ttl != PFSYNC_DFLTTL) { 430130613Smlaier pfsyncstats.pfsyncs_badttl++; 431130613Smlaier goto done; 432130613Smlaier } 433130613Smlaier 434130613Smlaier iplen = ip->ip_hl << 2; 435130613Smlaier 436130613Smlaier if (m->m_pkthdr.len < iplen + sizeof(*ph)) { 437130613Smlaier pfsyncstats.pfsyncs_hdrops++; 438130613Smlaier goto done; 439130613Smlaier } 440130613Smlaier 441130613Smlaier if (iplen + sizeof(*ph) > m->m_len) { 442130613Smlaier if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) { 443130613Smlaier pfsyncstats.pfsyncs_hdrops++; 444130613Smlaier goto done; 445130613Smlaier } 446130613Smlaier ip = mtod(m, struct ip *); 447130613Smlaier } 448130613Smlaier ph = (struct pfsync_header *)((char *)ip + iplen); 449130613Smlaier 450130613Smlaier /* verify the version */ 451130613Smlaier if (ph->version != PFSYNC_VERSION) { 452130613Smlaier pfsyncstats.pfsyncs_badver++; 453130613Smlaier goto done; 454130613Smlaier } 455130613Smlaier 456130613Smlaier action = ph->action; 457130613Smlaier count = ph->count; 458130613Smlaier 459130613Smlaier /* make sure it's a valid action code */ 460130613Smlaier if (action >= PFSYNC_ACT_MAX) { 461130613Smlaier pfsyncstats.pfsyncs_badact++; 462130613Smlaier goto done; 463130613Smlaier } 464130613Smlaier 465130613Smlaier /* Cheaper to grab this now than having to mess with mbufs later */ 466130613Smlaier src = ip->ip_src; 467130613Smlaier 468130613Smlaier switch (action) { 469130613Smlaier case PFSYNC_ACT_CLR: { 470145836Smlaier struct pf_state *nexts; 471130613Smlaier struct pfi_kif *kif; 472130613Smlaier u_int32_t creatorid; 473130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 474130613Smlaier sizeof(*cp), &offp)) == NULL) { 475130613Smlaier pfsyncstats.pfsyncs_badlen++; 476130613Smlaier return; 477130613Smlaier } 478130613Smlaier cp = (struct pfsync_state_clr *)(mp->m_data + offp); 479130613Smlaier creatorid = cp->creatorid; 480130613Smlaier 481130613Smlaier s = splsoftnet(); 482130613Smlaier#ifdef __FreeBSD__ 483130613Smlaier PF_LOCK(); 484130613Smlaier#endif 485130613Smlaier if (cp->ifname[0] == '\0') { 486145836Smlaier for (st = RB_MIN(pf_state_tree_id, &tree_id); 487145836Smlaier st; st = nexts) { 488145836Smlaier nexts = RB_NEXT(pf_state_tree_id, &tree_id, st); 489145836Smlaier if (st->creatorid == creatorid) { 490130613Smlaier st->timeout = PFTM_PURGE; 491145836Smlaier pf_purge_expired_state(st); 492145836Smlaier } 493130613Smlaier } 494130613Smlaier } else { 495130613Smlaier kif = pfi_lookup_if(cp->ifname); 496130613Smlaier if (kif == NULL) { 497130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 498130613Smlaier printf("pfsync_input: PFSYNC_ACT_CLR " 499130613Smlaier "bad interface: %s\n", cp->ifname); 500130613Smlaier splx(s); 501130613Smlaier#ifdef __FreeBSD__ 502130613Smlaier PF_UNLOCK(); 503130613Smlaier#endif 504130613Smlaier goto done; 505130613Smlaier } 506145836Smlaier for (st = RB_MIN(pf_state_tree_lan_ext, 507145836Smlaier &kif->pfik_lan_ext); st; st = nexts) { 508145836Smlaier nexts = RB_NEXT(pf_state_tree_lan_ext, 509145836Smlaier &kif->pfik_lan_ext, st); 510145836Smlaier if (st->creatorid == creatorid) { 511130613Smlaier st->timeout = PFTM_PURGE; 512145836Smlaier pf_purge_expired_state(st); 513145836Smlaier } 514130613Smlaier } 515130613Smlaier } 516130613Smlaier#ifdef __FreeBSD__ 517130613Smlaier PF_UNLOCK(); 518130613Smlaier#endif 519130613Smlaier splx(s); 520130613Smlaier 521130613Smlaier break; 522130613Smlaier } 523130613Smlaier case PFSYNC_ACT_INS: 524130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 525130613Smlaier count * sizeof(*sp), &offp)) == NULL) { 526130613Smlaier pfsyncstats.pfsyncs_badlen++; 527130613Smlaier return; 528130613Smlaier } 529130613Smlaier 530130613Smlaier s = splsoftnet(); 531130613Smlaier#ifdef __FreeBSD__ 532130613Smlaier PF_LOCK(); 533130613Smlaier#endif 534130613Smlaier for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 535130613Smlaier i < count; i++, sp++) { 536130613Smlaier /* check for invalid values */ 537130613Smlaier if (sp->timeout >= PFTM_MAX || 538130613Smlaier sp->src.state > PF_TCPS_PROXY_DST || 539130613Smlaier sp->dst.state > PF_TCPS_PROXY_DST || 540130613Smlaier sp->direction > PF_OUT || 541130613Smlaier (sp->af != AF_INET && sp->af != AF_INET6)) { 542130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 543130613Smlaier printf("pfsync_insert: PFSYNC_ACT_INS: " 544130613Smlaier "invalid value\n"); 545130613Smlaier pfsyncstats.pfsyncs_badstate++; 546130613Smlaier continue; 547130613Smlaier } 548130613Smlaier 549130613Smlaier if ((error = pfsync_insert_net_state(sp))) { 550130613Smlaier if (error == ENOMEM) { 551130613Smlaier splx(s); 552130613Smlaier#ifdef __FreeBSD__ 553130613Smlaier PF_UNLOCK(); 554130613Smlaier#endif 555130613Smlaier goto done; 556130613Smlaier } 557130613Smlaier continue; 558130613Smlaier } 559130613Smlaier } 560130613Smlaier#ifdef __FreeBSD__ 561130613Smlaier PF_UNLOCK(); 562130613Smlaier#endif 563130613Smlaier splx(s); 564130613Smlaier break; 565130613Smlaier case PFSYNC_ACT_UPD: 566130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 567130613Smlaier count * sizeof(*sp), &offp)) == NULL) { 568130613Smlaier pfsyncstats.pfsyncs_badlen++; 569130613Smlaier return; 570130613Smlaier } 571130613Smlaier 572130613Smlaier s = splsoftnet(); 573130613Smlaier#ifdef __FreeBSD__ 574130613Smlaier PF_LOCK(); 575130613Smlaier#endif 576130613Smlaier for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 577130613Smlaier i < count; i++, sp++) { 578145836Smlaier int flags = PFSYNC_FLAG_STALE; 579145836Smlaier 580130613Smlaier /* check for invalid values */ 581130613Smlaier if (sp->timeout >= PFTM_MAX || 582130613Smlaier sp->src.state > PF_TCPS_PROXY_DST || 583130613Smlaier sp->dst.state > PF_TCPS_PROXY_DST) { 584130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 585130613Smlaier printf("pfsync_insert: PFSYNC_ACT_UPD: " 586130613Smlaier "invalid value\n"); 587130613Smlaier pfsyncstats.pfsyncs_badstate++; 588130613Smlaier continue; 589130613Smlaier } 590130613Smlaier 591130613Smlaier bcopy(sp->id, &key.id, sizeof(key.id)); 592130613Smlaier key.creatorid = sp->creatorid; 593130613Smlaier 594130613Smlaier st = pf_find_state_byid(&key); 595130613Smlaier if (st == NULL) { 596130613Smlaier /* insert the update */ 597130613Smlaier if (pfsync_insert_net_state(sp)) 598130613Smlaier pfsyncstats.pfsyncs_badstate++; 599130613Smlaier continue; 600130613Smlaier } 601145836Smlaier sfail = 0; 602145836Smlaier if (st->proto == IPPROTO_TCP) { 603145836Smlaier /* 604145836Smlaier * The state should never go backwards except 605145836Smlaier * for syn-proxy states. Neither should the 606145836Smlaier * sequence window slide backwards. 607145836Smlaier */ 608145836Smlaier if (st->src.state > sp->src.state && 609145836Smlaier (st->src.state < PF_TCPS_PROXY_SRC || 610145836Smlaier sp->src.state >= PF_TCPS_PROXY_SRC)) 611145836Smlaier sfail = 1; 612145836Smlaier else if (SEQ_GT(st->src.seqlo, 613145836Smlaier ntohl(sp->src.seqlo))) 614145836Smlaier sfail = 3; 615145836Smlaier else if (st->dst.state > sp->dst.state) { 616145836Smlaier /* There might still be useful 617145836Smlaier * information about the src state here, 618145836Smlaier * so import that part of the update, 619145836Smlaier * then "fail" so we send the updated 620145836Smlaier * state back to the peer who is missing 621145836Smlaier * our what we know. */ 622145836Smlaier pf_state_peer_ntoh(&sp->src, &st->src); 623145836Smlaier /* XXX do anything with timeouts? */ 624145836Smlaier sfail = 7; 625145836Smlaier flags = 0; 626145836Smlaier } else if (st->dst.state >= TCPS_SYN_SENT && 627145836Smlaier SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo))) 628145836Smlaier sfail = 4; 629145836Smlaier } else { 630145836Smlaier /* 631145836Smlaier * Non-TCP protocol state machine always go 632145836Smlaier * forwards 633145836Smlaier */ 634145836Smlaier if (st->src.state > sp->src.state) 635145836Smlaier sfail = 5; 636145836Smlaier else if ( st->dst.state > sp->dst.state) 637145836Smlaier sfail = 6; 638145836Smlaier } 639145836Smlaier if (sfail) { 640145836Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 641145836Smlaier printf("pfsync: %s stale update " 642145836Smlaier "(%d) id: %016llx " 643145836Smlaier "creatorid: %08x\n", 644145836Smlaier (sfail < 7 ? "ignoring" 645145836Smlaier : "partial"), sfail, 646145836Smlaier#ifdef __FreeBSD__ 647145836Smlaier (unsigned long long)be64toh(st->id), 648145836Smlaier#else 649145836Smlaier betoh64(st->id), 650145836Smlaier#endif 651145836Smlaier ntohl(st->creatorid)); 652145836Smlaier pfsyncstats.pfsyncs_badstate++; 653145836Smlaier 654145836Smlaier if (!(sp->sync_flags & PFSTATE_STALE)) { 655145836Smlaier /* we have a better state, send it */ 656145836Smlaier if (sc->sc_mbuf != NULL && !stale) 657145836Smlaier pfsync_sendout(sc); 658145836Smlaier stale++; 659145836Smlaier if (!st->sync_flags) 660145836Smlaier pfsync_pack_state( 661145836Smlaier PFSYNC_ACT_UPD, st, flags); 662145836Smlaier } 663145836Smlaier continue; 664145836Smlaier } 665130613Smlaier pf_state_peer_ntoh(&sp->src, &st->src); 666130613Smlaier pf_state_peer_ntoh(&sp->dst, &st->dst); 667130613Smlaier st->expire = ntohl(sp->expire) + time_second; 668130613Smlaier st->timeout = sp->timeout; 669130613Smlaier } 670145836Smlaier if (stale && sc->sc_mbuf != NULL) 671145836Smlaier pfsync_sendout(sc); 672130613Smlaier#ifdef __FreeBSD__ 673130613Smlaier PF_UNLOCK(); 674130613Smlaier#endif 675130613Smlaier splx(s); 676130613Smlaier break; 677130613Smlaier /* 678130613Smlaier * It's not strictly necessary for us to support the "uncompressed" 679130613Smlaier * delete action, but it's relatively simple and maintains consistency. 680130613Smlaier */ 681130613Smlaier case PFSYNC_ACT_DEL: 682130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 683130613Smlaier count * sizeof(*sp), &offp)) == NULL) { 684130613Smlaier pfsyncstats.pfsyncs_badlen++; 685130613Smlaier return; 686130613Smlaier } 687130613Smlaier 688130613Smlaier s = splsoftnet(); 689130613Smlaier#ifdef __FreeBSD__ 690130613Smlaier PF_LOCK(); 691130613Smlaier#endif 692130613Smlaier for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 693130613Smlaier i < count; i++, sp++) { 694130613Smlaier bcopy(sp->id, &key.id, sizeof(key.id)); 695130613Smlaier key.creatorid = sp->creatorid; 696130613Smlaier 697130613Smlaier st = pf_find_state_byid(&key); 698130613Smlaier if (st == NULL) { 699130613Smlaier pfsyncstats.pfsyncs_badstate++; 700130613Smlaier continue; 701130613Smlaier } 702130613Smlaier st->timeout = PFTM_PURGE; 703130613Smlaier st->sync_flags |= PFSTATE_FROMSYNC; 704145836Smlaier pf_purge_expired_state(st); 705130613Smlaier } 706130613Smlaier#ifdef __FreeBSD__ 707130613Smlaier PF_UNLOCK(); 708130613Smlaier#endif 709130613Smlaier splx(s); 710130613Smlaier break; 711130613Smlaier case PFSYNC_ACT_UPD_C: { 712130613Smlaier int update_requested = 0; 713130613Smlaier 714130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 715130613Smlaier count * sizeof(*up), &offp)) == NULL) { 716130613Smlaier pfsyncstats.pfsyncs_badlen++; 717130613Smlaier return; 718130613Smlaier } 719130613Smlaier 720130613Smlaier s = splsoftnet(); 721130613Smlaier#ifdef __FreeBSD__ 722130613Smlaier PF_LOCK(); 723130613Smlaier#endif 724130613Smlaier for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp); 725130613Smlaier i < count; i++, up++) { 726130613Smlaier /* check for invalid values */ 727130613Smlaier if (up->timeout >= PFTM_MAX || 728130613Smlaier up->src.state > PF_TCPS_PROXY_DST || 729130613Smlaier up->dst.state > PF_TCPS_PROXY_DST) { 730130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 731130613Smlaier printf("pfsync_insert: " 732130613Smlaier "PFSYNC_ACT_UPD_C: " 733130613Smlaier "invalid value\n"); 734130613Smlaier pfsyncstats.pfsyncs_badstate++; 735130613Smlaier continue; 736130613Smlaier } 737130613Smlaier 738130613Smlaier bcopy(up->id, &key.id, sizeof(key.id)); 739130613Smlaier key.creatorid = up->creatorid; 740130613Smlaier 741130613Smlaier st = pf_find_state_byid(&key); 742130613Smlaier if (st == NULL) { 743130613Smlaier /* We don't have this state. Ask for it. */ 744145836Smlaier error = pfsync_request_update(up, &src); 745145836Smlaier if (error == ENOMEM) { 746145836Smlaier splx(s); 747145836Smlaier goto done; 748145836Smlaier } 749130613Smlaier update_requested = 1; 750130613Smlaier pfsyncstats.pfsyncs_badstate++; 751130613Smlaier continue; 752130613Smlaier } 753145836Smlaier sfail = 0; 754145836Smlaier if (st->proto == IPPROTO_TCP) { 755145836Smlaier /* 756145836Smlaier * The state should never go backwards except 757145836Smlaier * for syn-proxy states. Neither should the 758145836Smlaier * sequence window slide backwards. 759145836Smlaier */ 760145836Smlaier if (st->src.state > up->src.state && 761145836Smlaier (st->src.state < PF_TCPS_PROXY_SRC || 762145836Smlaier up->src.state >= PF_TCPS_PROXY_SRC)) 763145836Smlaier sfail = 1; 764145836Smlaier else if (st->dst.state > up->dst.state) 765145836Smlaier sfail = 2; 766145836Smlaier else if (SEQ_GT(st->src.seqlo, 767145836Smlaier ntohl(up->src.seqlo))) 768145836Smlaier sfail = 3; 769145836Smlaier else if (st->dst.state >= TCPS_SYN_SENT && 770145836Smlaier SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo))) 771145836Smlaier sfail = 4; 772145836Smlaier } else { 773145836Smlaier /* 774145836Smlaier * Non-TCP protocol state machine always go 775145836Smlaier * forwards 776145836Smlaier */ 777145836Smlaier if (st->src.state > up->src.state) 778145836Smlaier sfail = 5; 779145836Smlaier else if (st->dst.state > up->dst.state) 780145836Smlaier sfail = 6; 781145836Smlaier } 782145836Smlaier if (sfail) { 783145836Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 784145836Smlaier printf("pfsync: ignoring stale update " 785145836Smlaier "(%d) id: %016llx " 786145836Smlaier "creatorid: %08x\n", sfail, 787145836Smlaier#ifdef __FreeBSD__ 788145836Smlaier (unsigned long long)be64toh(st->id), 789145836Smlaier#else 790145836Smlaier betoh64(st->id), 791145836Smlaier#endif 792145836Smlaier ntohl(st->creatorid)); 793145836Smlaier pfsyncstats.pfsyncs_badstate++; 794145836Smlaier 795145836Smlaier /* we have a better state, send it out */ 796145836Smlaier if ((!stale || update_requested) && 797145836Smlaier sc->sc_mbuf != NULL) { 798145836Smlaier pfsync_sendout(sc); 799145836Smlaier update_requested = 0; 800145836Smlaier } 801145836Smlaier stale++; 802145836Smlaier if (!st->sync_flags) 803145836Smlaier pfsync_pack_state(PFSYNC_ACT_UPD, st, 804145836Smlaier PFSYNC_FLAG_STALE); 805145836Smlaier continue; 806145836Smlaier } 807130613Smlaier pf_state_peer_ntoh(&up->src, &st->src); 808130613Smlaier pf_state_peer_ntoh(&up->dst, &st->dst); 809130613Smlaier st->expire = ntohl(up->expire) + time_second; 810130613Smlaier st->timeout = up->timeout; 811130613Smlaier } 812145836Smlaier if ((update_requested || stale) && sc->sc_mbuf) 813130613Smlaier pfsync_sendout(sc); 814130613Smlaier#ifdef __FreeBSD__ 815130613Smlaier PF_UNLOCK(); 816130613Smlaier#endif 817130613Smlaier splx(s); 818130613Smlaier break; 819130613Smlaier } 820130613Smlaier case PFSYNC_ACT_DEL_C: 821130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 822130613Smlaier count * sizeof(*dp), &offp)) == NULL) { 823130613Smlaier pfsyncstats.pfsyncs_badlen++; 824130613Smlaier return; 825130613Smlaier } 826130613Smlaier 827130613Smlaier s = splsoftnet(); 828130613Smlaier#ifdef __FreeBSD__ 829130613Smlaier PF_LOCK(); 830130613Smlaier#endif 831130613Smlaier for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp); 832130613Smlaier i < count; i++, dp++) { 833130613Smlaier bcopy(dp->id, &key.id, sizeof(key.id)); 834130613Smlaier key.creatorid = dp->creatorid; 835130613Smlaier 836130613Smlaier st = pf_find_state_byid(&key); 837130613Smlaier if (st == NULL) { 838130613Smlaier pfsyncstats.pfsyncs_badstate++; 839130613Smlaier continue; 840130613Smlaier } 841130613Smlaier st->timeout = PFTM_PURGE; 842130613Smlaier st->sync_flags |= PFSTATE_FROMSYNC; 843145836Smlaier pf_purge_expired_state(st); 844130613Smlaier } 845130613Smlaier#ifdef __FreeBSD__ 846130613Smlaier PF_UNLOCK(); 847130613Smlaier#endif 848130613Smlaier splx(s); 849130613Smlaier break; 850130613Smlaier case PFSYNC_ACT_INS_F: 851130613Smlaier case PFSYNC_ACT_DEL_F: 852130613Smlaier /* not implemented */ 853130613Smlaier break; 854130613Smlaier case PFSYNC_ACT_UREQ: 855130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 856130613Smlaier count * sizeof(*rup), &offp)) == NULL) { 857130613Smlaier pfsyncstats.pfsyncs_badlen++; 858130613Smlaier return; 859130613Smlaier } 860130613Smlaier 861130613Smlaier s = splsoftnet(); 862130613Smlaier#ifdef __FreeBSD__ 863130613Smlaier PF_LOCK(); 864130613Smlaier#endif 865130613Smlaier if (sc->sc_mbuf != NULL) 866130613Smlaier pfsync_sendout(sc); 867130613Smlaier for (i = 0, 868130613Smlaier rup = (struct pfsync_state_upd_req *)(mp->m_data + offp); 869130613Smlaier i < count; i++, rup++) { 870130613Smlaier bcopy(rup->id, &key.id, sizeof(key.id)); 871130613Smlaier key.creatorid = rup->creatorid; 872130613Smlaier 873130613Smlaier if (key.id == 0 && key.creatorid == 0) { 874130613Smlaier sc->sc_ureq_received = time_uptime; 875130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 876130613Smlaier printf("pfsync: received " 877130613Smlaier "bulk update request\n"); 878130613Smlaier pfsync_send_bus(sc, PFSYNC_BUS_START); 879130613Smlaier#ifdef __FreeBSD__ 880130613Smlaier callout_reset(&sc->sc_bulk_tmo, 1 * hz, 881130613Smlaier pfsync_bulk_update, 882130613Smlaier LIST_FIRST(&pfsync_list)); 883130613Smlaier#else 884130613Smlaier timeout_add(&sc->sc_bulk_tmo, 1 * hz); 885130613Smlaier#endif 886130613Smlaier } else { 887130613Smlaier st = pf_find_state_byid(&key); 888130613Smlaier if (st == NULL) { 889130613Smlaier pfsyncstats.pfsyncs_badstate++; 890130613Smlaier continue; 891130613Smlaier } 892145836Smlaier if (!st->sync_flags) 893145836Smlaier pfsync_pack_state(PFSYNC_ACT_UPD, 894145836Smlaier st, 0); 895130613Smlaier } 896130613Smlaier } 897130613Smlaier if (sc->sc_mbuf != NULL) 898130613Smlaier pfsync_sendout(sc); 899130613Smlaier#ifdef __FreeBSD__ 900130613Smlaier PF_UNLOCK(); 901130613Smlaier#endif 902130613Smlaier splx(s); 903130613Smlaier break; 904130613Smlaier case PFSYNC_ACT_BUS: 905130613Smlaier /* If we're not waiting for a bulk update, who cares. */ 906130613Smlaier if (sc->sc_ureq_sent == 0) 907130613Smlaier break; 908130613Smlaier 909130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 910130613Smlaier sizeof(*bus), &offp)) == NULL) { 911130613Smlaier pfsyncstats.pfsyncs_badlen++; 912130613Smlaier return; 913130613Smlaier } 914130613Smlaier bus = (struct pfsync_state_bus *)(mp->m_data + offp); 915130613Smlaier switch (bus->status) { 916130613Smlaier case PFSYNC_BUS_START: 917130613Smlaier#ifdef __FreeBSD__ 918130613Smlaier callout_reset(&sc->sc_bulkfail_tmo, 919130613Smlaier pf_pool_limits[PF_LIMIT_STATES].limit / 920130613Smlaier (PFSYNC_BULKPACKETS * sc->sc_maxcount), 921130613Smlaier pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 922130613Smlaier#else 923130613Smlaier timeout_add(&sc->sc_bulkfail_tmo, 924130613Smlaier pf_pool_limits[PF_LIMIT_STATES].limit / 925130613Smlaier (PFSYNC_BULKPACKETS * sc->sc_maxcount)); 926130613Smlaier#endif 927130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 928130613Smlaier printf("pfsync: received bulk " 929130613Smlaier "update start\n"); 930130613Smlaier break; 931130613Smlaier case PFSYNC_BUS_END: 932130613Smlaier if (time_uptime - ntohl(bus->endtime) >= 933130613Smlaier sc->sc_ureq_sent) { 934130613Smlaier /* that's it, we're happy */ 935130613Smlaier sc->sc_ureq_sent = 0; 936130613Smlaier sc->sc_bulk_tries = 0; 937130613Smlaier#ifdef __FreeBSD__ 938130613Smlaier callout_stop(&sc->sc_bulkfail_tmo); 939130613Smlaier#else 940130613Smlaier timeout_del(&sc->sc_bulkfail_tmo); 941130613Smlaier#endif 942145836Smlaier#if NCARP > 0 /* XXX_IMPORT */ 943145836Smlaier if (!pfsync_sync_ok) 944145836Smlaier carp_suppress_preempt--; 945145836Smlaier#endif 946130613Smlaier pfsync_sync_ok = 1; 947130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 948130613Smlaier printf("pfsync: received valid " 949130613Smlaier "bulk update end\n"); 950130613Smlaier } else { 951130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 952130613Smlaier printf("pfsync: received invalid " 953130613Smlaier "bulk update end: bad timestamp\n"); 954130613Smlaier } 955130613Smlaier break; 956130613Smlaier } 957130613Smlaier break; 958130613Smlaier } 959130613Smlaier 960130613Smlaierdone: 961130613Smlaier if (m) 962130613Smlaier m_freem(m); 963130613Smlaier} 964130613Smlaier 965130613Smlaierint 966126258Smlaierpfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 967126258Smlaier struct rtentry *rt) 968126258Smlaier{ 969126258Smlaier m_freem(m); 970126258Smlaier return (0); 971126258Smlaier} 972126258Smlaier 973126258Smlaier/* ARGSUSED */ 974126258Smlaierint 975126258Smlaierpfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 976126258Smlaier{ 977130613Smlaier#ifndef __FreeBSD__ 978130613Smlaier struct proc *p = curproc; 979130613Smlaier#endif 980126258Smlaier struct pfsync_softc *sc = ifp->if_softc; 981126258Smlaier struct ifreq *ifr = (struct ifreq *)data; 982130613Smlaier struct ip_moptions *imo = &sc->sc_imo; 983130613Smlaier struct pfsyncreq pfsyncr; 984130613Smlaier struct ifnet *sifp; 985130613Smlaier int s, error; 986126258Smlaier 987126258Smlaier switch (cmd) { 988126258Smlaier case SIOCSIFADDR: 989126258Smlaier case SIOCAIFADDR: 990126258Smlaier case SIOCSIFDSTADDR: 991126258Smlaier case SIOCSIFFLAGS: 992126258Smlaier if (ifp->if_flags & IFF_UP) 993126258Smlaier ifp->if_flags |= IFF_RUNNING; 994126258Smlaier else 995126258Smlaier ifp->if_flags &= ~IFF_RUNNING; 996126258Smlaier break; 997126258Smlaier case SIOCSIFMTU: 998126258Smlaier if (ifr->ifr_mtu < PFSYNC_MINMTU) 999126258Smlaier return (EINVAL); 1000126258Smlaier if (ifr->ifr_mtu > MCLBYTES) 1001126258Smlaier ifr->ifr_mtu = MCLBYTES; 1002126258Smlaier s = splnet(); 1003130613Smlaier#ifdef __FreeBSD__ 1004130613Smlaier PF_LOCK(); 1005130613Smlaier#endif 1006130613Smlaier if (ifr->ifr_mtu < ifp->if_mtu) { 1007126258Smlaier pfsync_sendout(sc); 1008130613Smlaier } 1009126258Smlaier pfsync_setmtu(sc, ifr->ifr_mtu); 1010130613Smlaier#ifdef __FreeBSD__ 1011130613Smlaier PF_UNLOCK(); 1012130613Smlaier#endif 1013126258Smlaier splx(s); 1014126258Smlaier break; 1015130613Smlaier case SIOCGETPFSYNC: 1016130613Smlaier#ifdef __FreeBSD__ 1017130613Smlaier /* XXX: read unlocked */ 1018130613Smlaier#endif 1019130613Smlaier bzero(&pfsyncr, sizeof(pfsyncr)); 1020130613Smlaier if (sc->sc_sync_ifp) 1021145836Smlaier strlcpy(pfsyncr.pfsyncr_syncdev, 1022130613Smlaier sc->sc_sync_ifp->if_xname, IFNAMSIZ); 1023145836Smlaier pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer; 1024130613Smlaier pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates; 1025130613Smlaier if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr)))) 1026130613Smlaier return (error); 1027130613Smlaier break; 1028130613Smlaier case SIOCSETPFSYNC: 1029130613Smlaier#ifdef __FreeBSD__ 1030130613Smlaier if ((error = suser(curthread)) != 0) 1031130613Smlaier#else 1032130613Smlaier if ((error = suser(p, p->p_acflag)) != 0) 1033130613Smlaier#endif 1034130613Smlaier return (error); 1035130613Smlaier if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr)))) 1036130613Smlaier return (error); 1037130613Smlaier 1038145836Smlaier if (pfsyncr.pfsyncr_syncpeer.s_addr == 0) 1039145836Smlaier sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP; 1040145836Smlaier else 1041145836Smlaier sc->sc_sync_peer.s_addr = 1042145836Smlaier pfsyncr.pfsyncr_syncpeer.s_addr; 1043145836Smlaier 1044130613Smlaier if (pfsyncr.pfsyncr_maxupdates > 255) 1045130613Smlaier return (EINVAL); 1046130613Smlaier#ifdef __FreeBSD__ 1047147261Smlaier callout_drain(&sc->sc_send_tmo); 1048130613Smlaier PF_LOCK(); 1049130613Smlaier#endif 1050130613Smlaier sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; 1051130613Smlaier 1052145836Smlaier if (pfsyncr.pfsyncr_syncdev[0] == 0) { 1053130613Smlaier sc->sc_sync_ifp = NULL; 1054130613Smlaier if (sc->sc_mbuf_net != NULL) { 1055130613Smlaier /* Don't keep stale pfsync packets around. */ 1056130613Smlaier s = splnet(); 1057130613Smlaier m_freem(sc->sc_mbuf_net); 1058130613Smlaier sc->sc_mbuf_net = NULL; 1059130613Smlaier sc->sc_statep_net.s = NULL; 1060130613Smlaier splx(s); 1061130613Smlaier } 1062145836Smlaier if (imo->imo_num_memberships > 0) { 1063145836Smlaier in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1064145836Smlaier imo->imo_multicast_ifp = NULL; 1065145836Smlaier } 1066130613Smlaier#ifdef __FreeBSD__ 1067130613Smlaier PF_UNLOCK(); 1068130613Smlaier#endif 1069130613Smlaier break; 1070130613Smlaier } 1071145836Smlaier 1072145836Smlaier if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) { 1073130613Smlaier#ifdef __FreeBSD__ 1074130613Smlaier PF_UNLOCK(); 1075130613Smlaier#endif 1076130613Smlaier return (EINVAL); 1077130613Smlaier } 1078130613Smlaier 1079130613Smlaier s = splnet(); 1080141584Smlaier#ifdef __FreeBSD__ 1081141584Smlaier if (sifp->if_mtu < SCP2IFP(sc)->if_mtu || 1082141584Smlaier#else 1083130613Smlaier if (sifp->if_mtu < sc->sc_if.if_mtu || 1084141584Smlaier#endif 1085130613Smlaier (sc->sc_sync_ifp != NULL && 1086130613Smlaier sifp->if_mtu < sc->sc_sync_ifp->if_mtu) || 1087130613Smlaier sifp->if_mtu < MCLBYTES - sizeof(struct ip)) 1088130613Smlaier pfsync_sendout(sc); 1089130613Smlaier sc->sc_sync_ifp = sifp; 1090130613Smlaier 1091141584Smlaier#ifdef __FreeBSD__ 1092141584Smlaier pfsync_setmtu(sc, SCP2IFP(sc)->if_mtu); 1093141584Smlaier#else 1094130613Smlaier pfsync_setmtu(sc, sc->sc_if.if_mtu); 1095141584Smlaier#endif 1096130613Smlaier 1097130613Smlaier if (imo->imo_num_memberships > 0) { 1098130613Smlaier in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1099130613Smlaier imo->imo_multicast_ifp = NULL; 1100130613Smlaier } 1101130613Smlaier 1102145836Smlaier if (sc->sc_sync_ifp && 1103145836Smlaier sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) { 1104130613Smlaier struct in_addr addr; 1105130613Smlaier 1106145836Smlaier if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) { 1107145836Smlaier sc->sc_sync_ifp = NULL; 1108130613Smlaier#ifdef __FreeBSD__ 1109145836Smlaier PF_UNLOCK(); 1110145836Smlaier#endif 1111145836Smlaier splx(s); 1112145836Smlaier return (EADDRNOTAVAIL); 1113145836Smlaier } 1114145836Smlaier#ifdef __FreeBSD__ 1115130613Smlaier PF_UNLOCK(); /* addmulti mallocs w/ WAITOK */ 1116130613Smlaier addr.s_addr = htonl(INADDR_PFSYNC_GROUP); 1117130613Smlaier#else 1118130613Smlaier addr.s_addr = INADDR_PFSYNC_GROUP; 1119130613Smlaier#endif 1120145836Smlaier 1121130613Smlaier if ((imo->imo_membership[0] = 1122130613Smlaier in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) { 1123145836Smlaier sc->sc_sync_ifp = NULL; 1124130613Smlaier splx(s); 1125130613Smlaier return (ENOBUFS); 1126130613Smlaier } 1127130613Smlaier imo->imo_num_memberships++; 1128130613Smlaier imo->imo_multicast_ifp = sc->sc_sync_ifp; 1129130613Smlaier imo->imo_multicast_ttl = PFSYNC_DFLTTL; 1130130613Smlaier imo->imo_multicast_loop = 0; 1131145836Smlaier } 1132130613Smlaier 1133145836Smlaier if (sc->sc_sync_ifp || 1134145836Smlaier sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) { 1135130613Smlaier /* Request a full state table update. */ 1136130613Smlaier#ifdef __FreeBSD__ 1137130613Smlaier PF_LOCK(); 1138145836Smlaier#endif 1139130613Smlaier sc->sc_ureq_sent = time_uptime; 1140145836Smlaier#if NCARP > 0 1141145836Smlaier if (pfsync_sync_ok) 1142145836Smlaier carp_suppress_preempt++; 1143130613Smlaier#endif 1144130613Smlaier pfsync_sync_ok = 0; 1145130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1146130613Smlaier printf("pfsync: requesting bulk update\n"); 1147130613Smlaier#ifdef __FreeBSD__ 1148130613Smlaier callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, 1149130613Smlaier pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 1150130613Smlaier#else 1151130613Smlaier timeout_add(&sc->sc_bulkfail_tmo, 5 * hz); 1152130613Smlaier#endif 1153145836Smlaier error = pfsync_request_update(NULL, NULL); 1154145836Smlaier if (error == ENOMEM) { 1155145836Smlaier#ifdef __FreeBSD__ 1156145836Smlaier PF_UNLOCK(); 1157145836Smlaier#endif 1158145836Smlaier splx(s); 1159145836Smlaier return (ENOMEM); 1160145836Smlaier } 1161130613Smlaier pfsync_sendout(sc); 1162130613Smlaier } 1163130613Smlaier#ifdef __FreeBSD__ 1164130613Smlaier PF_UNLOCK(); 1165130613Smlaier#endif 1166130613Smlaier splx(s); 1167130613Smlaier 1168130613Smlaier break; 1169130613Smlaier 1170126258Smlaier default: 1171126258Smlaier return (ENOTTY); 1172126258Smlaier } 1173126258Smlaier 1174126258Smlaier return (0); 1175126258Smlaier} 1176126258Smlaier 1177126258Smlaiervoid 1178130613Smlaierpfsync_setmtu(struct pfsync_softc *sc, int mtu_req) 1179130613Smlaier{ 1180126258Smlaier int mtu; 1181130613Smlaier 1182130613Smlaier if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req) 1183130613Smlaier mtu = sc->sc_sync_ifp->if_mtu; 1184130613Smlaier else 1185130613Smlaier mtu = mtu_req; 1186130613Smlaier 1187130613Smlaier sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) / 1188130613Smlaier sizeof(struct pfsync_state); 1189130613Smlaier if (sc->sc_maxcount > 254) 1190130613Smlaier sc->sc_maxcount = 254; 1191141584Smlaier#ifdef __FreeBSD__ 1192141584Smlaier SCP2IFP(sc)->if_mtu = sizeof(struct pfsync_header) + 1193141584Smlaier sc->sc_maxcount * sizeof(struct pfsync_state); 1194141584Smlaier#else 1195126258Smlaier sc->sc_if.if_mtu = sizeof(struct pfsync_header) + 1196130613Smlaier sc->sc_maxcount * sizeof(struct pfsync_state); 1197141584Smlaier#endif 1198126258Smlaier} 1199126258Smlaier 1200126258Smlaierstruct mbuf * 1201130613Smlaierpfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp) 1202126258Smlaier{ 1203126258Smlaier struct pfsync_header *h; 1204126258Smlaier struct mbuf *m; 1205126258Smlaier int len; 1206126258Smlaier 1207130613Smlaier#ifdef __FreeBSD__ 1208130613Smlaier PF_ASSERT(MA_OWNED); 1209130613Smlaier#endif 1210126258Smlaier MGETHDR(m, M_DONTWAIT, MT_DATA); 1211126258Smlaier if (m == NULL) { 1212141584Smlaier#ifdef __FreeBSD__ 1213141584Smlaier SCP2IFP(sc)->if_oerrors++; 1214141584Smlaier#else 1215126258Smlaier sc->sc_if.if_oerrors++; 1216141584Smlaier#endif 1217126258Smlaier return (NULL); 1218126258Smlaier } 1219126258Smlaier 1220130613Smlaier switch (action) { 1221130613Smlaier case PFSYNC_ACT_CLR: 1222130613Smlaier len = sizeof(struct pfsync_header) + 1223130613Smlaier sizeof(struct pfsync_state_clr); 1224130613Smlaier break; 1225130613Smlaier case PFSYNC_ACT_UPD_C: 1226130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) + 1227130613Smlaier sizeof(struct pfsync_header); 1228130613Smlaier break; 1229130613Smlaier case PFSYNC_ACT_DEL_C: 1230130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) + 1231130613Smlaier sizeof(struct pfsync_header); 1232130613Smlaier break; 1233130613Smlaier case PFSYNC_ACT_UREQ: 1234130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) + 1235130613Smlaier sizeof(struct pfsync_header); 1236130613Smlaier break; 1237130613Smlaier case PFSYNC_ACT_BUS: 1238130613Smlaier len = sizeof(struct pfsync_header) + 1239130613Smlaier sizeof(struct pfsync_state_bus); 1240130613Smlaier break; 1241130613Smlaier default: 1242130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state)) + 1243130613Smlaier sizeof(struct pfsync_header); 1244130613Smlaier break; 1245130613Smlaier } 1246130613Smlaier 1247126258Smlaier if (len > MHLEN) { 1248126258Smlaier MCLGET(m, M_DONTWAIT); 1249126258Smlaier if ((m->m_flags & M_EXT) == 0) { 1250126258Smlaier m_free(m); 1251141584Smlaier#ifdef __FreeBSD__ 1252141584Smlaier SCP2IFP(sc)->if_oerrors++; 1253141584Smlaier#else 1254126258Smlaier sc->sc_if.if_oerrors++; 1255141584Smlaier#endif 1256126258Smlaier return (NULL); 1257126258Smlaier } 1258130613Smlaier m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1); 1259130613Smlaier } else 1260130613Smlaier MH_ALIGN(m, len); 1261130613Smlaier 1262126258Smlaier m->m_pkthdr.rcvif = NULL; 1263130613Smlaier m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header); 1264126258Smlaier h = mtod(m, struct pfsync_header *); 1265126258Smlaier h->version = PFSYNC_VERSION; 1266126258Smlaier h->af = 0; 1267126258Smlaier h->count = 0; 1268126258Smlaier h->action = action; 1269126258Smlaier 1270130613Smlaier *sp = (void *)((char *)h + PFSYNC_HDRLEN); 1271127145Smlaier#ifdef __FreeBSD__ 1272126261Smlaier callout_reset(&sc->sc_tmo, hz, pfsync_timeout, 1273126261Smlaier LIST_FIRST(&pfsync_list)); 1274126261Smlaier#else 1275126258Smlaier timeout_add(&sc->sc_tmo, hz); 1276126261Smlaier#endif 1277126258Smlaier return (m); 1278126258Smlaier} 1279126258Smlaier 1280126258Smlaierint 1281145836Smlaierpfsync_pack_state(u_int8_t action, struct pf_state *st, int flags) 1282126258Smlaier{ 1283127145Smlaier#ifdef __FreeBSD__ 1284141584Smlaier struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1285126261Smlaier#else 1286126258Smlaier struct ifnet *ifp = &pfsyncif.sc_if; 1287130613Smlaier#endif 1288126258Smlaier struct pfsync_softc *sc = ifp->if_softc; 1289130613Smlaier struct pfsync_header *h, *h_net; 1290130613Smlaier struct pfsync_state *sp = NULL; 1291130613Smlaier struct pfsync_state_upd *up = NULL; 1292130613Smlaier struct pfsync_state_del *dp = NULL; 1293130613Smlaier struct pf_rule *r; 1294126258Smlaier u_long secs; 1295130613Smlaier int s, ret = 0; 1296130613Smlaier u_int8_t i = 255, newaction = 0; 1297126258Smlaier 1298130613Smlaier#ifdef __FreeBSD__ 1299130613Smlaier PF_ASSERT(MA_OWNED); 1300130613Smlaier#endif 1301130613Smlaier /* 1302130613Smlaier * If a packet falls in the forest and there's nobody around to 1303130613Smlaier * hear, does it make a sound? 1304130613Smlaier */ 1305145836Smlaier if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL && 1306145836Smlaier sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) { 1307130613Smlaier /* Don't leave any stale pfsync packets hanging around. */ 1308130613Smlaier if (sc->sc_mbuf != NULL) { 1309130613Smlaier m_freem(sc->sc_mbuf); 1310130613Smlaier sc->sc_mbuf = NULL; 1311130613Smlaier sc->sc_statep.s = NULL; 1312130613Smlaier } 1313130613Smlaier return (0); 1314130613Smlaier } 1315130613Smlaier 1316126258Smlaier if (action >= PFSYNC_ACT_MAX) 1317126258Smlaier return (EINVAL); 1318126258Smlaier 1319126258Smlaier s = splnet(); 1320130613Smlaier if (sc->sc_mbuf == NULL) { 1321130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 1322130613Smlaier (void *)&sc->sc_statep.s)) == NULL) { 1323126258Smlaier splx(s); 1324126258Smlaier return (ENOMEM); 1325126258Smlaier } 1326130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1327126258Smlaier } else { 1328130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1329126258Smlaier if (h->action != action) { 1330126258Smlaier pfsync_sendout(sc); 1331130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 1332130613Smlaier (void *)&sc->sc_statep.s)) == NULL) { 1333126258Smlaier splx(s); 1334126258Smlaier return (ENOMEM); 1335126258Smlaier } 1336130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1337130613Smlaier } else { 1338130613Smlaier /* 1339130613Smlaier * If it's an update, look in the packet to see if 1340130613Smlaier * we already have an update for the state. 1341130613Smlaier */ 1342130613Smlaier if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) { 1343130613Smlaier struct pfsync_state *usp = 1344130613Smlaier (void *)((char *)h + PFSYNC_HDRLEN); 1345130613Smlaier 1346130613Smlaier for (i = 0; i < h->count; i++) { 1347130613Smlaier if (!memcmp(usp->id, &st->id, 1348130613Smlaier PFSYNC_ID_LEN) && 1349130613Smlaier usp->creatorid == st->creatorid) { 1350130613Smlaier sp = usp; 1351130613Smlaier sp->updates++; 1352130613Smlaier break; 1353130613Smlaier } 1354130613Smlaier usp++; 1355130613Smlaier } 1356130613Smlaier } 1357126258Smlaier } 1358126258Smlaier } 1359126258Smlaier 1360130613Smlaier secs = time_second; 1361126258Smlaier 1362130613Smlaier st->pfsync_time = time_uptime; 1363130613Smlaier TAILQ_REMOVE(&state_updates, st, u.s.entry_updates); 1364130613Smlaier TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates); 1365130613Smlaier 1366130613Smlaier if (sp == NULL) { 1367130613Smlaier /* not a "duplicate" update */ 1368130613Smlaier i = 255; 1369130613Smlaier sp = sc->sc_statep.s++; 1370130613Smlaier sc->sc_mbuf->m_pkthdr.len = 1371130613Smlaier sc->sc_mbuf->m_len += sizeof(struct pfsync_state); 1372130613Smlaier h->count++; 1373130613Smlaier bzero(sp, sizeof(*sp)); 1374130613Smlaier 1375130613Smlaier bcopy(&st->id, sp->id, sizeof(sp->id)); 1376130613Smlaier sp->creatorid = st->creatorid; 1377130613Smlaier 1378130613Smlaier strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname)); 1379130613Smlaier pf_state_host_hton(&st->lan, &sp->lan); 1380130613Smlaier pf_state_host_hton(&st->gwy, &sp->gwy); 1381130613Smlaier pf_state_host_hton(&st->ext, &sp->ext); 1382130613Smlaier 1383130613Smlaier bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); 1384130613Smlaier 1385130613Smlaier sp->creation = htonl(secs - st->creation); 1386130613Smlaier sp->packets[0] = htonl(st->packets[0]); 1387130613Smlaier sp->packets[1] = htonl(st->packets[1]); 1388130613Smlaier sp->bytes[0] = htonl(st->bytes[0]); 1389130613Smlaier sp->bytes[1] = htonl(st->bytes[1]); 1390130613Smlaier if ((r = st->rule.ptr) == NULL) 1391130613Smlaier sp->rule = htonl(-1); 1392130613Smlaier else 1393130613Smlaier sp->rule = htonl(r->nr); 1394130613Smlaier if ((r = st->anchor.ptr) == NULL) 1395130613Smlaier sp->anchor = htonl(-1); 1396130613Smlaier else 1397130613Smlaier sp->anchor = htonl(r->nr); 1398130613Smlaier sp->af = st->af; 1399130613Smlaier sp->proto = st->proto; 1400130613Smlaier sp->direction = st->direction; 1401130613Smlaier sp->log = st->log; 1402130613Smlaier sp->allow_opts = st->allow_opts; 1403130613Smlaier sp->timeout = st->timeout; 1404130613Smlaier 1405145836Smlaier if (flags & PFSYNC_FLAG_STALE) 1406145836Smlaier sp->sync_flags |= PFSTATE_STALE; 1407130613Smlaier } 1408130613Smlaier 1409126258Smlaier pf_state_peer_hton(&st->src, &sp->src); 1410126258Smlaier pf_state_peer_hton(&st->dst, &sp->dst); 1411126258Smlaier 1412126258Smlaier if (st->expire <= secs) 1413126258Smlaier sp->expire = htonl(0); 1414126258Smlaier else 1415126258Smlaier sp->expire = htonl(st->expire - secs); 1416126258Smlaier 1417130613Smlaier /* do we need to build "compressed" actions for network transfer? */ 1418145836Smlaier if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) { 1419130613Smlaier switch (action) { 1420130613Smlaier case PFSYNC_ACT_UPD: 1421130613Smlaier newaction = PFSYNC_ACT_UPD_C; 1422130613Smlaier break; 1423130613Smlaier case PFSYNC_ACT_DEL: 1424130613Smlaier newaction = PFSYNC_ACT_DEL_C; 1425130613Smlaier break; 1426130613Smlaier default: 1427130613Smlaier /* by default we just send the uncompressed states */ 1428130613Smlaier break; 1429130613Smlaier } 1430130613Smlaier } 1431130613Smlaier 1432130613Smlaier if (newaction) { 1433130613Smlaier if (sc->sc_mbuf_net == NULL) { 1434130613Smlaier if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction, 1435130613Smlaier (void *)&sc->sc_statep_net.s)) == NULL) { 1436130613Smlaier splx(s); 1437130613Smlaier return (ENOMEM); 1438130613Smlaier } 1439130613Smlaier } 1440130613Smlaier h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *); 1441130613Smlaier 1442130613Smlaier switch (newaction) { 1443130613Smlaier case PFSYNC_ACT_UPD_C: 1444130613Smlaier if (i != 255) { 1445130613Smlaier up = (void *)((char *)h_net + 1446130613Smlaier PFSYNC_HDRLEN + (i * sizeof(*up))); 1447130613Smlaier up->updates++; 1448130613Smlaier } else { 1449130613Smlaier h_net->count++; 1450130613Smlaier sc->sc_mbuf_net->m_pkthdr.len = 1451130613Smlaier sc->sc_mbuf_net->m_len += sizeof(*up); 1452130613Smlaier up = sc->sc_statep_net.u++; 1453130613Smlaier 1454130613Smlaier bzero(up, sizeof(*up)); 1455130613Smlaier bcopy(&st->id, up->id, sizeof(up->id)); 1456130613Smlaier up->creatorid = st->creatorid; 1457130613Smlaier } 1458130613Smlaier up->timeout = st->timeout; 1459130613Smlaier up->expire = sp->expire; 1460130613Smlaier up->src = sp->src; 1461130613Smlaier up->dst = sp->dst; 1462130613Smlaier break; 1463130613Smlaier case PFSYNC_ACT_DEL_C: 1464130613Smlaier sc->sc_mbuf_net->m_pkthdr.len = 1465130613Smlaier sc->sc_mbuf_net->m_len += sizeof(*dp); 1466130613Smlaier dp = sc->sc_statep_net.d++; 1467130613Smlaier h_net->count++; 1468130613Smlaier 1469130613Smlaier bzero(dp, sizeof(*dp)); 1470130613Smlaier bcopy(&st->id, dp->id, sizeof(dp->id)); 1471130613Smlaier dp->creatorid = st->creatorid; 1472130613Smlaier break; 1473130613Smlaier } 1474130613Smlaier } 1475130613Smlaier 1476130613Smlaier if (h->count == sc->sc_maxcount || 1477130613Smlaier (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates))) 1478126258Smlaier ret = pfsync_sendout(sc); 1479126258Smlaier 1480126258Smlaier splx(s); 1481130613Smlaier return (ret); 1482126258Smlaier} 1483126258Smlaier 1484130613Smlaier/* This must be called in splnet() */ 1485126258Smlaierint 1486130613Smlaierpfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src) 1487126258Smlaier{ 1488127145Smlaier#ifdef __FreeBSD__ 1489141584Smlaier struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1490126261Smlaier#else 1491126258Smlaier struct ifnet *ifp = &pfsyncif.sc_if; 1492130613Smlaier#endif 1493130613Smlaier struct pfsync_header *h; 1494126258Smlaier struct pfsync_softc *sc = ifp->if_softc; 1495130613Smlaier struct pfsync_state_upd_req *rup; 1496145836Smlaier int ret = 0; 1497130613Smlaier 1498130613Smlaier#ifdef __FreeBSD__ 1499130613Smlaier PF_ASSERT(MA_OWNED); 1500126261Smlaier#endif 1501130613Smlaier if (sc->sc_mbuf == NULL) { 1502130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1503145836Smlaier (void *)&sc->sc_statep.s)) == NULL) 1504130613Smlaier return (ENOMEM); 1505130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1506130613Smlaier } else { 1507130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1508130613Smlaier if (h->action != PFSYNC_ACT_UREQ) { 1509130613Smlaier pfsync_sendout(sc); 1510130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1511145836Smlaier (void *)&sc->sc_statep.s)) == NULL) 1512130613Smlaier return (ENOMEM); 1513130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1514130613Smlaier } 1515130613Smlaier } 1516130613Smlaier 1517130613Smlaier if (src != NULL) 1518130613Smlaier sc->sc_sendaddr = *src; 1519130613Smlaier sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup); 1520130613Smlaier h->count++; 1521130613Smlaier rup = sc->sc_statep.r++; 1522130613Smlaier bzero(rup, sizeof(*rup)); 1523130613Smlaier if (up != NULL) { 1524130613Smlaier bcopy(up->id, rup->id, sizeof(rup->id)); 1525130613Smlaier rup->creatorid = up->creatorid; 1526130613Smlaier } 1527130613Smlaier 1528130613Smlaier if (h->count == sc->sc_maxcount) 1529130613Smlaier ret = pfsync_sendout(sc); 1530130613Smlaier 1531130613Smlaier return (ret); 1532130613Smlaier} 1533130613Smlaier 1534130613Smlaierint 1535130613Smlaierpfsync_clear_states(u_int32_t creatorid, char *ifname) 1536130613Smlaier{ 1537130613Smlaier#ifdef __FreeBSD__ 1538141584Smlaier struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1539130613Smlaier#else 1540130613Smlaier struct ifnet *ifp = &pfsyncif.sc_if; 1541130613Smlaier#endif 1542130613Smlaier struct pfsync_softc *sc = ifp->if_softc; 1543130613Smlaier struct pfsync_state_clr *cp; 1544126258Smlaier int s, ret; 1545126258Smlaier 1546126258Smlaier s = splnet(); 1547130613Smlaier#ifdef __FreeBSD__ 1548130613Smlaier PF_ASSERT(MA_OWNED); 1549130613Smlaier#endif 1550130613Smlaier if (sc->sc_mbuf != NULL) 1551130613Smlaier pfsync_sendout(sc); 1552130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR, 1553130613Smlaier (void *)&sc->sc_statep.c)) == NULL) { 1554126258Smlaier splx(s); 1555126258Smlaier return (ENOMEM); 1556126258Smlaier } 1557130613Smlaier sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp); 1558130613Smlaier cp = sc->sc_statep.c; 1559130613Smlaier cp->creatorid = creatorid; 1560130613Smlaier if (ifname != NULL) 1561130613Smlaier strlcpy(cp->ifname, ifname, IFNAMSIZ); 1562126258Smlaier 1563126258Smlaier ret = (pfsync_sendout(sc)); 1564126258Smlaier splx(s); 1565126258Smlaier return (ret); 1566126258Smlaier} 1567126258Smlaier 1568126258Smlaiervoid 1569126258Smlaierpfsync_timeout(void *v) 1570126258Smlaier{ 1571126258Smlaier struct pfsync_softc *sc = v; 1572126258Smlaier int s; 1573126258Smlaier 1574126258Smlaier s = splnet(); 1575130613Smlaier#ifdef __FreeBSD__ 1576130613Smlaier PF_LOCK(); 1577130613Smlaier#endif 1578126258Smlaier pfsync_sendout(sc); 1579130613Smlaier#ifdef __FreeBSD__ 1580130613Smlaier PF_UNLOCK(); 1581130613Smlaier#endif 1582126258Smlaier splx(s); 1583126258Smlaier} 1584126258Smlaier 1585145836Smlaier/* This must be called in splnet() */ 1586130613Smlaiervoid 1587130613Smlaierpfsync_send_bus(struct pfsync_softc *sc, u_int8_t status) 1588130613Smlaier{ 1589130613Smlaier struct pfsync_state_bus *bus; 1590130613Smlaier 1591130613Smlaier#ifdef __FreeBSD__ 1592130613Smlaier PF_ASSERT(MA_OWNED); 1593130613Smlaier#endif 1594130613Smlaier if (sc->sc_mbuf != NULL) 1595130613Smlaier pfsync_sendout(sc); 1596130613Smlaier 1597130613Smlaier if (pfsync_sync_ok && 1598130613Smlaier (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS, 1599130613Smlaier (void *)&sc->sc_statep.b)) != NULL) { 1600130613Smlaier sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus); 1601130613Smlaier bus = sc->sc_statep.b; 1602130613Smlaier bus->creatorid = pf_status.hostid; 1603130613Smlaier bus->status = status; 1604130613Smlaier bus->endtime = htonl(time_uptime - sc->sc_ureq_received); 1605130613Smlaier pfsync_sendout(sc); 1606130613Smlaier } 1607130613Smlaier} 1608130613Smlaier 1609130613Smlaiervoid 1610130613Smlaierpfsync_bulk_update(void *v) 1611130613Smlaier{ 1612130613Smlaier struct pfsync_softc *sc = v; 1613130613Smlaier int s, i = 0; 1614130613Smlaier struct pf_state *state; 1615130613Smlaier 1616130613Smlaier#ifdef __FreeBSD__ 1617130613Smlaier PF_LOCK(); 1618130613Smlaier#endif 1619130613Smlaier s = splnet(); 1620130613Smlaier if (sc->sc_mbuf != NULL) 1621130613Smlaier pfsync_sendout(sc); 1622130613Smlaier 1623130613Smlaier /* 1624130613Smlaier * Grab at most PFSYNC_BULKPACKETS worth of states which have not 1625130613Smlaier * been sent since the latest request was made. 1626130613Smlaier */ 1627130613Smlaier while ((state = TAILQ_FIRST(&state_updates)) != NULL && 1628130613Smlaier ++i < (sc->sc_maxcount * PFSYNC_BULKPACKETS)) { 1629130613Smlaier if (state->pfsync_time > sc->sc_ureq_received) { 1630130613Smlaier /* we're done */ 1631130613Smlaier pfsync_send_bus(sc, PFSYNC_BUS_END); 1632130613Smlaier sc->sc_ureq_received = 0; 1633130613Smlaier#ifdef __FreeBSD__ 1634130613Smlaier callout_stop(&sc->sc_bulk_tmo); 1635130613Smlaier#else 1636130613Smlaier timeout_del(&sc->sc_bulk_tmo); 1637130613Smlaier#endif 1638130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1639130613Smlaier printf("pfsync: bulk update complete\n"); 1640130613Smlaier break; 1641130613Smlaier } else { 1642130613Smlaier /* send an update and move to end of list */ 1643130613Smlaier if (!state->sync_flags) 1644130613Smlaier pfsync_pack_state(PFSYNC_ACT_UPD, state, 0); 1645130613Smlaier state->pfsync_time = time_uptime; 1646130613Smlaier TAILQ_REMOVE(&state_updates, state, u.s.entry_updates); 1647130613Smlaier TAILQ_INSERT_TAIL(&state_updates, state, 1648130613Smlaier u.s.entry_updates); 1649130613Smlaier 1650130613Smlaier /* look again for more in a bit */ 1651130613Smlaier#ifdef __FreeBSD__ 1652130613Smlaier callout_reset(&sc->sc_bulk_tmo, 1, pfsync_timeout, 1653130613Smlaier LIST_FIRST(&pfsync_list)); 1654130613Smlaier#else 1655130613Smlaier timeout_add(&sc->sc_bulk_tmo, 1); 1656130613Smlaier#endif 1657130613Smlaier } 1658130613Smlaier } 1659130613Smlaier if (sc->sc_mbuf != NULL) 1660130613Smlaier pfsync_sendout(sc); 1661130613Smlaier splx(s); 1662130613Smlaier#ifdef __FreeBSD__ 1663130613Smlaier PF_UNLOCK(); 1664130613Smlaier#endif 1665130613Smlaier} 1666130613Smlaier 1667130613Smlaiervoid 1668130613Smlaierpfsync_bulkfail(void *v) 1669130613Smlaier{ 1670130613Smlaier struct pfsync_softc *sc = v; 1671145836Smlaier int s, error; 1672130613Smlaier 1673130613Smlaier#ifdef __FreeBSD__ 1674130613Smlaier PF_LOCK(); 1675130613Smlaier#endif 1676130613Smlaier if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) { 1677130613Smlaier /* Try again in a bit */ 1678130613Smlaier#ifdef __FreeBSD__ 1679130613Smlaier callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail, 1680130613Smlaier LIST_FIRST(&pfsync_list)); 1681130613Smlaier#else 1682130613Smlaier timeout_add(&sc->sc_bulkfail_tmo, 5 * hz); 1683130613Smlaier#endif 1684145836Smlaier s = splnet(); 1685145836Smlaier error = pfsync_request_update(NULL, NULL); 1686145836Smlaier if (error == ENOMEM) { 1687145836Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1688145836Smlaier printf("pfsync: cannot allocate mbufs for " 1689145836Smlaier "bulk update\n"); 1690145836Smlaier } else 1691145836Smlaier pfsync_sendout(sc); 1692145836Smlaier splx(s); 1693130613Smlaier } else { 1694130613Smlaier /* Pretend like the transfer was ok */ 1695130613Smlaier sc->sc_ureq_sent = 0; 1696130613Smlaier sc->sc_bulk_tries = 0; 1697145836Smlaier#if NCARP > 0 1698145836Smlaier if (!pfsync_sync_ok) 1699145836Smlaier carp_suppress_preempt--; 1700145836Smlaier#endif 1701130613Smlaier pfsync_sync_ok = 1; 1702130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1703130613Smlaier printf("pfsync: failed to receive " 1704130613Smlaier "bulk update status\n"); 1705130613Smlaier#ifdef __FreeBSD__ 1706130613Smlaier callout_stop(&sc->sc_bulkfail_tmo); 1707130613Smlaier#else 1708130613Smlaier timeout_del(&sc->sc_bulkfail_tmo); 1709130613Smlaier#endif 1710130613Smlaier } 1711130613Smlaier#ifdef __FreeBSD__ 1712130613Smlaier PF_UNLOCK(); 1713130613Smlaier#endif 1714130613Smlaier} 1715130613Smlaier 1716145836Smlaier/* This must be called in splnet() */ 1717126258Smlaierint 1718126258Smlaierpfsync_sendout(sc) 1719126258Smlaier struct pfsync_softc *sc; 1720126258Smlaier{ 1721138666Smlaier#if NBPFILTER > 0 1722141584Smlaier# ifdef __FreeBSD__ 1723141584Smlaier struct ifnet *ifp = SCP2IFP(sc); 1724141584Smlaier# else 1725141584Smlaier struct ifnet *ifp = &sc->if_sc; 1726141584Smlaier# endif 1727138666Smlaier#endif 1728130613Smlaier struct mbuf *m; 1729126258Smlaier 1730127145Smlaier#ifdef __FreeBSD__ 1731130613Smlaier PF_ASSERT(MA_OWNED); 1732126261Smlaier callout_stop(&sc->sc_tmo); 1733126261Smlaier#else 1734126258Smlaier timeout_del(&sc->sc_tmo); 1735126261Smlaier#endif 1736130613Smlaier 1737130613Smlaier if (sc->sc_mbuf == NULL) 1738130613Smlaier return (0); 1739130613Smlaier m = sc->sc_mbuf; 1740126258Smlaier sc->sc_mbuf = NULL; 1741130613Smlaier sc->sc_statep.s = NULL; 1742126258Smlaier 1743127145Smlaier#ifdef __FreeBSD__ 1744126261Smlaier KASSERT(m != NULL, ("pfsync_sendout: null mbuf")); 1745126261Smlaier#endif 1746126258Smlaier#if NBPFILTER > 0 1747126258Smlaier if (ifp->if_bpf) 1748126258Smlaier bpf_mtap(ifp->if_bpf, m); 1749126258Smlaier#endif 1750126258Smlaier 1751130613Smlaier if (sc->sc_mbuf_net) { 1752130613Smlaier m_freem(m); 1753130613Smlaier m = sc->sc_mbuf_net; 1754130613Smlaier sc->sc_mbuf_net = NULL; 1755130613Smlaier sc->sc_statep_net.s = NULL; 1756130613Smlaier } 1757126258Smlaier 1758145836Smlaier if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) { 1759130613Smlaier struct ip *ip; 1760130613Smlaier struct sockaddr sa; 1761130613Smlaier 1762130613Smlaier M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 1763130613Smlaier if (m == NULL) { 1764130613Smlaier pfsyncstats.pfsyncs_onomem++; 1765130613Smlaier return (0); 1766130613Smlaier } 1767130613Smlaier ip = mtod(m, struct ip *); 1768130613Smlaier ip->ip_v = IPVERSION; 1769130613Smlaier ip->ip_hl = sizeof(*ip) >> 2; 1770130613Smlaier ip->ip_tos = IPTOS_LOWDELAY; 1771130613Smlaier#ifdef __FreeBSD__ 1772130613Smlaier ip->ip_len = m->m_pkthdr.len; 1773130613Smlaier#else 1774130613Smlaier ip->ip_len = htons(m->m_pkthdr.len); 1775130613Smlaier#endif 1776130613Smlaier ip->ip_id = htons(ip_randomid()); 1777130613Smlaier#ifdef __FreeBSD__ 1778130613Smlaier ip->ip_off = IP_DF; 1779130613Smlaier#else 1780130613Smlaier ip->ip_off = htons(IP_DF); 1781130613Smlaier#endif 1782130613Smlaier ip->ip_ttl = PFSYNC_DFLTTL; 1783130613Smlaier ip->ip_p = IPPROTO_PFSYNC; 1784130613Smlaier ip->ip_sum = 0; 1785130613Smlaier 1786130613Smlaier bzero(&sa, sizeof(sa)); 1787145836Smlaier ip->ip_src.s_addr = INADDR_ANY; 1788130613Smlaier 1789130613Smlaier#ifdef __FreeBSD__ 1790130613Smlaier if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP)) 1791130613Smlaier#else 1792130613Smlaier if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP) 1793130613Smlaier#endif 1794130613Smlaier m->m_flags |= M_MCAST; 1795130613Smlaier ip->ip_dst = sc->sc_sendaddr; 1796130613Smlaier#ifdef __FreeBSD__ 1797145836Smlaier /* XXX_IMPORT */ 1798145836Smlaier sc->sc_sendaddr.s_addr = htonl(sc->sc_sync_peer.s_addr); 1799130613Smlaier#else 1800145836Smlaier sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr; 1801130613Smlaier#endif 1802130613Smlaier 1803130613Smlaier pfsyncstats.pfsyncs_opackets++; 1804130613Smlaier#ifdef __FreeBSD__ 1805147614Smlaier if (!IF_HANDOFF(&sc->sc_ifq, m, NULL)) 1806147261Smlaier pfsyncstats.pfsyncs_oerrors++; 1807147261Smlaier callout_reset(&sc->sc_send_tmo, 1, pfsync_senddef, sc); 1808147261Smlaier#else 1809130613Smlaier if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 1810130613Smlaier pfsyncstats.pfsyncs_oerrors++; 1811130613Smlaier#endif 1812130613Smlaier } else 1813130613Smlaier m_freem(m); 1814130613Smlaier 1815126258Smlaier return (0); 1816126258Smlaier} 1817126261Smlaier 1818147261Smlaier#ifdef __FreeBSD__ 1819147261Smlaierstatic void 1820147261Smlaierpfsync_senddef(void *arg) 1821147261Smlaier{ 1822147261Smlaier struct pfsync_softc *sc = (struct pfsync_softc *)arg; 1823147261Smlaier struct mbuf *m; 1824126261Smlaier 1825147261Smlaier for(;;) { 1826147261Smlaier IF_DEQUEUE(&sc->sc_ifq, m); 1827147261Smlaier if (m == NULL) 1828147261Smlaier break; 1829147261Smlaier if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 1830147261Smlaier pfsyncstats.pfsyncs_oerrors++; 1831147261Smlaier } 1832147261Smlaier} 1833147261Smlaier 1834126261Smlaierstatic int 1835126261Smlaierpfsync_modevent(module_t mod, int type, void *data) 1836126261Smlaier{ 1837126261Smlaier int error = 0; 1838126261Smlaier 1839126261Smlaier switch (type) { 1840126261Smlaier case MOD_LOAD: 1841126261Smlaier LIST_INIT(&pfsync_list); 1842126261Smlaier if_clone_attach(&pfsync_cloner); 1843126261Smlaier break; 1844126261Smlaier 1845126261Smlaier case MOD_UNLOAD: 1846126261Smlaier if_clone_detach(&pfsync_cloner); 1847126261Smlaier while (!LIST_EMPTY(&pfsync_list)) 1848126261Smlaier pfsync_clone_destroy( 1849141584Smlaier SCP2IFP(LIST_FIRST(&pfsync_list))); 1850126261Smlaier break; 1851126261Smlaier 1852126261Smlaier default: 1853126261Smlaier error = EINVAL; 1854126261Smlaier break; 1855126261Smlaier } 1856126261Smlaier 1857126261Smlaier return error; 1858126261Smlaier} 1859126261Smlaier 1860126261Smlaierstatic moduledata_t pfsync_mod = { 1861126261Smlaier "pfsync", 1862126261Smlaier pfsync_modevent, 1863126261Smlaier 0 1864126261Smlaier}; 1865126261Smlaier 1866126261Smlaier#define PFSYNC_MODVER 1 1867126261Smlaier 1868135196SmlaierDECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 1869126261SmlaierMODULE_VERSION(pfsync, PFSYNC_MODVER); 1870126261Smlaier#endif /* __FreeBSD__ */ 1871