Home | History | Annotate | Line # | Download | only in net
if_pfsync.c revision 1.1.1.2
      1 /*	$OpenBSD: if_pfsync.c,v 1.37 2004/08/30 07:44:28 mcbride Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2002 Michael Shalayeff
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
     20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     26  * THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "bpfilter.h"
     30 #include "pfsync.h"
     31 
     32 #include <sys/param.h>
     33 #include <sys/proc.h>
     34 #include <sys/systm.h>
     35 #include <sys/time.h>
     36 #include <sys/mbuf.h>
     37 #include <sys/socket.h>
     38 #include <sys/ioctl.h>
     39 #include <sys/timeout.h>
     40 #include <sys/kernel.h>
     41 
     42 #include <net/if.h>
     43 #include <net/if_types.h>
     44 #include <net/route.h>
     45 #include <net/bpf.h>
     46 #include <netinet/tcp.h>
     47 #include <netinet/tcp_seq.h>
     48 
     49 #ifdef	INET
     50 #include <netinet/in.h>
     51 #include <netinet/in_systm.h>
     52 #include <netinet/in_var.h>
     53 #include <netinet/ip.h>
     54 #include <netinet/ip_var.h>
     55 #endif
     56 
     57 #ifdef INET6
     58 #ifndef INET
     59 #include <netinet/in.h>
     60 #endif
     61 #include <netinet6/nd6.h>
     62 #endif /* INET6 */
     63 
     64 #include "carp.h"
     65 #if NCARP > 0
     66 extern int carp_suppress_preempt;
     67 #endif
     68 
     69 #include <net/pfvar.h>
     70 #include <net/if_pfsync.h>
     71 
     72 #define PFSYNC_MINMTU	\
     73     (sizeof(struct pfsync_header) + sizeof(struct pf_state))
     74 
     75 #ifdef PFSYNCDEBUG
     76 #define DPRINTF(x)    do { if (pfsyncdebug) printf x ; } while (0)
     77 int pfsyncdebug;
     78 #else
     79 #define DPRINTF(x)
     80 #endif
     81 
     82 struct pfsync_softc	pfsyncif;
     83 struct pfsyncstats	pfsyncstats;
     84 
     85 void	pfsyncattach(int);
     86 void	pfsync_setmtu(struct pfsync_softc *, int);
     87 int	pfsync_insert_net_state(struct pfsync_state *);
     88 int	pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
     89 	    struct rtentry *);
     90 int	pfsyncioctl(struct ifnet *, u_long, caddr_t);
     91 void	pfsyncstart(struct ifnet *);
     92 
     93 struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
     94 int	pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
     95 int	pfsync_sendout(struct pfsync_softc *);
     96 void	pfsync_timeout(void *);
     97 void	pfsync_send_bus(struct pfsync_softc *, u_int8_t);
     98 void	pfsync_bulk_update(void *);
     99 void	pfsync_bulkfail(void *);
    100 
    101 int	pfsync_sync_ok;
    102 extern int ifqmaxlen;
    103 
    104 void
    105 pfsyncattach(int npfsync)
    106 {
    107 	struct ifnet *ifp;
    108 
    109 	pfsync_sync_ok = 1;
    110 	bzero(&pfsyncif, sizeof(pfsyncif));
    111 	pfsyncif.sc_mbuf = NULL;
    112 	pfsyncif.sc_mbuf_net = NULL;
    113 	pfsyncif.sc_statep.s = NULL;
    114 	pfsyncif.sc_statep_net.s = NULL;
    115 	pfsyncif.sc_maxupdates = 128;
    116 	pfsyncif.sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
    117 	pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
    118 	pfsyncif.sc_ureq_received = 0;
    119 	pfsyncif.sc_ureq_sent = 0;
    120 	ifp = &pfsyncif.sc_if;
    121 	strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname);
    122 	ifp->if_softc = &pfsyncif;
    123 	ifp->if_ioctl = pfsyncioctl;
    124 	ifp->if_output = pfsyncoutput;
    125 	ifp->if_start = pfsyncstart;
    126 	ifp->if_type = IFT_PFSYNC;
    127 	ifp->if_snd.ifq_maxlen = ifqmaxlen;
    128 	ifp->if_hdrlen = PFSYNC_HDRLEN;
    129 	pfsync_setmtu(&pfsyncif, MCLBYTES);
    130 	timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif);
    131 	timeout_set(&pfsyncif.sc_bulk_tmo, pfsync_bulk_update, &pfsyncif);
    132 	timeout_set(&pfsyncif.sc_bulkfail_tmo, pfsync_bulkfail, &pfsyncif);
    133 	if_attach(ifp);
    134 	if_alloc_sadl(ifp);
    135 
    136 #if NBPFILTER > 0
    137 	bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
    138 #endif
    139 }
    140 
    141 /*
    142  * Start output on the pfsync interface.
    143  */
    144 void
    145 pfsyncstart(struct ifnet *ifp)
    146 {
    147 	struct mbuf *m;
    148 	int s;
    149 
    150 	for (;;) {
    151 		s = splimp();
    152 		IF_DROP(&ifp->if_snd);
    153 		IF_DEQUEUE(&ifp->if_snd, m);
    154 		splx(s);
    155 
    156 		if (m == NULL)
    157 			return;
    158 		else
    159 			m_freem(m);
    160 	}
    161 }
    162 
    163 int
    164 pfsync_insert_net_state(struct pfsync_state *sp)
    165 {
    166 	struct pf_state	*st = NULL;
    167 	struct pf_rule *r = NULL;
    168 	struct pfi_kif	*kif;
    169 
    170 	if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
    171 		printf("pfsync_insert_net_state: invalid creator id:"
    172 		    " %08x\n", ntohl(sp->creatorid));
    173 		return (EINVAL);
    174 	}
    175 
    176 	kif = pfi_lookup_create(sp->ifname);
    177 	if (kif == NULL) {
    178 		if (pf_status.debug >= PF_DEBUG_MISC)
    179 			printf("pfsync_insert_net_state: "
    180 			    "unknown interface: %s\n", sp->ifname);
    181 		/* skip this state */
    182 		return (0);
    183 	}
    184 
    185 	/*
    186 	 * Just use the default rule until we have infrastructure to find the
    187 	 * best matching rule.
    188 	 */
    189 	r = &pf_default_rule;
    190 
    191 	if (!r->max_states || r->states < r->max_states)
    192 		st = pool_get(&pf_state_pl, PR_NOWAIT);
    193 	if (st == NULL) {
    194 		pfi_maybe_destroy(kif);
    195 		return (ENOMEM);
    196 	}
    197 	bzero(st, sizeof(*st));
    198 
    199 	st->rule.ptr = r;
    200 	/* XXX get pointers to nat_rule and anchor */
    201 
    202 	r->states++;
    203 
    204 	/* fill in the rest of the state entry */
    205 	pf_state_host_ntoh(&sp->lan, &st->lan);
    206 	pf_state_host_ntoh(&sp->gwy, &st->gwy);
    207 	pf_state_host_ntoh(&sp->ext, &st->ext);
    208 
    209 	pf_state_peer_ntoh(&sp->src, &st->src);
    210 	pf_state_peer_ntoh(&sp->dst, &st->dst);
    211 
    212 	bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
    213 	st->creation = ntohl(sp->creation) + time_second;
    214 	st->expire = ntohl(sp->expire) + time_second;
    215 
    216 	st->af = sp->af;
    217 	st->proto = sp->proto;
    218 	st->direction = sp->direction;
    219 	st->log = sp->log;
    220 	st->timeout = sp->timeout;
    221 	st->allow_opts = sp->allow_opts;
    222 
    223 	bcopy(sp->id, &st->id, sizeof(st->id));
    224 	st->creatorid = sp->creatorid;
    225 	st->sync_flags = sp->sync_flags | PFSTATE_FROMSYNC;
    226 
    227 
    228 	if (pf_insert_state(kif, st)) {
    229 		pfi_maybe_destroy(kif);
    230 		pool_put(&pf_state_pl, st);
    231 		return (EINVAL);
    232 	}
    233 
    234 	return (0);
    235 }
    236 
    237 void
    238 pfsync_input(struct mbuf *m, ...)
    239 {
    240 	struct ip *ip = mtod(m, struct ip *);
    241 	struct pfsync_header *ph;
    242 	struct pfsync_softc *sc = &pfsyncif;
    243 	struct pf_state *st, key;
    244 	struct pfsync_state *sp;
    245 	struct pfsync_state_upd *up;
    246 	struct pfsync_state_del *dp;
    247 	struct pfsync_state_clr *cp;
    248 	struct pfsync_state_upd_req *rup;
    249 	struct pfsync_state_bus *bus;
    250 	struct in_addr src;
    251 	struct mbuf *mp;
    252 	int iplen, action, error, i, s, count, offp, sfail, stale = 0;
    253 
    254 	pfsyncstats.pfsyncs_ipackets++;
    255 
    256 	/* verify that we have a sync interface configured */
    257 	if (!sc->sc_sync_ifp || !pf_status.running)
    258 		goto done;
    259 
    260 	/* verify that the packet came in on the right interface */
    261 	if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
    262 		pfsyncstats.pfsyncs_badif++;
    263 		goto done;
    264 	}
    265 
    266 	/* verify that the IP TTL is 255.  */
    267 	if (ip->ip_ttl != PFSYNC_DFLTTL) {
    268 		pfsyncstats.pfsyncs_badttl++;
    269 		goto done;
    270 	}
    271 
    272 	iplen = ip->ip_hl << 2;
    273 
    274 	if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
    275 		pfsyncstats.pfsyncs_hdrops++;
    276 		goto done;
    277 	}
    278 
    279 	if (iplen + sizeof(*ph) > m->m_len) {
    280 		if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
    281 			pfsyncstats.pfsyncs_hdrops++;
    282 			goto done;
    283 		}
    284 		ip = mtod(m, struct ip *);
    285 	}
    286 	ph = (struct pfsync_header *)((char *)ip + iplen);
    287 
    288 	/* verify the version */
    289 	if (ph->version != PFSYNC_VERSION) {
    290 		pfsyncstats.pfsyncs_badver++;
    291 		goto done;
    292 	}
    293 
    294 	action = ph->action;
    295 	count = ph->count;
    296 
    297 	/* make sure it's a valid action code */
    298 	if (action >= PFSYNC_ACT_MAX) {
    299 		pfsyncstats.pfsyncs_badact++;
    300 		goto done;
    301 	}
    302 
    303 	/* Cheaper to grab this now than having to mess with mbufs later */
    304 	src = ip->ip_src;
    305 
    306 	switch (action) {
    307 	case PFSYNC_ACT_CLR: {
    308 		struct pfi_kif	*kif;
    309 		u_int32_t creatorid;
    310 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    311 		    sizeof(*cp), &offp)) == NULL) {
    312 			pfsyncstats.pfsyncs_badlen++;
    313 			return;
    314 		}
    315 		cp = (struct pfsync_state_clr *)(mp->m_data + offp);
    316 		creatorid = cp->creatorid;
    317 
    318 		s = splsoftnet();
    319 		if (cp->ifname[0] == '\0') {
    320 			RB_FOREACH(st, pf_state_tree_id, &tree_id) {
    321 				if (st->creatorid == creatorid)
    322 					st->timeout = PFTM_PURGE;
    323 			}
    324 		} else {
    325 			kif = pfi_lookup_if(cp->ifname);
    326 			if (kif == NULL) {
    327 				if (pf_status.debug >= PF_DEBUG_MISC)
    328 					printf("pfsync_input: PFSYNC_ACT_CLR "
    329 					    "bad interface: %s\n", cp->ifname);
    330 				splx(s);
    331 				goto done;
    332 			}
    333 			RB_FOREACH(st, pf_state_tree_lan_ext,
    334 			    &kif->pfik_lan_ext) {
    335 				if (st->creatorid == creatorid) {
    336 					st->timeout = PFTM_PURGE;
    337 					pf_purge_expired_state(st);
    338 				}
    339 			}
    340 		}
    341 		splx(s);
    342 
    343 		break;
    344 	}
    345 	case PFSYNC_ACT_INS:
    346 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    347 		    count * sizeof(*sp), &offp)) == NULL) {
    348 			pfsyncstats.pfsyncs_badlen++;
    349 			return;
    350 		}
    351 
    352 		s = splsoftnet();
    353 		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
    354 		    i < count; i++, sp++) {
    355 			/* check for invalid values */
    356 			if (sp->timeout >= PFTM_MAX ||
    357 			    sp->src.state > PF_TCPS_PROXY_DST ||
    358 			    sp->dst.state > PF_TCPS_PROXY_DST ||
    359 			    sp->direction > PF_OUT ||
    360 			    (sp->af != AF_INET && sp->af != AF_INET6)) {
    361 				if (pf_status.debug >= PF_DEBUG_MISC)
    362 					printf("pfsync_insert: PFSYNC_ACT_INS: "
    363 					    "invalid value\n");
    364 				pfsyncstats.pfsyncs_badstate++;
    365 				continue;
    366 			}
    367 
    368 			if ((error = pfsync_insert_net_state(sp))) {
    369 				if (error == ENOMEM) {
    370 					splx(s);
    371 					goto done;
    372 				}
    373 				continue;
    374 			}
    375 		}
    376 		splx(s);
    377 		break;
    378 	case PFSYNC_ACT_UPD:
    379 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    380 		    count * sizeof(*sp), &offp)) == NULL) {
    381 			pfsyncstats.pfsyncs_badlen++;
    382 			return;
    383 		}
    384 
    385 		s = splsoftnet();
    386 		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
    387 		    i < count; i++, sp++) {
    388 			/* check for invalid values */
    389 			if (sp->timeout >= PFTM_MAX ||
    390 			    sp->src.state > PF_TCPS_PROXY_DST ||
    391 			    sp->dst.state > PF_TCPS_PROXY_DST) {
    392 				if (pf_status.debug >= PF_DEBUG_MISC)
    393 					printf("pfsync_insert: PFSYNC_ACT_UPD: "
    394 					    "invalid value\n");
    395 				pfsyncstats.pfsyncs_badstate++;
    396 				continue;
    397 			}
    398 
    399 			bcopy(sp->id, &key.id, sizeof(key.id));
    400 			key.creatorid = sp->creatorid;
    401 
    402 			st = pf_find_state_byid(&key);
    403 			if (st == NULL) {
    404 				/* insert the update */
    405 				if (pfsync_insert_net_state(sp))
    406 					pfsyncstats.pfsyncs_badstate++;
    407 				continue;
    408 			}
    409 			sfail = 0;
    410 			if (st->proto == IPPROTO_TCP) {
    411 				/*
    412 				 * The state should never go backwards except
    413 				 * for syn-proxy states.  Neither should the
    414 				 * sequence window slide backwards.
    415 				 */
    416 				if (st->src.state > sp->src.state &&
    417 				    (st->src.state < PF_TCPS_PROXY_SRC ||
    418 				    sp->src.state >= PF_TCPS_PROXY_SRC))
    419 					sfail = 1;
    420 				else if (st->dst.state > sp->dst.state)
    421 					sfail = 2;
    422 				else if (SEQ_GT(st->src.seqlo,
    423 				    ntohl(sp->src.seqlo)))
    424 					sfail = 3;
    425 				else if (st->dst.state >= TCPS_SYN_SENT &&
    426 				    SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
    427 					sfail = 4;
    428 			} else {
    429 				/*
    430 				 * Non-TCP protocol state machine always go
    431 				 * forwards
    432 				 */
    433 				if (st->src.state > sp->src.state)
    434 					sfail = 5;
    435 				else if ( st->dst.state > sp->dst.state)
    436 					sfail = 6;
    437 			}
    438 			if (sfail) {
    439 				if (pf_status.debug >= PF_DEBUG_MISC)
    440 					printf("pfsync: ignoring stale update "
    441 					    "(%d) id: %016llx "
    442 					    "creatorid: %08x\n", sfail,
    443 					    betoh64(st->id),
    444 					    ntohl(st->creatorid));
    445 				pfsyncstats.pfsyncs_badstate++;
    446 
    447 				/* we have a better state, send it out */
    448 				if (sc->sc_mbuf != NULL && !stale)
    449 					pfsync_sendout(sc);
    450 				stale++;
    451 				pfsync_pack_state(PFSYNC_ACT_UPD, st, 0);
    452 				continue;
    453 			}
    454 			pf_state_peer_ntoh(&sp->src, &st->src);
    455 			pf_state_peer_ntoh(&sp->dst, &st->dst);
    456 			st->expire = ntohl(sp->expire) + time_second;
    457 			st->timeout = sp->timeout;
    458 		}
    459 		if (stale && sc->sc_mbuf != NULL)
    460 			pfsync_sendout(sc);
    461 		splx(s);
    462 		break;
    463 	/*
    464 	 * It's not strictly necessary for us to support the "uncompressed"
    465 	 * delete action, but it's relatively simple and maintains consistency.
    466 	 */
    467 	case PFSYNC_ACT_DEL:
    468 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    469 		    count * sizeof(*sp), &offp)) == NULL) {
    470 			pfsyncstats.pfsyncs_badlen++;
    471 			return;
    472 		}
    473 
    474 		s = splsoftnet();
    475 		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
    476 		    i < count; i++, sp++) {
    477 			bcopy(sp->id, &key.id, sizeof(key.id));
    478 			key.creatorid = sp->creatorid;
    479 
    480 			st = pf_find_state_byid(&key);
    481 			if (st == NULL) {
    482 				pfsyncstats.pfsyncs_badstate++;
    483 				continue;
    484 			}
    485 			st->timeout = PFTM_PURGE;
    486 			st->sync_flags |= PFSTATE_FROMSYNC;
    487 			pf_purge_expired_state(st);
    488 		}
    489 		splx(s);
    490 		break;
    491 	case PFSYNC_ACT_UPD_C: {
    492 		int update_requested = 0;
    493 
    494 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    495 		    count * sizeof(*up), &offp)) == NULL) {
    496 			pfsyncstats.pfsyncs_badlen++;
    497 			return;
    498 		}
    499 
    500 		s = splsoftnet();
    501 		for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
    502 		    i < count; i++, up++) {
    503 			/* check for invalid values */
    504 			if (up->timeout >= PFTM_MAX ||
    505 			    up->src.state > PF_TCPS_PROXY_DST ||
    506 			    up->dst.state > PF_TCPS_PROXY_DST) {
    507 				if (pf_status.debug >= PF_DEBUG_MISC)
    508 					printf("pfsync_insert: "
    509 					    "PFSYNC_ACT_UPD_C: "
    510 					    "invalid value\n");
    511 				pfsyncstats.pfsyncs_badstate++;
    512 				continue;
    513 			}
    514 
    515 			bcopy(up->id, &key.id, sizeof(key.id));
    516 			key.creatorid = up->creatorid;
    517 
    518 			st = pf_find_state_byid(&key);
    519 			if (st == NULL) {
    520 				/* We don't have this state. Ask for it. */
    521 				error = pfsync_request_update(up, &src);
    522 				if (error == ENOMEM) {
    523 					splx(s);
    524 					goto done;
    525 				}
    526 				update_requested = 1;
    527 				pfsyncstats.pfsyncs_badstate++;
    528 				continue;
    529 			}
    530 			sfail = 0;
    531 			if (st->proto == IPPROTO_TCP) {
    532 				/*
    533 				 * The state should never go backwards except
    534 				 * for syn-proxy states.  Neither should the
    535 				 * sequence window slide backwards.
    536 				 */
    537 				if (st->src.state > up->src.state &&
    538 				    (st->src.state < PF_TCPS_PROXY_SRC ||
    539 				    up->src.state >= PF_TCPS_PROXY_SRC))
    540 					sfail = 1;
    541 				else if (st->dst.state > up->dst.state)
    542 					sfail = 2;
    543 				else if (SEQ_GT(st->src.seqlo,
    544 				    ntohl(up->src.seqlo)))
    545 					sfail = 3;
    546 				else if (st->dst.state >= TCPS_SYN_SENT &&
    547 				    SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
    548 					sfail = 4;
    549 			} else {
    550 				/*
    551 				 * Non-TCP protocol state machine always go
    552 				 * forwards
    553 				 */
    554 				if (st->src.state > up->src.state)
    555 					sfail = 5;
    556 				else if (st->dst.state > up->dst.state)
    557 					sfail = 6;
    558 			}
    559 			if (sfail) {
    560 				if (pf_status.debug >= PF_DEBUG_MISC)
    561 					printf("pfsync: ignoring stale update "
    562 					    "(%d) id: %016llx "
    563 					    "creatorid: %08x\n", sfail,
    564 					    betoh64(st->id),
    565 					    ntohl(st->creatorid));
    566 				pfsyncstats.pfsyncs_badstate++;
    567 
    568 				/* we have a better state, send it out */
    569 				if ((!stale || update_requested) &&
    570 				    sc->sc_mbuf != NULL) {
    571 					pfsync_sendout(sc);
    572 					update_requested = 0;
    573 				}
    574 				stale++;
    575 				pfsync_pack_state(PFSYNC_ACT_UPD, st, 0);
    576 				continue;
    577 			}
    578 			pf_state_peer_ntoh(&up->src, &st->src);
    579 			pf_state_peer_ntoh(&up->dst, &st->dst);
    580 			st->expire = ntohl(up->expire) + time_second;
    581 			st->timeout = up->timeout;
    582 		}
    583 		if ((update_requested || stale) && sc->sc_mbuf)
    584 			pfsync_sendout(sc);
    585 		splx(s);
    586 		break;
    587 	}
    588 	case PFSYNC_ACT_DEL_C:
    589 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    590 		    count * sizeof(*dp), &offp)) == NULL) {
    591 			pfsyncstats.pfsyncs_badlen++;
    592 			return;
    593 		}
    594 
    595 		s = splsoftnet();
    596 		for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
    597 		    i < count; i++, dp++) {
    598 			bcopy(dp->id, &key.id, sizeof(key.id));
    599 			key.creatorid = dp->creatorid;
    600 
    601 			st = pf_find_state_byid(&key);
    602 			if (st == NULL) {
    603 				pfsyncstats.pfsyncs_badstate++;
    604 				continue;
    605 			}
    606 			st->timeout = PFTM_PURGE;
    607 			st->sync_flags |= PFSTATE_FROMSYNC;
    608 			pf_purge_expired_state(st);
    609 		}
    610 		splx(s);
    611 		break;
    612 	case PFSYNC_ACT_INS_F:
    613 	case PFSYNC_ACT_DEL_F:
    614 		/* not implemented */
    615 		break;
    616 	case PFSYNC_ACT_UREQ:
    617 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    618 		    count * sizeof(*rup), &offp)) == NULL) {
    619 			pfsyncstats.pfsyncs_badlen++;
    620 			return;
    621 		}
    622 
    623 		s = splsoftnet();
    624 		if (sc->sc_mbuf != NULL)
    625 			pfsync_sendout(sc);
    626 		for (i = 0,
    627 		    rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
    628 		    i < count; i++, rup++) {
    629 			bcopy(rup->id, &key.id, sizeof(key.id));
    630 			key.creatorid = rup->creatorid;
    631 
    632 			if (key.id == 0 && key.creatorid == 0) {
    633 				sc->sc_ureq_received = time_uptime;
    634 				if (pf_status.debug >= PF_DEBUG_MISC)
    635 					printf("pfsync: received "
    636 					    "bulk update request\n");
    637 				pfsync_send_bus(sc, PFSYNC_BUS_START);
    638 				timeout_add(&sc->sc_bulk_tmo, 1 * hz);
    639 			} else {
    640 				st = pf_find_state_byid(&key);
    641 				if (st == NULL) {
    642 					pfsyncstats.pfsyncs_badstate++;
    643 					continue;
    644 				}
    645 				pfsync_pack_state(PFSYNC_ACT_UPD, st, 0);
    646 			}
    647 		}
    648 		if (sc->sc_mbuf != NULL)
    649 			pfsync_sendout(sc);
    650 		splx(s);
    651 		break;
    652 	case PFSYNC_ACT_BUS:
    653 		/* If we're not waiting for a bulk update, who cares. */
    654 		if (sc->sc_ureq_sent == 0)
    655 			break;
    656 
    657 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
    658 		    sizeof(*bus), &offp)) == NULL) {
    659 			pfsyncstats.pfsyncs_badlen++;
    660 			return;
    661 		}
    662 		bus = (struct pfsync_state_bus *)(mp->m_data + offp);
    663 		switch (bus->status) {
    664 		case PFSYNC_BUS_START:
    665 			timeout_add(&sc->sc_bulkfail_tmo,
    666 			    pf_pool_limits[PF_LIMIT_STATES].limit /
    667 			    (PFSYNC_BULKPACKETS * sc->sc_maxcount));
    668 			if (pf_status.debug >= PF_DEBUG_MISC)
    669 				printf("pfsync: received bulk "
    670 				    "update start\n");
    671 			break;
    672 		case PFSYNC_BUS_END:
    673 			if (time_uptime - ntohl(bus->endtime) >=
    674 			    sc->sc_ureq_sent) {
    675 				/* that's it, we're happy */
    676 				sc->sc_ureq_sent = 0;
    677 				sc->sc_bulk_tries = 0;
    678 				timeout_del(&sc->sc_bulkfail_tmo);
    679 #if NCARP > 0
    680 				if (!pfsync_sync_ok)
    681 					carp_suppress_preempt--;
    682 #endif
    683 				pfsync_sync_ok = 1;
    684 				if (pf_status.debug >= PF_DEBUG_MISC)
    685 					printf("pfsync: received valid "
    686 					    "bulk update end\n");
    687 			} else {
    688 				if (pf_status.debug >= PF_DEBUG_MISC)
    689 					printf("pfsync: received invalid "
    690 					    "bulk update end: bad timestamp\n");
    691 			}
    692 			break;
    693 		}
    694 		break;
    695 	}
    696 
    697 done:
    698 	if (m)
    699 		m_freem(m);
    700 }
    701 
    702 int
    703 pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
    704 	struct rtentry *rt)
    705 {
    706 	m_freem(m);
    707 	return (0);
    708 }
    709 
    710 /* ARGSUSED */
    711 int
    712 pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    713 {
    714 	struct proc *p = curproc;
    715 	struct pfsync_softc *sc = ifp->if_softc;
    716 	struct ifreq *ifr = (struct ifreq *)data;
    717 	struct ip_moptions *imo = &sc->sc_imo;
    718 	struct pfsyncreq pfsyncr;
    719 	struct ifnet    *sifp;
    720 	int s, error;
    721 
    722 	switch (cmd) {
    723 	case SIOCSIFADDR:
    724 	case SIOCAIFADDR:
    725 	case SIOCSIFDSTADDR:
    726 	case SIOCSIFFLAGS:
    727 		if (ifp->if_flags & IFF_UP)
    728 			ifp->if_flags |= IFF_RUNNING;
    729 		else
    730 			ifp->if_flags &= ~IFF_RUNNING;
    731 		break;
    732 	case SIOCSIFMTU:
    733 		if (ifr->ifr_mtu < PFSYNC_MINMTU)
    734 			return (EINVAL);
    735 		if (ifr->ifr_mtu > MCLBYTES)
    736 			ifr->ifr_mtu = MCLBYTES;
    737 		s = splnet();
    738 		if (ifr->ifr_mtu < ifp->if_mtu)
    739 			pfsync_sendout(sc);
    740 		pfsync_setmtu(sc, ifr->ifr_mtu);
    741 		splx(s);
    742 		break;
    743 	case SIOCGETPFSYNC:
    744 		bzero(&pfsyncr, sizeof(pfsyncr));
    745 		if (sc->sc_sync_ifp)
    746 			strlcpy(pfsyncr.pfsyncr_syncif,
    747 			    sc->sc_sync_ifp->if_xname, IFNAMSIZ);
    748 		pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
    749 		pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
    750 		if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
    751 			return (error);
    752 		break;
    753 	case SIOCSETPFSYNC:
    754 		if ((error = suser(p, p->p_acflag)) != 0)
    755 			return (error);
    756 		if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
    757 			return (error);
    758 
    759 		if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
    760 			sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
    761 		else
    762 			sc->sc_sync_peer.s_addr =
    763 			    pfsyncr.pfsyncr_syncpeer.s_addr;
    764 
    765 		if (pfsyncr.pfsyncr_maxupdates > 255)
    766 			return (EINVAL);
    767 		sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
    768 
    769 		if (pfsyncr.pfsyncr_syncif[0] == 0) {
    770 			sc->sc_sync_ifp = NULL;
    771 			if (sc->sc_mbuf_net != NULL) {
    772 				/* Don't keep stale pfsync packets around. */
    773 				s = splnet();
    774 				m_freem(sc->sc_mbuf_net);
    775 				sc->sc_mbuf_net = NULL;
    776 				sc->sc_statep_net.s = NULL;
    777 				splx(s);
    778 			}
    779 			if (imo->imo_num_memberships > 0) {
    780 				in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
    781 				imo->imo_multicast_ifp = NULL;
    782 			}
    783 			break;
    784 		}
    785 
    786 		if ((sifp = ifunit(pfsyncr.pfsyncr_syncif)) == NULL)
    787 			return (EINVAL);
    788 
    789 		s = splnet();
    790 		if (sifp->if_mtu < sc->sc_if.if_mtu ||
    791 		    (sc->sc_sync_ifp != NULL &&
    792 		    sifp->if_mtu < sc->sc_sync_ifp->if_mtu) ||
    793 		    sifp->if_mtu < MCLBYTES - sizeof(struct ip))
    794 			pfsync_sendout(sc);
    795 		sc->sc_sync_ifp = sifp;
    796 
    797 		pfsync_setmtu(sc, sc->sc_if.if_mtu);
    798 
    799 		if (imo->imo_num_memberships > 0) {
    800 			in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
    801 			imo->imo_multicast_ifp = NULL;
    802 		}
    803 
    804 		if (sc->sc_sync_ifp &&
    805 		    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
    806 			struct in_addr addr;
    807 
    808 			if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
    809 				splx(s);
    810 				return (EADDRNOTAVAIL);
    811 			}
    812 
    813 			addr.s_addr = INADDR_PFSYNC_GROUP;
    814 
    815 			if ((imo->imo_membership[0] =
    816 			    in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
    817 				splx(s);
    818 				return (ENOBUFS);
    819 			}
    820 			imo->imo_num_memberships++;
    821 			imo->imo_multicast_ifp = sc->sc_sync_ifp;
    822 			imo->imo_multicast_ttl = PFSYNC_DFLTTL;
    823 			imo->imo_multicast_loop = 0;
    824 		}
    825 
    826 		if (sc->sc_sync_ifp ||
    827 		    sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
    828 			/* Request a full state table update. */
    829 			sc->sc_ureq_sent = time_uptime;
    830 #if NCARP > 0
    831 			if (pfsync_sync_ok)
    832 				carp_suppress_preempt++;
    833 #endif
    834 			pfsync_sync_ok = 0;
    835 			if (pf_status.debug >= PF_DEBUG_MISC)
    836 				printf("pfsync: requesting bulk update\n");
    837 			timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
    838 			error = pfsync_request_update(NULL, NULL);
    839 			if (error == ENOMEM) {
    840 				splx(s);
    841 				return (ENOMEM);
    842 			}
    843 			pfsync_sendout(sc);
    844 		}
    845 		splx(s);
    846 
    847 		break;
    848 
    849 	default:
    850 		return (ENOTTY);
    851 	}
    852 
    853 	return (0);
    854 }
    855 
    856 void
    857 pfsync_setmtu(struct pfsync_softc *sc, int mtu_req)
    858 {
    859 	int mtu;
    860 
    861 	if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req)
    862 		mtu = sc->sc_sync_ifp->if_mtu;
    863 	else
    864 		mtu = mtu_req;
    865 
    866 	sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) /
    867 	    sizeof(struct pfsync_state);
    868 	if (sc->sc_maxcount > 254)
    869 	    sc->sc_maxcount = 254;
    870 	sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
    871 	    sc->sc_maxcount * sizeof(struct pfsync_state);
    872 }
    873 
    874 struct mbuf *
    875 pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
    876 {
    877 	struct pfsync_header *h;
    878 	struct mbuf *m;
    879 	int len;
    880 
    881 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    882 	if (m == NULL) {
    883 		sc->sc_if.if_oerrors++;
    884 		return (NULL);
    885 	}
    886 
    887 	switch (action) {
    888 	case PFSYNC_ACT_CLR:
    889 		len = sizeof(struct pfsync_header) +
    890 		    sizeof(struct pfsync_state_clr);
    891 		break;
    892 	case PFSYNC_ACT_UPD_C:
    893 		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) +
    894 		    sizeof(struct pfsync_header);
    895 		break;
    896 	case PFSYNC_ACT_DEL_C:
    897 		len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) +
    898 		    sizeof(struct pfsync_header);
    899 		break;
    900 	case PFSYNC_ACT_UREQ:
    901 		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) +
    902 		    sizeof(struct pfsync_header);
    903 		break;
    904 	case PFSYNC_ACT_BUS:
    905 		len = sizeof(struct pfsync_header) +
    906 		    sizeof(struct pfsync_state_bus);
    907 		break;
    908 	default:
    909 		len = (sc->sc_maxcount * sizeof(struct pfsync_state)) +
    910 		    sizeof(struct pfsync_header);
    911 		break;
    912 	}
    913 
    914 	if (len > MHLEN) {
    915 		MCLGET(m, M_DONTWAIT);
    916 		if ((m->m_flags & M_EXT) == 0) {
    917 			m_free(m);
    918 			sc->sc_if.if_oerrors++;
    919 			return (NULL);
    920 		}
    921 		m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1);
    922 	} else
    923 		MH_ALIGN(m, len);
    924 
    925 	m->m_pkthdr.rcvif = NULL;
    926 	m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header);
    927 	h = mtod(m, struct pfsync_header *);
    928 	h->version = PFSYNC_VERSION;
    929 	h->af = 0;
    930 	h->count = 0;
    931 	h->action = action;
    932 
    933 	*sp = (void *)((char *)h + PFSYNC_HDRLEN);
    934 	timeout_add(&sc->sc_tmo, hz);
    935 	return (m);
    936 }
    937 
    938 int
    939 pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
    940 {
    941 	struct ifnet *ifp = &pfsyncif.sc_if;
    942 	struct pfsync_softc *sc = ifp->if_softc;
    943 	struct pfsync_header *h, *h_net;
    944 	struct pfsync_state *sp = NULL;
    945 	struct pfsync_state_upd *up = NULL;
    946 	struct pfsync_state_del *dp = NULL;
    947 	struct pf_rule *r;
    948 	u_long secs;
    949 	int s, ret = 0;
    950 	u_int8_t i = 255, newaction = 0;
    951 
    952 	/*
    953 	 * If a packet falls in the forest and there's nobody around to
    954 	 * hear, does it make a sound?
    955 	 */
    956 	if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
    957 	    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
    958 		/* Don't leave any stale pfsync packets hanging around. */
    959 		if (sc->sc_mbuf != NULL) {
    960 			m_freem(sc->sc_mbuf);
    961 			sc->sc_mbuf = NULL;
    962 			sc->sc_statep.s = NULL;
    963 		}
    964 		return (0);
    965 	}
    966 
    967 	if (action >= PFSYNC_ACT_MAX)
    968 		return (EINVAL);
    969 
    970 	s = splnet();
    971 	if (sc->sc_mbuf == NULL) {
    972 		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
    973 		    (void *)&sc->sc_statep.s)) == NULL) {
    974 			splx(s);
    975 			return (ENOMEM);
    976 		}
    977 		h = mtod(sc->sc_mbuf, struct pfsync_header *);
    978 	} else {
    979 		h = mtod(sc->sc_mbuf, struct pfsync_header *);
    980 		if (h->action != action) {
    981 			pfsync_sendout(sc);
    982 			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
    983 			    (void *)&sc->sc_statep.s)) == NULL) {
    984 				splx(s);
    985 				return (ENOMEM);
    986 			}
    987 			h = mtod(sc->sc_mbuf, struct pfsync_header *);
    988 		} else {
    989 			/*
    990 			 * If it's an update, look in the packet to see if
    991 			 * we already have an update for the state.
    992 			 */
    993 			if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) {
    994 				struct pfsync_state *usp =
    995 				    (void *)((char *)h + PFSYNC_HDRLEN);
    996 
    997 				for (i = 0; i < h->count; i++) {
    998 					if (!memcmp(usp->id, &st->id,
    999 					    PFSYNC_ID_LEN) &&
   1000 					    usp->creatorid == st->creatorid) {
   1001 						sp = usp;
   1002 						sp->updates++;
   1003 						break;
   1004 					}
   1005 					usp++;
   1006 				}
   1007 			}
   1008 		}
   1009 	}
   1010 
   1011 	secs = time_second;
   1012 
   1013 	st->pfsync_time = time_uptime;
   1014 	TAILQ_REMOVE(&state_updates, st, u.s.entry_updates);
   1015 	TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates);
   1016 
   1017 	if (sp == NULL) {
   1018 		/* not a "duplicate" update */
   1019 		i = 255;
   1020 		sp = sc->sc_statep.s++;
   1021 		sc->sc_mbuf->m_pkthdr.len =
   1022 		    sc->sc_mbuf->m_len += sizeof(struct pfsync_state);
   1023 		h->count++;
   1024 		bzero(sp, sizeof(*sp));
   1025 
   1026 		bcopy(&st->id, sp->id, sizeof(sp->id));
   1027 		sp->creatorid = st->creatorid;
   1028 
   1029 		strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
   1030 		pf_state_host_hton(&st->lan, &sp->lan);
   1031 		pf_state_host_hton(&st->gwy, &sp->gwy);
   1032 		pf_state_host_hton(&st->ext, &sp->ext);
   1033 
   1034 		bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
   1035 
   1036 		sp->creation = htonl(secs - st->creation);
   1037 		sp->packets[0] = htonl(st->packets[0]);
   1038 		sp->packets[1] = htonl(st->packets[1]);
   1039 		sp->bytes[0] = htonl(st->bytes[0]);
   1040 		sp->bytes[1] = htonl(st->bytes[1]);
   1041 		if ((r = st->rule.ptr) == NULL)
   1042 			sp->rule = htonl(-1);
   1043 		else
   1044 			sp->rule = htonl(r->nr);
   1045 		if ((r = st->anchor.ptr) == NULL)
   1046 			sp->anchor = htonl(-1);
   1047 		else
   1048 			sp->anchor = htonl(r->nr);
   1049 		sp->af = st->af;
   1050 		sp->proto = st->proto;
   1051 		sp->direction = st->direction;
   1052 		sp->log = st->log;
   1053 		sp->allow_opts = st->allow_opts;
   1054 		sp->timeout = st->timeout;
   1055 
   1056 		sp->sync_flags = st->sync_flags & PFSTATE_NOSYNC;
   1057 	}
   1058 
   1059 	pf_state_peer_hton(&st->src, &sp->src);
   1060 	pf_state_peer_hton(&st->dst, &sp->dst);
   1061 
   1062 	if (st->expire <= secs)
   1063 		sp->expire = htonl(0);
   1064 	else
   1065 		sp->expire = htonl(st->expire - secs);
   1066 
   1067 	/* do we need to build "compressed" actions for network transfer? */
   1068 	if (sc->sc_sync_ifp && compress) {
   1069 		switch (action) {
   1070 		case PFSYNC_ACT_UPD:
   1071 			newaction = PFSYNC_ACT_UPD_C;
   1072 			break;
   1073 		case PFSYNC_ACT_DEL:
   1074 			newaction = PFSYNC_ACT_DEL_C;
   1075 			break;
   1076 		default:
   1077 			/* by default we just send the uncompressed states */
   1078 			break;
   1079 		}
   1080 	}
   1081 
   1082 	if (newaction) {
   1083 		if (sc->sc_mbuf_net == NULL) {
   1084 			if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction,
   1085 			    (void *)&sc->sc_statep_net.s)) == NULL) {
   1086 				splx(s);
   1087 				return (ENOMEM);
   1088 			}
   1089 		}
   1090 		h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *);
   1091 
   1092 		switch (newaction) {
   1093 		case PFSYNC_ACT_UPD_C:
   1094 			if (i != 255) {
   1095 				up = (void *)((char *)h_net +
   1096 				    PFSYNC_HDRLEN + (i * sizeof(*up)));
   1097 				up->updates++;
   1098 			} else {
   1099 				h_net->count++;
   1100 				sc->sc_mbuf_net->m_pkthdr.len =
   1101 				    sc->sc_mbuf_net->m_len += sizeof(*up);
   1102 				up = sc->sc_statep_net.u++;
   1103 
   1104 				bzero(up, sizeof(*up));
   1105 				bcopy(&st->id, up->id, sizeof(up->id));
   1106 				up->creatorid = st->creatorid;
   1107 			}
   1108 			up->timeout = st->timeout;
   1109 			up->expire = sp->expire;
   1110 			up->src = sp->src;
   1111 			up->dst = sp->dst;
   1112 			break;
   1113 		case PFSYNC_ACT_DEL_C:
   1114 			sc->sc_mbuf_net->m_pkthdr.len =
   1115 			    sc->sc_mbuf_net->m_len += sizeof(*dp);
   1116 			dp = sc->sc_statep_net.d++;
   1117 			h_net->count++;
   1118 
   1119 			bzero(dp, sizeof(*dp));
   1120 			bcopy(&st->id, dp->id, sizeof(dp->id));
   1121 			dp->creatorid = st->creatorid;
   1122 			break;
   1123 		}
   1124 	}
   1125 
   1126 	if (h->count == sc->sc_maxcount ||
   1127 	    (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates)))
   1128 		ret = pfsync_sendout(sc);
   1129 
   1130 	splx(s);
   1131 	return (ret);
   1132 }
   1133 
   1134 /* This must be called in splnet() */
   1135 int
   1136 pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
   1137 {
   1138 	struct ifnet *ifp = &pfsyncif.sc_if;
   1139 	struct pfsync_header *h;
   1140 	struct pfsync_softc *sc = ifp->if_softc;
   1141 	struct pfsync_state_upd_req *rup;
   1142 	int ret = 0;
   1143 
   1144 	if (sc->sc_mbuf == NULL) {
   1145 		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
   1146 		    (void *)&sc->sc_statep.s)) == NULL)
   1147 			return (ENOMEM);
   1148 		h = mtod(sc->sc_mbuf, struct pfsync_header *);
   1149 	} else {
   1150 		h = mtod(sc->sc_mbuf, struct pfsync_header *);
   1151 		if (h->action != PFSYNC_ACT_UREQ) {
   1152 			pfsync_sendout(sc);
   1153 			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
   1154 			    (void *)&sc->sc_statep.s)) == NULL)
   1155 				return (ENOMEM);
   1156 			h = mtod(sc->sc_mbuf, struct pfsync_header *);
   1157 		}
   1158 	}
   1159 
   1160 	if (src != NULL)
   1161 		sc->sc_sendaddr = *src;
   1162 	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
   1163 	h->count++;
   1164 	rup = sc->sc_statep.r++;
   1165 	bzero(rup, sizeof(*rup));
   1166 	if (up != NULL) {
   1167 		bcopy(up->id, rup->id, sizeof(rup->id));
   1168 		rup->creatorid = up->creatorid;
   1169 	}
   1170 
   1171 	if (h->count == sc->sc_maxcount)
   1172 		ret = pfsync_sendout(sc);
   1173 
   1174 	return (ret);
   1175 }
   1176 
   1177 int
   1178 pfsync_clear_states(u_int32_t creatorid, char *ifname)
   1179 {
   1180 	struct ifnet *ifp = &pfsyncif.sc_if;
   1181 	struct pfsync_softc *sc = ifp->if_softc;
   1182 	struct pfsync_state_clr *cp;
   1183 	int s, ret;
   1184 
   1185 	s = splnet();
   1186 	if (sc->sc_mbuf != NULL)
   1187 		pfsync_sendout(sc);
   1188 	if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR,
   1189 	    (void *)&sc->sc_statep.c)) == NULL) {
   1190 		splx(s);
   1191 		return (ENOMEM);
   1192 	}
   1193 	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp);
   1194 	cp = sc->sc_statep.c;
   1195 	cp->creatorid = creatorid;
   1196 	if (ifname != NULL)
   1197 		strlcpy(cp->ifname, ifname, IFNAMSIZ);
   1198 
   1199 	ret = (pfsync_sendout(sc));
   1200 	splx(s);
   1201 	return (ret);
   1202 }
   1203 
   1204 void
   1205 pfsync_timeout(void *v)
   1206 {
   1207 	struct pfsync_softc *sc = v;
   1208 	int s;
   1209 
   1210 	s = splnet();
   1211 	pfsync_sendout(sc);
   1212 	splx(s);
   1213 }
   1214 
   1215 /* This must be called in splnet() */
   1216 void
   1217 pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
   1218 {
   1219 	struct pfsync_state_bus *bus;
   1220 
   1221 	if (sc->sc_mbuf != NULL)
   1222 		pfsync_sendout(sc);
   1223 
   1224 	if (pfsync_sync_ok &&
   1225 	    (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
   1226 	    (void *)&sc->sc_statep.b)) != NULL) {
   1227 		sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
   1228 		bus = sc->sc_statep.b;
   1229 		bus->creatorid = pf_status.hostid;
   1230 		bus->status = status;
   1231 		bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
   1232 		pfsync_sendout(sc);
   1233 	}
   1234 }
   1235 
   1236 void
   1237 pfsync_bulk_update(void *v)
   1238 {
   1239 	struct pfsync_softc *sc = v;
   1240 	int s, i = 0;
   1241 	struct pf_state *state;
   1242 
   1243 	s = splnet();
   1244 	if (sc->sc_mbuf != NULL)
   1245 		pfsync_sendout(sc);
   1246 
   1247 	/*
   1248 	 * Grab at most PFSYNC_BULKPACKETS worth of states which have not
   1249 	 * been sent since the latest request was made.
   1250 	 */
   1251 	while ((state = TAILQ_FIRST(&state_updates)) != NULL &&
   1252 	    ++i < (sc->sc_maxcount * PFSYNC_BULKPACKETS)) {
   1253 		if (state->pfsync_time > sc->sc_ureq_received) {
   1254 			/* we're done */
   1255 			pfsync_send_bus(sc, PFSYNC_BUS_END);
   1256 			sc->sc_ureq_received = 0;
   1257 			timeout_del(&sc->sc_bulk_tmo);
   1258 			if (pf_status.debug >= PF_DEBUG_MISC)
   1259 				printf("pfsync: bulk update complete\n");
   1260 			break;
   1261 		} else {
   1262 			/* send an update and move to end of list */
   1263 			if (!state->sync_flags)
   1264 				pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
   1265 			state->pfsync_time = time_uptime;
   1266 			TAILQ_REMOVE(&state_updates, state, u.s.entry_updates);
   1267 			TAILQ_INSERT_TAIL(&state_updates, state,
   1268 			    u.s.entry_updates);
   1269 
   1270 			/* look again for more in a bit */
   1271 			timeout_add(&sc->sc_bulk_tmo, 1);
   1272 		}
   1273 	}
   1274 	if (sc->sc_mbuf != NULL)
   1275 		pfsync_sendout(sc);
   1276 	splx(s);
   1277 }
   1278 
   1279 void
   1280 pfsync_bulkfail(void *v)
   1281 {
   1282 	struct pfsync_softc *sc = v;
   1283 	int s, error;
   1284 
   1285 	if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
   1286 		/* Try again in a bit */
   1287 		timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
   1288 		s = splnet();
   1289 		error = pfsync_request_update(NULL, NULL);
   1290 		if (error == ENOMEM) {
   1291 			if (pf_status.debug >= PF_DEBUG_MISC)
   1292 				printf("pfsync: cannot allocate mbufs for "
   1293 				    "bulk update\n");
   1294 		} else
   1295 			pfsync_sendout(sc);
   1296 		splx(s);
   1297 	} else {
   1298 		/* Pretend like the transfer was ok */
   1299 		sc->sc_ureq_sent = 0;
   1300 		sc->sc_bulk_tries = 0;
   1301 #if NCARP > 0
   1302 		if (!pfsync_sync_ok)
   1303 			carp_suppress_preempt--;
   1304 #endif
   1305 		pfsync_sync_ok = 1;
   1306 		if (pf_status.debug >= PF_DEBUG_MISC)
   1307 			printf("pfsync: failed to receive "
   1308 			    "bulk update status\n");
   1309 		timeout_del(&sc->sc_bulkfail_tmo);
   1310 	}
   1311 }
   1312 
   1313 /* This must be called in splnet() */
   1314 int
   1315 pfsync_sendout(sc)
   1316 	struct pfsync_softc *sc;
   1317 {
   1318 	struct ifnet *ifp = &sc->sc_if;
   1319 	struct mbuf *m;
   1320 
   1321 	timeout_del(&sc->sc_tmo);
   1322 
   1323 	if (sc->sc_mbuf == NULL)
   1324 		return (0);
   1325 	m = sc->sc_mbuf;
   1326 	sc->sc_mbuf = NULL;
   1327 	sc->sc_statep.s = NULL;
   1328 
   1329 #if NBPFILTER > 0
   1330 	if (ifp->if_bpf)
   1331 		bpf_mtap(ifp->if_bpf, m);
   1332 #endif
   1333 
   1334 	if (sc->sc_mbuf_net) {
   1335 		m_freem(m);
   1336 		m = sc->sc_mbuf_net;
   1337 		sc->sc_mbuf_net = NULL;
   1338 		sc->sc_statep_net.s = NULL;
   1339 	}
   1340 
   1341 	if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
   1342 		struct ip *ip;
   1343 		struct sockaddr sa;
   1344 
   1345 		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
   1346 		if (m == NULL) {
   1347 			pfsyncstats.pfsyncs_onomem++;
   1348 			return (0);
   1349 		}
   1350 		ip = mtod(m, struct ip *);
   1351 		ip->ip_v = IPVERSION;
   1352 		ip->ip_hl = sizeof(*ip) >> 2;
   1353 		ip->ip_tos = IPTOS_LOWDELAY;
   1354 		ip->ip_len = htons(m->m_pkthdr.len);
   1355 		ip->ip_id = htons(ip_randomid());
   1356 		ip->ip_off = htons(IP_DF);
   1357 		ip->ip_ttl = PFSYNC_DFLTTL;
   1358 		ip->ip_p = IPPROTO_PFSYNC;
   1359 		ip->ip_sum = 0;
   1360 
   1361 		bzero(&sa, sizeof(sa));
   1362 		ip->ip_src.s_addr = INADDR_ANY;
   1363 
   1364 		if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
   1365 			m->m_flags |= M_MCAST;
   1366 		ip->ip_dst = sc->sc_sendaddr;
   1367 		sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
   1368 
   1369 		pfsyncstats.pfsyncs_opackets++;
   1370 
   1371 		if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
   1372 			pfsyncstats.pfsyncs_oerrors++;
   1373 	} else
   1374 		m_freem(m);
   1375 
   1376 	return (0);
   1377 }
   1378