if_pfsync.c revision 191148
1/*	$OpenBSD: if_pfsync.c,v 1.73 2006/11/16 13:13:38 henning 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#ifdef __FreeBSD__
30#include "opt_inet.h"
31#include "opt_inet6.h"
32#include "opt_carp.h"
33#include "opt_bpf.h"
34#include "opt_pf.h"
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/sys/contrib/pf/net/if_pfsync.c 191148 2009-04-16 20:30:28Z kmacy $");
38
39#ifdef DEV_BPF
40#define	NBPFILTER	DEV_BPF
41#else
42#define	NBPFILTER	0
43#endif
44
45#ifdef DEV_PFSYNC
46#define	NPFSYNC		DEV_PFSYNC
47#else
48#define	NPFSYNC		0
49#endif
50
51#ifdef DEV_CARP
52#define	NCARP		DEV_CARP
53#else
54#define	NCARP		0
55#endif
56#endif /* __FreeBSD__ */
57
58#include <sys/param.h>
59#ifdef __FreeBSD__
60#include <sys/priv.h>
61#endif
62#include <sys/proc.h>
63#include <sys/systm.h>
64#include <sys/time.h>
65#include <sys/mbuf.h>
66#include <sys/socket.h>
67#ifdef __FreeBSD__
68#include <sys/endian.h>
69#include <sys/malloc.h>
70#include <sys/module.h>
71#include <sys/sockio.h>
72#include <sys/taskqueue.h>
73#include <sys/lock.h>
74#include <sys/mutex.h>
75#include <sys/sysctl.h>
76#else
77#include <sys/ioctl.h>
78#include <sys/timeout.h>
79#endif
80#include <sys/kernel.h>
81
82#include <net/if.h>
83#ifdef __FreeBSD__
84#include <net/if_clone.h>
85#endif
86#include <net/if_types.h>
87#include <net/route.h>
88#include <net/bpf.h>
89#include <netinet/in.h>
90#include <netinet/if_ether.h>
91#include <netinet/tcp.h>
92#include <netinet/tcp_seq.h>
93
94#ifdef	INET
95#include <netinet/in_systm.h>
96#include <netinet/in_var.h>
97#include <netinet/ip.h>
98#include <netinet/ip_var.h>
99#endif
100
101#ifdef INET6
102#include <netinet6/nd6.h>
103#endif /* INET6 */
104
105#ifndef __FreeBSD__
106#include "carp.h"
107#endif
108#if NCARP > 0
109#include <netinet/ip_carp.h>
110#endif
111
112#include <net/pfvar.h>
113#include <net/if_pfsync.h>
114
115#ifndef __FreeBSD__
116#include "bpfilter.h"
117#include "pfsync.h"
118#endif
119
120#define PFSYNC_MINMTU	\
121    (sizeof(struct pfsync_header) + sizeof(struct pf_state))
122
123#ifdef PFSYNCDEBUG
124#define DPRINTF(x)    do { if (pfsyncdebug) printf x ; } while (0)
125int pfsyncdebug;
126#else
127#define DPRINTF(x)
128#endif
129
130struct pfsync_softc	*pfsyncif = NULL;
131struct pfsyncstats	 pfsyncstats;
132#ifdef __FreeBSD__
133SYSCTL_DECL(_net_inet_pfsync);
134SYSCTL_STRUCT(_net_inet_pfsync, 0, stats, CTLFLAG_RW,
135    &pfsyncstats, pfsyncstats,
136    "PFSYNC statistics (struct pfsyncstats, net/if_pfsync.h)");
137#endif
138
139void	pfsyncattach(int);
140#ifdef __FreeBSD__
141int	pfsync_clone_create(struct if_clone *, int, caddr_t);
142void	pfsync_clone_destroy(struct ifnet *);
143#else
144int	pfsync_clone_create(struct if_clone *, int);
145int	pfsync_clone_destroy(struct ifnet *);
146#endif
147void	pfsync_setmtu(struct pfsync_softc *, int);
148int	pfsync_alloc_scrub_memory(struct pfsync_state_peer *,
149	    struct pf_state_peer *);
150int	pfsync_insert_net_state(struct pfsync_state *, u_int8_t);
151#ifdef PFSYNC_TDB
152void	pfsync_update_net_tdb(struct pfsync_tdb *);
153#endif
154int	pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
155	    struct route *);
156int	pfsyncioctl(struct ifnet *, u_long, caddr_t);
157void	pfsyncstart(struct ifnet *);
158
159struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
160int	pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
161int	pfsync_sendout(struct pfsync_softc *);
162#ifdef PFSYNC_TDB
163int	pfsync_tdb_sendout(struct pfsync_softc *);
164#endif
165int	pfsync_sendout_mbuf(struct pfsync_softc *, struct mbuf *);
166void	pfsync_timeout(void *);
167#ifdef PFSYNC_TDB
168void	pfsync_tdb_timeout(void *);
169#endif
170void	pfsync_send_bus(struct pfsync_softc *, u_int8_t);
171void	pfsync_bulk_update(void *);
172void	pfsync_bulkfail(void *);
173
174#ifdef __FreeBSD__
175void	pfsync_ifdetach(void *, struct ifnet *);
176void	pfsync_senddef(void *, int);
177
178/* XXX: ugly */
179#define	betoh64		(unsigned long long)be64toh
180#define	timeout_del	callout_stop
181#endif
182
183int	pfsync_sync_ok;
184#ifndef __FreeBSD__
185extern int ifqmaxlen;
186#endif
187
188#ifdef __FreeBSD__
189IFC_SIMPLE_DECLARE(pfsync, 1);
190#else
191struct if_clone	pfsync_cloner =
192    IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create, pfsync_clone_destroy);
193#endif
194
195void
196pfsyncattach(int npfsync)
197{
198	if_clone_attach(&pfsync_cloner);
199}
200
201int
202#ifdef __FreeBSD__
203pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param)
204#else
205pfsync_clone_create(struct if_clone *ifc, int unit)
206#endif
207{
208	struct ifnet *ifp;
209
210	if (unit != 0)
211		return (EINVAL);
212
213	pfsync_sync_ok = 1;
214	if ((pfsyncif = malloc(sizeof(*pfsyncif), M_DEVBUF, M_NOWAIT)) == NULL)
215		return (ENOMEM);
216	bzero(pfsyncif, sizeof(*pfsyncif));
217#ifdef __FreeBSD__
218	if ((pfsyncif->sc_imo.imo_membership = (struct in_multi **)malloc(
219	    (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_DEVBUF,
220	    M_NOWAIT)) == NULL) {
221		free(pfsyncif, M_DEVBUF);
222		return (ENOSPC);
223	}
224	pfsyncif->sc_imo.imo_mfilters = NULL;
225	pfsyncif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
226	pfsyncif->sc_imo.imo_multicast_vif = -1;
227
228	ifp = pfsyncif->sc_ifp = if_alloc(IFT_PFSYNC);
229	if (ifp == NULL) {
230		free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
231		free(pfsyncif, M_DEVBUF);
232		return (ENOSPC);
233	}
234	if_initname(ifp, ifc->ifc_name, unit);
235
236	pfsyncif->sc_detachtag = EVENTHANDLER_REGISTER(ifnet_departure_event,
237	    pfsync_ifdetach, pfsyncif, EVENTHANDLER_PRI_ANY);
238	if (pfsyncif->sc_detachtag == NULL) {
239		if_free(ifp);
240		free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
241		free(pfsyncif, M_DEVBUF);
242		return (ENOSPC);
243	}
244
245	pfsyncif->sc_ifq.ifq_maxlen = ifqmaxlen;
246	mtx_init(&pfsyncif->sc_ifq.ifq_mtx, ifp->if_xname,
247	    "pfsync send queue", MTX_DEF);
248	TASK_INIT(&pfsyncif->sc_send_task, 0, pfsync_senddef, pfsyncif);
249#endif
250	pfsyncif->sc_mbuf = NULL;
251	pfsyncif->sc_mbuf_net = NULL;
252#ifdef PFSYNC_TDB
253	pfsyncif->sc_mbuf_tdb = NULL;
254#endif
255	pfsyncif->sc_statep.s = NULL;
256	pfsyncif->sc_statep_net.s = NULL;
257#ifdef PFSYNC_TDB
258	pfsyncif->sc_statep_tdb.t = NULL;
259#endif
260	pfsyncif->sc_maxupdates = 128;
261#ifdef __FreeBSD__
262	pfsyncif->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP);
263	pfsyncif->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP);
264#else
265	pfsyncif->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
266	pfsyncif->sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
267#endif
268	pfsyncif->sc_ureq_received = 0;
269	pfsyncif->sc_ureq_sent = 0;
270	pfsyncif->sc_bulk_send_next = NULL;
271	pfsyncif->sc_bulk_terminator = NULL;
272#ifndef __FreeBSD__
273	ifp = &pfsyncif->sc_if;
274	snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit);
275#endif
276	ifp->if_softc = pfsyncif;
277	ifp->if_ioctl = pfsyncioctl;
278	ifp->if_output = pfsyncoutput;
279	ifp->if_start = pfsyncstart;
280	ifp->if_type = IFT_PFSYNC;
281	ifp->if_snd.ifq_maxlen = ifqmaxlen;
282	ifp->if_hdrlen = PFSYNC_HDRLEN;
283	pfsync_setmtu(pfsyncif, ETHERMTU);
284#ifdef __FreeBSD__
285	callout_init(&pfsyncif->sc_tmo, CALLOUT_MPSAFE);
286#ifdef PFSYNC_TDB
287	callout_init(&pfsyncif->sc_tdb_tmo, CALLOUT_MPSAFE);
288#endif
289	callout_init(&pfsyncif->sc_bulk_tmo, CALLOUT_MPSAFE);
290	callout_init(&pfsyncif->sc_bulkfail_tmo, CALLOUT_MPSAFE);
291#else
292	timeout_set(&pfsyncif->sc_tmo, pfsync_timeout, pfsyncif);
293	timeout_set(&pfsyncif->sc_tdb_tmo, pfsync_tdb_timeout, pfsyncif);
294	timeout_set(&pfsyncif->sc_bulk_tmo, pfsync_bulk_update, pfsyncif);
295	timeout_set(&pfsyncif->sc_bulkfail_tmo, pfsync_bulkfail, pfsyncif);
296#endif
297	if_attach(ifp);
298#ifndef __FreeBSD__
299	if_alloc_sadl(ifp);
300#endif
301
302#if NCARP > 0
303	if_addgroup(ifp, "carp");
304#endif
305
306#if NBPFILTER > 0
307#ifdef __FreeBSD__
308	bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
309#else
310	bpfattach(&pfsyncif->sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
311#endif
312#endif
313
314	return (0);
315}
316
317#ifdef __FreeBSD__
318void
319#else
320int
321#endif
322pfsync_clone_destroy(struct ifnet *ifp)
323{
324#ifdef __FreeBSD__
325	EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfsyncif->sc_detachtag);
326	callout_stop(&pfsyncif->sc_tmo);
327#ifdef PFSYNC_TDB
328	callout_stop(&pfsyncif->sc_tdb_tmo);
329#endif
330	callout_stop(&pfsyncif->sc_bulk_tmo);
331	callout_stop(&pfsyncif->sc_bulkfail_tmo);
332	/* XXX: more? */
333#endif
334
335#if NBPFILTER > 0
336	bpfdetach(ifp);
337#endif
338	if_detach(ifp);
339#ifdef __FreeBSD__
340	if_free(ifp);
341	free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
342#endif
343	free(pfsyncif, M_DEVBUF);
344	pfsyncif = NULL;
345#ifndef __FreeBSD__
346	return (0);
347#endif
348}
349
350/*
351 * Start output on the pfsync interface.
352 */
353void
354pfsyncstart(struct ifnet *ifp)
355{
356	struct mbuf *m;
357#ifndef __FreeBSD__
358	int s;
359#endif
360
361	for (;;) {
362#ifdef __FreeBSD__
363		IF_LOCK(&ifp->if_snd);
364		_IF_DROP(&ifp->if_snd);
365		_IF_DEQUEUE(&ifp->if_snd, m);
366		IF_UNLOCK(&ifp->if_snd);
367#else
368		s = splnet();
369		IF_DROP(&ifp->if_snd);
370		IF_DEQUEUE(&ifp->if_snd, m);
371		splx(s);
372#endif
373
374		if (m == NULL)
375			return;
376		else
377			m_freem(m);
378	}
379}
380
381int
382pfsync_alloc_scrub_memory(struct pfsync_state_peer *s,
383    struct pf_state_peer *d)
384{
385	if (s->scrub.scrub_flag && d->scrub == NULL) {
386		d->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
387		if (d->scrub == NULL)
388			return (ENOMEM);
389		bzero(d->scrub, sizeof(*d->scrub));
390	}
391
392	return (0);
393}
394
395int
396pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
397{
398	struct pf_state	*st = NULL;
399	struct pf_rule *r = NULL;
400	struct pfi_kif	*kif;
401
402	if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
403		printf("pfsync_insert_net_state: invalid creator id:"
404		    " %08x\n", ntohl(sp->creatorid));
405		return (EINVAL);
406	}
407
408	kif = pfi_kif_get(sp->ifname);
409	if (kif == NULL) {
410		if (pf_status.debug >= PF_DEBUG_MISC)
411			printf("pfsync_insert_net_state: "
412			    "unknown interface: %s\n", sp->ifname);
413		/* skip this state */
414		return (0);
415	}
416
417	/*
418	 * If the ruleset checksums match, it's safe to associate the state
419	 * with the rule of that number.
420	 */
421	if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && chksum_flag)
422		r = pf_main_ruleset.rules[
423		    PF_RULESET_FILTER].active.ptr_array[ntohl(sp->rule)];
424	else
425		r = &pf_default_rule;
426
427	if (!r->max_states || r->states < r->max_states)
428		st = pool_get(&pf_state_pl, PR_NOWAIT);
429	if (st == NULL) {
430		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
431		return (ENOMEM);
432	}
433	bzero(st, sizeof(*st));
434
435	/* allocate memory for scrub info */
436	if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
437	    pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) {
438		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
439		if (st->src.scrub)
440			pool_put(&pf_state_scrub_pl, st->src.scrub);
441		pool_put(&pf_state_pl, st);
442		return (ENOMEM);
443	}
444
445	st->rule.ptr = r;
446	/* XXX get pointers to nat_rule and anchor */
447
448	/* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
449	r->states++;
450
451	/* fill in the rest of the state entry */
452	pf_state_host_ntoh(&sp->lan, &st->lan);
453	pf_state_host_ntoh(&sp->gwy, &st->gwy);
454	pf_state_host_ntoh(&sp->ext, &st->ext);
455
456	pf_state_peer_ntoh(&sp->src, &st->src);
457	pf_state_peer_ntoh(&sp->dst, &st->dst);
458
459	bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
460	st->creation = time_second - ntohl(sp->creation);
461	st->expire = ntohl(sp->expire) + time_second;
462
463	st->af = sp->af;
464	st->proto = sp->proto;
465	st->direction = sp->direction;
466	st->log = sp->log;
467	st->timeout = sp->timeout;
468	st->allow_opts = sp->allow_opts;
469
470	bcopy(sp->id, &st->id, sizeof(st->id));
471	st->creatorid = sp->creatorid;
472	st->sync_flags = PFSTATE_FROMSYNC;
473
474	if (pf_insert_state(kif, st)) {
475		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
476		/* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
477		r->states--;
478		if (st->dst.scrub)
479			pool_put(&pf_state_scrub_pl, st->dst.scrub);
480		if (st->src.scrub)
481			pool_put(&pf_state_scrub_pl, st->src.scrub);
482		pool_put(&pf_state_pl, st);
483		return (EINVAL);
484	}
485
486	return (0);
487}
488
489void
490#ifdef __FreeBSD__
491pfsync_input(struct mbuf *m, __unused int off)
492#else
493pfsync_input(struct mbuf *m, ...)
494#endif
495{
496	struct ip *ip = mtod(m, struct ip *);
497	struct pfsync_header *ph;
498	struct pfsync_softc *sc = pfsyncif;
499	struct pf_state *st;
500	struct pf_state_cmp key;
501	struct pfsync_state *sp;
502	struct pfsync_state_upd *up;
503	struct pfsync_state_del *dp;
504	struct pfsync_state_clr *cp;
505	struct pfsync_state_upd_req *rup;
506	struct pfsync_state_bus *bus;
507#ifdef PFSYNC_TDB
508	struct pfsync_tdb *pt;
509#endif
510	struct in_addr src;
511	struct mbuf *mp;
512	int iplen, action, error, i, s, count, offp, sfail, stale = 0;
513	u_int8_t chksum_flag = 0;
514
515	pfsyncstats.pfsyncs_ipackets++;
516
517	/* verify that we have a sync interface configured */
518	if (!sc || !sc->sc_sync_ifp || !pf_status.running)
519		goto done;
520
521	/* verify that the packet came in on the right interface */
522	if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
523		pfsyncstats.pfsyncs_badif++;
524		goto done;
525	}
526
527	/* verify that the IP TTL is 255.  */
528	if (ip->ip_ttl != PFSYNC_DFLTTL) {
529		pfsyncstats.pfsyncs_badttl++;
530		goto done;
531	}
532
533	iplen = ip->ip_hl << 2;
534
535	if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
536		pfsyncstats.pfsyncs_hdrops++;
537		goto done;
538	}
539
540	if (iplen + sizeof(*ph) > m->m_len) {
541		if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
542			pfsyncstats.pfsyncs_hdrops++;
543			goto done;
544		}
545		ip = mtod(m, struct ip *);
546	}
547	ph = (struct pfsync_header *)((char *)ip + iplen);
548
549	/* verify the version */
550	if (ph->version != PFSYNC_VERSION) {
551		pfsyncstats.pfsyncs_badver++;
552		goto done;
553	}
554
555	action = ph->action;
556	count = ph->count;
557
558	/* make sure it's a valid action code */
559	if (action >= PFSYNC_ACT_MAX) {
560		pfsyncstats.pfsyncs_badact++;
561		goto done;
562	}
563
564	/* Cheaper to grab this now than having to mess with mbufs later */
565	src = ip->ip_src;
566
567	if (!bcmp(&ph->pf_chksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
568		chksum_flag++;
569
570	switch (action) {
571	case PFSYNC_ACT_CLR: {
572		struct pf_state *nexts;
573		struct pfi_kif	*kif;
574		u_int32_t creatorid;
575		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
576		    sizeof(*cp), &offp)) == NULL) {
577			pfsyncstats.pfsyncs_badlen++;
578			return;
579		}
580		cp = (struct pfsync_state_clr *)(mp->m_data + offp);
581		creatorid = cp->creatorid;
582
583		s = splsoftnet();
584#ifdef __FreeBSD__
585		PF_LOCK();
586#endif
587		if (cp->ifname[0] == '\0') {
588			for (st = RB_MIN(pf_state_tree_id, &tree_id);
589			    st; st = nexts) {
590				nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
591				if (st->creatorid == creatorid) {
592					st->sync_flags |= PFSTATE_FROMSYNC;
593					pf_unlink_state(st);
594				}
595			}
596		} else {
597			if ((kif = pfi_kif_get(cp->ifname)) == NULL) {
598#ifdef __FreeBSD__
599				PF_UNLOCK();
600#endif
601				splx(s);
602				return;
603			}
604			for (st = RB_MIN(pf_state_tree_lan_ext,
605			    &kif->pfik_lan_ext); st; st = nexts) {
606				nexts = RB_NEXT(pf_state_tree_lan_ext,
607				    &kif->pfik_lan_ext, st);
608				if (st->creatorid == creatorid) {
609					st->sync_flags |= PFSTATE_FROMSYNC;
610					pf_unlink_state(st);
611				}
612			}
613		}
614#ifdef __FreeBSD__
615		PF_UNLOCK();
616#endif
617		splx(s);
618
619		break;
620	}
621	case PFSYNC_ACT_INS:
622		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
623		    count * sizeof(*sp), &offp)) == NULL) {
624			pfsyncstats.pfsyncs_badlen++;
625			return;
626		}
627
628		s = splsoftnet();
629#ifdef __FreeBSD__
630		PF_LOCK();
631#endif
632		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
633		    i < count; i++, sp++) {
634			/* check for invalid values */
635			if (sp->timeout >= PFTM_MAX ||
636			    sp->src.state > PF_TCPS_PROXY_DST ||
637			    sp->dst.state > PF_TCPS_PROXY_DST ||
638			    sp->direction > PF_OUT ||
639			    (sp->af != AF_INET && sp->af != AF_INET6)) {
640				if (pf_status.debug >= PF_DEBUG_MISC)
641					printf("pfsync_insert: PFSYNC_ACT_INS: "
642					    "invalid value\n");
643				pfsyncstats.pfsyncs_badstate++;
644				continue;
645			}
646
647			if ((error = pfsync_insert_net_state(sp,
648			    chksum_flag))) {
649				if (error == ENOMEM) {
650#ifdef __FreeBSD__
651					PF_UNLOCK();
652#endif
653					splx(s);
654					goto done;
655				}
656				continue;
657			}
658		}
659#ifdef __FreeBSD__
660		PF_UNLOCK();
661#endif
662		splx(s);
663		break;
664	case PFSYNC_ACT_UPD:
665		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
666		    count * sizeof(*sp), &offp)) == NULL) {
667			pfsyncstats.pfsyncs_badlen++;
668			return;
669		}
670
671		s = splsoftnet();
672#ifdef __FreeBSD__
673		PF_LOCK();
674#endif
675		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
676		    i < count; i++, sp++) {
677			int flags = PFSYNC_FLAG_STALE;
678
679			/* check for invalid values */
680			if (sp->timeout >= PFTM_MAX ||
681			    sp->src.state > PF_TCPS_PROXY_DST ||
682			    sp->dst.state > PF_TCPS_PROXY_DST) {
683				if (pf_status.debug >= PF_DEBUG_MISC)
684					printf("pfsync_insert: PFSYNC_ACT_UPD: "
685					    "invalid value\n");
686				pfsyncstats.pfsyncs_badstate++;
687				continue;
688			}
689
690			bcopy(sp->id, &key.id, sizeof(key.id));
691			key.creatorid = sp->creatorid;
692
693			st = pf_find_state_byid(&key);
694			if (st == NULL) {
695				/* insert the update */
696				if (pfsync_insert_net_state(sp, chksum_flag))
697					pfsyncstats.pfsyncs_badstate++;
698				continue;
699			}
700			sfail = 0;
701			if (st->proto == IPPROTO_TCP) {
702				/*
703				 * The state should never go backwards except
704				 * for syn-proxy states.  Neither should the
705				 * sequence window slide backwards.
706				 */
707				if (st->src.state > sp->src.state &&
708				    (st->src.state < PF_TCPS_PROXY_SRC ||
709				    sp->src.state >= PF_TCPS_PROXY_SRC))
710					sfail = 1;
711				else if (SEQ_GT(st->src.seqlo,
712				    ntohl(sp->src.seqlo)))
713					sfail = 3;
714				else if (st->dst.state > sp->dst.state) {
715					/* There might still be useful
716					 * information about the src state here,
717					 * so import that part of the update,
718					 * then "fail" so we send the updated
719					 * state back to the peer who is missing
720					 * our what we know. */
721					pf_state_peer_ntoh(&sp->src, &st->src);
722					/* XXX do anything with timeouts? */
723					sfail = 7;
724					flags = 0;
725				} else if (st->dst.state >= TCPS_SYN_SENT &&
726				    SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
727					sfail = 4;
728			} else {
729				/*
730				 * Non-TCP protocol state machine always go
731				 * forwards
732				 */
733				if (st->src.state > sp->src.state)
734					sfail = 5;
735				else if (st->dst.state > sp->dst.state)
736					sfail = 6;
737			}
738			if (sfail) {
739				if (pf_status.debug >= PF_DEBUG_MISC)
740					printf("pfsync: %s stale update "
741					    "(%d) id: %016llx "
742					    "creatorid: %08x\n",
743					    (sfail < 7 ?  "ignoring"
744					     : "partial"), sfail,
745					    betoh64(st->id),
746					    ntohl(st->creatorid));
747				pfsyncstats.pfsyncs_badstate++;
748
749				if (!(sp->sync_flags & PFSTATE_STALE)) {
750					/* we have a better state, send it */
751					if (sc->sc_mbuf != NULL && !stale)
752						pfsync_sendout(sc);
753					stale++;
754					if (!st->sync_flags)
755						pfsync_pack_state(
756						    PFSYNC_ACT_UPD, st, flags);
757				}
758				continue;
759			}
760	    		pfsync_alloc_scrub_memory(&sp->dst, &st->dst);
761			pf_state_peer_ntoh(&sp->src, &st->src);
762			pf_state_peer_ntoh(&sp->dst, &st->dst);
763			st->expire = ntohl(sp->expire) + time_second;
764			st->timeout = sp->timeout;
765		}
766		if (stale && sc->sc_mbuf != NULL)
767			pfsync_sendout(sc);
768#ifdef __FreeBSD__
769		PF_UNLOCK();
770#endif
771		splx(s);
772		break;
773	/*
774	 * It's not strictly necessary for us to support the "uncompressed"
775	 * delete action, but it's relatively simple and maintains consistency.
776	 */
777	case PFSYNC_ACT_DEL:
778		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
779		    count * sizeof(*sp), &offp)) == NULL) {
780			pfsyncstats.pfsyncs_badlen++;
781			return;
782		}
783
784		s = splsoftnet();
785#ifdef __FreeBSD__
786		PF_LOCK();
787#endif
788		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
789		    i < count; i++, sp++) {
790			bcopy(sp->id, &key.id, sizeof(key.id));
791			key.creatorid = sp->creatorid;
792
793			st = pf_find_state_byid(&key);
794			if (st == NULL) {
795				pfsyncstats.pfsyncs_badstate++;
796				continue;
797			}
798			st->sync_flags |= PFSTATE_FROMSYNC;
799			pf_unlink_state(st);
800		}
801#ifdef __FreeBSD__
802		PF_UNLOCK();
803#endif
804		splx(s);
805		break;
806	case PFSYNC_ACT_UPD_C: {
807		int update_requested = 0;
808
809		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
810		    count * sizeof(*up), &offp)) == NULL) {
811			pfsyncstats.pfsyncs_badlen++;
812			return;
813		}
814
815		s = splsoftnet();
816#ifdef __FreeBSD__
817		PF_LOCK();
818#endif
819		for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
820		    i < count; i++, up++) {
821			/* check for invalid values */
822			if (up->timeout >= PFTM_MAX ||
823			    up->src.state > PF_TCPS_PROXY_DST ||
824			    up->dst.state > PF_TCPS_PROXY_DST) {
825				if (pf_status.debug >= PF_DEBUG_MISC)
826					printf("pfsync_insert: "
827					    "PFSYNC_ACT_UPD_C: "
828					    "invalid value\n");
829				pfsyncstats.pfsyncs_badstate++;
830				continue;
831			}
832
833			bcopy(up->id, &key.id, sizeof(key.id));
834			key.creatorid = up->creatorid;
835
836			st = pf_find_state_byid(&key);
837			if (st == NULL) {
838				/* We don't have this state. Ask for it. */
839				error = pfsync_request_update(up, &src);
840				if (error == ENOMEM) {
841#ifdef __FreeBSD__
842					PF_UNLOCK();
843#endif
844					splx(s);
845					goto done;
846				}
847				update_requested = 1;
848				pfsyncstats.pfsyncs_badstate++;
849				continue;
850			}
851			sfail = 0;
852			if (st->proto == IPPROTO_TCP) {
853				/*
854				 * The state should never go backwards except
855				 * for syn-proxy states.  Neither should the
856				 * sequence window slide backwards.
857				 */
858				if (st->src.state > up->src.state &&
859				    (st->src.state < PF_TCPS_PROXY_SRC ||
860				    up->src.state >= PF_TCPS_PROXY_SRC))
861					sfail = 1;
862				else if (st->dst.state > up->dst.state)
863					sfail = 2;
864				else if (SEQ_GT(st->src.seqlo,
865				    ntohl(up->src.seqlo)))
866					sfail = 3;
867				else if (st->dst.state >= TCPS_SYN_SENT &&
868				    SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
869					sfail = 4;
870			} else {
871				/*
872				 * Non-TCP protocol state machine always go
873				 * forwards
874				 */
875				if (st->src.state > up->src.state)
876					sfail = 5;
877				else if (st->dst.state > up->dst.state)
878					sfail = 6;
879			}
880			if (sfail) {
881				if (pf_status.debug >= PF_DEBUG_MISC)
882					printf("pfsync: ignoring stale update "
883					    "(%d) id: %016llx "
884					    "creatorid: %08x\n", sfail,
885					    betoh64(st->id),
886					    ntohl(st->creatorid));
887				pfsyncstats.pfsyncs_badstate++;
888
889				/* we have a better state, send it out */
890				if ((!stale || update_requested) &&
891				    sc->sc_mbuf != NULL) {
892					pfsync_sendout(sc);
893					update_requested = 0;
894				}
895				stale++;
896				if (!st->sync_flags)
897					pfsync_pack_state(PFSYNC_ACT_UPD, st,
898					    PFSYNC_FLAG_STALE);
899				continue;
900			}
901	    		pfsync_alloc_scrub_memory(&up->dst, &st->dst);
902			pf_state_peer_ntoh(&up->src, &st->src);
903			pf_state_peer_ntoh(&up->dst, &st->dst);
904			st->expire = ntohl(up->expire) + time_second;
905			st->timeout = up->timeout;
906		}
907		if ((update_requested || stale) && sc->sc_mbuf)
908			pfsync_sendout(sc);
909#ifdef __FreeBSD__
910		PF_UNLOCK();
911#endif
912		splx(s);
913		break;
914	}
915	case PFSYNC_ACT_DEL_C:
916		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
917		    count * sizeof(*dp), &offp)) == NULL) {
918			pfsyncstats.pfsyncs_badlen++;
919			return;
920		}
921
922		s = splsoftnet();
923#ifdef __FreeBSD__
924		PF_LOCK();
925#endif
926		for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
927		    i < count; i++, dp++) {
928			bcopy(dp->id, &key.id, sizeof(key.id));
929			key.creatorid = dp->creatorid;
930
931			st = pf_find_state_byid(&key);
932			if (st == NULL) {
933				pfsyncstats.pfsyncs_badstate++;
934				continue;
935			}
936			st->sync_flags |= PFSTATE_FROMSYNC;
937			pf_unlink_state(st);
938		}
939#ifdef __FreeBSD__
940		PF_UNLOCK();
941#endif
942		splx(s);
943		break;
944	case PFSYNC_ACT_INS_F:
945	case PFSYNC_ACT_DEL_F:
946		/* not implemented */
947		break;
948	case PFSYNC_ACT_UREQ:
949		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
950		    count * sizeof(*rup), &offp)) == NULL) {
951			pfsyncstats.pfsyncs_badlen++;
952			return;
953		}
954
955		s = splsoftnet();
956#ifdef __FreeBSD__
957		PF_LOCK();
958#endif
959		if (sc->sc_mbuf != NULL)
960			pfsync_sendout(sc);
961		for (i = 0,
962		    rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
963		    i < count; i++, rup++) {
964			bcopy(rup->id, &key.id, sizeof(key.id));
965			key.creatorid = rup->creatorid;
966
967			if (key.id == 0 && key.creatorid == 0) {
968				sc->sc_ureq_received = time_uptime;
969				if (sc->sc_bulk_send_next == NULL)
970					sc->sc_bulk_send_next =
971					    TAILQ_FIRST(&state_list);
972				sc->sc_bulk_terminator = sc->sc_bulk_send_next;
973				if (pf_status.debug >= PF_DEBUG_MISC)
974					printf("pfsync: received "
975					    "bulk update request\n");
976				pfsync_send_bus(sc, PFSYNC_BUS_START);
977#ifdef __FreeBSD__
978				callout_reset(&sc->sc_bulk_tmo, 1 * hz,
979				    pfsync_bulk_update, pfsyncif);
980#else
981				timeout_add(&sc->sc_bulk_tmo, 1 * hz);
982#endif
983			} else {
984				st = pf_find_state_byid(&key);
985				if (st == NULL) {
986					pfsyncstats.pfsyncs_badstate++;
987					continue;
988				}
989				if (!st->sync_flags)
990					pfsync_pack_state(PFSYNC_ACT_UPD,
991					    st, 0);
992			}
993		}
994		if (sc->sc_mbuf != NULL)
995			pfsync_sendout(sc);
996#ifdef __FreeBSD__
997		PF_UNLOCK();
998#endif
999		splx(s);
1000		break;
1001	case PFSYNC_ACT_BUS:
1002		/* If we're not waiting for a bulk update, who cares. */
1003		if (sc->sc_ureq_sent == 0)
1004			break;
1005
1006		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
1007		    sizeof(*bus), &offp)) == NULL) {
1008			pfsyncstats.pfsyncs_badlen++;
1009			return;
1010		}
1011		bus = (struct pfsync_state_bus *)(mp->m_data + offp);
1012		switch (bus->status) {
1013		case PFSYNC_BUS_START:
1014#ifdef __FreeBSD__
1015			callout_reset(&sc->sc_bulkfail_tmo,
1016			    pf_pool_limits[PF_LIMIT_STATES].limit /
1017			    (PFSYNC_BULKPACKETS * sc->sc_maxcount),
1018			    pfsync_bulkfail, pfsyncif);
1019#else
1020			timeout_add(&sc->sc_bulkfail_tmo,
1021			    pf_pool_limits[PF_LIMIT_STATES].limit /
1022			    (PFSYNC_BULKPACKETS * sc->sc_maxcount));
1023#endif
1024			if (pf_status.debug >= PF_DEBUG_MISC)
1025				printf("pfsync: received bulk "
1026				    "update start\n");
1027			break;
1028		case PFSYNC_BUS_END:
1029			if (time_uptime - ntohl(bus->endtime) >=
1030			    sc->sc_ureq_sent) {
1031				/* that's it, we're happy */
1032				sc->sc_ureq_sent = 0;
1033				sc->sc_bulk_tries = 0;
1034				timeout_del(&sc->sc_bulkfail_tmo);
1035#if NCARP > 0
1036				if (!pfsync_sync_ok)
1037#ifdef __FreeBSD__
1038#ifdef CARP_ADVANCED
1039					carp_group_demote_adj(sc->sc_ifp, -1);
1040#endif
1041#else
1042					carp_group_demote_adj(&sc->sc_if, -1);
1043#endif
1044#endif
1045				pfsync_sync_ok = 1;
1046				if (pf_status.debug >= PF_DEBUG_MISC)
1047					printf("pfsync: received valid "
1048					    "bulk update end\n");
1049			} else {
1050				if (pf_status.debug >= PF_DEBUG_MISC)
1051					printf("pfsync: received invalid "
1052					    "bulk update end: bad timestamp\n");
1053			}
1054			break;
1055		}
1056		break;
1057#ifdef PFSYNC_TDB
1058	case PFSYNC_ACT_TDB_UPD:
1059		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
1060		    count * sizeof(*pt), &offp)) == NULL) {
1061			pfsyncstats.pfsyncs_badlen++;
1062			return;
1063		}
1064		s = splsoftnet();
1065#ifdef __FreeBSD__
1066		PF_LOCK();
1067#endif
1068		for (i = 0, pt = (struct pfsync_tdb *)(mp->m_data + offp);
1069		    i < count; i++, pt++)
1070			pfsync_update_net_tdb(pt);
1071#ifdef __FreeBSD__
1072		PF_UNLOCK();
1073#endif
1074		splx(s);
1075		break;
1076#endif
1077	}
1078
1079done:
1080	if (m)
1081		m_freem(m);
1082}
1083
1084int
1085pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
1086	struct route *ro)
1087{
1088	m_freem(m);
1089	return (0);
1090}
1091
1092/* ARGSUSED */
1093int
1094pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1095{
1096#ifndef __FreeBSD__
1097	struct proc *p = curproc;
1098#endif
1099	struct pfsync_softc *sc = ifp->if_softc;
1100	struct ifreq *ifr = (struct ifreq *)data;
1101	struct ip_moptions *imo = &sc->sc_imo;
1102	struct pfsyncreq pfsyncr;
1103	struct ifnet    *sifp;
1104	int s, error;
1105
1106	switch (cmd) {
1107	case SIOCSIFADDR:
1108	case SIOCAIFADDR:
1109	case SIOCSIFDSTADDR:
1110	case SIOCSIFFLAGS:
1111#ifdef __FreeBSD__
1112		if (ifp->if_flags & IFF_UP)
1113			ifp->if_drv_flags |= IFF_DRV_RUNNING;
1114		else
1115			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1116#else
1117		if (ifp->if_flags & IFF_UP)
1118			ifp->if_flags |= IFF_RUNNING;
1119		else
1120			ifp->if_flags &= ~IFF_RUNNING;
1121#endif
1122		break;
1123	case SIOCSIFMTU:
1124		if (ifr->ifr_mtu < PFSYNC_MINMTU)
1125			return (EINVAL);
1126		if (ifr->ifr_mtu > MCLBYTES)
1127			ifr->ifr_mtu = MCLBYTES;
1128		s = splnet();
1129#ifdef __FreeBSD__
1130		PF_LOCK();
1131#endif
1132		if (ifr->ifr_mtu < ifp->if_mtu)
1133			pfsync_sendout(sc);
1134		pfsync_setmtu(sc, ifr->ifr_mtu);
1135#ifdef __FreeBSD__
1136		PF_UNLOCK();
1137#endif
1138		splx(s);
1139		break;
1140	case SIOCGETPFSYNC:
1141		bzero(&pfsyncr, sizeof(pfsyncr));
1142		if (sc->sc_sync_ifp)
1143			strlcpy(pfsyncr.pfsyncr_syncdev,
1144			    sc->sc_sync_ifp->if_xname, IFNAMSIZ);
1145		pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
1146		pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
1147		if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
1148			return (error);
1149		break;
1150	case SIOCSETPFSYNC:
1151#ifdef __FreeBSD__
1152		if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
1153#else
1154		if ((error = suser(p, p->p_acflag)) != 0)
1155#endif
1156			return (error);
1157		if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
1158			return (error);
1159
1160#ifdef __FreeBSD__
1161		PF_LOCK();
1162#endif
1163		if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
1164#ifdef __FreeBSD__
1165			sc->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP);
1166#else
1167			sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
1168#endif
1169		else
1170			sc->sc_sync_peer.s_addr =
1171			    pfsyncr.pfsyncr_syncpeer.s_addr;
1172
1173		if (pfsyncr.pfsyncr_maxupdates > 255)
1174#ifdef __FreeBSD__
1175		{
1176			PF_UNLOCK();
1177#endif
1178			return (EINVAL);
1179#ifdef __FreeBSD__
1180		}
1181#endif
1182		sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
1183
1184		if (pfsyncr.pfsyncr_syncdev[0] == 0) {
1185			sc->sc_sync_ifp = NULL;
1186			if (sc->sc_mbuf_net != NULL) {
1187				/* Don't keep stale pfsync packets around. */
1188				s = splnet();
1189				m_freem(sc->sc_mbuf_net);
1190				sc->sc_mbuf_net = NULL;
1191				sc->sc_statep_net.s = NULL;
1192				splx(s);
1193			}
1194#ifdef __FreeBSD__
1195			PF_UNLOCK();
1196#endif
1197			if (imo->imo_num_memberships > 0) {
1198				in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
1199				imo->imo_multicast_ifp = NULL;
1200			}
1201			break;
1202		}
1203
1204#ifdef __FreeBSD__
1205		PF_UNLOCK();
1206#endif
1207		if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL)
1208			return (EINVAL);
1209#ifdef __FreeBSD__
1210		PF_LOCK();
1211#endif
1212
1213		s = splnet();
1214#ifdef __FreeBSD__
1215		if (sifp->if_mtu < sc->sc_ifp->if_mtu ||
1216#else
1217		if (sifp->if_mtu < sc->sc_if.if_mtu ||
1218#endif
1219		    (sc->sc_sync_ifp != NULL &&
1220		    sifp->if_mtu < sc->sc_sync_ifp->if_mtu) ||
1221		    sifp->if_mtu < MCLBYTES - sizeof(struct ip))
1222			pfsync_sendout(sc);
1223		sc->sc_sync_ifp = sifp;
1224
1225#ifdef __FreeBSD__
1226		pfsync_setmtu(sc, sc->sc_ifp->if_mtu);
1227#else
1228		pfsync_setmtu(sc, sc->sc_if.if_mtu);
1229#endif
1230
1231		if (imo->imo_num_memberships > 0) {
1232#ifdef __FreeBSD__
1233			PF_UNLOCK();
1234#endif
1235			in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
1236#ifdef __FreeBSD__
1237			PF_LOCK();
1238#endif
1239			imo->imo_multicast_ifp = NULL;
1240		}
1241
1242		if (sc->sc_sync_ifp &&
1243#ifdef __FreeBSD__
1244		    sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
1245#else
1246		    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1247#endif
1248			struct in_addr addr;
1249
1250			if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
1251				sc->sc_sync_ifp = NULL;
1252#ifdef __FreeBSD__
1253				PF_UNLOCK();
1254#endif
1255				splx(s);
1256				return (EADDRNOTAVAIL);
1257			}
1258
1259#ifdef __FreeBSD__
1260			addr.s_addr = htonl(INADDR_PFSYNC_GROUP);
1261#else
1262			addr.s_addr = INADDR_PFSYNC_GROUP;
1263#endif
1264
1265#ifdef __FreeBSD__
1266			PF_UNLOCK();
1267#endif
1268			if ((imo->imo_membership[0] =
1269			    in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
1270				sc->sc_sync_ifp = NULL;
1271				splx(s);
1272				return (ENOBUFS);
1273			}
1274#ifdef __FreeBSD__
1275			PF_LOCK();
1276#endif
1277			imo->imo_num_memberships++;
1278			imo->imo_multicast_ifp = sc->sc_sync_ifp;
1279			imo->imo_multicast_ttl = PFSYNC_DFLTTL;
1280			imo->imo_multicast_loop = 0;
1281		}
1282
1283		if (sc->sc_sync_ifp ||
1284#ifdef __FreeBSD__
1285		    sc->sc_sendaddr.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
1286#else
1287		    sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
1288#endif
1289			/* Request a full state table update. */
1290			sc->sc_ureq_sent = time_uptime;
1291#if NCARP > 0
1292			if (pfsync_sync_ok)
1293#ifdef __FreeBSD__
1294#ifdef CARP_ADVANCED
1295				carp_group_demote_adj(sc->sc_ifp, 1);
1296#endif
1297#else
1298				carp_group_demote_adj(&sc->sc_if, 1);
1299#endif
1300#endif
1301			pfsync_sync_ok = 0;
1302			if (pf_status.debug >= PF_DEBUG_MISC)
1303				printf("pfsync: requesting bulk update\n");
1304#ifdef __FreeBSD__
1305			callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
1306			    pfsync_bulkfail, pfsyncif);
1307#else
1308			timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
1309#endif
1310			error = pfsync_request_update(NULL, NULL);
1311			if (error == ENOMEM) {
1312#ifdef __FreeBSD__
1313				PF_UNLOCK();
1314#endif
1315				splx(s);
1316				return (ENOMEM);
1317			}
1318			pfsync_sendout(sc);
1319		}
1320#ifdef __FreeBSD__
1321		PF_UNLOCK();
1322#endif
1323		splx(s);
1324
1325		break;
1326
1327	default:
1328		return (ENOTTY);
1329	}
1330
1331	return (0);
1332}
1333
1334void
1335pfsync_setmtu(struct pfsync_softc *sc, int mtu_req)
1336{
1337	int mtu;
1338
1339	if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req)
1340		mtu = sc->sc_sync_ifp->if_mtu;
1341	else
1342		mtu = mtu_req;
1343
1344	sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) /
1345	    sizeof(struct pfsync_state);
1346	if (sc->sc_maxcount > 254)
1347	    sc->sc_maxcount = 254;
1348#ifdef __FreeBSD__
1349	sc->sc_ifp->if_mtu = sizeof(struct pfsync_header) +
1350#else
1351	sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
1352#endif
1353	    sc->sc_maxcount * sizeof(struct pfsync_state);
1354}
1355
1356struct mbuf *
1357pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
1358{
1359	struct pfsync_header *h;
1360	struct mbuf *m;
1361	int len;
1362
1363	MGETHDR(m, M_DONTWAIT, MT_DATA);
1364	if (m == NULL) {
1365#ifdef __FreeBSD__
1366		sc->sc_ifp->if_oerrors++;
1367#else
1368		sc->sc_if.if_oerrors++;
1369#endif
1370		return (NULL);
1371	}
1372
1373	switch (action) {
1374	case PFSYNC_ACT_CLR:
1375		len = sizeof(struct pfsync_header) +
1376		    sizeof(struct pfsync_state_clr);
1377		break;
1378	case PFSYNC_ACT_UPD_C:
1379		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) +
1380		    sizeof(struct pfsync_header);
1381		break;
1382	case PFSYNC_ACT_DEL_C:
1383		len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) +
1384		    sizeof(struct pfsync_header);
1385		break;
1386	case PFSYNC_ACT_UREQ:
1387		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) +
1388		    sizeof(struct pfsync_header);
1389		break;
1390	case PFSYNC_ACT_BUS:
1391		len = sizeof(struct pfsync_header) +
1392		    sizeof(struct pfsync_state_bus);
1393		break;
1394#ifdef PFSYNC_TDB
1395	case PFSYNC_ACT_TDB_UPD:
1396		len = (sc->sc_maxcount * sizeof(struct pfsync_tdb)) +
1397		    sizeof(struct pfsync_header);
1398		break;
1399#endif
1400	default:
1401		len = (sc->sc_maxcount * sizeof(struct pfsync_state)) +
1402		    sizeof(struct pfsync_header);
1403		break;
1404	}
1405
1406	if (len > MHLEN) {
1407		MCLGET(m, M_DONTWAIT);
1408		if ((m->m_flags & M_EXT) == 0) {
1409			m_free(m);
1410#ifdef __FreeBSD__
1411			sc->sc_ifp->if_oerrors++;
1412#else
1413			sc->sc_if.if_oerrors++;
1414#endif
1415			return (NULL);
1416		}
1417		m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1);
1418	} else
1419		MH_ALIGN(m, len);
1420
1421	m->m_pkthdr.rcvif = NULL;
1422	m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header);
1423	h = mtod(m, struct pfsync_header *);
1424	h->version = PFSYNC_VERSION;
1425	h->af = 0;
1426	h->count = 0;
1427	h->action = action;
1428#ifndef PFSYNC_TDB
1429	if (action != PFSYNC_ACT_TDB_UPD)
1430#endif
1431		bcopy(&pf_status.pf_chksum, &h->pf_chksum,
1432		    PF_MD5_DIGEST_LENGTH);
1433
1434	*sp = (void *)((char *)h + PFSYNC_HDRLEN);
1435#ifdef PFSYNC_TDB
1436	if (action == PFSYNC_ACT_TDB_UPD)
1437#ifdef __FreeBSD__
1438		callout_reset(&sc->sc_tdb_tmo, hz, pfsync_tdb_timeout,
1439		    pfsyncif);
1440#else
1441		timeout_add(&sc->sc_tdb_tmo, hz);
1442#endif
1443	else
1444#endif
1445#ifdef __FreeBSD__
1446		callout_reset(&sc->sc_tmo, hz, pfsync_timeout, pfsyncif);
1447#else
1448		timeout_add(&sc->sc_tmo, hz);
1449#endif
1450	return (m);
1451}
1452
1453int
1454pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
1455{
1456	struct ifnet *ifp = NULL;
1457	struct pfsync_softc *sc = pfsyncif;
1458	struct pfsync_header *h, *h_net;
1459	struct pfsync_state *sp = NULL;
1460	struct pfsync_state_upd *up = NULL;
1461	struct pfsync_state_del *dp = NULL;
1462	struct pf_rule *r;
1463	u_long secs;
1464	int s, ret = 0;
1465	u_int8_t i = 255, newaction = 0;
1466
1467	if (sc == NULL)
1468		return (0);
1469#ifdef __FreeBSD__
1470	ifp = sc->sc_ifp;
1471#else
1472	ifp = &sc->sc_if;
1473#endif
1474
1475	/*
1476	 * If a packet falls in the forest and there's nobody around to
1477	 * hear, does it make a sound?
1478	 */
1479	if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
1480#ifdef __FreeBSD__
1481	    sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
1482#else
1483	    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1484#endif
1485		/* Don't leave any stale pfsync packets hanging around. */
1486		if (sc->sc_mbuf != NULL) {
1487			m_freem(sc->sc_mbuf);
1488			sc->sc_mbuf = NULL;
1489			sc->sc_statep.s = NULL;
1490		}
1491		return (0);
1492	}
1493
1494	if (action >= PFSYNC_ACT_MAX)
1495		return (EINVAL);
1496
1497	s = splnet();
1498#ifdef __FreeBSD__
1499	PF_ASSERT(MA_OWNED);
1500#endif
1501	if (sc->sc_mbuf == NULL) {
1502		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
1503		    (void *)&sc->sc_statep.s)) == NULL) {
1504			splx(s);
1505			return (ENOMEM);
1506		}
1507		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1508	} else {
1509		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1510		if (h->action != action) {
1511			pfsync_sendout(sc);
1512			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
1513			    (void *)&sc->sc_statep.s)) == NULL) {
1514				splx(s);
1515				return (ENOMEM);
1516			}
1517			h = mtod(sc->sc_mbuf, struct pfsync_header *);
1518		} else {
1519			/*
1520			 * If it's an update, look in the packet to see if
1521			 * we already have an update for the state.
1522			 */
1523			if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) {
1524				struct pfsync_state *usp =
1525				    (void *)((char *)h + PFSYNC_HDRLEN);
1526
1527				for (i = 0; i < h->count; i++) {
1528					if (!memcmp(usp->id, &st->id,
1529					    PFSYNC_ID_LEN) &&
1530					    usp->creatorid == st->creatorid) {
1531						sp = usp;
1532						sp->updates++;
1533						break;
1534					}
1535					usp++;
1536				}
1537			}
1538		}
1539	}
1540
1541	secs = time_second;
1542
1543	st->pfsync_time = time_uptime;
1544
1545	if (sp == NULL) {
1546		/* not a "duplicate" update */
1547		i = 255;
1548		sp = sc->sc_statep.s++;
1549		sc->sc_mbuf->m_pkthdr.len =
1550		    sc->sc_mbuf->m_len += sizeof(struct pfsync_state);
1551		h->count++;
1552		bzero(sp, sizeof(*sp));
1553
1554		bcopy(&st->id, sp->id, sizeof(sp->id));
1555		sp->creatorid = st->creatorid;
1556
1557		strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
1558		pf_state_host_hton(&st->lan, &sp->lan);
1559		pf_state_host_hton(&st->gwy, &sp->gwy);
1560		pf_state_host_hton(&st->ext, &sp->ext);
1561
1562		bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
1563
1564		sp->creation = htonl(secs - st->creation);
1565		pf_state_counter_hton(st->packets[0], sp->packets[0]);
1566		pf_state_counter_hton(st->packets[1], sp->packets[1]);
1567		pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
1568		pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
1569		if ((r = st->rule.ptr) == NULL)
1570			sp->rule = htonl(-1);
1571		else
1572			sp->rule = htonl(r->nr);
1573		if ((r = st->anchor.ptr) == NULL)
1574			sp->anchor = htonl(-1);
1575		else
1576			sp->anchor = htonl(r->nr);
1577		sp->af = st->af;
1578		sp->proto = st->proto;
1579		sp->direction = st->direction;
1580		sp->log = st->log;
1581		sp->allow_opts = st->allow_opts;
1582		sp->timeout = st->timeout;
1583
1584		if (flags & PFSYNC_FLAG_STALE)
1585			sp->sync_flags |= PFSTATE_STALE;
1586	}
1587
1588	pf_state_peer_hton(&st->src, &sp->src);
1589	pf_state_peer_hton(&st->dst, &sp->dst);
1590
1591	if (st->expire <= secs)
1592		sp->expire = htonl(0);
1593	else
1594		sp->expire = htonl(st->expire - secs);
1595
1596	/* do we need to build "compressed" actions for network transfer? */
1597	if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
1598		switch (action) {
1599		case PFSYNC_ACT_UPD:
1600			newaction = PFSYNC_ACT_UPD_C;
1601			break;
1602		case PFSYNC_ACT_DEL:
1603			newaction = PFSYNC_ACT_DEL_C;
1604			break;
1605		default:
1606			/* by default we just send the uncompressed states */
1607			break;
1608		}
1609	}
1610
1611	if (newaction) {
1612		if (sc->sc_mbuf_net == NULL) {
1613			if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction,
1614			    (void *)&sc->sc_statep_net.s)) == NULL) {
1615				splx(s);
1616				return (ENOMEM);
1617			}
1618		}
1619		h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *);
1620
1621		switch (newaction) {
1622		case PFSYNC_ACT_UPD_C:
1623			if (i != 255) {
1624				up = (void *)((char *)h_net +
1625				    PFSYNC_HDRLEN + (i * sizeof(*up)));
1626				up->updates++;
1627			} else {
1628				h_net->count++;
1629				sc->sc_mbuf_net->m_pkthdr.len =
1630				    sc->sc_mbuf_net->m_len += sizeof(*up);
1631				up = sc->sc_statep_net.u++;
1632
1633				bzero(up, sizeof(*up));
1634				bcopy(&st->id, up->id, sizeof(up->id));
1635				up->creatorid = st->creatorid;
1636			}
1637			up->timeout = st->timeout;
1638			up->expire = sp->expire;
1639			up->src = sp->src;
1640			up->dst = sp->dst;
1641			break;
1642		case PFSYNC_ACT_DEL_C:
1643			sc->sc_mbuf_net->m_pkthdr.len =
1644			    sc->sc_mbuf_net->m_len += sizeof(*dp);
1645			dp = sc->sc_statep_net.d++;
1646			h_net->count++;
1647
1648			bzero(dp, sizeof(*dp));
1649			bcopy(&st->id, dp->id, sizeof(dp->id));
1650			dp->creatorid = st->creatorid;
1651			break;
1652		}
1653	}
1654
1655	if (h->count == sc->sc_maxcount ||
1656	    (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates)))
1657		ret = pfsync_sendout(sc);
1658
1659	splx(s);
1660	return (ret);
1661}
1662
1663/* This must be called in splnet() */
1664int
1665pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
1666{
1667	struct ifnet *ifp = NULL;
1668	struct pfsync_header *h;
1669	struct pfsync_softc *sc = pfsyncif;
1670	struct pfsync_state_upd_req *rup;
1671	int ret = 0;
1672
1673	if (sc == NULL)
1674		return (0);
1675
1676#ifdef __FreeBSD__
1677	ifp = sc->sc_ifp;
1678#else
1679	ifp = &sc->sc_if;
1680#endif
1681	if (sc->sc_mbuf == NULL) {
1682		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1683		    (void *)&sc->sc_statep.s)) == NULL)
1684			return (ENOMEM);
1685		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1686	} else {
1687		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1688		if (h->action != PFSYNC_ACT_UREQ) {
1689			pfsync_sendout(sc);
1690			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1691			    (void *)&sc->sc_statep.s)) == NULL)
1692				return (ENOMEM);
1693			h = mtod(sc->sc_mbuf, struct pfsync_header *);
1694		}
1695	}
1696
1697	if (src != NULL)
1698		sc->sc_sendaddr = *src;
1699	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
1700	h->count++;
1701	rup = sc->sc_statep.r++;
1702	bzero(rup, sizeof(*rup));
1703	if (up != NULL) {
1704		bcopy(up->id, rup->id, sizeof(rup->id));
1705		rup->creatorid = up->creatorid;
1706	}
1707
1708	if (h->count == sc->sc_maxcount)
1709		ret = pfsync_sendout(sc);
1710
1711	return (ret);
1712}
1713
1714int
1715pfsync_clear_states(u_int32_t creatorid, char *ifname)
1716{
1717	struct ifnet *ifp = NULL;
1718	struct pfsync_softc *sc = pfsyncif;
1719	struct pfsync_state_clr *cp;
1720	int s, ret;
1721
1722	if (sc == NULL)
1723		return (0);
1724
1725#ifdef __FreeBSD__
1726	ifp = sc->sc_ifp;
1727#else
1728	ifp = &sc->sc_if;
1729#endif
1730#ifdef __FreeBSD__
1731	PF_ASSERT(MA_OWNED);
1732#endif
1733	s = splnet();
1734	if (sc->sc_mbuf != NULL)
1735		pfsync_sendout(sc);
1736	if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR,
1737	    (void *)&sc->sc_statep.c)) == NULL) {
1738		splx(s);
1739		return (ENOMEM);
1740	}
1741	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp);
1742	cp = sc->sc_statep.c;
1743	cp->creatorid = creatorid;
1744	if (ifname != NULL)
1745		strlcpy(cp->ifname, ifname, IFNAMSIZ);
1746
1747	ret = (pfsync_sendout(sc));
1748	splx(s);
1749	return (ret);
1750}
1751
1752void
1753pfsync_timeout(void *v)
1754{
1755	struct pfsync_softc *sc = v;
1756	int s;
1757
1758	s = splnet();
1759#ifdef __FreeBSD__
1760	PF_LOCK();
1761#endif
1762	pfsync_sendout(sc);
1763#ifdef __FreeBSD__
1764	PF_UNLOCK();
1765#endif
1766	splx(s);
1767}
1768
1769#ifdef PFSYNC_TDB
1770void
1771pfsync_tdb_timeout(void *v)
1772{
1773	struct pfsync_softc *sc = v;
1774	int s;
1775
1776	s = splnet();
1777#ifdef __FreeBSD__
1778	PF_LOCK();
1779#endif
1780	pfsync_tdb_sendout(sc);
1781#ifdef __FreeBSD__
1782	PF_UNLOCK();
1783#endif
1784	splx(s);
1785}
1786#endif
1787
1788/* This must be called in splnet() */
1789void
1790pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
1791{
1792	struct pfsync_state_bus *bus;
1793
1794#ifdef __FreeBSD__
1795	PF_ASSERT(MA_OWNED);
1796#endif
1797	if (sc->sc_mbuf != NULL)
1798		pfsync_sendout(sc);
1799
1800	if (pfsync_sync_ok &&
1801	    (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
1802	    (void *)&sc->sc_statep.b)) != NULL) {
1803		sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
1804		bus = sc->sc_statep.b;
1805		bus->creatorid = pf_status.hostid;
1806		bus->status = status;
1807		bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
1808		pfsync_sendout(sc);
1809	}
1810}
1811
1812void
1813pfsync_bulk_update(void *v)
1814{
1815	struct pfsync_softc *sc = v;
1816	int s, i = 0;
1817	struct pf_state *state;
1818
1819	s = splnet();
1820#ifdef __FreeBSD__
1821	PF_LOCK();
1822#endif
1823	if (sc->sc_mbuf != NULL)
1824		pfsync_sendout(sc);
1825
1826	/*
1827	 * Grab at most PFSYNC_BULKPACKETS worth of states which have not
1828	 * been sent since the latest request was made.
1829	 */
1830	state = sc->sc_bulk_send_next;
1831	if (state)
1832		do {
1833			/* send state update if syncable and not already sent */
1834			if (!state->sync_flags
1835			    && state->timeout < PFTM_MAX
1836			    && state->pfsync_time <= sc->sc_ureq_received) {
1837				pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
1838				i++;
1839			}
1840
1841			/* figure next state to send */
1842			state = TAILQ_NEXT(state, u.s.entry_list);
1843
1844			/* wrap to start of list if we hit the end */
1845			if (!state)
1846				state = TAILQ_FIRST(&state_list);
1847		} while (i < sc->sc_maxcount * PFSYNC_BULKPACKETS &&
1848		    state != sc->sc_bulk_terminator);
1849
1850	if (!state || state == sc->sc_bulk_terminator) {
1851		/* we're done */
1852		pfsync_send_bus(sc, PFSYNC_BUS_END);
1853		sc->sc_ureq_received = 0;
1854		sc->sc_bulk_send_next = NULL;
1855		sc->sc_bulk_terminator = NULL;
1856		timeout_del(&sc->sc_bulk_tmo);
1857		if (pf_status.debug >= PF_DEBUG_MISC)
1858			printf("pfsync: bulk update complete\n");
1859	} else {
1860		/* look again for more in a bit */
1861#ifdef __FreeBSD__
1862		callout_reset(&sc->sc_bulk_tmo, 1, pfsync_bulk_update,
1863		    pfsyncif);
1864#else
1865		timeout_add(&sc->sc_bulk_tmo, 1);
1866#endif
1867		sc->sc_bulk_send_next = state;
1868	}
1869	if (sc->sc_mbuf != NULL)
1870		pfsync_sendout(sc);
1871	splx(s);
1872#ifdef __FreeBSD__
1873	PF_UNLOCK();
1874#endif
1875}
1876
1877void
1878pfsync_bulkfail(void *v)
1879{
1880	struct pfsync_softc *sc = v;
1881	int s, error;
1882
1883#ifdef __FreeBSD__
1884	PF_LOCK();
1885#endif
1886	if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
1887		/* Try again in a bit */
1888#ifdef __FreeBSD__
1889		callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail,
1890		    pfsyncif);
1891#else
1892		timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
1893#endif
1894		s = splnet();
1895		error = pfsync_request_update(NULL, NULL);
1896		if (error == ENOMEM) {
1897			if (pf_status.debug >= PF_DEBUG_MISC)
1898				printf("pfsync: cannot allocate mbufs for "
1899				    "bulk update\n");
1900		} else
1901			pfsync_sendout(sc);
1902		splx(s);
1903	} else {
1904		/* Pretend like the transfer was ok */
1905		sc->sc_ureq_sent = 0;
1906		sc->sc_bulk_tries = 0;
1907#if NCARP > 0
1908		if (!pfsync_sync_ok)
1909#ifdef __FreeBSD__
1910#ifdef CARP_ADVANCED
1911			carp_group_demote_adj(sc->sc_ifp, -1);
1912#endif
1913#else
1914			carp_group_demote_adj(&sc->sc_if, -1);
1915#endif
1916#endif
1917		pfsync_sync_ok = 1;
1918		if (pf_status.debug >= PF_DEBUG_MISC)
1919			printf("pfsync: failed to receive "
1920			    "bulk update status\n");
1921		timeout_del(&sc->sc_bulkfail_tmo);
1922	}
1923#ifdef __FreeBSD__
1924	PF_UNLOCK();
1925#endif
1926}
1927
1928/* This must be called in splnet() */
1929int
1930pfsync_sendout(struct pfsync_softc *sc)
1931{
1932#if NBPFILTER > 0
1933#ifdef __FreeBSD__
1934	struct ifnet *ifp = sc->sc_ifp;
1935#else
1936	struct ifnet *ifp = &sc->sc_if;
1937#endif
1938#endif
1939	struct mbuf *m;
1940
1941#ifdef __FreeBSD__
1942	PF_ASSERT(MA_OWNED);
1943#endif
1944	timeout_del(&sc->sc_tmo);
1945
1946	if (sc->sc_mbuf == NULL)
1947		return (0);
1948	m = sc->sc_mbuf;
1949	sc->sc_mbuf = NULL;
1950	sc->sc_statep.s = NULL;
1951
1952#if NBPFILTER > 0
1953	if (ifp->if_bpf)
1954#ifdef __FreeBSD__
1955		BPF_MTAP(ifp, m);
1956#else
1957		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1958#endif
1959#endif
1960
1961	if (sc->sc_mbuf_net) {
1962		m_freem(m);
1963		m = sc->sc_mbuf_net;
1964		sc->sc_mbuf_net = NULL;
1965		sc->sc_statep_net.s = NULL;
1966	}
1967
1968	return pfsync_sendout_mbuf(sc, m);
1969}
1970
1971#ifdef PFSYNC_TDB
1972int
1973pfsync_tdb_sendout(struct pfsync_softc *sc)
1974{
1975#if NBPFILTER > 0
1976#ifdef __FreeBSD__
1977	struct ifnet *ifp = sc->sc_ifp;
1978#else
1979	struct ifnet *ifp = &sc->sc_if;
1980#endif
1981#endif
1982	struct mbuf *m;
1983
1984#ifdef __FreeBSD__
1985	PF_ASSERT(MA_OWNED);
1986#endif
1987	timeout_del(&sc->sc_tdb_tmo);
1988
1989	if (sc->sc_mbuf_tdb == NULL)
1990		return (0);
1991	m = sc->sc_mbuf_tdb;
1992	sc->sc_mbuf_tdb = NULL;
1993	sc->sc_statep_tdb.t = NULL;
1994
1995#if NBPFILTER > 0
1996	if (ifp->if_bpf)
1997#ifdef __FreeBSD__
1998		BPF_MTAP(ifp, m);
1999#else
2000		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
2001#endif
2002#endif
2003
2004	return pfsync_sendout_mbuf(sc, m);
2005}
2006#endif
2007
2008int
2009pfsync_sendout_mbuf(struct pfsync_softc *sc, struct mbuf *m)
2010{
2011	struct sockaddr sa;
2012	struct ip *ip;
2013
2014#ifdef __FreeBSD__
2015	PF_ASSERT(MA_OWNED);
2016#endif
2017	if (sc->sc_sync_ifp ||
2018#ifdef __FreeBSD__
2019	    sc->sc_sync_peer.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
2020#else
2021	    sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
2022#endif
2023		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
2024		if (m == NULL) {
2025			pfsyncstats.pfsyncs_onomem++;
2026			return (0);
2027		}
2028		ip = mtod(m, struct ip *);
2029		ip->ip_v = IPVERSION;
2030		ip->ip_hl = sizeof(*ip) >> 2;
2031		ip->ip_tos = IPTOS_LOWDELAY;
2032#ifdef __FreeBSD__
2033		ip->ip_len = m->m_pkthdr.len;
2034#else
2035		ip->ip_len = htons(m->m_pkthdr.len);
2036#endif
2037		ip->ip_id = htons(ip_randomid());
2038#ifdef __FreeBSD__
2039		ip->ip_off = IP_DF;
2040#else
2041		ip->ip_off = htons(IP_DF);
2042#endif
2043		ip->ip_ttl = PFSYNC_DFLTTL;
2044		ip->ip_p = IPPROTO_PFSYNC;
2045		ip->ip_sum = 0;
2046
2047		bzero(&sa, sizeof(sa));
2048		ip->ip_src.s_addr = INADDR_ANY;
2049
2050#ifdef __FreeBSD__
2051		if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP))
2052#else
2053		if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
2054#endif
2055			m->m_flags |= M_MCAST;
2056		ip->ip_dst = sc->sc_sendaddr;
2057		sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
2058
2059		pfsyncstats.pfsyncs_opackets++;
2060
2061#ifdef __FreeBSD__
2062		if (!IF_HANDOFF(&sc->sc_ifq, m, NULL))
2063			pfsyncstats.pfsyncs_oerrors++;
2064		taskqueue_enqueue(taskqueue_thread, &pfsyncif->sc_send_task);
2065#else
2066		if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
2067			pfsyncstats.pfsyncs_oerrors++;
2068#endif
2069	} else
2070		m_freem(m);
2071
2072	return (0);
2073}
2074
2075#ifdef PFSYNC_TDB
2076/* Update an in-kernel tdb. Silently fail if no tdb is found. */
2077void
2078pfsync_update_net_tdb(struct pfsync_tdb *pt)
2079{
2080	struct tdb		*tdb;
2081	int			 s;
2082
2083	/* check for invalid values */
2084	if (ntohl(pt->spi) <= SPI_RESERVED_MAX ||
2085	    (pt->dst.sa.sa_family != AF_INET &&
2086	     pt->dst.sa.sa_family != AF_INET6))
2087		goto bad;
2088
2089	s = spltdb();
2090	tdb = gettdb(pt->spi, &pt->dst, pt->sproto);
2091	if (tdb) {
2092		pt->rpl = ntohl(pt->rpl);
2093		pt->cur_bytes = betoh64(pt->cur_bytes);
2094
2095		/* Neither replay nor byte counter should ever decrease. */
2096		if (pt->rpl < tdb->tdb_rpl ||
2097		    pt->cur_bytes < tdb->tdb_cur_bytes) {
2098			splx(s);
2099			goto bad;
2100		}
2101
2102		tdb->tdb_rpl = pt->rpl;
2103		tdb->tdb_cur_bytes = pt->cur_bytes;
2104	}
2105	splx(s);
2106	return;
2107
2108 bad:
2109	if (pf_status.debug >= PF_DEBUG_MISC)
2110		printf("pfsync_insert: PFSYNC_ACT_TDB_UPD: "
2111		    "invalid value\n");
2112	pfsyncstats.pfsyncs_badstate++;
2113	return;
2114}
2115
2116/* One of our local tdbs have been updated, need to sync rpl with others */
2117int
2118pfsync_update_tdb(struct tdb *tdb, int output)
2119{
2120	struct ifnet *ifp = NULL;
2121	struct pfsync_softc *sc = pfsyncif;
2122	struct pfsync_header *h;
2123	struct pfsync_tdb *pt = NULL;
2124	int s, i, ret;
2125
2126	if (sc == NULL)
2127		return (0);
2128
2129#ifdef __FreeBSD__
2130	ifp = sc->sc_ifp;
2131#else
2132	ifp = &sc->sc_if;
2133#endif
2134	if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
2135#ifdef __FreeBSD__
2136	    sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
2137#else
2138	    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
2139#endif
2140		/* Don't leave any stale pfsync packets hanging around. */
2141		if (sc->sc_mbuf_tdb != NULL) {
2142			m_freem(sc->sc_mbuf_tdb);
2143			sc->sc_mbuf_tdb = NULL;
2144			sc->sc_statep_tdb.t = NULL;
2145		}
2146		return (0);
2147	}
2148
2149#ifdef __FreeBSD__
2150	PF_ASSERT(MA_OWNED);
2151#endif
2152	s = splnet();
2153	if (sc->sc_mbuf_tdb == NULL) {
2154		if ((sc->sc_mbuf_tdb = pfsync_get_mbuf(sc, PFSYNC_ACT_TDB_UPD,
2155		    (void *)&sc->sc_statep_tdb.t)) == NULL) {
2156			splx(s);
2157			return (ENOMEM);
2158		}
2159		h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
2160	} else {
2161		h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
2162		if (h->action != PFSYNC_ACT_TDB_UPD) {
2163			/*
2164			 * XXX will never happen as long as there's
2165			 * only one "TDB action".
2166			 */
2167			pfsync_tdb_sendout(sc);
2168			sc->sc_mbuf_tdb = pfsync_get_mbuf(sc,
2169			    PFSYNC_ACT_TDB_UPD, (void *)&sc->sc_statep_tdb.t);
2170			if (sc->sc_mbuf_tdb == NULL) {
2171				splx(s);
2172				return (ENOMEM);
2173			}
2174			h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
2175		} else if (sc->sc_maxupdates) {
2176			/*
2177			 * If it's an update, look in the packet to see if
2178			 * we already have an update for the state.
2179			 */
2180			struct pfsync_tdb *u =
2181			    (void *)((char *)h + PFSYNC_HDRLEN);
2182
2183			for (i = 0; !pt && i < h->count; i++) {
2184				if (tdb->tdb_spi == u->spi &&
2185				    tdb->tdb_sproto == u->sproto &&
2186			            !bcmp(&tdb->tdb_dst, &u->dst,
2187				    SA_LEN(&u->dst.sa))) {
2188					pt = u;
2189					pt->updates++;
2190				}
2191				u++;
2192			}
2193		}
2194	}
2195
2196	if (pt == NULL) {
2197		/* not a "duplicate" update */
2198		pt = sc->sc_statep_tdb.t++;
2199		sc->sc_mbuf_tdb->m_pkthdr.len =
2200		    sc->sc_mbuf_tdb->m_len += sizeof(struct pfsync_tdb);
2201		h->count++;
2202		bzero(pt, sizeof(*pt));
2203
2204		pt->spi = tdb->tdb_spi;
2205		memcpy(&pt->dst, &tdb->tdb_dst, sizeof pt->dst);
2206		pt->sproto = tdb->tdb_sproto;
2207	}
2208
2209	/*
2210	 * When a failover happens, the master's rpl is probably above
2211	 * what we see here (we may be up to a second late), so
2212	 * increase it a bit for outbound tdbs to manage most such
2213	 * situations.
2214	 *
2215	 * For now, just add an offset that is likely to be larger
2216	 * than the number of packets we can see in one second. The RFC
2217	 * just says the next packet must have a higher seq value.
2218	 *
2219	 * XXX What is a good algorithm for this? We could use
2220	 * a rate-determined increase, but to know it, we would have
2221	 * to extend struct tdb.
2222	 * XXX pt->rpl can wrap over MAXINT, but if so the real tdb
2223	 * will soon be replaced anyway. For now, just don't handle
2224	 * this edge case.
2225	 */
2226#define RPL_INCR 16384
2227	pt->rpl = htonl(tdb->tdb_rpl + (output ? RPL_INCR : 0));
2228	pt->cur_bytes = htobe64(tdb->tdb_cur_bytes);
2229
2230	if (h->count == sc->sc_maxcount ||
2231	    (sc->sc_maxupdates && (pt->updates >= sc->sc_maxupdates)))
2232		ret = pfsync_tdb_sendout(sc);
2233
2234	splx(s);
2235	return (ret);
2236}
2237#endif /* PFSYNC_TDB */
2238
2239#ifdef __FreeBSD__
2240void
2241pfsync_ifdetach(void *arg, struct ifnet *ifp)
2242{
2243	struct pfsync_softc *sc = (struct pfsync_softc *)arg;
2244	struct ip_moptions *imo;
2245
2246	if (sc == NULL || sc->sc_sync_ifp != ifp)
2247		return;         /* not for us; unlocked read */
2248
2249	PF_LOCK();
2250
2251	/* Deal with a member interface going away from under us. */
2252	sc->sc_sync_ifp = NULL;
2253	if (sc->sc_mbuf_net != NULL) {
2254		m_freem(sc->sc_mbuf_net);
2255		sc->sc_mbuf_net = NULL;
2256		sc->sc_statep_net.s = NULL;
2257	}
2258	imo = &sc->sc_imo;
2259	if (imo->imo_num_memberships > 0) {
2260		KASSERT(imo->imo_num_memberships == 1,
2261		    ("%s: imo_num_memberships != 1", __func__));
2262		/*
2263		 * Our event handler is always called after protocol
2264		 * domains have been detached from the underlying ifnet.
2265		 * Do not call in_delmulti(); we held a single reference
2266		 * which the protocol domain has purged in in_purgemaddrs().
2267		 */
2268		PF_UNLOCK();
2269		imo->imo_membership[--imo->imo_num_memberships] = NULL;
2270		PF_LOCK();
2271		imo->imo_multicast_ifp = NULL;
2272	}
2273
2274	PF_UNLOCK();
2275}
2276
2277void
2278pfsync_senddef(void *arg, __unused int pending)
2279{
2280	struct pfsync_softc *sc = (struct pfsync_softc *)arg;
2281	struct mbuf *m;
2282
2283	for(;;) {
2284		IF_DEQUEUE(&sc->sc_ifq, m);
2285		if (m == NULL)
2286			break;
2287		/* Deal with a member interface going away from under us. */
2288		if (sc->sc_sync_ifp == NULL) {
2289			pfsyncstats.pfsyncs_oerrors++;
2290			m_freem(m);
2291			continue;
2292		}
2293		if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
2294			pfsyncstats.pfsyncs_oerrors++;
2295	}
2296}
2297
2298static int
2299pfsync_modevent(module_t mod, int type, void *data)
2300{
2301	int error = 0;
2302
2303	switch (type) {
2304	case MOD_LOAD:
2305		pfsyncattach(0);
2306		break;
2307	case MOD_UNLOAD:
2308		if_clone_detach(&pfsync_cloner);
2309		break;
2310	default:
2311		error = EINVAL;
2312		break;
2313	}
2314
2315	return error;
2316}
2317
2318static moduledata_t pfsync_mod = {
2319	"pfsync",
2320	pfsync_modevent,
2321	0
2322};
2323
2324#define PFSYNC_MODVER 1
2325
2326DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
2327MODULE_VERSION(pfsync, PFSYNC_MODVER);
2328MODULE_DEPEND(pflog, pf, PF_MODVER, PF_MODVER, PF_MODVER);
2329#endif /* __FreeBSD__ */
2330