if_pfsync.c revision 145836
1138269Snik/*	$FreeBSD: head/sys/contrib/pf/net/if_pfsync.c 145836 2005-05-03 16:43:32Z mlaier $	*/
2138269Snik/*	$OpenBSD: if_pfsync.c,v 1.46 2005/02/20 15:58:38 mcbride Exp $	*/
3138269Snik
4138269Snik/*
5138269Snik * Copyright (c) 2002 Michael Shalayeff
6138269Snik * All rights reserved.
7138269Snik *
8138269Snik * Redistribution and use in source and binary forms, with or without
9138269Snik * modification, are permitted provided that the following conditions
10138269Snik * are met:
11138269Snik * 1. Redistributions of source code must retain the above copyright
12138269Snik *    notice, this list of conditions and the following disclaimer.
13138269Snik * 2. Redistributions in binary form must reproduce the above copyright
14138269Snik *    notice, this list of conditions and the following disclaimer in the
15138269Snik *    documentation and/or other materials provided with the distribution.
16138269Snik *
17138269Snik * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18138269Snik * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19138269Snik * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20138269Snik * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
21138269Snik * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22138269Snik * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23138269Snik * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24138269Snik * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25138269Snik * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26138269Snik * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27138269Snik * THE POSSIBILITY OF SUCH DAMAGE.
28138269Snik */
29138269Snik
30138269Snik#ifdef __FreeBSD__
31138269Snik#include "opt_inet.h"
32138269Snik#include "opt_inet6.h"
33138269Snik#endif
34138269Snik
35138269Snik#ifndef __FreeBSD__
36138269Snik#include "bpfilter.h"
37138269Snik#include "pfsync.h"
38222485Srwatson#elif __FreeBSD__ >= 5
39138269Snik#include "opt_bpf.h"
40138269Snik#include "opt_pf.h"
41138269Snik#define	NBPFILTER	DEV_BPF
42138269Snik#define	NPFSYNC		DEV_PFSYNC
43138269Snik#endif
44138269Snik
45138269Snik#include <sys/param.h>
46138269Snik#include <sys/proc.h>
47138269Snik#include <sys/systm.h>
48138269Snik#include <sys/time.h>
49138269Snik#include <sys/mbuf.h>
50138269Snik#include <sys/socket.h>
51138269Snik#include <sys/kernel.h>
52138269Snik#ifdef __FreeBSD__
53138269Snik#include <sys/endian.h>
54138269Snik#include <sys/malloc.h>
55138269Snik#include <sys/module.h>
56138269Snik#include <sys/sockio.h>
57138269Snik#include <sys/lock.h>
58138269Snik#include <sys/mutex.h>
59138269Snik#else
60138269Snik#include <sys/ioctl.h>
61138269Snik#include <sys/timeout.h>
62138269Snik#endif
63138269Snik
64138269Snik#include <net/if.h>
65138269Snik#if defined(__FreeBSD__)
66138269Snik#include <net/if_clone.h>
67138269Snik#endif
68138269Snik#include <net/if_types.h>
69138269Snik#include <net/route.h>
70138269Snik#include <net/bpf.h>
71138269Snik#include <netinet/tcp.h>
72138269Snik#include <netinet/tcp_seq.h>
73138269Snik
74138269Snik#ifdef	INET
75138269Snik#include <netinet/in.h>
76138269Snik#include <netinet/in_systm.h>
77138269Snik#include <netinet/in_var.h>
78138269Snik#include <netinet/ip.h>
79138269Snik#include <netinet/ip_var.h>
80138269Snik#endif
81138269Snik
82138269Snik#ifdef INET6
83138269Snik#ifndef INET
84138269Snik#include <netinet/in.h>
85138269Snik#endif
86138269Snik#include <netinet6/nd6.h>
87138269Snik#endif /* INET6 */
88138269Snik
89138269Snik#ifdef __FreeBSD__
90138269Snik#include "opt_carp.h"
91138269Snik#ifdef DEV_CARP
92138269Snik#define	NCARP	1
93138269Snik#endif
94138269Snik#else
95138269Snik#include "carp.h"
96138269Snik#endif
97138269Snik#if NCARP > 0
98138269Snikextern int carp_suppress_preempt;
99138269Snik#endif
100138269Snik
101138269Snik#include <net/pfvar.h>
102138269Snik#include <net/if_pfsync.h>
103138269Snik
104138269Snik#ifdef __FreeBSD__
105138269Snik#define	PFSYNCNAME	"pfsync"
106138269Snik#endif
107138269Snik
108138269Snik#define PFSYNC_MINMTU	\
109138269Snik    (sizeof(struct pfsync_header) + sizeof(struct pf_state))
110138269Snik
111138269Snik#ifdef PFSYNCDEBUG
112138269Snik#define DPRINTF(x)    do { if (pfsyncdebug) printf x ; } while (0)
113138269Snikint pfsyncdebug;
114138269Snik#else
115138269Snik#define DPRINTF(x)
116138269Snik#endif
117138269Snik
118138269Snik#ifndef __FreeBSD__
119138269Snikstruct pfsync_softc	pfsyncif;
120138269Snik#endif
121138269Snikstruct pfsyncstats	pfsyncstats;
122138269Snik
123138269Snik#ifdef __FreeBSD__
124138269Snik
125138269Snik/*
126138269Snik * Locking notes:
127138269Snik * Whenever we really touch/look at the state table we have to hold the
128138269Snik * PF_LOCK. Functions that do just the interface handling, grab the per
129138269Snik * softc lock instead.
130138269Snik *
131138269Snik */
132138269Snik
133static void	pfsync_clone_destroy(struct ifnet *);
134static int	pfsync_clone_create(struct if_clone *, int);
135#else
136void	pfsyncattach(int);
137#endif
138void	pfsync_setmtu(struct pfsync_softc *, int);
139int	pfsync_insert_net_state(struct pfsync_state *);
140int	pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
141	    struct rtentry *);
142int	pfsyncioctl(struct ifnet *, u_long, caddr_t);
143void	pfsyncstart(struct ifnet *);
144
145struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
146int	pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
147int	pfsync_sendout(struct pfsync_softc *);
148void	pfsync_timeout(void *);
149void	pfsync_send_bus(struct pfsync_softc *, u_int8_t);
150void	pfsync_bulk_update(void *);
151void	pfsync_bulkfail(void *);
152
153int	pfsync_sync_ok;
154#ifndef __FreeBSD__
155extern int ifqmaxlen;
156extern struct timeval time;
157extern struct timeval mono_time;
158extern int hz;
159#endif
160
161#ifdef __FreeBSD__
162static MALLOC_DEFINE(M_PFSYNC, PFSYNCNAME, "Packet Filter State Sync. Interface");
163static LIST_HEAD(pfsync_list, pfsync_softc) pfsync_list;
164#define	SCP2IFP(sc)		(&(sc)->sc_if)
165IFC_SIMPLE_DECLARE(pfsync, 1);
166
167static void
168pfsync_clone_destroy(struct ifnet *ifp)
169{
170        struct pfsync_softc *sc;
171
172	sc = ifp->if_softc;
173	callout_stop(&sc->sc_tmo);
174	callout_stop(&sc->sc_bulk_tmo);
175	callout_stop(&sc->sc_bulkfail_tmo);
176
177#if NBPFILTER > 0
178        bpfdetach(ifp);
179#endif
180        if_detach(ifp);
181        LIST_REMOVE(sc, sc_next);
182        free(sc, M_PFSYNC);
183}
184
185static int
186pfsync_clone_create(struct if_clone *ifc, int unit)
187{
188	struct pfsync_softc *sc;
189	struct ifnet *ifp;
190
191	MALLOC(sc, struct pfsync_softc *, sizeof(*sc), M_PFSYNC,
192	    M_WAITOK|M_ZERO);
193
194	pfsync_sync_ok = 1;
195	sc->sc_mbuf = NULL;
196	sc->sc_mbuf_net = NULL;
197	sc->sc_statep.s = NULL;
198	sc->sc_statep_net.s = NULL;
199	sc->sc_maxupdates = 128;
200	sc->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP);
201	sc->sc_ureq_received = 0;
202	sc->sc_ureq_sent = 0;
203
204	ifp = SCP2IFP(sc);
205	if_initname(ifp, ifc->ifc_name, unit);
206	ifp->if_ioctl = pfsyncioctl;
207	ifp->if_output = pfsyncoutput;
208	ifp->if_start = pfsyncstart;
209	ifp->if_type = IFT_PFSYNC;
210	ifp->if_snd.ifq_maxlen = ifqmaxlen;
211	ifp->if_hdrlen = PFSYNC_HDRLEN;
212	ifp->if_baudrate = IF_Mbps(100);
213	ifp->if_softc = sc;
214	pfsync_setmtu(sc, MCLBYTES);
215	/*
216	 * XXX
217	 *  The 2nd arg. 0 to callout_init(9) shoule be set to CALLOUT_MPSAFE
218	 * if Gaint lock is removed from the network stack.
219	 */
220	callout_init(&sc->sc_tmo, 0);
221	callout_init(&sc->sc_bulk_tmo, 0);
222	callout_init(&sc->sc_bulkfail_tmo, 0);
223	if_attach(ifp);
224
225	LIST_INSERT_HEAD(&pfsync_list, sc, sc_next);
226#if NBPFILTER > 0
227	bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
228#endif
229
230	return (0);
231}
232#else /* !__FreeBSD__ */
233void
234pfsyncattach(int npfsync)
235{
236	struct ifnet *ifp;
237
238	pfsync_sync_ok = 1;
239	bzero(&pfsyncif, sizeof(pfsyncif));
240	pfsyncif.sc_mbuf = NULL;
241	pfsyncif.sc_mbuf_net = NULL;
242	pfsyncif.sc_statep.s = NULL;
243	pfsyncif.sc_statep_net.s = NULL;
244	pfsyncif.sc_maxupdates = 128;
245	pfsyncif.sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
246	pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
247	pfsyncif.sc_ureq_received = 0;
248	pfsyncif.sc_ureq_sent = 0;
249	ifp = &pfsyncif.sc_if;
250	strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname);
251	ifp->if_softc = &pfsyncif;
252	ifp->if_ioctl = pfsyncioctl;
253	ifp->if_output = pfsyncoutput;
254	ifp->if_start = pfsyncstart;
255	ifp->if_type = IFT_PFSYNC;
256	ifp->if_snd.ifq_maxlen = ifqmaxlen;
257	ifp->if_hdrlen = PFSYNC_HDRLEN;
258	pfsync_setmtu(&pfsyncif, MCLBYTES);
259	timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif);
260	timeout_set(&pfsyncif.sc_bulk_tmo, pfsync_bulk_update, &pfsyncif);
261	timeout_set(&pfsyncif.sc_bulkfail_tmo, pfsync_bulkfail, &pfsyncif);
262	if_attach(ifp);
263	if_alloc_sadl(ifp);
264
265#if NBPFILTER > 0
266	bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
267#endif
268}
269#endif
270
271/*
272 * Start output on the pfsync interface.
273 */
274void
275pfsyncstart(struct ifnet *ifp)
276{
277#ifdef __FreeBSD__
278	IF_LOCK(&ifp->if_snd);
279	_IF_DROP(&ifp->if_snd);
280	_IF_DRAIN(&ifp->if_snd);
281	IF_UNLOCK(&ifp->if_snd);
282#else
283	struct mbuf *m;
284	int s;
285
286	for (;;) {
287		s = splimp();
288		IF_DROP(&ifp->if_snd);
289		IF_DEQUEUE(&ifp->if_snd, m);
290		splx(s);
291
292		if (m == NULL)
293			return;
294		else
295			m_freem(m);
296	}
297#endif
298}
299
300int
301pfsync_insert_net_state(struct pfsync_state *sp)
302{
303	struct pf_state	*st = NULL;
304	struct pf_rule *r = NULL;
305	struct pfi_kif	*kif;
306
307#ifdef __FreeBSD__
308	PF_ASSERT(MA_OWNED);
309#endif
310	if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
311		printf("pfsync_insert_net_state: invalid creator id:"
312		    " %08x\n", ntohl(sp->creatorid));
313		return (EINVAL);
314	}
315
316	kif = pfi_lookup_create(sp->ifname);
317	if (kif == NULL) {
318		if (pf_status.debug >= PF_DEBUG_MISC)
319			printf("pfsync_insert_net_state: "
320			    "unknown interface: %s\n", sp->ifname);
321		/* skip this state */
322		return (0);
323	}
324
325	/*
326	 * Just use the default rule until we have infrastructure to find the
327	 * best matching rule.
328	 */
329	r = &pf_default_rule;
330
331	if (!r->max_states || r->states < r->max_states)
332		st = pool_get(&pf_state_pl, PR_NOWAIT);
333	if (st == NULL) {
334		pfi_maybe_destroy(kif);
335		return (ENOMEM);
336	}
337	bzero(st, sizeof(*st));
338
339	st->rule.ptr = r;
340	/* XXX get pointers to nat_rule and anchor */
341
342	/* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
343	r->states++;
344
345	/* fill in the rest of the state entry */
346	pf_state_host_ntoh(&sp->lan, &st->lan);
347	pf_state_host_ntoh(&sp->gwy, &st->gwy);
348	pf_state_host_ntoh(&sp->ext, &st->ext);
349
350	pf_state_peer_ntoh(&sp->src, &st->src);
351	pf_state_peer_ntoh(&sp->dst, &st->dst);
352
353	bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
354	st->creation = time_second - ntohl(sp->creation);
355	st->expire = ntohl(sp->expire) + time_second;
356
357	st->af = sp->af;
358	st->proto = sp->proto;
359	st->direction = sp->direction;
360	st->log = sp->log;
361	st->timeout = sp->timeout;
362	st->allow_opts = sp->allow_opts;
363
364	bcopy(sp->id, &st->id, sizeof(st->id));
365	st->creatorid = sp->creatorid;
366	st->sync_flags = PFSTATE_FROMSYNC;
367
368
369	if (pf_insert_state(kif, st)) {
370		pfi_maybe_destroy(kif);
371		/* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
372		r->states--;
373		pool_put(&pf_state_pl, st);
374		return (EINVAL);
375	}
376
377	return (0);
378}
379
380void
381#ifdef __FreeBSD__
382pfsync_input(struct mbuf *m, __unused int off)
383#else
384pfsync_input(struct mbuf *m, ...)
385#endif
386{
387	struct ip *ip = mtod(m, struct ip *);
388	struct pfsync_header *ph;
389#ifdef __FreeBSD__
390	struct pfsync_softc *sc = LIST_FIRST(&pfsync_list);
391#else
392	struct pfsync_softc *sc = &pfsyncif;
393#endif
394	struct pf_state *st, key;
395	struct pfsync_state *sp;
396	struct pfsync_state_upd *up;
397	struct pfsync_state_del *dp;
398	struct pfsync_state_clr *cp;
399	struct pfsync_state_upd_req *rup;
400	struct pfsync_state_bus *bus;
401	struct in_addr src;
402	struct mbuf *mp;
403	int iplen, action, error, i, s, count, offp, sfail, stale = 0;
404
405	pfsyncstats.pfsyncs_ipackets++;
406
407	/* verify that we have a sync interface configured */
408	if (!sc->sc_sync_ifp || !pf_status.running) /* XXX PF_LOCK? */
409		goto done;
410
411	/* verify that the packet came in on the right interface */
412	if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
413		pfsyncstats.pfsyncs_badif++;
414		goto done;
415	}
416
417	/* verify that the IP TTL is 255.  */
418	if (ip->ip_ttl != PFSYNC_DFLTTL) {
419		pfsyncstats.pfsyncs_badttl++;
420		goto done;
421	}
422
423	iplen = ip->ip_hl << 2;
424
425	if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
426		pfsyncstats.pfsyncs_hdrops++;
427		goto done;
428	}
429
430	if (iplen + sizeof(*ph) > m->m_len) {
431		if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
432			pfsyncstats.pfsyncs_hdrops++;
433			goto done;
434		}
435		ip = mtod(m, struct ip *);
436	}
437	ph = (struct pfsync_header *)((char *)ip + iplen);
438
439	/* verify the version */
440	if (ph->version != PFSYNC_VERSION) {
441		pfsyncstats.pfsyncs_badver++;
442		goto done;
443	}
444
445	action = ph->action;
446	count = ph->count;
447
448	/* make sure it's a valid action code */
449	if (action >= PFSYNC_ACT_MAX) {
450		pfsyncstats.pfsyncs_badact++;
451		goto done;
452	}
453
454	/* Cheaper to grab this now than having to mess with mbufs later */
455	src = ip->ip_src;
456
457	switch (action) {
458	case PFSYNC_ACT_CLR: {
459		struct pf_state *nexts;
460		struct pfi_kif	*kif;
461		u_int32_t creatorid;
462		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
463		    sizeof(*cp), &offp)) == NULL) {
464			pfsyncstats.pfsyncs_badlen++;
465			return;
466		}
467		cp = (struct pfsync_state_clr *)(mp->m_data + offp);
468		creatorid = cp->creatorid;
469
470		s = splsoftnet();
471#ifdef __FreeBSD__
472		PF_LOCK();
473#endif
474		if (cp->ifname[0] == '\0') {
475			for (st = RB_MIN(pf_state_tree_id, &tree_id);
476			    st; st = nexts) {
477                		nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
478				if (st->creatorid == creatorid) {
479					st->timeout = PFTM_PURGE;
480					pf_purge_expired_state(st);
481				}
482			}
483		} else {
484			kif = pfi_lookup_if(cp->ifname);
485			if (kif == NULL) {
486				if (pf_status.debug >= PF_DEBUG_MISC)
487					printf("pfsync_input: PFSYNC_ACT_CLR "
488					    "bad interface: %s\n", cp->ifname);
489				splx(s);
490#ifdef __FreeBSD__
491				PF_UNLOCK();
492#endif
493				goto done;
494			}
495			for (st = RB_MIN(pf_state_tree_lan_ext,
496			    &kif->pfik_lan_ext); st; st = nexts) {
497				nexts = RB_NEXT(pf_state_tree_lan_ext,
498				    &kif->pfik_lan_ext, st);
499				if (st->creatorid == creatorid) {
500					st->timeout = PFTM_PURGE;
501					pf_purge_expired_state(st);
502				}
503			}
504		}
505#ifdef __FreeBSD__
506		PF_UNLOCK();
507#endif
508		splx(s);
509
510		break;
511	}
512	case PFSYNC_ACT_INS:
513		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
514		    count * sizeof(*sp), &offp)) == NULL) {
515			pfsyncstats.pfsyncs_badlen++;
516			return;
517		}
518
519		s = splsoftnet();
520#ifdef __FreeBSD__
521		PF_LOCK();
522#endif
523		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
524		    i < count; i++, sp++) {
525			/* check for invalid values */
526			if (sp->timeout >= PFTM_MAX ||
527			    sp->src.state > PF_TCPS_PROXY_DST ||
528			    sp->dst.state > PF_TCPS_PROXY_DST ||
529			    sp->direction > PF_OUT ||
530			    (sp->af != AF_INET && sp->af != AF_INET6)) {
531				if (pf_status.debug >= PF_DEBUG_MISC)
532					printf("pfsync_insert: PFSYNC_ACT_INS: "
533					    "invalid value\n");
534				pfsyncstats.pfsyncs_badstate++;
535				continue;
536			}
537
538			if ((error = pfsync_insert_net_state(sp))) {
539				if (error == ENOMEM) {
540					splx(s);
541#ifdef __FreeBSD__
542					PF_UNLOCK();
543#endif
544					goto done;
545				}
546				continue;
547			}
548		}
549#ifdef __FreeBSD__
550		PF_UNLOCK();
551#endif
552		splx(s);
553		break;
554	case PFSYNC_ACT_UPD:
555		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
556		    count * sizeof(*sp), &offp)) == NULL) {
557			pfsyncstats.pfsyncs_badlen++;
558			return;
559		}
560
561		s = splsoftnet();
562#ifdef __FreeBSD__
563		PF_LOCK();
564#endif
565		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
566		    i < count; i++, sp++) {
567			int flags = PFSYNC_FLAG_STALE;
568
569			/* check for invalid values */
570			if (sp->timeout >= PFTM_MAX ||
571			    sp->src.state > PF_TCPS_PROXY_DST ||
572			    sp->dst.state > PF_TCPS_PROXY_DST) {
573				if (pf_status.debug >= PF_DEBUG_MISC)
574					printf("pfsync_insert: PFSYNC_ACT_UPD: "
575					    "invalid value\n");
576				pfsyncstats.pfsyncs_badstate++;
577				continue;
578			}
579
580			bcopy(sp->id, &key.id, sizeof(key.id));
581			key.creatorid = sp->creatorid;
582
583			st = pf_find_state_byid(&key);
584			if (st == NULL) {
585				/* insert the update */
586				if (pfsync_insert_net_state(sp))
587					pfsyncstats.pfsyncs_badstate++;
588				continue;
589			}
590			sfail = 0;
591			if (st->proto == IPPROTO_TCP) {
592				/*
593				 * The state should never go backwards except
594				 * for syn-proxy states.  Neither should the
595				 * sequence window slide backwards.
596				 */
597				if (st->src.state > sp->src.state &&
598				    (st->src.state < PF_TCPS_PROXY_SRC ||
599				    sp->src.state >= PF_TCPS_PROXY_SRC))
600					sfail = 1;
601				else if (SEQ_GT(st->src.seqlo,
602				    ntohl(sp->src.seqlo)))
603					sfail = 3;
604				else if (st->dst.state > sp->dst.state) {
605					/* There might still be useful
606					 * information about the src state here,
607					 * so import that part of the update,
608					 * then "fail" so we send the updated
609					 * state back to the peer who is missing
610					 * our what we know. */
611					pf_state_peer_ntoh(&sp->src, &st->src);
612					/* XXX do anything with timeouts? */
613					sfail = 7;
614					flags = 0;
615				} else if (st->dst.state >= TCPS_SYN_SENT &&
616				    SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
617					sfail = 4;
618			} else {
619				/*
620				 * Non-TCP protocol state machine always go
621				 * forwards
622				 */
623				if (st->src.state > sp->src.state)
624					sfail = 5;
625				else if ( st->dst.state > sp->dst.state)
626					sfail = 6;
627			}
628			if (sfail) {
629				if (pf_status.debug >= PF_DEBUG_MISC)
630					printf("pfsync: %s stale update "
631					    "(%d) id: %016llx "
632					    "creatorid: %08x\n",
633					    (sfail < 7 ?  "ignoring"
634					     : "partial"), sfail,
635#ifdef __FreeBSD__
636					    (unsigned long long)be64toh(st->id),
637#else
638					    betoh64(st->id),
639#endif
640					    ntohl(st->creatorid));
641				pfsyncstats.pfsyncs_badstate++;
642
643				if (!(sp->sync_flags & PFSTATE_STALE)) {
644					/* we have a better state, send it */
645					if (sc->sc_mbuf != NULL && !stale)
646						pfsync_sendout(sc);
647					stale++;
648					if (!st->sync_flags)
649						pfsync_pack_state(
650						    PFSYNC_ACT_UPD, st, flags);
651				}
652				continue;
653			}
654			pf_state_peer_ntoh(&sp->src, &st->src);
655			pf_state_peer_ntoh(&sp->dst, &st->dst);
656			st->expire = ntohl(sp->expire) + time_second;
657			st->timeout = sp->timeout;
658		}
659		if (stale && sc->sc_mbuf != NULL)
660			pfsync_sendout(sc);
661#ifdef __FreeBSD__
662		PF_UNLOCK();
663#endif
664		splx(s);
665		break;
666	/*
667	 * It's not strictly necessary for us to support the "uncompressed"
668	 * delete action, but it's relatively simple and maintains consistency.
669	 */
670	case PFSYNC_ACT_DEL:
671		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
672		    count * sizeof(*sp), &offp)) == NULL) {
673			pfsyncstats.pfsyncs_badlen++;
674			return;
675		}
676
677		s = splsoftnet();
678#ifdef __FreeBSD__
679		PF_LOCK();
680#endif
681		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
682		    i < count; i++, sp++) {
683			bcopy(sp->id, &key.id, sizeof(key.id));
684			key.creatorid = sp->creatorid;
685
686			st = pf_find_state_byid(&key);
687			if (st == NULL) {
688				pfsyncstats.pfsyncs_badstate++;
689				continue;
690			}
691			st->timeout = PFTM_PURGE;
692			st->sync_flags |= PFSTATE_FROMSYNC;
693			pf_purge_expired_state(st);
694		}
695#ifdef __FreeBSD__
696		PF_UNLOCK();
697#endif
698		splx(s);
699		break;
700	case PFSYNC_ACT_UPD_C: {
701		int update_requested = 0;
702
703		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
704		    count * sizeof(*up), &offp)) == NULL) {
705			pfsyncstats.pfsyncs_badlen++;
706			return;
707		}
708
709		s = splsoftnet();
710#ifdef __FreeBSD__
711		PF_LOCK();
712#endif
713		for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
714		    i < count; i++, up++) {
715			/* check for invalid values */
716			if (up->timeout >= PFTM_MAX ||
717			    up->src.state > PF_TCPS_PROXY_DST ||
718			    up->dst.state > PF_TCPS_PROXY_DST) {
719				if (pf_status.debug >= PF_DEBUG_MISC)
720					printf("pfsync_insert: "
721					    "PFSYNC_ACT_UPD_C: "
722					    "invalid value\n");
723				pfsyncstats.pfsyncs_badstate++;
724				continue;
725			}
726
727			bcopy(up->id, &key.id, sizeof(key.id));
728			key.creatorid = up->creatorid;
729
730			st = pf_find_state_byid(&key);
731			if (st == NULL) {
732				/* We don't have this state. Ask for it. */
733				error = pfsync_request_update(up, &src);
734				if (error == ENOMEM) {
735					splx(s);
736					goto done;
737				}
738				update_requested = 1;
739				pfsyncstats.pfsyncs_badstate++;
740				continue;
741			}
742			sfail = 0;
743			if (st->proto == IPPROTO_TCP) {
744				/*
745				 * The state should never go backwards except
746				 * for syn-proxy states.  Neither should the
747				 * sequence window slide backwards.
748				 */
749				if (st->src.state > up->src.state &&
750				    (st->src.state < PF_TCPS_PROXY_SRC ||
751				    up->src.state >= PF_TCPS_PROXY_SRC))
752					sfail = 1;
753				else if (st->dst.state > up->dst.state)
754					sfail = 2;
755				else if (SEQ_GT(st->src.seqlo,
756				    ntohl(up->src.seqlo)))
757					sfail = 3;
758				else if (st->dst.state >= TCPS_SYN_SENT &&
759				    SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
760					sfail = 4;
761			} else {
762				/*
763				 * Non-TCP protocol state machine always go
764				 * forwards
765				 */
766				if (st->src.state > up->src.state)
767					sfail = 5;
768				else if (st->dst.state > up->dst.state)
769					sfail = 6;
770			}
771			if (sfail) {
772				if (pf_status.debug >= PF_DEBUG_MISC)
773					printf("pfsync: ignoring stale update "
774					    "(%d) id: %016llx "
775					    "creatorid: %08x\n", sfail,
776#ifdef __FreeBSD__
777					    (unsigned long long)be64toh(st->id),
778#else
779					    betoh64(st->id),
780#endif
781					    ntohl(st->creatorid));
782				pfsyncstats.pfsyncs_badstate++;
783
784				/* we have a better state, send it out */
785				if ((!stale || update_requested) &&
786				    sc->sc_mbuf != NULL) {
787					pfsync_sendout(sc);
788					update_requested = 0;
789				}
790				stale++;
791				if (!st->sync_flags)
792					pfsync_pack_state(PFSYNC_ACT_UPD, st,
793					    PFSYNC_FLAG_STALE);
794				continue;
795			}
796			pf_state_peer_ntoh(&up->src, &st->src);
797			pf_state_peer_ntoh(&up->dst, &st->dst);
798			st->expire = ntohl(up->expire) + time_second;
799			st->timeout = up->timeout;
800		}
801		if ((update_requested || stale) && sc->sc_mbuf)
802			pfsync_sendout(sc);
803#ifdef __FreeBSD__
804		PF_UNLOCK();
805#endif
806		splx(s);
807		break;
808	}
809	case PFSYNC_ACT_DEL_C:
810		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
811		    count * sizeof(*dp), &offp)) == NULL) {
812			pfsyncstats.pfsyncs_badlen++;
813			return;
814		}
815
816		s = splsoftnet();
817#ifdef __FreeBSD__
818		PF_LOCK();
819#endif
820		for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
821		    i < count; i++, dp++) {
822			bcopy(dp->id, &key.id, sizeof(key.id));
823			key.creatorid = dp->creatorid;
824
825			st = pf_find_state_byid(&key);
826			if (st == NULL) {
827				pfsyncstats.pfsyncs_badstate++;
828				continue;
829			}
830			st->timeout = PFTM_PURGE;
831			st->sync_flags |= PFSTATE_FROMSYNC;
832			pf_purge_expired_state(st);
833		}
834#ifdef __FreeBSD__
835		PF_UNLOCK();
836#endif
837		splx(s);
838		break;
839	case PFSYNC_ACT_INS_F:
840	case PFSYNC_ACT_DEL_F:
841		/* not implemented */
842		break;
843	case PFSYNC_ACT_UREQ:
844		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
845		    count * sizeof(*rup), &offp)) == NULL) {
846			pfsyncstats.pfsyncs_badlen++;
847			return;
848		}
849
850		s = splsoftnet();
851#ifdef __FreeBSD__
852		PF_LOCK();
853#endif
854		if (sc->sc_mbuf != NULL)
855			pfsync_sendout(sc);
856		for (i = 0,
857		    rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
858		    i < count; i++, rup++) {
859			bcopy(rup->id, &key.id, sizeof(key.id));
860			key.creatorid = rup->creatorid;
861
862			if (key.id == 0 && key.creatorid == 0) {
863				sc->sc_ureq_received = time_uptime;
864				if (pf_status.debug >= PF_DEBUG_MISC)
865					printf("pfsync: received "
866					    "bulk update request\n");
867				pfsync_send_bus(sc, PFSYNC_BUS_START);
868#ifdef __FreeBSD__
869				callout_reset(&sc->sc_bulk_tmo, 1 * hz,
870				    pfsync_bulk_update,
871				    LIST_FIRST(&pfsync_list));
872#else
873				timeout_add(&sc->sc_bulk_tmo, 1 * hz);
874#endif
875			} else {
876				st = pf_find_state_byid(&key);
877				if (st == NULL) {
878					pfsyncstats.pfsyncs_badstate++;
879					continue;
880				}
881				if (!st->sync_flags)
882					pfsync_pack_state(PFSYNC_ACT_UPD,
883					    st, 0);
884			}
885		}
886		if (sc->sc_mbuf != NULL)
887			pfsync_sendout(sc);
888#ifdef __FreeBSD__
889		PF_UNLOCK();
890#endif
891		splx(s);
892		break;
893	case PFSYNC_ACT_BUS:
894		/* If we're not waiting for a bulk update, who cares. */
895		if (sc->sc_ureq_sent == 0)
896			break;
897
898		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
899		    sizeof(*bus), &offp)) == NULL) {
900			pfsyncstats.pfsyncs_badlen++;
901			return;
902		}
903		bus = (struct pfsync_state_bus *)(mp->m_data + offp);
904		switch (bus->status) {
905		case PFSYNC_BUS_START:
906#ifdef __FreeBSD__
907			callout_reset(&sc->sc_bulkfail_tmo,
908			    pf_pool_limits[PF_LIMIT_STATES].limit /
909			    (PFSYNC_BULKPACKETS * sc->sc_maxcount),
910			    pfsync_bulkfail, LIST_FIRST(&pfsync_list));
911#else
912			timeout_add(&sc->sc_bulkfail_tmo,
913			    pf_pool_limits[PF_LIMIT_STATES].limit /
914			    (PFSYNC_BULKPACKETS * sc->sc_maxcount));
915#endif
916			if (pf_status.debug >= PF_DEBUG_MISC)
917				printf("pfsync: received bulk "
918				    "update start\n");
919			break;
920		case PFSYNC_BUS_END:
921			if (time_uptime - ntohl(bus->endtime) >=
922			    sc->sc_ureq_sent) {
923				/* that's it, we're happy */
924				sc->sc_ureq_sent = 0;
925				sc->sc_bulk_tries = 0;
926#ifdef __FreeBSD__
927				callout_stop(&sc->sc_bulkfail_tmo);
928#else
929				timeout_del(&sc->sc_bulkfail_tmo);
930#endif
931#if NCARP > 0	/* XXX_IMPORT */
932				if (!pfsync_sync_ok)
933					carp_suppress_preempt--;
934#endif
935				pfsync_sync_ok = 1;
936				if (pf_status.debug >= PF_DEBUG_MISC)
937					printf("pfsync: received valid "
938					    "bulk update end\n");
939			} else {
940				if (pf_status.debug >= PF_DEBUG_MISC)
941					printf("pfsync: received invalid "
942					    "bulk update end: bad timestamp\n");
943			}
944			break;
945		}
946		break;
947	}
948
949done:
950	if (m)
951		m_freem(m);
952}
953
954int
955pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
956	struct rtentry *rt)
957{
958	m_freem(m);
959	return (0);
960}
961
962/* ARGSUSED */
963int
964pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
965{
966#ifndef __FreeBSD__
967	struct proc *p = curproc;
968#endif
969	struct pfsync_softc *sc = ifp->if_softc;
970	struct ifreq *ifr = (struct ifreq *)data;
971	struct ip_moptions *imo = &sc->sc_imo;
972	struct pfsyncreq pfsyncr;
973	struct ifnet    *sifp;
974	int s, error;
975
976	switch (cmd) {
977	case SIOCSIFADDR:
978	case SIOCAIFADDR:
979	case SIOCSIFDSTADDR:
980	case SIOCSIFFLAGS:
981		if (ifp->if_flags & IFF_UP)
982			ifp->if_flags |= IFF_RUNNING;
983		else
984			ifp->if_flags &= ~IFF_RUNNING;
985		break;
986	case SIOCSIFMTU:
987		if (ifr->ifr_mtu < PFSYNC_MINMTU)
988			return (EINVAL);
989		if (ifr->ifr_mtu > MCLBYTES)
990			ifr->ifr_mtu = MCLBYTES;
991		s = splnet();
992#ifdef __FreeBSD__
993		PF_LOCK();
994#endif
995		if (ifr->ifr_mtu < ifp->if_mtu) {
996			pfsync_sendout(sc);
997		}
998		pfsync_setmtu(sc, ifr->ifr_mtu);
999#ifdef __FreeBSD__
1000		PF_UNLOCK();
1001#endif
1002		splx(s);
1003		break;
1004	case SIOCGETPFSYNC:
1005#ifdef __FreeBSD__
1006		/* XXX: read unlocked */
1007#endif
1008		bzero(&pfsyncr, sizeof(pfsyncr));
1009		if (sc->sc_sync_ifp)
1010			strlcpy(pfsyncr.pfsyncr_syncdev,
1011			    sc->sc_sync_ifp->if_xname, IFNAMSIZ);
1012		pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
1013		pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
1014		if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
1015			return (error);
1016		break;
1017	case SIOCSETPFSYNC:
1018#ifdef __FreeBSD__
1019		if ((error = suser(curthread)) != 0)
1020#else
1021		if ((error = suser(p, p->p_acflag)) != 0)
1022#endif
1023			return (error);
1024		if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
1025			return (error);
1026
1027		if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
1028			sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
1029		else
1030			sc->sc_sync_peer.s_addr =
1031			    pfsyncr.pfsyncr_syncpeer.s_addr;
1032
1033		if (pfsyncr.pfsyncr_maxupdates > 255)
1034			return (EINVAL);
1035#ifdef __FreeBSD__
1036		PF_LOCK();
1037#endif
1038		sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
1039
1040		if (pfsyncr.pfsyncr_syncdev[0] == 0) {
1041			sc->sc_sync_ifp = NULL;
1042			if (sc->sc_mbuf_net != NULL) {
1043				/* Don't keep stale pfsync packets around. */
1044				s = splnet();
1045				m_freem(sc->sc_mbuf_net);
1046				sc->sc_mbuf_net = NULL;
1047				sc->sc_statep_net.s = NULL;
1048				splx(s);
1049			}
1050			if (imo->imo_num_memberships > 0) {
1051				in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
1052				imo->imo_multicast_ifp = NULL;
1053			}
1054#ifdef __FreeBSD__
1055			PF_UNLOCK();
1056#endif
1057			break;
1058		}
1059
1060		if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) {
1061#ifdef __FreeBSD__
1062			PF_UNLOCK();
1063#endif
1064			return (EINVAL);
1065		}
1066
1067		s = splnet();
1068#ifdef __FreeBSD__
1069		if (sifp->if_mtu < SCP2IFP(sc)->if_mtu ||
1070#else
1071		if (sifp->if_mtu < sc->sc_if.if_mtu ||
1072#endif
1073		    (sc->sc_sync_ifp != NULL &&
1074		    sifp->if_mtu < sc->sc_sync_ifp->if_mtu) ||
1075		    sifp->if_mtu < MCLBYTES - sizeof(struct ip))
1076			pfsync_sendout(sc);
1077		sc->sc_sync_ifp = sifp;
1078
1079#ifdef __FreeBSD__
1080		pfsync_setmtu(sc, SCP2IFP(sc)->if_mtu);
1081#else
1082		pfsync_setmtu(sc, sc->sc_if.if_mtu);
1083#endif
1084
1085		if (imo->imo_num_memberships > 0) {
1086			in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
1087			imo->imo_multicast_ifp = NULL;
1088		}
1089
1090		if (sc->sc_sync_ifp &&
1091		    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1092			struct in_addr addr;
1093
1094			if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
1095				sc->sc_sync_ifp = NULL;
1096#ifdef __FreeBSD__
1097				PF_UNLOCK();
1098#endif
1099				splx(s);
1100				return (EADDRNOTAVAIL);
1101			}
1102#ifdef __FreeBSD__
1103			PF_UNLOCK();		/* addmulti mallocs w/ WAITOK */
1104			addr.s_addr = htonl(INADDR_PFSYNC_GROUP);
1105#else
1106			addr.s_addr = INADDR_PFSYNC_GROUP;
1107#endif
1108
1109			if ((imo->imo_membership[0] =
1110			    in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
1111				sc->sc_sync_ifp = NULL;
1112				splx(s);
1113				return (ENOBUFS);
1114			}
1115			imo->imo_num_memberships++;
1116			imo->imo_multicast_ifp = sc->sc_sync_ifp;
1117			imo->imo_multicast_ttl = PFSYNC_DFLTTL;
1118			imo->imo_multicast_loop = 0;
1119		}
1120
1121		if (sc->sc_sync_ifp ||
1122		    sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
1123			/* Request a full state table update. */
1124#ifdef __FreeBSD__
1125			PF_LOCK();
1126#endif
1127			sc->sc_ureq_sent = time_uptime;
1128#if NCARP > 0
1129			if (pfsync_sync_ok)
1130				carp_suppress_preempt++;
1131#endif
1132			pfsync_sync_ok = 0;
1133			if (pf_status.debug >= PF_DEBUG_MISC)
1134				printf("pfsync: requesting bulk update\n");
1135#ifdef __FreeBSD__
1136			callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
1137			    pfsync_bulkfail, LIST_FIRST(&pfsync_list));
1138#else
1139			timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
1140#endif
1141			error = pfsync_request_update(NULL, NULL);
1142			if (error == ENOMEM) {
1143#ifdef __FreeBSD__
1144				PF_UNLOCK();
1145#endif
1146				splx(s);
1147				return (ENOMEM);
1148			}
1149			pfsync_sendout(sc);
1150		}
1151#ifdef __FreeBSD__
1152		PF_UNLOCK();
1153#endif
1154		splx(s);
1155
1156		break;
1157
1158	default:
1159		return (ENOTTY);
1160	}
1161
1162	return (0);
1163}
1164
1165void
1166pfsync_setmtu(struct pfsync_softc *sc, int mtu_req)
1167{
1168	int mtu;
1169
1170	if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req)
1171		mtu = sc->sc_sync_ifp->if_mtu;
1172	else
1173		mtu = mtu_req;
1174
1175	sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) /
1176	    sizeof(struct pfsync_state);
1177	if (sc->sc_maxcount > 254)
1178	    sc->sc_maxcount = 254;
1179#ifdef __FreeBSD__
1180	SCP2IFP(sc)->if_mtu = sizeof(struct pfsync_header) +
1181	    sc->sc_maxcount * sizeof(struct pfsync_state);
1182#else
1183	sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
1184	    sc->sc_maxcount * sizeof(struct pfsync_state);
1185#endif
1186}
1187
1188struct mbuf *
1189pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
1190{
1191	struct pfsync_header *h;
1192	struct mbuf *m;
1193	int len;
1194
1195#ifdef __FreeBSD__
1196	PF_ASSERT(MA_OWNED);
1197#endif
1198	MGETHDR(m, M_DONTWAIT, MT_DATA);
1199	if (m == NULL) {
1200#ifdef __FreeBSD__
1201		SCP2IFP(sc)->if_oerrors++;
1202#else
1203		sc->sc_if.if_oerrors++;
1204#endif
1205		return (NULL);
1206	}
1207
1208	switch (action) {
1209	case PFSYNC_ACT_CLR:
1210		len = sizeof(struct pfsync_header) +
1211		    sizeof(struct pfsync_state_clr);
1212		break;
1213	case PFSYNC_ACT_UPD_C:
1214		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) +
1215		    sizeof(struct pfsync_header);
1216		break;
1217	case PFSYNC_ACT_DEL_C:
1218		len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) +
1219		    sizeof(struct pfsync_header);
1220		break;
1221	case PFSYNC_ACT_UREQ:
1222		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) +
1223		    sizeof(struct pfsync_header);
1224		break;
1225	case PFSYNC_ACT_BUS:
1226		len = sizeof(struct pfsync_header) +
1227		    sizeof(struct pfsync_state_bus);
1228		break;
1229	default:
1230		len = (sc->sc_maxcount * sizeof(struct pfsync_state)) +
1231		    sizeof(struct pfsync_header);
1232		break;
1233	}
1234
1235	if (len > MHLEN) {
1236		MCLGET(m, M_DONTWAIT);
1237		if ((m->m_flags & M_EXT) == 0) {
1238			m_free(m);
1239#ifdef __FreeBSD__
1240			SCP2IFP(sc)->if_oerrors++;
1241#else
1242			sc->sc_if.if_oerrors++;
1243#endif
1244			return (NULL);
1245		}
1246		m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1);
1247	} else
1248		MH_ALIGN(m, len);
1249
1250	m->m_pkthdr.rcvif = NULL;
1251	m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header);
1252	h = mtod(m, struct pfsync_header *);
1253	h->version = PFSYNC_VERSION;
1254	h->af = 0;
1255	h->count = 0;
1256	h->action = action;
1257
1258	*sp = (void *)((char *)h + PFSYNC_HDRLEN);
1259#ifdef __FreeBSD__
1260	callout_reset(&sc->sc_tmo, hz, pfsync_timeout,
1261	    LIST_FIRST(&pfsync_list));
1262#else
1263	timeout_add(&sc->sc_tmo, hz);
1264#endif
1265	return (m);
1266}
1267
1268int
1269pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
1270{
1271#ifdef __FreeBSD__
1272	struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list));
1273#else
1274	struct ifnet *ifp = &pfsyncif.sc_if;
1275#endif
1276	struct pfsync_softc *sc = ifp->if_softc;
1277	struct pfsync_header *h, *h_net;
1278	struct pfsync_state *sp = NULL;
1279	struct pfsync_state_upd *up = NULL;
1280	struct pfsync_state_del *dp = NULL;
1281	struct pf_rule *r;
1282	u_long secs;
1283	int s, ret = 0;
1284	u_int8_t i = 255, newaction = 0;
1285
1286#ifdef __FreeBSD__
1287	PF_ASSERT(MA_OWNED);
1288#endif
1289	/*
1290	 * If a packet falls in the forest and there's nobody around to
1291	 * hear, does it make a sound?
1292	 */
1293	if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
1294	    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1295		/* Don't leave any stale pfsync packets hanging around. */
1296		if (sc->sc_mbuf != NULL) {
1297			m_freem(sc->sc_mbuf);
1298			sc->sc_mbuf = NULL;
1299			sc->sc_statep.s = NULL;
1300		}
1301		return (0);
1302	}
1303
1304	if (action >= PFSYNC_ACT_MAX)
1305		return (EINVAL);
1306
1307	s = splnet();
1308	if (sc->sc_mbuf == NULL) {
1309		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
1310		    (void *)&sc->sc_statep.s)) == NULL) {
1311			splx(s);
1312			return (ENOMEM);
1313		}
1314		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1315	} else {
1316		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1317		if (h->action != action) {
1318			pfsync_sendout(sc);
1319			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
1320			    (void *)&sc->sc_statep.s)) == NULL) {
1321				splx(s);
1322				return (ENOMEM);
1323			}
1324			h = mtod(sc->sc_mbuf, struct pfsync_header *);
1325		} else {
1326			/*
1327			 * If it's an update, look in the packet to see if
1328			 * we already have an update for the state.
1329			 */
1330			if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) {
1331				struct pfsync_state *usp =
1332				    (void *)((char *)h + PFSYNC_HDRLEN);
1333
1334				for (i = 0; i < h->count; i++) {
1335					if (!memcmp(usp->id, &st->id,
1336					    PFSYNC_ID_LEN) &&
1337					    usp->creatorid == st->creatorid) {
1338						sp = usp;
1339						sp->updates++;
1340						break;
1341					}
1342					usp++;
1343				}
1344			}
1345		}
1346	}
1347
1348	secs = time_second;
1349
1350	st->pfsync_time = time_uptime;
1351	TAILQ_REMOVE(&state_updates, st, u.s.entry_updates);
1352	TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates);
1353
1354	if (sp == NULL) {
1355		/* not a "duplicate" update */
1356		i = 255;
1357		sp = sc->sc_statep.s++;
1358		sc->sc_mbuf->m_pkthdr.len =
1359		    sc->sc_mbuf->m_len += sizeof(struct pfsync_state);
1360		h->count++;
1361		bzero(sp, sizeof(*sp));
1362
1363		bcopy(&st->id, sp->id, sizeof(sp->id));
1364		sp->creatorid = st->creatorid;
1365
1366		strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
1367		pf_state_host_hton(&st->lan, &sp->lan);
1368		pf_state_host_hton(&st->gwy, &sp->gwy);
1369		pf_state_host_hton(&st->ext, &sp->ext);
1370
1371		bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
1372
1373		sp->creation = htonl(secs - st->creation);
1374		sp->packets[0] = htonl(st->packets[0]);
1375		sp->packets[1] = htonl(st->packets[1]);
1376		sp->bytes[0] = htonl(st->bytes[0]);
1377		sp->bytes[1] = htonl(st->bytes[1]);
1378		if ((r = st->rule.ptr) == NULL)
1379			sp->rule = htonl(-1);
1380		else
1381			sp->rule = htonl(r->nr);
1382		if ((r = st->anchor.ptr) == NULL)
1383			sp->anchor = htonl(-1);
1384		else
1385			sp->anchor = htonl(r->nr);
1386		sp->af = st->af;
1387		sp->proto = st->proto;
1388		sp->direction = st->direction;
1389		sp->log = st->log;
1390		sp->allow_opts = st->allow_opts;
1391		sp->timeout = st->timeout;
1392
1393		if (flags & PFSYNC_FLAG_STALE)
1394			sp->sync_flags |= PFSTATE_STALE;
1395	}
1396
1397	pf_state_peer_hton(&st->src, &sp->src);
1398	pf_state_peer_hton(&st->dst, &sp->dst);
1399
1400	if (st->expire <= secs)
1401		sp->expire = htonl(0);
1402	else
1403		sp->expire = htonl(st->expire - secs);
1404
1405	/* do we need to build "compressed" actions for network transfer? */
1406	if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
1407		switch (action) {
1408		case PFSYNC_ACT_UPD:
1409			newaction = PFSYNC_ACT_UPD_C;
1410			break;
1411		case PFSYNC_ACT_DEL:
1412			newaction = PFSYNC_ACT_DEL_C;
1413			break;
1414		default:
1415			/* by default we just send the uncompressed states */
1416			break;
1417		}
1418	}
1419
1420	if (newaction) {
1421		if (sc->sc_mbuf_net == NULL) {
1422			if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction,
1423			    (void *)&sc->sc_statep_net.s)) == NULL) {
1424				splx(s);
1425				return (ENOMEM);
1426			}
1427		}
1428		h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *);
1429
1430		switch (newaction) {
1431		case PFSYNC_ACT_UPD_C:
1432			if (i != 255) {
1433				up = (void *)((char *)h_net +
1434				    PFSYNC_HDRLEN + (i * sizeof(*up)));
1435				up->updates++;
1436			} else {
1437				h_net->count++;
1438				sc->sc_mbuf_net->m_pkthdr.len =
1439				    sc->sc_mbuf_net->m_len += sizeof(*up);
1440				up = sc->sc_statep_net.u++;
1441
1442				bzero(up, sizeof(*up));
1443				bcopy(&st->id, up->id, sizeof(up->id));
1444				up->creatorid = st->creatorid;
1445			}
1446			up->timeout = st->timeout;
1447			up->expire = sp->expire;
1448			up->src = sp->src;
1449			up->dst = sp->dst;
1450			break;
1451		case PFSYNC_ACT_DEL_C:
1452			sc->sc_mbuf_net->m_pkthdr.len =
1453			    sc->sc_mbuf_net->m_len += sizeof(*dp);
1454			dp = sc->sc_statep_net.d++;
1455			h_net->count++;
1456
1457			bzero(dp, sizeof(*dp));
1458			bcopy(&st->id, dp->id, sizeof(dp->id));
1459			dp->creatorid = st->creatorid;
1460			break;
1461		}
1462	}
1463
1464	if (h->count == sc->sc_maxcount ||
1465	    (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates)))
1466		ret = pfsync_sendout(sc);
1467
1468	splx(s);
1469	return (ret);
1470}
1471
1472/* This must be called in splnet() */
1473int
1474pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
1475{
1476#ifdef __FreeBSD__
1477	struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list));
1478#else
1479	struct ifnet *ifp = &pfsyncif.sc_if;
1480#endif
1481	struct pfsync_header *h;
1482	struct pfsync_softc *sc = ifp->if_softc;
1483	struct pfsync_state_upd_req *rup;
1484	int ret = 0;
1485
1486#ifdef __FreeBSD__
1487	PF_ASSERT(MA_OWNED);
1488#endif
1489	if (sc->sc_mbuf == NULL) {
1490		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1491		    (void *)&sc->sc_statep.s)) == NULL)
1492			return (ENOMEM);
1493		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1494	} else {
1495		h = mtod(sc->sc_mbuf, struct pfsync_header *);
1496		if (h->action != PFSYNC_ACT_UREQ) {
1497			pfsync_sendout(sc);
1498			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1499			    (void *)&sc->sc_statep.s)) == NULL)
1500				return (ENOMEM);
1501			h = mtod(sc->sc_mbuf, struct pfsync_header *);
1502		}
1503	}
1504
1505	if (src != NULL)
1506		sc->sc_sendaddr = *src;
1507	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
1508	h->count++;
1509	rup = sc->sc_statep.r++;
1510	bzero(rup, sizeof(*rup));
1511	if (up != NULL) {
1512		bcopy(up->id, rup->id, sizeof(rup->id));
1513		rup->creatorid = up->creatorid;
1514	}
1515
1516	if (h->count == sc->sc_maxcount)
1517		ret = pfsync_sendout(sc);
1518
1519	return (ret);
1520}
1521
1522int
1523pfsync_clear_states(u_int32_t creatorid, char *ifname)
1524{
1525#ifdef __FreeBSD__
1526	struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list));
1527#else
1528	struct ifnet *ifp = &pfsyncif.sc_if;
1529#endif
1530	struct pfsync_softc *sc = ifp->if_softc;
1531	struct pfsync_state_clr *cp;
1532	int s, ret;
1533
1534	s = splnet();
1535#ifdef __FreeBSD__
1536	PF_ASSERT(MA_OWNED);
1537#endif
1538	if (sc->sc_mbuf != NULL)
1539		pfsync_sendout(sc);
1540	if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR,
1541	    (void *)&sc->sc_statep.c)) == NULL) {
1542		splx(s);
1543		return (ENOMEM);
1544	}
1545	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp);
1546	cp = sc->sc_statep.c;
1547	cp->creatorid = creatorid;
1548	if (ifname != NULL)
1549		strlcpy(cp->ifname, ifname, IFNAMSIZ);
1550
1551	ret = (pfsync_sendout(sc));
1552	splx(s);
1553	return (ret);
1554}
1555
1556void
1557pfsync_timeout(void *v)
1558{
1559	struct pfsync_softc *sc = v;
1560	int s;
1561
1562	s = splnet();
1563#ifdef __FreeBSD__
1564	PF_LOCK();
1565#endif
1566	pfsync_sendout(sc);
1567#ifdef __FreeBSD__
1568	PF_UNLOCK();
1569#endif
1570	splx(s);
1571}
1572
1573/* This must be called in splnet() */
1574void
1575pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
1576{
1577	struct pfsync_state_bus *bus;
1578
1579#ifdef __FreeBSD__
1580	PF_ASSERT(MA_OWNED);
1581#endif
1582	if (sc->sc_mbuf != NULL)
1583		pfsync_sendout(sc);
1584
1585	if (pfsync_sync_ok &&
1586	    (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
1587	    (void *)&sc->sc_statep.b)) != NULL) {
1588		sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
1589		bus = sc->sc_statep.b;
1590		bus->creatorid = pf_status.hostid;
1591		bus->status = status;
1592		bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
1593		pfsync_sendout(sc);
1594	}
1595}
1596
1597void
1598pfsync_bulk_update(void *v)
1599{
1600	struct pfsync_softc *sc = v;
1601	int s, i = 0;
1602	struct pf_state *state;
1603
1604#ifdef __FreeBSD__
1605	PF_LOCK();
1606#endif
1607	s = splnet();
1608	if (sc->sc_mbuf != NULL)
1609		pfsync_sendout(sc);
1610
1611	/*
1612	 * Grab at most PFSYNC_BULKPACKETS worth of states which have not
1613	 * been sent since the latest request was made.
1614	 */
1615	while ((state = TAILQ_FIRST(&state_updates)) != NULL &&
1616	    ++i < (sc->sc_maxcount * PFSYNC_BULKPACKETS)) {
1617		if (state->pfsync_time > sc->sc_ureq_received) {
1618			/* we're done */
1619			pfsync_send_bus(sc, PFSYNC_BUS_END);
1620			sc->sc_ureq_received = 0;
1621#ifdef __FreeBSD__
1622			callout_stop(&sc->sc_bulk_tmo);
1623#else
1624			timeout_del(&sc->sc_bulk_tmo);
1625#endif
1626			if (pf_status.debug >= PF_DEBUG_MISC)
1627				printf("pfsync: bulk update complete\n");
1628			break;
1629		} else {
1630			/* send an update and move to end of list */
1631			if (!state->sync_flags)
1632				pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
1633			state->pfsync_time = time_uptime;
1634			TAILQ_REMOVE(&state_updates, state, u.s.entry_updates);
1635			TAILQ_INSERT_TAIL(&state_updates, state,
1636			    u.s.entry_updates);
1637
1638			/* look again for more in a bit */
1639#ifdef __FreeBSD__
1640			callout_reset(&sc->sc_bulk_tmo, 1, pfsync_timeout,
1641			    LIST_FIRST(&pfsync_list));
1642#else
1643			timeout_add(&sc->sc_bulk_tmo, 1);
1644#endif
1645		}
1646	}
1647	if (sc->sc_mbuf != NULL)
1648		pfsync_sendout(sc);
1649	splx(s);
1650#ifdef __FreeBSD__
1651	PF_UNLOCK();
1652#endif
1653}
1654
1655void
1656pfsync_bulkfail(void *v)
1657{
1658	struct pfsync_softc *sc = v;
1659	int s, error;
1660
1661#ifdef __FreeBSD__
1662	PF_LOCK();
1663#endif
1664	if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
1665		/* Try again in a bit */
1666#ifdef __FreeBSD__
1667		callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail,
1668		    LIST_FIRST(&pfsync_list));
1669#else
1670		timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
1671#endif
1672		s = splnet();
1673		error = pfsync_request_update(NULL, NULL);
1674		if (error == ENOMEM) {
1675			if (pf_status.debug >= PF_DEBUG_MISC)
1676				printf("pfsync: cannot allocate mbufs for "
1677				    "bulk update\n");
1678		} else
1679			pfsync_sendout(sc);
1680		splx(s);
1681	} else {
1682		/* Pretend like the transfer was ok */
1683		sc->sc_ureq_sent = 0;
1684		sc->sc_bulk_tries = 0;
1685#if NCARP > 0
1686		if (!pfsync_sync_ok)
1687			carp_suppress_preempt--;
1688#endif
1689		pfsync_sync_ok = 1;
1690		if (pf_status.debug >= PF_DEBUG_MISC)
1691			printf("pfsync: failed to receive "
1692			    "bulk update status\n");
1693#ifdef __FreeBSD__
1694		callout_stop(&sc->sc_bulkfail_tmo);
1695#else
1696		timeout_del(&sc->sc_bulkfail_tmo);
1697#endif
1698	}
1699#ifdef __FreeBSD__
1700	PF_UNLOCK();
1701#endif
1702}
1703
1704/* This must be called in splnet() */
1705int
1706pfsync_sendout(sc)
1707	struct pfsync_softc *sc;
1708{
1709#if NBPFILTER > 0
1710# ifdef __FreeBSD__
1711	struct ifnet *ifp = SCP2IFP(sc);
1712# else
1713	struct ifnet *ifp = &sc->if_sc;
1714# endif
1715#endif
1716	struct mbuf *m;
1717
1718#ifdef __FreeBSD__
1719	PF_ASSERT(MA_OWNED);
1720	callout_stop(&sc->sc_tmo);
1721#else
1722	timeout_del(&sc->sc_tmo);
1723#endif
1724
1725	if (sc->sc_mbuf == NULL)
1726		return (0);
1727	m = sc->sc_mbuf;
1728	sc->sc_mbuf = NULL;
1729	sc->sc_statep.s = NULL;
1730
1731#ifdef __FreeBSD__
1732	KASSERT(m != NULL, ("pfsync_sendout: null mbuf"));
1733#endif
1734#if NBPFILTER > 0
1735	if (ifp->if_bpf)
1736		bpf_mtap(ifp->if_bpf, m);
1737#endif
1738
1739	if (sc->sc_mbuf_net) {
1740		m_freem(m);
1741		m = sc->sc_mbuf_net;
1742		sc->sc_mbuf_net = NULL;
1743		sc->sc_statep_net.s = NULL;
1744	}
1745
1746	if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
1747		struct ip *ip;
1748		struct sockaddr sa;
1749
1750		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
1751		if (m == NULL) {
1752			pfsyncstats.pfsyncs_onomem++;
1753			return (0);
1754		}
1755		ip = mtod(m, struct ip *);
1756		ip->ip_v = IPVERSION;
1757		ip->ip_hl = sizeof(*ip) >> 2;
1758		ip->ip_tos = IPTOS_LOWDELAY;
1759#ifdef __FreeBSD__
1760		ip->ip_len = m->m_pkthdr.len;
1761#else
1762		ip->ip_len = htons(m->m_pkthdr.len);
1763#endif
1764		ip->ip_id = htons(ip_randomid());
1765#ifdef __FreeBSD__
1766		ip->ip_off = IP_DF;
1767#else
1768		ip->ip_off = htons(IP_DF);
1769#endif
1770		ip->ip_ttl = PFSYNC_DFLTTL;
1771		ip->ip_p = IPPROTO_PFSYNC;
1772		ip->ip_sum = 0;
1773
1774		bzero(&sa, sizeof(sa));
1775		ip->ip_src.s_addr = INADDR_ANY;
1776
1777#ifdef __FreeBSD__
1778		if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP))
1779#else
1780		if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
1781#endif
1782			m->m_flags |= M_MCAST;
1783		ip->ip_dst = sc->sc_sendaddr;
1784#ifdef __FreeBSD__
1785		/* XXX_IMPORT */
1786		sc->sc_sendaddr.s_addr = htonl(sc->sc_sync_peer.s_addr);
1787#else
1788		sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
1789#endif
1790
1791		pfsyncstats.pfsyncs_opackets++;
1792
1793#ifdef __FreeBSD__
1794		PF_UNLOCK();
1795#endif
1796		if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
1797			pfsyncstats.pfsyncs_oerrors++;
1798
1799#ifdef __FreeBSD__
1800		PF_LOCK();
1801#endif
1802	} else
1803		m_freem(m);
1804
1805	return (0);
1806}
1807
1808
1809#ifdef __FreeBSD__
1810static int
1811pfsync_modevent(module_t mod, int type, void *data)
1812{
1813	int error = 0;
1814
1815	switch (type) {
1816	case MOD_LOAD:
1817		LIST_INIT(&pfsync_list);
1818		if_clone_attach(&pfsync_cloner);
1819		break;
1820
1821	case MOD_UNLOAD:
1822		if_clone_detach(&pfsync_cloner);
1823		while (!LIST_EMPTY(&pfsync_list))
1824			pfsync_clone_destroy(
1825			    SCP2IFP(LIST_FIRST(&pfsync_list)));
1826		break;
1827
1828	default:
1829		error = EINVAL;
1830		break;
1831	}
1832
1833	return error;
1834}
1835
1836static moduledata_t pfsync_mod = {
1837	"pfsync",
1838	pfsync_modevent,
1839	0
1840};
1841
1842#define PFSYNC_MODVER 1
1843
1844DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
1845MODULE_VERSION(pfsync, PFSYNC_MODVER);
1846#endif /* __FreeBSD__ */
1847