if_pfsync.c revision 147321
1126261Smlaier/* $FreeBSD: head/sys/contrib/pf/net/if_pfsync.c 147321 2005-06-12 16:46:20Z 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> 59126261Smlaier#else 60126258Smlaier#include <sys/ioctl.h> 61126258Smlaier#include <sys/timeout.h> 62126261Smlaier#endif 63126258Smlaier 64126258Smlaier#include <net/if.h> 65130933Sbrooks#if defined(__FreeBSD__) 66130933Sbrooks#include <net/if_clone.h> 67130933Sbrooks#endif 68126258Smlaier#include <net/if_types.h> 69126258Smlaier#include <net/route.h> 70126258Smlaier#include <net/bpf.h> 71145836Smlaier#include <netinet/tcp.h> 72145836Smlaier#include <netinet/tcp_seq.h> 73126258Smlaier 74126258Smlaier#ifdef INET 75126258Smlaier#include <netinet/in.h> 76130613Smlaier#include <netinet/in_systm.h> 77126258Smlaier#include <netinet/in_var.h> 78130613Smlaier#include <netinet/ip.h> 79130613Smlaier#include <netinet/ip_var.h> 80126258Smlaier#endif 81126258Smlaier 82126258Smlaier#ifdef INET6 83126258Smlaier#ifndef INET 84126258Smlaier#include <netinet/in.h> 85126258Smlaier#endif 86126258Smlaier#include <netinet6/nd6.h> 87126258Smlaier#endif /* INET6 */ 88126258Smlaier 89145836Smlaier#ifdef __FreeBSD__ 90145836Smlaier#include "opt_carp.h" 91145836Smlaier#ifdef DEV_CARP 92145836Smlaier#define NCARP 1 93145836Smlaier#endif 94145836Smlaier#else 95145836Smlaier#include "carp.h" 96145836Smlaier#endif 97145836Smlaier#if NCARP > 0 98145836Smlaierextern int carp_suppress_preempt; 99145836Smlaier#endif 100145836Smlaier 101126258Smlaier#include <net/pfvar.h> 102126258Smlaier#include <net/if_pfsync.h> 103126258Smlaier 104127145Smlaier#ifdef __FreeBSD__ 105127145Smlaier#define PFSYNCNAME "pfsync" 106126261Smlaier#endif 107126261Smlaier 108126258Smlaier#define PFSYNC_MINMTU \ 109126258Smlaier (sizeof(struct pfsync_header) + sizeof(struct pf_state)) 110126258Smlaier 111126258Smlaier#ifdef PFSYNCDEBUG 112126258Smlaier#define DPRINTF(x) do { if (pfsyncdebug) printf x ; } while (0) 113126258Smlaierint pfsyncdebug; 114126258Smlaier#else 115126258Smlaier#define DPRINTF(x) 116126258Smlaier#endif 117126258Smlaier 118127145Smlaier#ifndef __FreeBSD__ 119130613Smlaierstruct pfsync_softc pfsyncif; 120126261Smlaier#endif 121130613Smlaierstruct pfsyncstats pfsyncstats; 122126258Smlaier 123127145Smlaier#ifdef __FreeBSD__ 124130613Smlaier 125130613Smlaier/* 126130613Smlaier * Locking notes: 127130613Smlaier * Whenever we really touch/look at the state table we have to hold the 128130613Smlaier * PF_LOCK. Functions that do just the interface handling, grab the per 129130613Smlaier * softc lock instead. 130130613Smlaier * 131130613Smlaier */ 132130613Smlaier 133128209Sbrooksstatic void pfsync_clone_destroy(struct ifnet *); 134128209Sbrooksstatic int pfsync_clone_create(struct if_clone *, int); 135147261Smlaierstatic void pfsync_senddef(void *); 136126261Smlaier#else 137126258Smlaiervoid pfsyncattach(int); 138126261Smlaier#endif 139130613Smlaiervoid pfsync_setmtu(struct pfsync_softc *, int); 140130613Smlaierint pfsync_insert_net_state(struct pfsync_state *); 141126258Smlaierint pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 142130613Smlaier struct rtentry *); 143126258Smlaierint pfsyncioctl(struct ifnet *, u_long, caddr_t); 144126258Smlaiervoid pfsyncstart(struct ifnet *); 145126258Smlaier 146130613Smlaierstruct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **); 147130613Smlaierint pfsync_request_update(struct pfsync_state_upd *, struct in_addr *); 148130613Smlaierint pfsync_sendout(struct pfsync_softc *); 149130613Smlaiervoid pfsync_timeout(void *); 150130613Smlaiervoid pfsync_send_bus(struct pfsync_softc *, u_int8_t); 151130613Smlaiervoid pfsync_bulk_update(void *); 152130613Smlaiervoid pfsync_bulkfail(void *); 153126258Smlaier 154145836Smlaierint pfsync_sync_ok; 155127145Smlaier#ifndef __FreeBSD__ 156126258Smlaierextern int ifqmaxlen; 157130613Smlaierextern struct timeval time; 158130613Smlaierextern struct timeval mono_time; 159130613Smlaierextern int hz; 160126261Smlaier#endif 161126258Smlaier 162127145Smlaier#ifdef __FreeBSD__ 163126261Smlaierstatic MALLOC_DEFINE(M_PFSYNC, PFSYNCNAME, "Packet Filter State Sync. Interface"); 164126261Smlaierstatic LIST_HEAD(pfsync_list, pfsync_softc) pfsync_list; 165147256Sbrooks#define SCP2IFP(sc) ((sc)->sc_ifp) 166130933SbrooksIFC_SIMPLE_DECLARE(pfsync, 1); 167126261Smlaier 168128209Sbrooksstatic void 169126261Smlaierpfsync_clone_destroy(struct ifnet *ifp) 170126261Smlaier{ 171126261Smlaier struct pfsync_softc *sc; 172126261Smlaier 173130613Smlaier sc = ifp->if_softc; 174126261Smlaier callout_stop(&sc->sc_tmo); 175130613Smlaier callout_stop(&sc->sc_bulk_tmo); 176130613Smlaier callout_stop(&sc->sc_bulkfail_tmo); 177126261Smlaier 178147261Smlaier callout_stop(&sc->sc_send_tmo); 179147261Smlaier 180126261Smlaier#if NBPFILTER > 0 181126261Smlaier bpfdetach(ifp); 182126261Smlaier#endif 183126261Smlaier if_detach(ifp); 184147256Sbrooks if_free(ifp); 185126261Smlaier LIST_REMOVE(sc, sc_next); 186126261Smlaier free(sc, M_PFSYNC); 187126261Smlaier} 188126261Smlaier 189128209Sbrooksstatic int 190126261Smlaierpfsync_clone_create(struct if_clone *ifc, int unit) 191126261Smlaier{ 192126261Smlaier struct pfsync_softc *sc; 193130613Smlaier struct ifnet *ifp; 194126261Smlaier 195126261Smlaier MALLOC(sc, struct pfsync_softc *, sizeof(*sc), M_PFSYNC, 196130613Smlaier M_WAITOK|M_ZERO); 197147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_PFSYNC); 198147256Sbrooks if (ifp == NULL) { 199147256Sbrooks free(sc, M_PFSYNC); 200147256Sbrooks return (ENOSPC); 201147256Sbrooks } 202126261Smlaier 203130613Smlaier pfsync_sync_ok = 1; 204130613Smlaier sc->sc_mbuf = NULL; 205130613Smlaier sc->sc_mbuf_net = NULL; 206130613Smlaier sc->sc_statep.s = NULL; 207130613Smlaier sc->sc_statep_net.s = NULL; 208130613Smlaier sc->sc_maxupdates = 128; 209130613Smlaier sc->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP); 210130613Smlaier sc->sc_ureq_received = 0; 211130613Smlaier sc->sc_ureq_sent = 0; 212130613Smlaier 213141584Smlaier ifp = SCP2IFP(sc); 214130613Smlaier if_initname(ifp, ifc->ifc_name, unit); 215130613Smlaier ifp->if_ioctl = pfsyncioctl; 216130613Smlaier ifp->if_output = pfsyncoutput; 217130613Smlaier ifp->if_start = pfsyncstart; 218130613Smlaier ifp->if_snd.ifq_maxlen = ifqmaxlen; 219130613Smlaier ifp->if_hdrlen = PFSYNC_HDRLEN; 220130613Smlaier ifp->if_baudrate = IF_Mbps(100); 221130613Smlaier ifp->if_softc = sc; 222126261Smlaier pfsync_setmtu(sc, MCLBYTES); 223147321Smlaier callout_init(&sc->sc_tmo, NET_CALLOUT_MPSAFE); 224147321Smlaier callout_init(&sc->sc_bulk_tmo, NET_CALLOUT_MPSAFE); 225147321Smlaier callout_init(&sc->sc_bulkfail_tmo, NET_CALLOUT_MPSAFE); 226147321Smlaier callout_init(&sc->sc_send_tmo, NET_CALLOUT_MPSAFE); 227147261Smlaier mtx_init(&sc->sc_ifq.ifq_mtx, ifp->if_xname, "pfsync send queue", 228147261Smlaier MTX_DEF); 229141584Smlaier if_attach(ifp); 230126261Smlaier 231126261Smlaier LIST_INSERT_HEAD(&pfsync_list, sc, sc_next); 232126261Smlaier#if NBPFILTER > 0 233141584Smlaier bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 234126261Smlaier#endif 235126261Smlaier 236126261Smlaier return (0); 237126261Smlaier} 238126261Smlaier#else /* !__FreeBSD__ */ 239126261Smlaiervoid 240126258Smlaierpfsyncattach(int npfsync) 241126258Smlaier{ 242126258Smlaier struct ifnet *ifp; 243126258Smlaier 244130613Smlaier pfsync_sync_ok = 1; 245130613Smlaier bzero(&pfsyncif, sizeof(pfsyncif)); 246126258Smlaier pfsyncif.sc_mbuf = NULL; 247130613Smlaier pfsyncif.sc_mbuf_net = NULL; 248130613Smlaier pfsyncif.sc_statep.s = NULL; 249130613Smlaier pfsyncif.sc_statep_net.s = NULL; 250130613Smlaier pfsyncif.sc_maxupdates = 128; 251145836Smlaier pfsyncif.sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP; 252130613Smlaier pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP; 253130613Smlaier pfsyncif.sc_ureq_received = 0; 254130613Smlaier pfsyncif.sc_ureq_sent = 0; 255126258Smlaier ifp = &pfsyncif.sc_if; 256126258Smlaier strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname); 257126258Smlaier ifp->if_softc = &pfsyncif; 258126258Smlaier ifp->if_ioctl = pfsyncioctl; 259126258Smlaier ifp->if_output = pfsyncoutput; 260126258Smlaier ifp->if_start = pfsyncstart; 261126258Smlaier ifp->if_type = IFT_PFSYNC; 262126258Smlaier ifp->if_snd.ifq_maxlen = ifqmaxlen; 263126258Smlaier ifp->if_hdrlen = PFSYNC_HDRLEN; 264126258Smlaier pfsync_setmtu(&pfsyncif, MCLBYTES); 265126258Smlaier timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif); 266130613Smlaier timeout_set(&pfsyncif.sc_bulk_tmo, pfsync_bulk_update, &pfsyncif); 267130613Smlaier timeout_set(&pfsyncif.sc_bulkfail_tmo, pfsync_bulkfail, &pfsyncif); 268126258Smlaier if_attach(ifp); 269126258Smlaier if_alloc_sadl(ifp); 270126258Smlaier 271126258Smlaier#if NBPFILTER > 0 272126258Smlaier bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN); 273126258Smlaier#endif 274126258Smlaier} 275126261Smlaier#endif 276126258Smlaier 277126258Smlaier/* 278126258Smlaier * Start output on the pfsync interface. 279126258Smlaier */ 280126258Smlaiervoid 281126258Smlaierpfsyncstart(struct ifnet *ifp) 282126258Smlaier{ 283130613Smlaier#ifdef __FreeBSD__ 284130613Smlaier IF_LOCK(&ifp->if_snd); 285130613Smlaier _IF_DROP(&ifp->if_snd); 286130613Smlaier _IF_DRAIN(&ifp->if_snd); 287130613Smlaier IF_UNLOCK(&ifp->if_snd); 288130613Smlaier#else 289126258Smlaier struct mbuf *m; 290126258Smlaier int s; 291126258Smlaier 292126258Smlaier for (;;) { 293126258Smlaier s = splimp(); 294126258Smlaier IF_DROP(&ifp->if_snd); 295126258Smlaier IF_DEQUEUE(&ifp->if_snd, m); 296126258Smlaier splx(s); 297126258Smlaier 298126258Smlaier if (m == NULL) 299126258Smlaier return; 300126258Smlaier else 301126258Smlaier m_freem(m); 302126258Smlaier } 303130613Smlaier#endif 304126258Smlaier} 305126258Smlaier 306126258Smlaierint 307130613Smlaierpfsync_insert_net_state(struct pfsync_state *sp) 308130613Smlaier{ 309130613Smlaier struct pf_state *st = NULL; 310130613Smlaier struct pf_rule *r = NULL; 311130613Smlaier struct pfi_kif *kif; 312130613Smlaier 313130613Smlaier#ifdef __FreeBSD__ 314130613Smlaier PF_ASSERT(MA_OWNED); 315130613Smlaier#endif 316130613Smlaier if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) { 317130613Smlaier printf("pfsync_insert_net_state: invalid creator id:" 318130613Smlaier " %08x\n", ntohl(sp->creatorid)); 319130613Smlaier return (EINVAL); 320130613Smlaier } 321130613Smlaier 322130613Smlaier kif = pfi_lookup_create(sp->ifname); 323130613Smlaier if (kif == NULL) { 324130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 325130613Smlaier printf("pfsync_insert_net_state: " 326130613Smlaier "unknown interface: %s\n", sp->ifname); 327130613Smlaier /* skip this state */ 328130613Smlaier return (0); 329130613Smlaier } 330130613Smlaier 331130613Smlaier /* 332130613Smlaier * Just use the default rule until we have infrastructure to find the 333130613Smlaier * best matching rule. 334130613Smlaier */ 335130613Smlaier r = &pf_default_rule; 336130613Smlaier 337130613Smlaier if (!r->max_states || r->states < r->max_states) 338130613Smlaier st = pool_get(&pf_state_pl, PR_NOWAIT); 339130613Smlaier if (st == NULL) { 340130613Smlaier pfi_maybe_destroy(kif); 341130613Smlaier return (ENOMEM); 342130613Smlaier } 343130613Smlaier bzero(st, sizeof(*st)); 344130613Smlaier 345130613Smlaier st->rule.ptr = r; 346130613Smlaier /* XXX get pointers to nat_rule and anchor */ 347130613Smlaier 348145836Smlaier /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */ 349145836Smlaier r->states++; 350145836Smlaier 351130613Smlaier /* fill in the rest of the state entry */ 352130613Smlaier pf_state_host_ntoh(&sp->lan, &st->lan); 353130613Smlaier pf_state_host_ntoh(&sp->gwy, &st->gwy); 354130613Smlaier pf_state_host_ntoh(&sp->ext, &st->ext); 355130613Smlaier 356130613Smlaier pf_state_peer_ntoh(&sp->src, &st->src); 357130613Smlaier pf_state_peer_ntoh(&sp->dst, &st->dst); 358130613Smlaier 359130613Smlaier bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr)); 360145836Smlaier st->creation = time_second - ntohl(sp->creation); 361130613Smlaier st->expire = ntohl(sp->expire) + time_second; 362130613Smlaier 363130613Smlaier st->af = sp->af; 364130613Smlaier st->proto = sp->proto; 365130613Smlaier st->direction = sp->direction; 366130613Smlaier st->log = sp->log; 367130613Smlaier st->timeout = sp->timeout; 368130613Smlaier st->allow_opts = sp->allow_opts; 369130613Smlaier 370130613Smlaier bcopy(sp->id, &st->id, sizeof(st->id)); 371130613Smlaier st->creatorid = sp->creatorid; 372145836Smlaier st->sync_flags = PFSTATE_FROMSYNC; 373130613Smlaier 374130613Smlaier 375130613Smlaier if (pf_insert_state(kif, st)) { 376130613Smlaier pfi_maybe_destroy(kif); 377145836Smlaier /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */ 378145836Smlaier r->states--; 379130613Smlaier pool_put(&pf_state_pl, st); 380130613Smlaier return (EINVAL); 381130613Smlaier } 382130613Smlaier 383130613Smlaier return (0); 384130613Smlaier} 385130613Smlaier 386130613Smlaiervoid 387130613Smlaier#ifdef __FreeBSD__ 388130613Smlaierpfsync_input(struct mbuf *m, __unused int off) 389130613Smlaier#else 390130613Smlaierpfsync_input(struct mbuf *m, ...) 391130613Smlaier#endif 392130613Smlaier{ 393130613Smlaier struct ip *ip = mtod(m, struct ip *); 394130613Smlaier struct pfsync_header *ph; 395130613Smlaier#ifdef __FreeBSD__ 396130613Smlaier struct pfsync_softc *sc = LIST_FIRST(&pfsync_list); 397130613Smlaier#else 398130613Smlaier struct pfsync_softc *sc = &pfsyncif; 399130613Smlaier#endif 400130613Smlaier struct pf_state *st, key; 401130613Smlaier struct pfsync_state *sp; 402130613Smlaier struct pfsync_state_upd *up; 403130613Smlaier struct pfsync_state_del *dp; 404130613Smlaier struct pfsync_state_clr *cp; 405130613Smlaier struct pfsync_state_upd_req *rup; 406130613Smlaier struct pfsync_state_bus *bus; 407130613Smlaier struct in_addr src; 408130613Smlaier struct mbuf *mp; 409145836Smlaier int iplen, action, error, i, s, count, offp, sfail, stale = 0; 410130613Smlaier 411130613Smlaier pfsyncstats.pfsyncs_ipackets++; 412130613Smlaier 413130613Smlaier /* verify that we have a sync interface configured */ 414130613Smlaier if (!sc->sc_sync_ifp || !pf_status.running) /* XXX PF_LOCK? */ 415130613Smlaier goto done; 416130613Smlaier 417130613Smlaier /* verify that the packet came in on the right interface */ 418130613Smlaier if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) { 419130613Smlaier pfsyncstats.pfsyncs_badif++; 420130613Smlaier goto done; 421130613Smlaier } 422130613Smlaier 423130613Smlaier /* verify that the IP TTL is 255. */ 424130613Smlaier if (ip->ip_ttl != PFSYNC_DFLTTL) { 425130613Smlaier pfsyncstats.pfsyncs_badttl++; 426130613Smlaier goto done; 427130613Smlaier } 428130613Smlaier 429130613Smlaier iplen = ip->ip_hl << 2; 430130613Smlaier 431130613Smlaier if (m->m_pkthdr.len < iplen + sizeof(*ph)) { 432130613Smlaier pfsyncstats.pfsyncs_hdrops++; 433130613Smlaier goto done; 434130613Smlaier } 435130613Smlaier 436130613Smlaier if (iplen + sizeof(*ph) > m->m_len) { 437130613Smlaier if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) { 438130613Smlaier pfsyncstats.pfsyncs_hdrops++; 439130613Smlaier goto done; 440130613Smlaier } 441130613Smlaier ip = mtod(m, struct ip *); 442130613Smlaier } 443130613Smlaier ph = (struct pfsync_header *)((char *)ip + iplen); 444130613Smlaier 445130613Smlaier /* verify the version */ 446130613Smlaier if (ph->version != PFSYNC_VERSION) { 447130613Smlaier pfsyncstats.pfsyncs_badver++; 448130613Smlaier goto done; 449130613Smlaier } 450130613Smlaier 451130613Smlaier action = ph->action; 452130613Smlaier count = ph->count; 453130613Smlaier 454130613Smlaier /* make sure it's a valid action code */ 455130613Smlaier if (action >= PFSYNC_ACT_MAX) { 456130613Smlaier pfsyncstats.pfsyncs_badact++; 457130613Smlaier goto done; 458130613Smlaier } 459130613Smlaier 460130613Smlaier /* Cheaper to grab this now than having to mess with mbufs later */ 461130613Smlaier src = ip->ip_src; 462130613Smlaier 463130613Smlaier switch (action) { 464130613Smlaier case PFSYNC_ACT_CLR: { 465145836Smlaier struct pf_state *nexts; 466130613Smlaier struct pfi_kif *kif; 467130613Smlaier u_int32_t creatorid; 468130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 469130613Smlaier sizeof(*cp), &offp)) == NULL) { 470130613Smlaier pfsyncstats.pfsyncs_badlen++; 471130613Smlaier return; 472130613Smlaier } 473130613Smlaier cp = (struct pfsync_state_clr *)(mp->m_data + offp); 474130613Smlaier creatorid = cp->creatorid; 475130613Smlaier 476130613Smlaier s = splsoftnet(); 477130613Smlaier#ifdef __FreeBSD__ 478130613Smlaier PF_LOCK(); 479130613Smlaier#endif 480130613Smlaier if (cp->ifname[0] == '\0') { 481145836Smlaier for (st = RB_MIN(pf_state_tree_id, &tree_id); 482145836Smlaier st; st = nexts) { 483145836Smlaier nexts = RB_NEXT(pf_state_tree_id, &tree_id, st); 484145836Smlaier if (st->creatorid == creatorid) { 485130613Smlaier st->timeout = PFTM_PURGE; 486145836Smlaier pf_purge_expired_state(st); 487145836Smlaier } 488130613Smlaier } 489130613Smlaier } else { 490130613Smlaier kif = pfi_lookup_if(cp->ifname); 491130613Smlaier if (kif == NULL) { 492130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 493130613Smlaier printf("pfsync_input: PFSYNC_ACT_CLR " 494130613Smlaier "bad interface: %s\n", cp->ifname); 495130613Smlaier splx(s); 496130613Smlaier#ifdef __FreeBSD__ 497130613Smlaier PF_UNLOCK(); 498130613Smlaier#endif 499130613Smlaier goto done; 500130613Smlaier } 501145836Smlaier for (st = RB_MIN(pf_state_tree_lan_ext, 502145836Smlaier &kif->pfik_lan_ext); st; st = nexts) { 503145836Smlaier nexts = RB_NEXT(pf_state_tree_lan_ext, 504145836Smlaier &kif->pfik_lan_ext, st); 505145836Smlaier if (st->creatorid == creatorid) { 506130613Smlaier st->timeout = PFTM_PURGE; 507145836Smlaier pf_purge_expired_state(st); 508145836Smlaier } 509130613Smlaier } 510130613Smlaier } 511130613Smlaier#ifdef __FreeBSD__ 512130613Smlaier PF_UNLOCK(); 513130613Smlaier#endif 514130613Smlaier splx(s); 515130613Smlaier 516130613Smlaier break; 517130613Smlaier } 518130613Smlaier case PFSYNC_ACT_INS: 519130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 520130613Smlaier count * sizeof(*sp), &offp)) == NULL) { 521130613Smlaier pfsyncstats.pfsyncs_badlen++; 522130613Smlaier return; 523130613Smlaier } 524130613Smlaier 525130613Smlaier s = splsoftnet(); 526130613Smlaier#ifdef __FreeBSD__ 527130613Smlaier PF_LOCK(); 528130613Smlaier#endif 529130613Smlaier for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 530130613Smlaier i < count; i++, sp++) { 531130613Smlaier /* check for invalid values */ 532130613Smlaier if (sp->timeout >= PFTM_MAX || 533130613Smlaier sp->src.state > PF_TCPS_PROXY_DST || 534130613Smlaier sp->dst.state > PF_TCPS_PROXY_DST || 535130613Smlaier sp->direction > PF_OUT || 536130613Smlaier (sp->af != AF_INET && sp->af != AF_INET6)) { 537130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 538130613Smlaier printf("pfsync_insert: PFSYNC_ACT_INS: " 539130613Smlaier "invalid value\n"); 540130613Smlaier pfsyncstats.pfsyncs_badstate++; 541130613Smlaier continue; 542130613Smlaier } 543130613Smlaier 544130613Smlaier if ((error = pfsync_insert_net_state(sp))) { 545130613Smlaier if (error == ENOMEM) { 546130613Smlaier splx(s); 547130613Smlaier#ifdef __FreeBSD__ 548130613Smlaier PF_UNLOCK(); 549130613Smlaier#endif 550130613Smlaier goto done; 551130613Smlaier } 552130613Smlaier continue; 553130613Smlaier } 554130613Smlaier } 555130613Smlaier#ifdef __FreeBSD__ 556130613Smlaier PF_UNLOCK(); 557130613Smlaier#endif 558130613Smlaier splx(s); 559130613Smlaier break; 560130613Smlaier case PFSYNC_ACT_UPD: 561130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 562130613Smlaier count * sizeof(*sp), &offp)) == NULL) { 563130613Smlaier pfsyncstats.pfsyncs_badlen++; 564130613Smlaier return; 565130613Smlaier } 566130613Smlaier 567130613Smlaier s = splsoftnet(); 568130613Smlaier#ifdef __FreeBSD__ 569130613Smlaier PF_LOCK(); 570130613Smlaier#endif 571130613Smlaier for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 572130613Smlaier i < count; i++, sp++) { 573145836Smlaier int flags = PFSYNC_FLAG_STALE; 574145836Smlaier 575130613Smlaier /* check for invalid values */ 576130613Smlaier if (sp->timeout >= PFTM_MAX || 577130613Smlaier sp->src.state > PF_TCPS_PROXY_DST || 578130613Smlaier sp->dst.state > PF_TCPS_PROXY_DST) { 579130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 580130613Smlaier printf("pfsync_insert: PFSYNC_ACT_UPD: " 581130613Smlaier "invalid value\n"); 582130613Smlaier pfsyncstats.pfsyncs_badstate++; 583130613Smlaier continue; 584130613Smlaier } 585130613Smlaier 586130613Smlaier bcopy(sp->id, &key.id, sizeof(key.id)); 587130613Smlaier key.creatorid = sp->creatorid; 588130613Smlaier 589130613Smlaier st = pf_find_state_byid(&key); 590130613Smlaier if (st == NULL) { 591130613Smlaier /* insert the update */ 592130613Smlaier if (pfsync_insert_net_state(sp)) 593130613Smlaier pfsyncstats.pfsyncs_badstate++; 594130613Smlaier continue; 595130613Smlaier } 596145836Smlaier sfail = 0; 597145836Smlaier if (st->proto == IPPROTO_TCP) { 598145836Smlaier /* 599145836Smlaier * The state should never go backwards except 600145836Smlaier * for syn-proxy states. Neither should the 601145836Smlaier * sequence window slide backwards. 602145836Smlaier */ 603145836Smlaier if (st->src.state > sp->src.state && 604145836Smlaier (st->src.state < PF_TCPS_PROXY_SRC || 605145836Smlaier sp->src.state >= PF_TCPS_PROXY_SRC)) 606145836Smlaier sfail = 1; 607145836Smlaier else if (SEQ_GT(st->src.seqlo, 608145836Smlaier ntohl(sp->src.seqlo))) 609145836Smlaier sfail = 3; 610145836Smlaier else if (st->dst.state > sp->dst.state) { 611145836Smlaier /* There might still be useful 612145836Smlaier * information about the src state here, 613145836Smlaier * so import that part of the update, 614145836Smlaier * then "fail" so we send the updated 615145836Smlaier * state back to the peer who is missing 616145836Smlaier * our what we know. */ 617145836Smlaier pf_state_peer_ntoh(&sp->src, &st->src); 618145836Smlaier /* XXX do anything with timeouts? */ 619145836Smlaier sfail = 7; 620145836Smlaier flags = 0; 621145836Smlaier } else if (st->dst.state >= TCPS_SYN_SENT && 622145836Smlaier SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo))) 623145836Smlaier sfail = 4; 624145836Smlaier } else { 625145836Smlaier /* 626145836Smlaier * Non-TCP protocol state machine always go 627145836Smlaier * forwards 628145836Smlaier */ 629145836Smlaier if (st->src.state > sp->src.state) 630145836Smlaier sfail = 5; 631145836Smlaier else if ( st->dst.state > sp->dst.state) 632145836Smlaier sfail = 6; 633145836Smlaier } 634145836Smlaier if (sfail) { 635145836Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 636145836Smlaier printf("pfsync: %s stale update " 637145836Smlaier "(%d) id: %016llx " 638145836Smlaier "creatorid: %08x\n", 639145836Smlaier (sfail < 7 ? "ignoring" 640145836Smlaier : "partial"), sfail, 641145836Smlaier#ifdef __FreeBSD__ 642145836Smlaier (unsigned long long)be64toh(st->id), 643145836Smlaier#else 644145836Smlaier betoh64(st->id), 645145836Smlaier#endif 646145836Smlaier ntohl(st->creatorid)); 647145836Smlaier pfsyncstats.pfsyncs_badstate++; 648145836Smlaier 649145836Smlaier if (!(sp->sync_flags & PFSTATE_STALE)) { 650145836Smlaier /* we have a better state, send it */ 651145836Smlaier if (sc->sc_mbuf != NULL && !stale) 652145836Smlaier pfsync_sendout(sc); 653145836Smlaier stale++; 654145836Smlaier if (!st->sync_flags) 655145836Smlaier pfsync_pack_state( 656145836Smlaier PFSYNC_ACT_UPD, st, flags); 657145836Smlaier } 658145836Smlaier continue; 659145836Smlaier } 660130613Smlaier pf_state_peer_ntoh(&sp->src, &st->src); 661130613Smlaier pf_state_peer_ntoh(&sp->dst, &st->dst); 662130613Smlaier st->expire = ntohl(sp->expire) + time_second; 663130613Smlaier st->timeout = sp->timeout; 664130613Smlaier } 665145836Smlaier if (stale && sc->sc_mbuf != NULL) 666145836Smlaier pfsync_sendout(sc); 667130613Smlaier#ifdef __FreeBSD__ 668130613Smlaier PF_UNLOCK(); 669130613Smlaier#endif 670130613Smlaier splx(s); 671130613Smlaier break; 672130613Smlaier /* 673130613Smlaier * It's not strictly necessary for us to support the "uncompressed" 674130613Smlaier * delete action, but it's relatively simple and maintains consistency. 675130613Smlaier */ 676130613Smlaier case PFSYNC_ACT_DEL: 677130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 678130613Smlaier count * sizeof(*sp), &offp)) == NULL) { 679130613Smlaier pfsyncstats.pfsyncs_badlen++; 680130613Smlaier return; 681130613Smlaier } 682130613Smlaier 683130613Smlaier s = splsoftnet(); 684130613Smlaier#ifdef __FreeBSD__ 685130613Smlaier PF_LOCK(); 686130613Smlaier#endif 687130613Smlaier for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 688130613Smlaier i < count; i++, sp++) { 689130613Smlaier bcopy(sp->id, &key.id, sizeof(key.id)); 690130613Smlaier key.creatorid = sp->creatorid; 691130613Smlaier 692130613Smlaier st = pf_find_state_byid(&key); 693130613Smlaier if (st == NULL) { 694130613Smlaier pfsyncstats.pfsyncs_badstate++; 695130613Smlaier continue; 696130613Smlaier } 697130613Smlaier st->timeout = PFTM_PURGE; 698130613Smlaier st->sync_flags |= PFSTATE_FROMSYNC; 699145836Smlaier pf_purge_expired_state(st); 700130613Smlaier } 701130613Smlaier#ifdef __FreeBSD__ 702130613Smlaier PF_UNLOCK(); 703130613Smlaier#endif 704130613Smlaier splx(s); 705130613Smlaier break; 706130613Smlaier case PFSYNC_ACT_UPD_C: { 707130613Smlaier int update_requested = 0; 708130613Smlaier 709130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 710130613Smlaier count * sizeof(*up), &offp)) == NULL) { 711130613Smlaier pfsyncstats.pfsyncs_badlen++; 712130613Smlaier return; 713130613Smlaier } 714130613Smlaier 715130613Smlaier s = splsoftnet(); 716130613Smlaier#ifdef __FreeBSD__ 717130613Smlaier PF_LOCK(); 718130613Smlaier#endif 719130613Smlaier for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp); 720130613Smlaier i < count; i++, up++) { 721130613Smlaier /* check for invalid values */ 722130613Smlaier if (up->timeout >= PFTM_MAX || 723130613Smlaier up->src.state > PF_TCPS_PROXY_DST || 724130613Smlaier up->dst.state > PF_TCPS_PROXY_DST) { 725130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 726130613Smlaier printf("pfsync_insert: " 727130613Smlaier "PFSYNC_ACT_UPD_C: " 728130613Smlaier "invalid value\n"); 729130613Smlaier pfsyncstats.pfsyncs_badstate++; 730130613Smlaier continue; 731130613Smlaier } 732130613Smlaier 733130613Smlaier bcopy(up->id, &key.id, sizeof(key.id)); 734130613Smlaier key.creatorid = up->creatorid; 735130613Smlaier 736130613Smlaier st = pf_find_state_byid(&key); 737130613Smlaier if (st == NULL) { 738130613Smlaier /* We don't have this state. Ask for it. */ 739145836Smlaier error = pfsync_request_update(up, &src); 740145836Smlaier if (error == ENOMEM) { 741145836Smlaier splx(s); 742145836Smlaier goto done; 743145836Smlaier } 744130613Smlaier update_requested = 1; 745130613Smlaier pfsyncstats.pfsyncs_badstate++; 746130613Smlaier continue; 747130613Smlaier } 748145836Smlaier sfail = 0; 749145836Smlaier if (st->proto == IPPROTO_TCP) { 750145836Smlaier /* 751145836Smlaier * The state should never go backwards except 752145836Smlaier * for syn-proxy states. Neither should the 753145836Smlaier * sequence window slide backwards. 754145836Smlaier */ 755145836Smlaier if (st->src.state > up->src.state && 756145836Smlaier (st->src.state < PF_TCPS_PROXY_SRC || 757145836Smlaier up->src.state >= PF_TCPS_PROXY_SRC)) 758145836Smlaier sfail = 1; 759145836Smlaier else if (st->dst.state > up->dst.state) 760145836Smlaier sfail = 2; 761145836Smlaier else if (SEQ_GT(st->src.seqlo, 762145836Smlaier ntohl(up->src.seqlo))) 763145836Smlaier sfail = 3; 764145836Smlaier else if (st->dst.state >= TCPS_SYN_SENT && 765145836Smlaier SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo))) 766145836Smlaier sfail = 4; 767145836Smlaier } else { 768145836Smlaier /* 769145836Smlaier * Non-TCP protocol state machine always go 770145836Smlaier * forwards 771145836Smlaier */ 772145836Smlaier if (st->src.state > up->src.state) 773145836Smlaier sfail = 5; 774145836Smlaier else if (st->dst.state > up->dst.state) 775145836Smlaier sfail = 6; 776145836Smlaier } 777145836Smlaier if (sfail) { 778145836Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 779145836Smlaier printf("pfsync: ignoring stale update " 780145836Smlaier "(%d) id: %016llx " 781145836Smlaier "creatorid: %08x\n", sfail, 782145836Smlaier#ifdef __FreeBSD__ 783145836Smlaier (unsigned long long)be64toh(st->id), 784145836Smlaier#else 785145836Smlaier betoh64(st->id), 786145836Smlaier#endif 787145836Smlaier ntohl(st->creatorid)); 788145836Smlaier pfsyncstats.pfsyncs_badstate++; 789145836Smlaier 790145836Smlaier /* we have a better state, send it out */ 791145836Smlaier if ((!stale || update_requested) && 792145836Smlaier sc->sc_mbuf != NULL) { 793145836Smlaier pfsync_sendout(sc); 794145836Smlaier update_requested = 0; 795145836Smlaier } 796145836Smlaier stale++; 797145836Smlaier if (!st->sync_flags) 798145836Smlaier pfsync_pack_state(PFSYNC_ACT_UPD, st, 799145836Smlaier PFSYNC_FLAG_STALE); 800145836Smlaier continue; 801145836Smlaier } 802130613Smlaier pf_state_peer_ntoh(&up->src, &st->src); 803130613Smlaier pf_state_peer_ntoh(&up->dst, &st->dst); 804130613Smlaier st->expire = ntohl(up->expire) + time_second; 805130613Smlaier st->timeout = up->timeout; 806130613Smlaier } 807145836Smlaier if ((update_requested || stale) && sc->sc_mbuf) 808130613Smlaier pfsync_sendout(sc); 809130613Smlaier#ifdef __FreeBSD__ 810130613Smlaier PF_UNLOCK(); 811130613Smlaier#endif 812130613Smlaier splx(s); 813130613Smlaier break; 814130613Smlaier } 815130613Smlaier case PFSYNC_ACT_DEL_C: 816130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 817130613Smlaier count * sizeof(*dp), &offp)) == NULL) { 818130613Smlaier pfsyncstats.pfsyncs_badlen++; 819130613Smlaier return; 820130613Smlaier } 821130613Smlaier 822130613Smlaier s = splsoftnet(); 823130613Smlaier#ifdef __FreeBSD__ 824130613Smlaier PF_LOCK(); 825130613Smlaier#endif 826130613Smlaier for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp); 827130613Smlaier i < count; i++, dp++) { 828130613Smlaier bcopy(dp->id, &key.id, sizeof(key.id)); 829130613Smlaier key.creatorid = dp->creatorid; 830130613Smlaier 831130613Smlaier st = pf_find_state_byid(&key); 832130613Smlaier if (st == NULL) { 833130613Smlaier pfsyncstats.pfsyncs_badstate++; 834130613Smlaier continue; 835130613Smlaier } 836130613Smlaier st->timeout = PFTM_PURGE; 837130613Smlaier st->sync_flags |= PFSTATE_FROMSYNC; 838145836Smlaier pf_purge_expired_state(st); 839130613Smlaier } 840130613Smlaier#ifdef __FreeBSD__ 841130613Smlaier PF_UNLOCK(); 842130613Smlaier#endif 843130613Smlaier splx(s); 844130613Smlaier break; 845130613Smlaier case PFSYNC_ACT_INS_F: 846130613Smlaier case PFSYNC_ACT_DEL_F: 847130613Smlaier /* not implemented */ 848130613Smlaier break; 849130613Smlaier case PFSYNC_ACT_UREQ: 850130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 851130613Smlaier count * sizeof(*rup), &offp)) == NULL) { 852130613Smlaier pfsyncstats.pfsyncs_badlen++; 853130613Smlaier return; 854130613Smlaier } 855130613Smlaier 856130613Smlaier s = splsoftnet(); 857130613Smlaier#ifdef __FreeBSD__ 858130613Smlaier PF_LOCK(); 859130613Smlaier#endif 860130613Smlaier if (sc->sc_mbuf != NULL) 861130613Smlaier pfsync_sendout(sc); 862130613Smlaier for (i = 0, 863130613Smlaier rup = (struct pfsync_state_upd_req *)(mp->m_data + offp); 864130613Smlaier i < count; i++, rup++) { 865130613Smlaier bcopy(rup->id, &key.id, sizeof(key.id)); 866130613Smlaier key.creatorid = rup->creatorid; 867130613Smlaier 868130613Smlaier if (key.id == 0 && key.creatorid == 0) { 869130613Smlaier sc->sc_ureq_received = time_uptime; 870130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 871130613Smlaier printf("pfsync: received " 872130613Smlaier "bulk update request\n"); 873130613Smlaier pfsync_send_bus(sc, PFSYNC_BUS_START); 874130613Smlaier#ifdef __FreeBSD__ 875130613Smlaier callout_reset(&sc->sc_bulk_tmo, 1 * hz, 876130613Smlaier pfsync_bulk_update, 877130613Smlaier LIST_FIRST(&pfsync_list)); 878130613Smlaier#else 879130613Smlaier timeout_add(&sc->sc_bulk_tmo, 1 * hz); 880130613Smlaier#endif 881130613Smlaier } else { 882130613Smlaier st = pf_find_state_byid(&key); 883130613Smlaier if (st == NULL) { 884130613Smlaier pfsyncstats.pfsyncs_badstate++; 885130613Smlaier continue; 886130613Smlaier } 887145836Smlaier if (!st->sync_flags) 888145836Smlaier pfsync_pack_state(PFSYNC_ACT_UPD, 889145836Smlaier st, 0); 890130613Smlaier } 891130613Smlaier } 892130613Smlaier if (sc->sc_mbuf != NULL) 893130613Smlaier pfsync_sendout(sc); 894130613Smlaier#ifdef __FreeBSD__ 895130613Smlaier PF_UNLOCK(); 896130613Smlaier#endif 897130613Smlaier splx(s); 898130613Smlaier break; 899130613Smlaier case PFSYNC_ACT_BUS: 900130613Smlaier /* If we're not waiting for a bulk update, who cares. */ 901130613Smlaier if (sc->sc_ureq_sent == 0) 902130613Smlaier break; 903130613Smlaier 904130613Smlaier if ((mp = m_pulldown(m, iplen + sizeof(*ph), 905130613Smlaier sizeof(*bus), &offp)) == NULL) { 906130613Smlaier pfsyncstats.pfsyncs_badlen++; 907130613Smlaier return; 908130613Smlaier } 909130613Smlaier bus = (struct pfsync_state_bus *)(mp->m_data + offp); 910130613Smlaier switch (bus->status) { 911130613Smlaier case PFSYNC_BUS_START: 912130613Smlaier#ifdef __FreeBSD__ 913130613Smlaier callout_reset(&sc->sc_bulkfail_tmo, 914130613Smlaier pf_pool_limits[PF_LIMIT_STATES].limit / 915130613Smlaier (PFSYNC_BULKPACKETS * sc->sc_maxcount), 916130613Smlaier pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 917130613Smlaier#else 918130613Smlaier timeout_add(&sc->sc_bulkfail_tmo, 919130613Smlaier pf_pool_limits[PF_LIMIT_STATES].limit / 920130613Smlaier (PFSYNC_BULKPACKETS * sc->sc_maxcount)); 921130613Smlaier#endif 922130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 923130613Smlaier printf("pfsync: received bulk " 924130613Smlaier "update start\n"); 925130613Smlaier break; 926130613Smlaier case PFSYNC_BUS_END: 927130613Smlaier if (time_uptime - ntohl(bus->endtime) >= 928130613Smlaier sc->sc_ureq_sent) { 929130613Smlaier /* that's it, we're happy */ 930130613Smlaier sc->sc_ureq_sent = 0; 931130613Smlaier sc->sc_bulk_tries = 0; 932130613Smlaier#ifdef __FreeBSD__ 933130613Smlaier callout_stop(&sc->sc_bulkfail_tmo); 934130613Smlaier#else 935130613Smlaier timeout_del(&sc->sc_bulkfail_tmo); 936130613Smlaier#endif 937145836Smlaier#if NCARP > 0 /* XXX_IMPORT */ 938145836Smlaier if (!pfsync_sync_ok) 939145836Smlaier carp_suppress_preempt--; 940145836Smlaier#endif 941130613Smlaier pfsync_sync_ok = 1; 942130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 943130613Smlaier printf("pfsync: received valid " 944130613Smlaier "bulk update end\n"); 945130613Smlaier } else { 946130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 947130613Smlaier printf("pfsync: received invalid " 948130613Smlaier "bulk update end: bad timestamp\n"); 949130613Smlaier } 950130613Smlaier break; 951130613Smlaier } 952130613Smlaier break; 953130613Smlaier } 954130613Smlaier 955130613Smlaierdone: 956130613Smlaier if (m) 957130613Smlaier m_freem(m); 958130613Smlaier} 959130613Smlaier 960130613Smlaierint 961126258Smlaierpfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 962126258Smlaier struct rtentry *rt) 963126258Smlaier{ 964126258Smlaier m_freem(m); 965126258Smlaier return (0); 966126258Smlaier} 967126258Smlaier 968126258Smlaier/* ARGSUSED */ 969126258Smlaierint 970126258Smlaierpfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 971126258Smlaier{ 972130613Smlaier#ifndef __FreeBSD__ 973130613Smlaier struct proc *p = curproc; 974130613Smlaier#endif 975126258Smlaier struct pfsync_softc *sc = ifp->if_softc; 976126258Smlaier struct ifreq *ifr = (struct ifreq *)data; 977130613Smlaier struct ip_moptions *imo = &sc->sc_imo; 978130613Smlaier struct pfsyncreq pfsyncr; 979130613Smlaier struct ifnet *sifp; 980130613Smlaier int s, error; 981126258Smlaier 982126258Smlaier switch (cmd) { 983126258Smlaier case SIOCSIFADDR: 984126258Smlaier case SIOCAIFADDR: 985126258Smlaier case SIOCSIFDSTADDR: 986126258Smlaier case SIOCSIFFLAGS: 987126258Smlaier if (ifp->if_flags & IFF_UP) 988126258Smlaier ifp->if_flags |= IFF_RUNNING; 989126258Smlaier else 990126258Smlaier ifp->if_flags &= ~IFF_RUNNING; 991126258Smlaier break; 992126258Smlaier case SIOCSIFMTU: 993126258Smlaier if (ifr->ifr_mtu < PFSYNC_MINMTU) 994126258Smlaier return (EINVAL); 995126258Smlaier if (ifr->ifr_mtu > MCLBYTES) 996126258Smlaier ifr->ifr_mtu = MCLBYTES; 997126258Smlaier s = splnet(); 998130613Smlaier#ifdef __FreeBSD__ 999130613Smlaier PF_LOCK(); 1000130613Smlaier#endif 1001130613Smlaier if (ifr->ifr_mtu < ifp->if_mtu) { 1002126258Smlaier pfsync_sendout(sc); 1003130613Smlaier } 1004126258Smlaier pfsync_setmtu(sc, ifr->ifr_mtu); 1005130613Smlaier#ifdef __FreeBSD__ 1006130613Smlaier PF_UNLOCK(); 1007130613Smlaier#endif 1008126258Smlaier splx(s); 1009126258Smlaier break; 1010130613Smlaier case SIOCGETPFSYNC: 1011130613Smlaier#ifdef __FreeBSD__ 1012130613Smlaier /* XXX: read unlocked */ 1013130613Smlaier#endif 1014130613Smlaier bzero(&pfsyncr, sizeof(pfsyncr)); 1015130613Smlaier if (sc->sc_sync_ifp) 1016145836Smlaier strlcpy(pfsyncr.pfsyncr_syncdev, 1017130613Smlaier sc->sc_sync_ifp->if_xname, IFNAMSIZ); 1018145836Smlaier pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer; 1019130613Smlaier pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates; 1020130613Smlaier if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr)))) 1021130613Smlaier return (error); 1022130613Smlaier break; 1023130613Smlaier case SIOCSETPFSYNC: 1024130613Smlaier#ifdef __FreeBSD__ 1025130613Smlaier if ((error = suser(curthread)) != 0) 1026130613Smlaier#else 1027130613Smlaier if ((error = suser(p, p->p_acflag)) != 0) 1028130613Smlaier#endif 1029130613Smlaier return (error); 1030130613Smlaier if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr)))) 1031130613Smlaier return (error); 1032130613Smlaier 1033145836Smlaier if (pfsyncr.pfsyncr_syncpeer.s_addr == 0) 1034145836Smlaier sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP; 1035145836Smlaier else 1036145836Smlaier sc->sc_sync_peer.s_addr = 1037145836Smlaier pfsyncr.pfsyncr_syncpeer.s_addr; 1038145836Smlaier 1039130613Smlaier if (pfsyncr.pfsyncr_maxupdates > 255) 1040130613Smlaier return (EINVAL); 1041130613Smlaier#ifdef __FreeBSD__ 1042147261Smlaier callout_drain(&sc->sc_send_tmo); 1043130613Smlaier PF_LOCK(); 1044130613Smlaier#endif 1045130613Smlaier sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; 1046130613Smlaier 1047145836Smlaier if (pfsyncr.pfsyncr_syncdev[0] == 0) { 1048130613Smlaier sc->sc_sync_ifp = NULL; 1049130613Smlaier if (sc->sc_mbuf_net != NULL) { 1050130613Smlaier /* Don't keep stale pfsync packets around. */ 1051130613Smlaier s = splnet(); 1052130613Smlaier m_freem(sc->sc_mbuf_net); 1053130613Smlaier sc->sc_mbuf_net = NULL; 1054130613Smlaier sc->sc_statep_net.s = NULL; 1055130613Smlaier splx(s); 1056130613Smlaier } 1057145836Smlaier if (imo->imo_num_memberships > 0) { 1058145836Smlaier in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1059145836Smlaier imo->imo_multicast_ifp = NULL; 1060145836Smlaier } 1061130613Smlaier#ifdef __FreeBSD__ 1062130613Smlaier PF_UNLOCK(); 1063130613Smlaier#endif 1064130613Smlaier break; 1065130613Smlaier } 1066145836Smlaier 1067145836Smlaier if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) { 1068130613Smlaier#ifdef __FreeBSD__ 1069130613Smlaier PF_UNLOCK(); 1070130613Smlaier#endif 1071130613Smlaier return (EINVAL); 1072130613Smlaier } 1073130613Smlaier 1074130613Smlaier s = splnet(); 1075141584Smlaier#ifdef __FreeBSD__ 1076141584Smlaier if (sifp->if_mtu < SCP2IFP(sc)->if_mtu || 1077141584Smlaier#else 1078130613Smlaier if (sifp->if_mtu < sc->sc_if.if_mtu || 1079141584Smlaier#endif 1080130613Smlaier (sc->sc_sync_ifp != NULL && 1081130613Smlaier sifp->if_mtu < sc->sc_sync_ifp->if_mtu) || 1082130613Smlaier sifp->if_mtu < MCLBYTES - sizeof(struct ip)) 1083130613Smlaier pfsync_sendout(sc); 1084130613Smlaier sc->sc_sync_ifp = sifp; 1085130613Smlaier 1086141584Smlaier#ifdef __FreeBSD__ 1087141584Smlaier pfsync_setmtu(sc, SCP2IFP(sc)->if_mtu); 1088141584Smlaier#else 1089130613Smlaier pfsync_setmtu(sc, sc->sc_if.if_mtu); 1090141584Smlaier#endif 1091130613Smlaier 1092130613Smlaier if (imo->imo_num_memberships > 0) { 1093130613Smlaier in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1094130613Smlaier imo->imo_multicast_ifp = NULL; 1095130613Smlaier } 1096130613Smlaier 1097145836Smlaier if (sc->sc_sync_ifp && 1098145836Smlaier sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) { 1099130613Smlaier struct in_addr addr; 1100130613Smlaier 1101145836Smlaier if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) { 1102145836Smlaier sc->sc_sync_ifp = NULL; 1103130613Smlaier#ifdef __FreeBSD__ 1104145836Smlaier PF_UNLOCK(); 1105145836Smlaier#endif 1106145836Smlaier splx(s); 1107145836Smlaier return (EADDRNOTAVAIL); 1108145836Smlaier } 1109145836Smlaier#ifdef __FreeBSD__ 1110130613Smlaier PF_UNLOCK(); /* addmulti mallocs w/ WAITOK */ 1111130613Smlaier addr.s_addr = htonl(INADDR_PFSYNC_GROUP); 1112130613Smlaier#else 1113130613Smlaier addr.s_addr = INADDR_PFSYNC_GROUP; 1114130613Smlaier#endif 1115145836Smlaier 1116130613Smlaier if ((imo->imo_membership[0] = 1117130613Smlaier in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) { 1118145836Smlaier sc->sc_sync_ifp = NULL; 1119130613Smlaier splx(s); 1120130613Smlaier return (ENOBUFS); 1121130613Smlaier } 1122130613Smlaier imo->imo_num_memberships++; 1123130613Smlaier imo->imo_multicast_ifp = sc->sc_sync_ifp; 1124130613Smlaier imo->imo_multicast_ttl = PFSYNC_DFLTTL; 1125130613Smlaier imo->imo_multicast_loop = 0; 1126145836Smlaier } 1127130613Smlaier 1128145836Smlaier if (sc->sc_sync_ifp || 1129145836Smlaier sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) { 1130130613Smlaier /* Request a full state table update. */ 1131130613Smlaier#ifdef __FreeBSD__ 1132130613Smlaier PF_LOCK(); 1133145836Smlaier#endif 1134130613Smlaier sc->sc_ureq_sent = time_uptime; 1135145836Smlaier#if NCARP > 0 1136145836Smlaier if (pfsync_sync_ok) 1137145836Smlaier carp_suppress_preempt++; 1138130613Smlaier#endif 1139130613Smlaier pfsync_sync_ok = 0; 1140130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1141130613Smlaier printf("pfsync: requesting bulk update\n"); 1142130613Smlaier#ifdef __FreeBSD__ 1143130613Smlaier callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, 1144130613Smlaier pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 1145130613Smlaier#else 1146130613Smlaier timeout_add(&sc->sc_bulkfail_tmo, 5 * hz); 1147130613Smlaier#endif 1148145836Smlaier error = pfsync_request_update(NULL, NULL); 1149145836Smlaier if (error == ENOMEM) { 1150145836Smlaier#ifdef __FreeBSD__ 1151145836Smlaier PF_UNLOCK(); 1152145836Smlaier#endif 1153145836Smlaier splx(s); 1154145836Smlaier return (ENOMEM); 1155145836Smlaier } 1156130613Smlaier pfsync_sendout(sc); 1157130613Smlaier } 1158130613Smlaier#ifdef __FreeBSD__ 1159130613Smlaier PF_UNLOCK(); 1160130613Smlaier#endif 1161130613Smlaier splx(s); 1162130613Smlaier 1163130613Smlaier break; 1164130613Smlaier 1165126258Smlaier default: 1166126258Smlaier return (ENOTTY); 1167126258Smlaier } 1168126258Smlaier 1169126258Smlaier return (0); 1170126258Smlaier} 1171126258Smlaier 1172126258Smlaiervoid 1173130613Smlaierpfsync_setmtu(struct pfsync_softc *sc, int mtu_req) 1174130613Smlaier{ 1175126258Smlaier int mtu; 1176130613Smlaier 1177130613Smlaier if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req) 1178130613Smlaier mtu = sc->sc_sync_ifp->if_mtu; 1179130613Smlaier else 1180130613Smlaier mtu = mtu_req; 1181130613Smlaier 1182130613Smlaier sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) / 1183130613Smlaier sizeof(struct pfsync_state); 1184130613Smlaier if (sc->sc_maxcount > 254) 1185130613Smlaier sc->sc_maxcount = 254; 1186141584Smlaier#ifdef __FreeBSD__ 1187141584Smlaier SCP2IFP(sc)->if_mtu = sizeof(struct pfsync_header) + 1188141584Smlaier sc->sc_maxcount * sizeof(struct pfsync_state); 1189141584Smlaier#else 1190126258Smlaier sc->sc_if.if_mtu = sizeof(struct pfsync_header) + 1191130613Smlaier sc->sc_maxcount * sizeof(struct pfsync_state); 1192141584Smlaier#endif 1193126258Smlaier} 1194126258Smlaier 1195126258Smlaierstruct mbuf * 1196130613Smlaierpfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp) 1197126258Smlaier{ 1198126258Smlaier struct pfsync_header *h; 1199126258Smlaier struct mbuf *m; 1200126258Smlaier int len; 1201126258Smlaier 1202130613Smlaier#ifdef __FreeBSD__ 1203130613Smlaier PF_ASSERT(MA_OWNED); 1204130613Smlaier#endif 1205126258Smlaier MGETHDR(m, M_DONTWAIT, MT_DATA); 1206126258Smlaier if (m == NULL) { 1207141584Smlaier#ifdef __FreeBSD__ 1208141584Smlaier SCP2IFP(sc)->if_oerrors++; 1209141584Smlaier#else 1210126258Smlaier sc->sc_if.if_oerrors++; 1211141584Smlaier#endif 1212126258Smlaier return (NULL); 1213126258Smlaier } 1214126258Smlaier 1215130613Smlaier switch (action) { 1216130613Smlaier case PFSYNC_ACT_CLR: 1217130613Smlaier len = sizeof(struct pfsync_header) + 1218130613Smlaier sizeof(struct pfsync_state_clr); 1219130613Smlaier break; 1220130613Smlaier case PFSYNC_ACT_UPD_C: 1221130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) + 1222130613Smlaier sizeof(struct pfsync_header); 1223130613Smlaier break; 1224130613Smlaier case PFSYNC_ACT_DEL_C: 1225130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) + 1226130613Smlaier sizeof(struct pfsync_header); 1227130613Smlaier break; 1228130613Smlaier case PFSYNC_ACT_UREQ: 1229130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) + 1230130613Smlaier sizeof(struct pfsync_header); 1231130613Smlaier break; 1232130613Smlaier case PFSYNC_ACT_BUS: 1233130613Smlaier len = sizeof(struct pfsync_header) + 1234130613Smlaier sizeof(struct pfsync_state_bus); 1235130613Smlaier break; 1236130613Smlaier default: 1237130613Smlaier len = (sc->sc_maxcount * sizeof(struct pfsync_state)) + 1238130613Smlaier sizeof(struct pfsync_header); 1239130613Smlaier break; 1240130613Smlaier } 1241130613Smlaier 1242126258Smlaier if (len > MHLEN) { 1243126258Smlaier MCLGET(m, M_DONTWAIT); 1244126258Smlaier if ((m->m_flags & M_EXT) == 0) { 1245126258Smlaier m_free(m); 1246141584Smlaier#ifdef __FreeBSD__ 1247141584Smlaier SCP2IFP(sc)->if_oerrors++; 1248141584Smlaier#else 1249126258Smlaier sc->sc_if.if_oerrors++; 1250141584Smlaier#endif 1251126258Smlaier return (NULL); 1252126258Smlaier } 1253130613Smlaier m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1); 1254130613Smlaier } else 1255130613Smlaier MH_ALIGN(m, len); 1256130613Smlaier 1257126258Smlaier m->m_pkthdr.rcvif = NULL; 1258130613Smlaier m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header); 1259126258Smlaier h = mtod(m, struct pfsync_header *); 1260126258Smlaier h->version = PFSYNC_VERSION; 1261126258Smlaier h->af = 0; 1262126258Smlaier h->count = 0; 1263126258Smlaier h->action = action; 1264126258Smlaier 1265130613Smlaier *sp = (void *)((char *)h + PFSYNC_HDRLEN); 1266127145Smlaier#ifdef __FreeBSD__ 1267126261Smlaier callout_reset(&sc->sc_tmo, hz, pfsync_timeout, 1268126261Smlaier LIST_FIRST(&pfsync_list)); 1269126261Smlaier#else 1270126258Smlaier timeout_add(&sc->sc_tmo, hz); 1271126261Smlaier#endif 1272126258Smlaier return (m); 1273126258Smlaier} 1274126258Smlaier 1275126258Smlaierint 1276145836Smlaierpfsync_pack_state(u_int8_t action, struct pf_state *st, int flags) 1277126258Smlaier{ 1278127145Smlaier#ifdef __FreeBSD__ 1279141584Smlaier struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1280126261Smlaier#else 1281126258Smlaier struct ifnet *ifp = &pfsyncif.sc_if; 1282130613Smlaier#endif 1283126258Smlaier struct pfsync_softc *sc = ifp->if_softc; 1284130613Smlaier struct pfsync_header *h, *h_net; 1285130613Smlaier struct pfsync_state *sp = NULL; 1286130613Smlaier struct pfsync_state_upd *up = NULL; 1287130613Smlaier struct pfsync_state_del *dp = NULL; 1288130613Smlaier struct pf_rule *r; 1289126258Smlaier u_long secs; 1290130613Smlaier int s, ret = 0; 1291130613Smlaier u_int8_t i = 255, newaction = 0; 1292126258Smlaier 1293130613Smlaier#ifdef __FreeBSD__ 1294130613Smlaier PF_ASSERT(MA_OWNED); 1295130613Smlaier#endif 1296130613Smlaier /* 1297130613Smlaier * If a packet falls in the forest and there's nobody around to 1298130613Smlaier * hear, does it make a sound? 1299130613Smlaier */ 1300145836Smlaier if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL && 1301145836Smlaier sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) { 1302130613Smlaier /* Don't leave any stale pfsync packets hanging around. */ 1303130613Smlaier if (sc->sc_mbuf != NULL) { 1304130613Smlaier m_freem(sc->sc_mbuf); 1305130613Smlaier sc->sc_mbuf = NULL; 1306130613Smlaier sc->sc_statep.s = NULL; 1307130613Smlaier } 1308130613Smlaier return (0); 1309130613Smlaier } 1310130613Smlaier 1311126258Smlaier if (action >= PFSYNC_ACT_MAX) 1312126258Smlaier return (EINVAL); 1313126258Smlaier 1314126258Smlaier s = splnet(); 1315130613Smlaier if (sc->sc_mbuf == NULL) { 1316130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 1317130613Smlaier (void *)&sc->sc_statep.s)) == NULL) { 1318126258Smlaier splx(s); 1319126258Smlaier return (ENOMEM); 1320126258Smlaier } 1321130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1322126258Smlaier } else { 1323130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1324126258Smlaier if (h->action != action) { 1325126258Smlaier pfsync_sendout(sc); 1326130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 1327130613Smlaier (void *)&sc->sc_statep.s)) == NULL) { 1328126258Smlaier splx(s); 1329126258Smlaier return (ENOMEM); 1330126258Smlaier } 1331130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1332130613Smlaier } else { 1333130613Smlaier /* 1334130613Smlaier * If it's an update, look in the packet to see if 1335130613Smlaier * we already have an update for the state. 1336130613Smlaier */ 1337130613Smlaier if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) { 1338130613Smlaier struct pfsync_state *usp = 1339130613Smlaier (void *)((char *)h + PFSYNC_HDRLEN); 1340130613Smlaier 1341130613Smlaier for (i = 0; i < h->count; i++) { 1342130613Smlaier if (!memcmp(usp->id, &st->id, 1343130613Smlaier PFSYNC_ID_LEN) && 1344130613Smlaier usp->creatorid == st->creatorid) { 1345130613Smlaier sp = usp; 1346130613Smlaier sp->updates++; 1347130613Smlaier break; 1348130613Smlaier } 1349130613Smlaier usp++; 1350130613Smlaier } 1351130613Smlaier } 1352126258Smlaier } 1353126258Smlaier } 1354126258Smlaier 1355130613Smlaier secs = time_second; 1356126258Smlaier 1357130613Smlaier st->pfsync_time = time_uptime; 1358130613Smlaier TAILQ_REMOVE(&state_updates, st, u.s.entry_updates); 1359130613Smlaier TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates); 1360130613Smlaier 1361130613Smlaier if (sp == NULL) { 1362130613Smlaier /* not a "duplicate" update */ 1363130613Smlaier i = 255; 1364130613Smlaier sp = sc->sc_statep.s++; 1365130613Smlaier sc->sc_mbuf->m_pkthdr.len = 1366130613Smlaier sc->sc_mbuf->m_len += sizeof(struct pfsync_state); 1367130613Smlaier h->count++; 1368130613Smlaier bzero(sp, sizeof(*sp)); 1369130613Smlaier 1370130613Smlaier bcopy(&st->id, sp->id, sizeof(sp->id)); 1371130613Smlaier sp->creatorid = st->creatorid; 1372130613Smlaier 1373130613Smlaier strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname)); 1374130613Smlaier pf_state_host_hton(&st->lan, &sp->lan); 1375130613Smlaier pf_state_host_hton(&st->gwy, &sp->gwy); 1376130613Smlaier pf_state_host_hton(&st->ext, &sp->ext); 1377130613Smlaier 1378130613Smlaier bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); 1379130613Smlaier 1380130613Smlaier sp->creation = htonl(secs - st->creation); 1381130613Smlaier sp->packets[0] = htonl(st->packets[0]); 1382130613Smlaier sp->packets[1] = htonl(st->packets[1]); 1383130613Smlaier sp->bytes[0] = htonl(st->bytes[0]); 1384130613Smlaier sp->bytes[1] = htonl(st->bytes[1]); 1385130613Smlaier if ((r = st->rule.ptr) == NULL) 1386130613Smlaier sp->rule = htonl(-1); 1387130613Smlaier else 1388130613Smlaier sp->rule = htonl(r->nr); 1389130613Smlaier if ((r = st->anchor.ptr) == NULL) 1390130613Smlaier sp->anchor = htonl(-1); 1391130613Smlaier else 1392130613Smlaier sp->anchor = htonl(r->nr); 1393130613Smlaier sp->af = st->af; 1394130613Smlaier sp->proto = st->proto; 1395130613Smlaier sp->direction = st->direction; 1396130613Smlaier sp->log = st->log; 1397130613Smlaier sp->allow_opts = st->allow_opts; 1398130613Smlaier sp->timeout = st->timeout; 1399130613Smlaier 1400145836Smlaier if (flags & PFSYNC_FLAG_STALE) 1401145836Smlaier sp->sync_flags |= PFSTATE_STALE; 1402130613Smlaier } 1403130613Smlaier 1404126258Smlaier pf_state_peer_hton(&st->src, &sp->src); 1405126258Smlaier pf_state_peer_hton(&st->dst, &sp->dst); 1406126258Smlaier 1407126258Smlaier if (st->expire <= secs) 1408126258Smlaier sp->expire = htonl(0); 1409126258Smlaier else 1410126258Smlaier sp->expire = htonl(st->expire - secs); 1411126258Smlaier 1412130613Smlaier /* do we need to build "compressed" actions for network transfer? */ 1413145836Smlaier if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) { 1414130613Smlaier switch (action) { 1415130613Smlaier case PFSYNC_ACT_UPD: 1416130613Smlaier newaction = PFSYNC_ACT_UPD_C; 1417130613Smlaier break; 1418130613Smlaier case PFSYNC_ACT_DEL: 1419130613Smlaier newaction = PFSYNC_ACT_DEL_C; 1420130613Smlaier break; 1421130613Smlaier default: 1422130613Smlaier /* by default we just send the uncompressed states */ 1423130613Smlaier break; 1424130613Smlaier } 1425130613Smlaier } 1426130613Smlaier 1427130613Smlaier if (newaction) { 1428130613Smlaier if (sc->sc_mbuf_net == NULL) { 1429130613Smlaier if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction, 1430130613Smlaier (void *)&sc->sc_statep_net.s)) == NULL) { 1431130613Smlaier splx(s); 1432130613Smlaier return (ENOMEM); 1433130613Smlaier } 1434130613Smlaier } 1435130613Smlaier h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *); 1436130613Smlaier 1437130613Smlaier switch (newaction) { 1438130613Smlaier case PFSYNC_ACT_UPD_C: 1439130613Smlaier if (i != 255) { 1440130613Smlaier up = (void *)((char *)h_net + 1441130613Smlaier PFSYNC_HDRLEN + (i * sizeof(*up))); 1442130613Smlaier up->updates++; 1443130613Smlaier } else { 1444130613Smlaier h_net->count++; 1445130613Smlaier sc->sc_mbuf_net->m_pkthdr.len = 1446130613Smlaier sc->sc_mbuf_net->m_len += sizeof(*up); 1447130613Smlaier up = sc->sc_statep_net.u++; 1448130613Smlaier 1449130613Smlaier bzero(up, sizeof(*up)); 1450130613Smlaier bcopy(&st->id, up->id, sizeof(up->id)); 1451130613Smlaier up->creatorid = st->creatorid; 1452130613Smlaier } 1453130613Smlaier up->timeout = st->timeout; 1454130613Smlaier up->expire = sp->expire; 1455130613Smlaier up->src = sp->src; 1456130613Smlaier up->dst = sp->dst; 1457130613Smlaier break; 1458130613Smlaier case PFSYNC_ACT_DEL_C: 1459130613Smlaier sc->sc_mbuf_net->m_pkthdr.len = 1460130613Smlaier sc->sc_mbuf_net->m_len += sizeof(*dp); 1461130613Smlaier dp = sc->sc_statep_net.d++; 1462130613Smlaier h_net->count++; 1463130613Smlaier 1464130613Smlaier bzero(dp, sizeof(*dp)); 1465130613Smlaier bcopy(&st->id, dp->id, sizeof(dp->id)); 1466130613Smlaier dp->creatorid = st->creatorid; 1467130613Smlaier break; 1468130613Smlaier } 1469130613Smlaier } 1470130613Smlaier 1471130613Smlaier if (h->count == sc->sc_maxcount || 1472130613Smlaier (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates))) 1473126258Smlaier ret = pfsync_sendout(sc); 1474126258Smlaier 1475126258Smlaier splx(s); 1476130613Smlaier return (ret); 1477126258Smlaier} 1478126258Smlaier 1479130613Smlaier/* This must be called in splnet() */ 1480126258Smlaierint 1481130613Smlaierpfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src) 1482126258Smlaier{ 1483127145Smlaier#ifdef __FreeBSD__ 1484141584Smlaier struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1485126261Smlaier#else 1486126258Smlaier struct ifnet *ifp = &pfsyncif.sc_if; 1487130613Smlaier#endif 1488130613Smlaier struct pfsync_header *h; 1489126258Smlaier struct pfsync_softc *sc = ifp->if_softc; 1490130613Smlaier struct pfsync_state_upd_req *rup; 1491145836Smlaier int ret = 0; 1492130613Smlaier 1493130613Smlaier#ifdef __FreeBSD__ 1494130613Smlaier PF_ASSERT(MA_OWNED); 1495126261Smlaier#endif 1496130613Smlaier if (sc->sc_mbuf == NULL) { 1497130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1498145836Smlaier (void *)&sc->sc_statep.s)) == NULL) 1499130613Smlaier return (ENOMEM); 1500130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1501130613Smlaier } else { 1502130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1503130613Smlaier if (h->action != PFSYNC_ACT_UREQ) { 1504130613Smlaier pfsync_sendout(sc); 1505130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1506145836Smlaier (void *)&sc->sc_statep.s)) == NULL) 1507130613Smlaier return (ENOMEM); 1508130613Smlaier h = mtod(sc->sc_mbuf, struct pfsync_header *); 1509130613Smlaier } 1510130613Smlaier } 1511130613Smlaier 1512130613Smlaier if (src != NULL) 1513130613Smlaier sc->sc_sendaddr = *src; 1514130613Smlaier sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup); 1515130613Smlaier h->count++; 1516130613Smlaier rup = sc->sc_statep.r++; 1517130613Smlaier bzero(rup, sizeof(*rup)); 1518130613Smlaier if (up != NULL) { 1519130613Smlaier bcopy(up->id, rup->id, sizeof(rup->id)); 1520130613Smlaier rup->creatorid = up->creatorid; 1521130613Smlaier } 1522130613Smlaier 1523130613Smlaier if (h->count == sc->sc_maxcount) 1524130613Smlaier ret = pfsync_sendout(sc); 1525130613Smlaier 1526130613Smlaier return (ret); 1527130613Smlaier} 1528130613Smlaier 1529130613Smlaierint 1530130613Smlaierpfsync_clear_states(u_int32_t creatorid, char *ifname) 1531130613Smlaier{ 1532130613Smlaier#ifdef __FreeBSD__ 1533141584Smlaier struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list)); 1534130613Smlaier#else 1535130613Smlaier struct ifnet *ifp = &pfsyncif.sc_if; 1536130613Smlaier#endif 1537130613Smlaier struct pfsync_softc *sc = ifp->if_softc; 1538130613Smlaier struct pfsync_state_clr *cp; 1539126258Smlaier int s, ret; 1540126258Smlaier 1541126258Smlaier s = splnet(); 1542130613Smlaier#ifdef __FreeBSD__ 1543130613Smlaier PF_ASSERT(MA_OWNED); 1544130613Smlaier#endif 1545130613Smlaier if (sc->sc_mbuf != NULL) 1546130613Smlaier pfsync_sendout(sc); 1547130613Smlaier if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR, 1548130613Smlaier (void *)&sc->sc_statep.c)) == NULL) { 1549126258Smlaier splx(s); 1550126258Smlaier return (ENOMEM); 1551126258Smlaier } 1552130613Smlaier sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp); 1553130613Smlaier cp = sc->sc_statep.c; 1554130613Smlaier cp->creatorid = creatorid; 1555130613Smlaier if (ifname != NULL) 1556130613Smlaier strlcpy(cp->ifname, ifname, IFNAMSIZ); 1557126258Smlaier 1558126258Smlaier ret = (pfsync_sendout(sc)); 1559126258Smlaier splx(s); 1560126258Smlaier return (ret); 1561126258Smlaier} 1562126258Smlaier 1563126258Smlaiervoid 1564126258Smlaierpfsync_timeout(void *v) 1565126258Smlaier{ 1566126258Smlaier struct pfsync_softc *sc = v; 1567126258Smlaier int s; 1568126258Smlaier 1569126258Smlaier s = splnet(); 1570130613Smlaier#ifdef __FreeBSD__ 1571130613Smlaier PF_LOCK(); 1572130613Smlaier#endif 1573126258Smlaier pfsync_sendout(sc); 1574130613Smlaier#ifdef __FreeBSD__ 1575130613Smlaier PF_UNLOCK(); 1576130613Smlaier#endif 1577126258Smlaier splx(s); 1578126258Smlaier} 1579126258Smlaier 1580145836Smlaier/* This must be called in splnet() */ 1581130613Smlaiervoid 1582130613Smlaierpfsync_send_bus(struct pfsync_softc *sc, u_int8_t status) 1583130613Smlaier{ 1584130613Smlaier struct pfsync_state_bus *bus; 1585130613Smlaier 1586130613Smlaier#ifdef __FreeBSD__ 1587130613Smlaier PF_ASSERT(MA_OWNED); 1588130613Smlaier#endif 1589130613Smlaier if (sc->sc_mbuf != NULL) 1590130613Smlaier pfsync_sendout(sc); 1591130613Smlaier 1592130613Smlaier if (pfsync_sync_ok && 1593130613Smlaier (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS, 1594130613Smlaier (void *)&sc->sc_statep.b)) != NULL) { 1595130613Smlaier sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus); 1596130613Smlaier bus = sc->sc_statep.b; 1597130613Smlaier bus->creatorid = pf_status.hostid; 1598130613Smlaier bus->status = status; 1599130613Smlaier bus->endtime = htonl(time_uptime - sc->sc_ureq_received); 1600130613Smlaier pfsync_sendout(sc); 1601130613Smlaier } 1602130613Smlaier} 1603130613Smlaier 1604130613Smlaiervoid 1605130613Smlaierpfsync_bulk_update(void *v) 1606130613Smlaier{ 1607130613Smlaier struct pfsync_softc *sc = v; 1608130613Smlaier int s, i = 0; 1609130613Smlaier struct pf_state *state; 1610130613Smlaier 1611130613Smlaier#ifdef __FreeBSD__ 1612130613Smlaier PF_LOCK(); 1613130613Smlaier#endif 1614130613Smlaier s = splnet(); 1615130613Smlaier if (sc->sc_mbuf != NULL) 1616130613Smlaier pfsync_sendout(sc); 1617130613Smlaier 1618130613Smlaier /* 1619130613Smlaier * Grab at most PFSYNC_BULKPACKETS worth of states which have not 1620130613Smlaier * been sent since the latest request was made. 1621130613Smlaier */ 1622130613Smlaier while ((state = TAILQ_FIRST(&state_updates)) != NULL && 1623130613Smlaier ++i < (sc->sc_maxcount * PFSYNC_BULKPACKETS)) { 1624130613Smlaier if (state->pfsync_time > sc->sc_ureq_received) { 1625130613Smlaier /* we're done */ 1626130613Smlaier pfsync_send_bus(sc, PFSYNC_BUS_END); 1627130613Smlaier sc->sc_ureq_received = 0; 1628130613Smlaier#ifdef __FreeBSD__ 1629130613Smlaier callout_stop(&sc->sc_bulk_tmo); 1630130613Smlaier#else 1631130613Smlaier timeout_del(&sc->sc_bulk_tmo); 1632130613Smlaier#endif 1633130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1634130613Smlaier printf("pfsync: bulk update complete\n"); 1635130613Smlaier break; 1636130613Smlaier } else { 1637130613Smlaier /* send an update and move to end of list */ 1638130613Smlaier if (!state->sync_flags) 1639130613Smlaier pfsync_pack_state(PFSYNC_ACT_UPD, state, 0); 1640130613Smlaier state->pfsync_time = time_uptime; 1641130613Smlaier TAILQ_REMOVE(&state_updates, state, u.s.entry_updates); 1642130613Smlaier TAILQ_INSERT_TAIL(&state_updates, state, 1643130613Smlaier u.s.entry_updates); 1644130613Smlaier 1645130613Smlaier /* look again for more in a bit */ 1646130613Smlaier#ifdef __FreeBSD__ 1647130613Smlaier callout_reset(&sc->sc_bulk_tmo, 1, pfsync_timeout, 1648130613Smlaier LIST_FIRST(&pfsync_list)); 1649130613Smlaier#else 1650130613Smlaier timeout_add(&sc->sc_bulk_tmo, 1); 1651130613Smlaier#endif 1652130613Smlaier } 1653130613Smlaier } 1654130613Smlaier if (sc->sc_mbuf != NULL) 1655130613Smlaier pfsync_sendout(sc); 1656130613Smlaier splx(s); 1657130613Smlaier#ifdef __FreeBSD__ 1658130613Smlaier PF_UNLOCK(); 1659130613Smlaier#endif 1660130613Smlaier} 1661130613Smlaier 1662130613Smlaiervoid 1663130613Smlaierpfsync_bulkfail(void *v) 1664130613Smlaier{ 1665130613Smlaier struct pfsync_softc *sc = v; 1666145836Smlaier int s, error; 1667130613Smlaier 1668130613Smlaier#ifdef __FreeBSD__ 1669130613Smlaier PF_LOCK(); 1670130613Smlaier#endif 1671130613Smlaier if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) { 1672130613Smlaier /* Try again in a bit */ 1673130613Smlaier#ifdef __FreeBSD__ 1674130613Smlaier callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail, 1675130613Smlaier LIST_FIRST(&pfsync_list)); 1676130613Smlaier#else 1677130613Smlaier timeout_add(&sc->sc_bulkfail_tmo, 5 * hz); 1678130613Smlaier#endif 1679145836Smlaier s = splnet(); 1680145836Smlaier error = pfsync_request_update(NULL, NULL); 1681145836Smlaier if (error == ENOMEM) { 1682145836Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1683145836Smlaier printf("pfsync: cannot allocate mbufs for " 1684145836Smlaier "bulk update\n"); 1685145836Smlaier } else 1686145836Smlaier pfsync_sendout(sc); 1687145836Smlaier splx(s); 1688130613Smlaier } else { 1689130613Smlaier /* Pretend like the transfer was ok */ 1690130613Smlaier sc->sc_ureq_sent = 0; 1691130613Smlaier sc->sc_bulk_tries = 0; 1692145836Smlaier#if NCARP > 0 1693145836Smlaier if (!pfsync_sync_ok) 1694145836Smlaier carp_suppress_preempt--; 1695145836Smlaier#endif 1696130613Smlaier pfsync_sync_ok = 1; 1697130613Smlaier if (pf_status.debug >= PF_DEBUG_MISC) 1698130613Smlaier printf("pfsync: failed to receive " 1699130613Smlaier "bulk update status\n"); 1700130613Smlaier#ifdef __FreeBSD__ 1701130613Smlaier callout_stop(&sc->sc_bulkfail_tmo); 1702130613Smlaier#else 1703130613Smlaier timeout_del(&sc->sc_bulkfail_tmo); 1704130613Smlaier#endif 1705130613Smlaier } 1706130613Smlaier#ifdef __FreeBSD__ 1707130613Smlaier PF_UNLOCK(); 1708130613Smlaier#endif 1709130613Smlaier} 1710130613Smlaier 1711145836Smlaier/* This must be called in splnet() */ 1712126258Smlaierint 1713126258Smlaierpfsync_sendout(sc) 1714126258Smlaier struct pfsync_softc *sc; 1715126258Smlaier{ 1716138666Smlaier#if NBPFILTER > 0 1717141584Smlaier# ifdef __FreeBSD__ 1718141584Smlaier struct ifnet *ifp = SCP2IFP(sc); 1719141584Smlaier# else 1720141584Smlaier struct ifnet *ifp = &sc->if_sc; 1721141584Smlaier# endif 1722138666Smlaier#endif 1723130613Smlaier struct mbuf *m; 1724126258Smlaier 1725127145Smlaier#ifdef __FreeBSD__ 1726130613Smlaier PF_ASSERT(MA_OWNED); 1727126261Smlaier callout_stop(&sc->sc_tmo); 1728126261Smlaier#else 1729126258Smlaier timeout_del(&sc->sc_tmo); 1730126261Smlaier#endif 1731130613Smlaier 1732130613Smlaier if (sc->sc_mbuf == NULL) 1733130613Smlaier return (0); 1734130613Smlaier m = sc->sc_mbuf; 1735126258Smlaier sc->sc_mbuf = NULL; 1736130613Smlaier sc->sc_statep.s = NULL; 1737126258Smlaier 1738127145Smlaier#ifdef __FreeBSD__ 1739126261Smlaier KASSERT(m != NULL, ("pfsync_sendout: null mbuf")); 1740126261Smlaier#endif 1741126258Smlaier#if NBPFILTER > 0 1742126258Smlaier if (ifp->if_bpf) 1743126258Smlaier bpf_mtap(ifp->if_bpf, m); 1744126258Smlaier#endif 1745126258Smlaier 1746130613Smlaier if (sc->sc_mbuf_net) { 1747130613Smlaier m_freem(m); 1748130613Smlaier m = sc->sc_mbuf_net; 1749130613Smlaier sc->sc_mbuf_net = NULL; 1750130613Smlaier sc->sc_statep_net.s = NULL; 1751130613Smlaier } 1752126258Smlaier 1753145836Smlaier if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) { 1754130613Smlaier struct ip *ip; 1755130613Smlaier struct sockaddr sa; 1756130613Smlaier 1757130613Smlaier M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 1758130613Smlaier if (m == NULL) { 1759130613Smlaier pfsyncstats.pfsyncs_onomem++; 1760130613Smlaier return (0); 1761130613Smlaier } 1762130613Smlaier ip = mtod(m, struct ip *); 1763130613Smlaier ip->ip_v = IPVERSION; 1764130613Smlaier ip->ip_hl = sizeof(*ip) >> 2; 1765130613Smlaier ip->ip_tos = IPTOS_LOWDELAY; 1766130613Smlaier#ifdef __FreeBSD__ 1767130613Smlaier ip->ip_len = m->m_pkthdr.len; 1768130613Smlaier#else 1769130613Smlaier ip->ip_len = htons(m->m_pkthdr.len); 1770130613Smlaier#endif 1771130613Smlaier ip->ip_id = htons(ip_randomid()); 1772130613Smlaier#ifdef __FreeBSD__ 1773130613Smlaier ip->ip_off = IP_DF; 1774130613Smlaier#else 1775130613Smlaier ip->ip_off = htons(IP_DF); 1776130613Smlaier#endif 1777130613Smlaier ip->ip_ttl = PFSYNC_DFLTTL; 1778130613Smlaier ip->ip_p = IPPROTO_PFSYNC; 1779130613Smlaier ip->ip_sum = 0; 1780130613Smlaier 1781130613Smlaier bzero(&sa, sizeof(sa)); 1782145836Smlaier ip->ip_src.s_addr = INADDR_ANY; 1783130613Smlaier 1784130613Smlaier#ifdef __FreeBSD__ 1785130613Smlaier if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP)) 1786130613Smlaier#else 1787130613Smlaier if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP) 1788130613Smlaier#endif 1789130613Smlaier m->m_flags |= M_MCAST; 1790130613Smlaier ip->ip_dst = sc->sc_sendaddr; 1791130613Smlaier#ifdef __FreeBSD__ 1792145836Smlaier /* XXX_IMPORT */ 1793145836Smlaier sc->sc_sendaddr.s_addr = htonl(sc->sc_sync_peer.s_addr); 1794130613Smlaier#else 1795145836Smlaier sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr; 1796130613Smlaier#endif 1797130613Smlaier 1798130613Smlaier pfsyncstats.pfsyncs_opackets++; 1799130613Smlaier#ifdef __FreeBSD__ 1800147261Smlaier if (IF_HANDOFF(&sc->sc_ifq, m, NULL)) 1801147261Smlaier pfsyncstats.pfsyncs_oerrors++; 1802147261Smlaier callout_reset(&sc->sc_send_tmo, 1, pfsync_senddef, sc); 1803147261Smlaier#else 1804130613Smlaier if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 1805130613Smlaier pfsyncstats.pfsyncs_oerrors++; 1806130613Smlaier#endif 1807130613Smlaier } else 1808130613Smlaier m_freem(m); 1809130613Smlaier 1810126258Smlaier return (0); 1811126258Smlaier} 1812126261Smlaier 1813147261Smlaier#ifdef __FreeBSD__ 1814147261Smlaierstatic void 1815147261Smlaierpfsync_senddef(void *arg) 1816147261Smlaier{ 1817147261Smlaier struct pfsync_softc *sc = (struct pfsync_softc *)arg; 1818147261Smlaier struct mbuf *m; 1819126261Smlaier 1820147261Smlaier for(;;) { 1821147261Smlaier IF_DEQUEUE(&sc->sc_ifq, m); 1822147261Smlaier if (m == NULL) 1823147261Smlaier break; 1824147261Smlaier if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 1825147261Smlaier pfsyncstats.pfsyncs_oerrors++; 1826147261Smlaier } 1827147261Smlaier} 1828147261Smlaier 1829126261Smlaierstatic int 1830126261Smlaierpfsync_modevent(module_t mod, int type, void *data) 1831126261Smlaier{ 1832126261Smlaier int error = 0; 1833126261Smlaier 1834126261Smlaier switch (type) { 1835126261Smlaier case MOD_LOAD: 1836126261Smlaier LIST_INIT(&pfsync_list); 1837126261Smlaier if_clone_attach(&pfsync_cloner); 1838126261Smlaier break; 1839126261Smlaier 1840126261Smlaier case MOD_UNLOAD: 1841126261Smlaier if_clone_detach(&pfsync_cloner); 1842126261Smlaier while (!LIST_EMPTY(&pfsync_list)) 1843126261Smlaier pfsync_clone_destroy( 1844141584Smlaier SCP2IFP(LIST_FIRST(&pfsync_list))); 1845126261Smlaier break; 1846126261Smlaier 1847126261Smlaier default: 1848126261Smlaier error = EINVAL; 1849126261Smlaier break; 1850126261Smlaier } 1851126261Smlaier 1852126261Smlaier return error; 1853126261Smlaier} 1854126261Smlaier 1855126261Smlaierstatic moduledata_t pfsync_mod = { 1856126261Smlaier "pfsync", 1857126261Smlaier pfsync_modevent, 1858126261Smlaier 0 1859126261Smlaier}; 1860126261Smlaier 1861126261Smlaier#define PFSYNC_MODVER 1 1862126261Smlaier 1863135196SmlaierDECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 1864126261SmlaierMODULE_VERSION(pfsync, PFSYNC_MODVER); 1865126261Smlaier#endif /* __FreeBSD__ */ 1866