Annotation of sys/net/if_pfsync.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_pfsync.c,v 1.83 2007/06/26 14:44:12 mcbride Exp $ */
2:
3: /*
4: * Copyright (c) 2002 Michael Shalayeff
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26: * THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29:
30: #include <sys/param.h>
31: #include <sys/proc.h>
32: #include <sys/systm.h>
33: #include <sys/time.h>
34: #include <sys/mbuf.h>
35: #include <sys/socket.h>
36: #include <sys/ioctl.h>
37: #include <sys/timeout.h>
38: #include <sys/kernel.h>
39:
40: #include <net/if.h>
41: #include <net/if_types.h>
42: #include <net/route.h>
43: #include <net/bpf.h>
44: #include <netinet/in.h>
45: #include <netinet/if_ether.h>
46: #include <netinet/tcp.h>
47: #include <netinet/tcp_seq.h>
48:
49: #ifdef INET
50: #include <netinet/in_systm.h>
51: #include <netinet/in_var.h>
52: #include <netinet/ip.h>
53: #include <netinet/ip_var.h>
54: #endif
55:
56: #ifdef INET6
57: #include <netinet6/nd6.h>
58: #endif /* INET6 */
59:
60: #include "carp.h"
61: #if NCARP > 0
62: #include <netinet/ip_carp.h>
63: #endif
64:
65: #include <net/pfvar.h>
66: #include <net/if_pfsync.h>
67:
68: #include "bpfilter.h"
69: #include "pfsync.h"
70:
71: #define PFSYNC_MINMTU \
72: (sizeof(struct pfsync_header) + sizeof(struct pf_state))
73:
74: #ifdef PFSYNCDEBUG
75: #define DPRINTF(x) do { if (pfsyncdebug) printf x ; } while (0)
76: int pfsyncdebug;
77: #else
78: #define DPRINTF(x)
79: #endif
80:
81: struct pfsync_softc *pfsyncif = NULL;
82: struct pfsyncstats pfsyncstats;
83:
84: void pfsyncattach(int);
85: int pfsync_clone_create(struct if_clone *, int);
86: int pfsync_clone_destroy(struct ifnet *);
87: void pfsync_setmtu(struct pfsync_softc *, int);
88: int pfsync_alloc_scrub_memory(struct pfsync_state_peer *,
89: struct pf_state_peer *);
90: int pfsync_insert_net_state(struct pfsync_state *, u_int8_t);
91: void pfsync_update_net_tdb(struct pfsync_tdb *);
92: int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
93: struct rtentry *);
94: int pfsyncioctl(struct ifnet *, u_long, caddr_t);
95: void pfsyncstart(struct ifnet *);
96:
97: struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
98: int pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
99: int pfsync_sendout(struct pfsync_softc *);
100: int pfsync_tdb_sendout(struct pfsync_softc *);
101: int pfsync_sendout_mbuf(struct pfsync_softc *, struct mbuf *);
102: void pfsync_timeout(void *);
103: void pfsync_tdb_timeout(void *);
104: void pfsync_send_bus(struct pfsync_softc *, u_int8_t);
105: void pfsync_bulk_update(void *);
106: void pfsync_bulkfail(void *);
107:
108: int pfsync_sync_ok;
109:
110: struct if_clone pfsync_cloner =
111: IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create, pfsync_clone_destroy);
112:
113: void
114: pfsyncattach(int npfsync)
115: {
116: if_clone_attach(&pfsync_cloner);
117: }
118: int
119: pfsync_clone_create(struct if_clone *ifc, int unit)
120: {
121: struct ifnet *ifp;
122:
123: if (unit != 0)
124: return (EINVAL);
125:
126: pfsync_sync_ok = 1;
127: if ((pfsyncif = malloc(sizeof(*pfsyncif), M_DEVBUF, M_NOWAIT)) == NULL)
128: return (ENOMEM);
129: bzero(pfsyncif, sizeof(*pfsyncif));
130: pfsyncif->sc_mbuf = NULL;
131: pfsyncif->sc_mbuf_net = NULL;
132: pfsyncif->sc_mbuf_tdb = NULL;
133: pfsyncif->sc_statep.s = NULL;
134: pfsyncif->sc_statep_net.s = NULL;
135: pfsyncif->sc_statep_tdb.t = NULL;
136: pfsyncif->sc_maxupdates = 128;
137: pfsyncif->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
138: pfsyncif->sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
139: pfsyncif->sc_ureq_received = 0;
140: pfsyncif->sc_ureq_sent = 0;
141: pfsyncif->sc_bulk_send_next = NULL;
142: pfsyncif->sc_bulk_terminator = NULL;
143: ifp = &pfsyncif->sc_if;
144: snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit);
145: ifp->if_softc = pfsyncif;
146: ifp->if_ioctl = pfsyncioctl;
147: ifp->if_output = pfsyncoutput;
148: ifp->if_start = pfsyncstart;
149: ifp->if_type = IFT_PFSYNC;
150: ifp->if_snd.ifq_maxlen = ifqmaxlen;
151: ifp->if_hdrlen = PFSYNC_HDRLEN;
152: pfsync_setmtu(pfsyncif, ETHERMTU);
153: timeout_set(&pfsyncif->sc_tmo, pfsync_timeout, pfsyncif);
154: timeout_set(&pfsyncif->sc_tdb_tmo, pfsync_tdb_timeout, pfsyncif);
155: timeout_set(&pfsyncif->sc_bulk_tmo, pfsync_bulk_update, pfsyncif);
156: timeout_set(&pfsyncif->sc_bulkfail_tmo, pfsync_bulkfail, pfsyncif);
157: if_attach(ifp);
158: if_alloc_sadl(ifp);
159:
160: #if NCARP > 0
161: if_addgroup(ifp, "carp");
162: #endif
163:
164: #if NBPFILTER > 0
165: bpfattach(&pfsyncif->sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
166: #endif
167:
168: return (0);
169: }
170:
171: int
172: pfsync_clone_destroy(struct ifnet *ifp)
173: {
174: #if NBPFILTER > 0
175: bpfdetach(ifp);
176: #endif
177: if_detach(ifp);
178: free(pfsyncif, M_DEVBUF);
179: pfsyncif = NULL;
180: return (0);
181: }
182:
183: /*
184: * Start output on the pfsync interface.
185: */
186: void
187: pfsyncstart(struct ifnet *ifp)
188: {
189: struct mbuf *m;
190: int s;
191:
192: for (;;) {
193: s = splnet();
194: IF_DROP(&ifp->if_snd);
195: IF_DEQUEUE(&ifp->if_snd, m);
196: splx(s);
197:
198: if (m == NULL)
199: return;
200: else
201: m_freem(m);
202: }
203: }
204:
205: int
206: pfsync_alloc_scrub_memory(struct pfsync_state_peer *s,
207: struct pf_state_peer *d)
208: {
209: if (s->scrub.scrub_flag && d->scrub == NULL) {
210: d->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
211: if (d->scrub == NULL)
212: return (ENOMEM);
213: bzero(d->scrub, sizeof(*d->scrub));
214: }
215:
216: return (0);
217: }
218:
219: int
220: pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
221: {
222: struct pf_state *st = NULL;
223: struct pf_state_key *sk = NULL;
224: struct pf_rule *r = NULL;
225: struct pfi_kif *kif;
226:
227: if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
228: printf("pfsync_insert_net_state: invalid creator id:"
229: " %08x\n", ntohl(sp->creatorid));
230: return (EINVAL);
231: }
232:
233: kif = pfi_kif_get(sp->ifname);
234: if (kif == NULL) {
235: if (pf_status.debug >= PF_DEBUG_MISC)
236: printf("pfsync_insert_net_state: "
237: "unknown interface: %s\n", sp->ifname);
238: /* skip this state */
239: return (0);
240: }
241:
242: /*
243: * If the ruleset checksums match, it's safe to associate the state
244: * with the rule of that number.
245: */
246: if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && chksum_flag &&
247: ntohl(sp->rule) <
248: pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount)
249: r = pf_main_ruleset.rules[
250: PF_RULESET_FILTER].active.ptr_array[ntohl(sp->rule)];
251: else
252: r = &pf_default_rule;
253:
254: if (!r->max_states || r->states < r->max_states)
255: st = pool_get(&pf_state_pl, PR_NOWAIT);
256: if (st == NULL) {
257: pfi_kif_unref(kif, PFI_KIF_REF_NONE);
258: return (ENOMEM);
259: }
260: bzero(st, sizeof(*st));
261:
262: if ((sk = pf_alloc_state_key(st)) == NULL) {
263: pool_put(&pf_state_pl, st);
264: pfi_kif_unref(kif, PFI_KIF_REF_NONE);
265: return (ENOMEM);
266: }
267:
268: /* allocate memory for scrub info */
269: if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
270: pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) {
271: pfi_kif_unref(kif, PFI_KIF_REF_NONE);
272: if (st->src.scrub)
273: pool_put(&pf_state_scrub_pl, st->src.scrub);
274: pool_put(&pf_state_pl, st);
275: pool_put(&pf_state_key_pl, sk);
276: return (ENOMEM);
277: }
278:
279: st->rule.ptr = r;
280: /* XXX get pointers to nat_rule and anchor */
281:
282: /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
283: r->states++;
284:
285: /* fill in the rest of the state entry */
286: pf_state_host_ntoh(&sp->lan, &sk->lan);
287: pf_state_host_ntoh(&sp->gwy, &sk->gwy);
288: pf_state_host_ntoh(&sp->ext, &sk->ext);
289:
290: pf_state_peer_ntoh(&sp->src, &st->src);
291: pf_state_peer_ntoh(&sp->dst, &st->dst);
292:
293: bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
294: st->creation = time_second - ntohl(sp->creation);
295: st->expire = ntohl(sp->expire) + time_second;
296:
297: sk->af = sp->af;
298: sk->proto = sp->proto;
299: sk->direction = sp->direction;
300: st->log = sp->log;
301: st->timeout = sp->timeout;
302: st->allow_opts = sp->allow_opts;
303:
304: bcopy(sp->id, &st->id, sizeof(st->id));
305: st->creatorid = sp->creatorid;
306: st->sync_flags = PFSTATE_FROMSYNC;
307:
308: if (pf_insert_state(kif, st)) {
309: pfi_kif_unref(kif, PFI_KIF_REF_NONE);
310: /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
311: r->states--;
312: if (st->dst.scrub)
313: pool_put(&pf_state_scrub_pl, st->dst.scrub);
314: if (st->src.scrub)
315: pool_put(&pf_state_scrub_pl, st->src.scrub);
316: pool_put(&pf_state_pl, st);
317: return (EINVAL);
318: }
319:
320: return (0);
321: }
322:
323: void
324: pfsync_input(struct mbuf *m, ...)
325: {
326: struct ip *ip = mtod(m, struct ip *);
327: struct pfsync_header *ph;
328: struct pfsync_softc *sc = pfsyncif;
329: struct pf_state *st;
330: struct pf_state_key *sk;
331: struct pf_state_cmp id_key;
332: struct pfsync_state *sp;
333: struct pfsync_state_upd *up;
334: struct pfsync_state_del *dp;
335: struct pfsync_state_clr *cp;
336: struct pfsync_state_upd_req *rup;
337: struct pfsync_state_bus *bus;
338: #ifdef IPSEC
339: struct pfsync_tdb *pt;
340: #endif
341: struct in_addr src;
342: struct mbuf *mp;
343: int iplen, action, error, i, s, count, offp, sfail, stale = 0;
344: u_int8_t chksum_flag = 0;
345:
346: pfsyncstats.pfsyncs_ipackets++;
347:
348: /* verify that we have a sync interface configured */
349: if (!sc || !sc->sc_sync_ifp || !pf_status.running)
350: goto done;
351:
352: /* verify that the packet came in on the right interface */
353: if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
354: pfsyncstats.pfsyncs_badif++;
355: goto done;
356: }
357:
358: /* verify that the IP TTL is 255. */
359: if (ip->ip_ttl != PFSYNC_DFLTTL) {
360: pfsyncstats.pfsyncs_badttl++;
361: goto done;
362: }
363:
364: iplen = ip->ip_hl << 2;
365:
366: if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
367: pfsyncstats.pfsyncs_hdrops++;
368: goto done;
369: }
370:
371: if (iplen + sizeof(*ph) > m->m_len) {
372: if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
373: pfsyncstats.pfsyncs_hdrops++;
374: goto done;
375: }
376: ip = mtod(m, struct ip *);
377: }
378: ph = (struct pfsync_header *)((char *)ip + iplen);
379:
380: /* verify the version */
381: if (ph->version != PFSYNC_VERSION) {
382: pfsyncstats.pfsyncs_badver++;
383: goto done;
384: }
385:
386: action = ph->action;
387: count = ph->count;
388:
389: /* make sure it's a valid action code */
390: if (action >= PFSYNC_ACT_MAX) {
391: pfsyncstats.pfsyncs_badact++;
392: goto done;
393: }
394:
395: /* Cheaper to grab this now than having to mess with mbufs later */
396: src = ip->ip_src;
397:
398: if (!bcmp(&ph->pf_chksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
399: chksum_flag++;
400:
401: switch (action) {
402: case PFSYNC_ACT_CLR: {
403: struct pf_state *nexts;
404: struct pf_state_key *nextsk;
405: struct pfi_kif *kif;
406: u_int32_t creatorid;
407: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
408: sizeof(*cp), &offp)) == NULL) {
409: pfsyncstats.pfsyncs_badlen++;
410: return;
411: }
412: cp = (struct pfsync_state_clr *)(mp->m_data + offp);
413: creatorid = cp->creatorid;
414:
415: s = splsoftnet();
416: if (cp->ifname[0] == '\0') {
417: for (st = RB_MIN(pf_state_tree_id, &tree_id);
418: st; st = nexts) {
419: nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
420: if (st->creatorid == creatorid) {
421: st->sync_flags |= PFSTATE_FROMSYNC;
422: pf_unlink_state(st);
423: }
424: }
425: } else {
426: if ((kif = pfi_kif_get(cp->ifname)) == NULL) {
427: splx(s);
428: return;
429: }
430: for (sk = RB_MIN(pf_state_tree_lan_ext,
431: &pf_statetbl_lan_ext); sk; sk = nextsk) {
432: nextsk = RB_NEXT(pf_state_tree_lan_ext,
433: &pf_statetbl_lan_ext, sk);
434: TAILQ_FOREACH(st, &sk->states, next) {
435: if (st->creatorid == creatorid) {
436: st->sync_flags |=
437: PFSTATE_FROMSYNC;
438: pf_unlink_state(st);
439: }
440: }
441: }
442: }
443: splx(s);
444:
445: break;
446: }
447: case PFSYNC_ACT_INS:
448: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
449: count * sizeof(*sp), &offp)) == NULL) {
450: pfsyncstats.pfsyncs_badlen++;
451: return;
452: }
453:
454: s = splsoftnet();
455: for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
456: i < count; i++, sp++) {
457: /* check for invalid values */
458: if (sp->timeout >= PFTM_MAX ||
459: sp->src.state > PF_TCPS_PROXY_DST ||
460: sp->dst.state > PF_TCPS_PROXY_DST ||
461: sp->direction > PF_OUT ||
462: (sp->af != AF_INET && sp->af != AF_INET6)) {
463: if (pf_status.debug >= PF_DEBUG_MISC)
464: printf("pfsync_insert: PFSYNC_ACT_INS: "
465: "invalid value\n");
466: pfsyncstats.pfsyncs_badstate++;
467: continue;
468: }
469:
470: if ((error = pfsync_insert_net_state(sp,
471: chksum_flag))) {
472: if (error == ENOMEM) {
473: splx(s);
474: goto done;
475: }
476: continue;
477: }
478: }
479: splx(s);
480: break;
481: case PFSYNC_ACT_UPD:
482: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
483: count * sizeof(*sp), &offp)) == NULL) {
484: pfsyncstats.pfsyncs_badlen++;
485: return;
486: }
487:
488: s = splsoftnet();
489: for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
490: i < count; i++, sp++) {
491: int flags = PFSYNC_FLAG_STALE;
492:
493: /* check for invalid values */
494: if (sp->timeout >= PFTM_MAX ||
495: sp->src.state > PF_TCPS_PROXY_DST ||
496: sp->dst.state > PF_TCPS_PROXY_DST) {
497: if (pf_status.debug >= PF_DEBUG_MISC)
498: printf("pfsync_insert: PFSYNC_ACT_UPD: "
499: "invalid value\n");
500: pfsyncstats.pfsyncs_badstate++;
501: continue;
502: }
503:
504: bcopy(sp->id, &id_key.id, sizeof(id_key.id));
505: id_key.creatorid = sp->creatorid;
506:
507: st = pf_find_state_byid(&id_key);
508: if (st == NULL) {
509: /* insert the update */
510: if (pfsync_insert_net_state(sp, chksum_flag))
511: pfsyncstats.pfsyncs_badstate++;
512: continue;
513: }
514: sk = st->state_key;
515: sfail = 0;
516: if (sk->proto == IPPROTO_TCP) {
517: /*
518: * The state should never go backwards except
519: * for syn-proxy states. Neither should the
520: * sequence window slide backwards.
521: */
522: if (st->src.state > sp->src.state &&
523: (st->src.state < PF_TCPS_PROXY_SRC ||
524: sp->src.state >= PF_TCPS_PROXY_SRC))
525: sfail = 1;
526: else if (SEQ_GT(st->src.seqlo,
527: ntohl(sp->src.seqlo)))
528: sfail = 3;
529: else if (st->dst.state > sp->dst.state) {
530: /* There might still be useful
531: * information about the src state here,
532: * so import that part of the update,
533: * then "fail" so we send the updated
534: * state back to the peer who is missing
535: * our what we know. */
536: pf_state_peer_ntoh(&sp->src, &st->src);
537: /* XXX do anything with timeouts? */
538: sfail = 7;
539: flags = 0;
540: } else if (st->dst.state >= TCPS_SYN_SENT &&
541: SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
542: sfail = 4;
543: } else {
544: /*
545: * Non-TCP protocol state machine always go
546: * forwards
547: */
548: if (st->src.state > sp->src.state)
549: sfail = 5;
550: else if (st->dst.state > sp->dst.state)
551: sfail = 6;
552: }
553: if (sfail) {
554: if (pf_status.debug >= PF_DEBUG_MISC)
555: printf("pfsync: %s stale update "
556: "(%d) id: %016llx "
557: "creatorid: %08x\n",
558: (sfail < 7 ? "ignoring"
559: : "partial"), sfail,
560: betoh64(st->id),
561: ntohl(st->creatorid));
562: pfsyncstats.pfsyncs_badstate++;
563:
564: if (!(sp->sync_flags & PFSTATE_STALE)) {
565: /* we have a better state, send it */
566: if (sc->sc_mbuf != NULL && !stale)
567: pfsync_sendout(sc);
568: stale++;
569: if (!st->sync_flags)
570: pfsync_pack_state(
571: PFSYNC_ACT_UPD, st, flags);
572: }
573: continue;
574: }
575: pfsync_alloc_scrub_memory(&sp->dst, &st->dst);
576: pf_state_peer_ntoh(&sp->src, &st->src);
577: pf_state_peer_ntoh(&sp->dst, &st->dst);
578: st->expire = ntohl(sp->expire) + time_second;
579: st->timeout = sp->timeout;
580: }
581: if (stale && sc->sc_mbuf != NULL)
582: pfsync_sendout(sc);
583: splx(s);
584: break;
585: /*
586: * It's not strictly necessary for us to support the "uncompressed"
587: * delete action, but it's relatively simple and maintains consistency.
588: */
589: case PFSYNC_ACT_DEL:
590: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
591: count * sizeof(*sp), &offp)) == NULL) {
592: pfsyncstats.pfsyncs_badlen++;
593: return;
594: }
595:
596: s = splsoftnet();
597: for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
598: i < count; i++, sp++) {
599: bcopy(sp->id, &id_key.id, sizeof(id_key.id));
600: id_key.creatorid = sp->creatorid;
601:
602: st = pf_find_state_byid(&id_key);
603: if (st == NULL) {
604: pfsyncstats.pfsyncs_badstate++;
605: continue;
606: }
607: st->sync_flags |= PFSTATE_FROMSYNC;
608: pf_unlink_state(st);
609: }
610: splx(s);
611: break;
612: case PFSYNC_ACT_UPD_C: {
613: int update_requested = 0;
614:
615: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
616: count * sizeof(*up), &offp)) == NULL) {
617: pfsyncstats.pfsyncs_badlen++;
618: return;
619: }
620:
621: s = splsoftnet();
622: for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
623: i < count; i++, up++) {
624: /* check for invalid values */
625: if (up->timeout >= PFTM_MAX ||
626: up->src.state > PF_TCPS_PROXY_DST ||
627: up->dst.state > PF_TCPS_PROXY_DST) {
628: if (pf_status.debug >= PF_DEBUG_MISC)
629: printf("pfsync_insert: "
630: "PFSYNC_ACT_UPD_C: "
631: "invalid value\n");
632: pfsyncstats.pfsyncs_badstate++;
633: continue;
634: }
635:
636: bcopy(up->id, &id_key.id, sizeof(id_key.id));
637: id_key.creatorid = up->creatorid;
638:
639: st = pf_find_state_byid(&id_key);
640: if (st == NULL) {
641: /* We don't have this state. Ask for it. */
642: error = pfsync_request_update(up, &src);
643: if (error == ENOMEM) {
644: splx(s);
645: goto done;
646: }
647: update_requested = 1;
648: pfsyncstats.pfsyncs_badstate++;
649: continue;
650: }
651: sk = st->state_key;
652: sfail = 0;
653: if (sk->proto == IPPROTO_TCP) {
654: /*
655: * The state should never go backwards except
656: * for syn-proxy states. Neither should the
657: * sequence window slide backwards.
658: */
659: if (st->src.state > up->src.state &&
660: (st->src.state < PF_TCPS_PROXY_SRC ||
661: up->src.state >= PF_TCPS_PROXY_SRC))
662: sfail = 1;
663: else if (st->dst.state > up->dst.state)
664: sfail = 2;
665: else if (SEQ_GT(st->src.seqlo,
666: ntohl(up->src.seqlo)))
667: sfail = 3;
668: else if (st->dst.state >= TCPS_SYN_SENT &&
669: SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
670: sfail = 4;
671: } else {
672: /*
673: * Non-TCP protocol state machine always go
674: * forwards
675: */
676: if (st->src.state > up->src.state)
677: sfail = 5;
678: else if (st->dst.state > up->dst.state)
679: sfail = 6;
680: }
681: if (sfail) {
682: if (pf_status.debug >= PF_DEBUG_MISC)
683: printf("pfsync: ignoring stale update "
684: "(%d) id: %016llx "
685: "creatorid: %08x\n", sfail,
686: betoh64(st->id),
687: ntohl(st->creatorid));
688: pfsyncstats.pfsyncs_badstate++;
689:
690: /* we have a better state, send it out */
691: if ((!stale || update_requested) &&
692: sc->sc_mbuf != NULL) {
693: pfsync_sendout(sc);
694: update_requested = 0;
695: }
696: stale++;
697: if (!st->sync_flags)
698: pfsync_pack_state(PFSYNC_ACT_UPD, st,
699: PFSYNC_FLAG_STALE);
700: continue;
701: }
702: pfsync_alloc_scrub_memory(&up->dst, &st->dst);
703: pf_state_peer_ntoh(&up->src, &st->src);
704: pf_state_peer_ntoh(&up->dst, &st->dst);
705: st->expire = ntohl(up->expire) + time_second;
706: st->timeout = up->timeout;
707: }
708: if ((update_requested || stale) && sc->sc_mbuf)
709: pfsync_sendout(sc);
710: splx(s);
711: break;
712: }
713: case PFSYNC_ACT_DEL_C:
714: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
715: count * sizeof(*dp), &offp)) == NULL) {
716: pfsyncstats.pfsyncs_badlen++;
717: return;
718: }
719:
720: s = splsoftnet();
721: for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
722: i < count; i++, dp++) {
723: bcopy(dp->id, &id_key.id, sizeof(id_key.id));
724: id_key.creatorid = dp->creatorid;
725:
726: st = pf_find_state_byid(&id_key);
727: if (st == NULL) {
728: pfsyncstats.pfsyncs_badstate++;
729: continue;
730: }
731: st->sync_flags |= PFSTATE_FROMSYNC;
732: pf_unlink_state(st);
733: }
734: splx(s);
735: break;
736: case PFSYNC_ACT_INS_F:
737: case PFSYNC_ACT_DEL_F:
738: /* not implemented */
739: break;
740: case PFSYNC_ACT_UREQ:
741: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
742: count * sizeof(*rup), &offp)) == NULL) {
743: pfsyncstats.pfsyncs_badlen++;
744: return;
745: }
746:
747: s = splsoftnet();
748: if (sc->sc_mbuf != NULL)
749: pfsync_sendout(sc);
750: for (i = 0,
751: rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
752: i < count; i++, rup++) {
753: bcopy(rup->id, &id_key.id, sizeof(id_key.id));
754: id_key.creatorid = rup->creatorid;
755:
756: if (id_key.id == 0 && id_key.creatorid == 0) {
757: sc->sc_ureq_received = time_uptime;
758: if (sc->sc_bulk_send_next == NULL)
759: sc->sc_bulk_send_next =
760: TAILQ_FIRST(&state_list);
761: sc->sc_bulk_terminator = sc->sc_bulk_send_next;
762: if (pf_status.debug >= PF_DEBUG_MISC)
763: printf("pfsync: received "
764: "bulk update request\n");
765: pfsync_send_bus(sc, PFSYNC_BUS_START);
766: timeout_add(&sc->sc_bulk_tmo, 1 * hz);
767: } else {
768: st = pf_find_state_byid(&id_key);
769: if (st == NULL) {
770: pfsyncstats.pfsyncs_badstate++;
771: continue;
772: }
773: if (!st->sync_flags)
774: pfsync_pack_state(PFSYNC_ACT_UPD,
775: st, 0);
776: }
777: }
778: if (sc->sc_mbuf != NULL)
779: pfsync_sendout(sc);
780: splx(s);
781: break;
782: case PFSYNC_ACT_BUS:
783: /* If we're not waiting for a bulk update, who cares. */
784: if (sc->sc_ureq_sent == 0)
785: break;
786:
787: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
788: sizeof(*bus), &offp)) == NULL) {
789: pfsyncstats.pfsyncs_badlen++;
790: return;
791: }
792: bus = (struct pfsync_state_bus *)(mp->m_data + offp);
793: switch (bus->status) {
794: case PFSYNC_BUS_START:
795: timeout_add(&sc->sc_bulkfail_tmo,
796: pf_pool_limits[PF_LIMIT_STATES].limit /
797: (PFSYNC_BULKPACKETS * sc->sc_maxcount));
798: if (pf_status.debug >= PF_DEBUG_MISC)
799: printf("pfsync: received bulk "
800: "update start\n");
801: break;
802: case PFSYNC_BUS_END:
803: if (time_uptime - ntohl(bus->endtime) >=
804: sc->sc_ureq_sent) {
805: /* that's it, we're happy */
806: sc->sc_ureq_sent = 0;
807: sc->sc_bulk_tries = 0;
808: timeout_del(&sc->sc_bulkfail_tmo);
809: #if NCARP > 0
810: if (!pfsync_sync_ok)
811: carp_group_demote_adj(&sc->sc_if, -1);
812: #endif
813: pfsync_sync_ok = 1;
814: if (pf_status.debug >= PF_DEBUG_MISC)
815: printf("pfsync: received valid "
816: "bulk update end\n");
817: } else {
818: if (pf_status.debug >= PF_DEBUG_MISC)
819: printf("pfsync: received invalid "
820: "bulk update end: bad timestamp\n");
821: }
822: break;
823: }
824: break;
825: #ifdef IPSEC
826: case PFSYNC_ACT_TDB_UPD:
827: if ((mp = m_pulldown(m, iplen + sizeof(*ph),
828: count * sizeof(*pt), &offp)) == NULL) {
829: pfsyncstats.pfsyncs_badlen++;
830: return;
831: }
832: s = splsoftnet();
833: for (i = 0, pt = (struct pfsync_tdb *)(mp->m_data + offp);
834: i < count; i++, pt++)
835: pfsync_update_net_tdb(pt);
836: splx(s);
837: break;
838: #endif
839: }
840:
841: done:
842: if (m)
843: m_freem(m);
844: }
845:
846: int
847: pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
848: struct rtentry *rt)
849: {
850: m_freem(m);
851: return (0);
852: }
853:
854: /* ARGSUSED */
855: int
856: pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
857: {
858: struct proc *p = curproc;
859: struct pfsync_softc *sc = ifp->if_softc;
860: struct ifreq *ifr = (struct ifreq *)data;
861: struct ip_moptions *imo = &sc->sc_imo;
862: struct pfsyncreq pfsyncr;
863: struct ifnet *sifp;
864: int s, error;
865:
866: switch (cmd) {
867: case SIOCSIFADDR:
868: case SIOCAIFADDR:
869: case SIOCSIFDSTADDR:
870: case SIOCSIFFLAGS:
871: if (ifp->if_flags & IFF_UP)
872: ifp->if_flags |= IFF_RUNNING;
873: else
874: ifp->if_flags &= ~IFF_RUNNING;
875: break;
876: case SIOCSIFMTU:
877: if (ifr->ifr_mtu < PFSYNC_MINMTU)
878: return (EINVAL);
879: if (ifr->ifr_mtu > MCLBYTES)
880: ifr->ifr_mtu = MCLBYTES;
881: s = splnet();
882: if (ifr->ifr_mtu < ifp->if_mtu)
883: pfsync_sendout(sc);
884: pfsync_setmtu(sc, ifr->ifr_mtu);
885: splx(s);
886: break;
887: case SIOCGETPFSYNC:
888: bzero(&pfsyncr, sizeof(pfsyncr));
889: if (sc->sc_sync_ifp)
890: strlcpy(pfsyncr.pfsyncr_syncdev,
891: sc->sc_sync_ifp->if_xname, IFNAMSIZ);
892: pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
893: pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
894: if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
895: return (error);
896: break;
897: case SIOCSETPFSYNC:
898: if ((error = suser(p, p->p_acflag)) != 0)
899: return (error);
900: if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
901: return (error);
902:
903: if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
904: sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
905: else
906: sc->sc_sync_peer.s_addr =
907: pfsyncr.pfsyncr_syncpeer.s_addr;
908:
909: if (pfsyncr.pfsyncr_maxupdates > 255)
910: return (EINVAL);
911: sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
912:
913: if (pfsyncr.pfsyncr_syncdev[0] == 0) {
914: sc->sc_sync_ifp = NULL;
915: if (sc->sc_mbuf_net != NULL) {
916: /* Don't keep stale pfsync packets around. */
917: s = splnet();
918: m_freem(sc->sc_mbuf_net);
919: sc->sc_mbuf_net = NULL;
920: sc->sc_statep_net.s = NULL;
921: splx(s);
922: }
923: if (imo->imo_num_memberships > 0) {
924: in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
925: imo->imo_multicast_ifp = NULL;
926: }
927: break;
928: }
929:
930: if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL)
931: return (EINVAL);
932:
933: s = splnet();
934: if (sifp->if_mtu < sc->sc_if.if_mtu ||
935: (sc->sc_sync_ifp != NULL &&
936: sifp->if_mtu < sc->sc_sync_ifp->if_mtu) ||
937: sifp->if_mtu < MCLBYTES - sizeof(struct ip))
938: pfsync_sendout(sc);
939: sc->sc_sync_ifp = sifp;
940:
941: pfsync_setmtu(sc, sc->sc_if.if_mtu);
942:
943: if (imo->imo_num_memberships > 0) {
944: in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
945: imo->imo_multicast_ifp = NULL;
946: }
947:
948: if (sc->sc_sync_ifp &&
949: sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
950: struct in_addr addr;
951:
952: if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
953: sc->sc_sync_ifp = NULL;
954: splx(s);
955: return (EADDRNOTAVAIL);
956: }
957:
958: addr.s_addr = INADDR_PFSYNC_GROUP;
959:
960: if ((imo->imo_membership[0] =
961: in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
962: sc->sc_sync_ifp = NULL;
963: splx(s);
964: return (ENOBUFS);
965: }
966: imo->imo_num_memberships++;
967: imo->imo_multicast_ifp = sc->sc_sync_ifp;
968: imo->imo_multicast_ttl = PFSYNC_DFLTTL;
969: imo->imo_multicast_loop = 0;
970: }
971:
972: if (sc->sc_sync_ifp ||
973: sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
974: /* Request a full state table update. */
975: sc->sc_ureq_sent = time_uptime;
976: #if NCARP > 0
977: if (pfsync_sync_ok)
978: carp_group_demote_adj(&sc->sc_if, 1);
979: #endif
980: pfsync_sync_ok = 0;
981: if (pf_status.debug >= PF_DEBUG_MISC)
982: printf("pfsync: requesting bulk update\n");
983: timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
984: error = pfsync_request_update(NULL, NULL);
985: if (error == ENOMEM) {
986: splx(s);
987: return (ENOMEM);
988: }
989: pfsync_sendout(sc);
990: }
991: splx(s);
992:
993: break;
994:
995: default:
996: return (ENOTTY);
997: }
998:
999: return (0);
1000: }
1001:
1002: void
1003: pfsync_setmtu(struct pfsync_softc *sc, int mtu_req)
1004: {
1005: int mtu;
1006:
1007: if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req)
1008: mtu = sc->sc_sync_ifp->if_mtu;
1009: else
1010: mtu = mtu_req;
1011:
1012: sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) /
1013: sizeof(struct pfsync_state);
1014: if (sc->sc_maxcount > 254)
1015: sc->sc_maxcount = 254;
1016: sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
1017: sc->sc_maxcount * sizeof(struct pfsync_state);
1018: }
1019:
1020: struct mbuf *
1021: pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
1022: {
1023: struct pfsync_header *h;
1024: struct mbuf *m;
1025: int len;
1026:
1027: MGETHDR(m, M_DONTWAIT, MT_DATA);
1028: if (m == NULL) {
1029: sc->sc_if.if_oerrors++;
1030: return (NULL);
1031: }
1032:
1033: switch (action) {
1034: case PFSYNC_ACT_CLR:
1035: len = sizeof(struct pfsync_header) +
1036: sizeof(struct pfsync_state_clr);
1037: break;
1038: case PFSYNC_ACT_UPD_C:
1039: len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) +
1040: sizeof(struct pfsync_header);
1041: break;
1042: case PFSYNC_ACT_DEL_C:
1043: len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) +
1044: sizeof(struct pfsync_header);
1045: break;
1046: case PFSYNC_ACT_UREQ:
1047: len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) +
1048: sizeof(struct pfsync_header);
1049: break;
1050: case PFSYNC_ACT_BUS:
1051: len = sizeof(struct pfsync_header) +
1052: sizeof(struct pfsync_state_bus);
1053: break;
1054: case PFSYNC_ACT_TDB_UPD:
1055: len = (sc->sc_maxcount * sizeof(struct pfsync_tdb)) +
1056: sizeof(struct pfsync_header);
1057: break;
1058: default:
1059: len = (sc->sc_maxcount * sizeof(struct pfsync_state)) +
1060: sizeof(struct pfsync_header);
1061: break;
1062: }
1063:
1064: if (len > MHLEN) {
1065: MCLGET(m, M_DONTWAIT);
1066: if ((m->m_flags & M_EXT) == 0) {
1067: m_free(m);
1068: sc->sc_if.if_oerrors++;
1069: return (NULL);
1070: }
1071: m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1);
1072: } else
1073: MH_ALIGN(m, len);
1074:
1075: m->m_pkthdr.rcvif = NULL;
1076: m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header);
1077: h = mtod(m, struct pfsync_header *);
1078: h->version = PFSYNC_VERSION;
1079: h->af = 0;
1080: h->count = 0;
1081: h->action = action;
1082: if (action != PFSYNC_ACT_TDB_UPD)
1083: bcopy(&pf_status.pf_chksum, &h->pf_chksum,
1084: PF_MD5_DIGEST_LENGTH);
1085:
1086: *sp = (void *)((char *)h + PFSYNC_HDRLEN);
1087: if (action == PFSYNC_ACT_TDB_UPD)
1088: timeout_add(&sc->sc_tdb_tmo, hz);
1089: else
1090: timeout_add(&sc->sc_tmo, hz);
1091: return (m);
1092: }
1093:
1094: int
1095: pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
1096: {
1097: struct ifnet *ifp = NULL;
1098: struct pfsync_softc *sc = pfsyncif;
1099: struct pfsync_header *h, *h_net;
1100: struct pfsync_state *sp = NULL;
1101: struct pfsync_state_upd *up = NULL;
1102: struct pfsync_state_del *dp = NULL;
1103: struct pf_state_key *sk = st->state_key;
1104: struct pf_rule *r;
1105: u_long secs;
1106: int s, ret = 0;
1107: u_int8_t i = 255, newaction = 0;
1108:
1109: if (sc == NULL)
1110: return (0);
1111: ifp = &sc->sc_if;
1112:
1113: /*
1114: * If a packet falls in the forest and there's nobody around to
1115: * hear, does it make a sound?
1116: */
1117: if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
1118: sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1119: /* Don't leave any stale pfsync packets hanging around. */
1120: if (sc->sc_mbuf != NULL) {
1121: m_freem(sc->sc_mbuf);
1122: sc->sc_mbuf = NULL;
1123: sc->sc_statep.s = NULL;
1124: }
1125: return (0);
1126: }
1127:
1128: if (action >= PFSYNC_ACT_MAX)
1129: return (EINVAL);
1130:
1131: s = splnet();
1132: if (sc->sc_mbuf == NULL) {
1133: if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
1134: (void *)&sc->sc_statep.s)) == NULL) {
1135: splx(s);
1136: return (ENOMEM);
1137: }
1138: h = mtod(sc->sc_mbuf, struct pfsync_header *);
1139: } else {
1140: h = mtod(sc->sc_mbuf, struct pfsync_header *);
1141: if (h->action != action) {
1142: pfsync_sendout(sc);
1143: if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
1144: (void *)&sc->sc_statep.s)) == NULL) {
1145: splx(s);
1146: return (ENOMEM);
1147: }
1148: h = mtod(sc->sc_mbuf, struct pfsync_header *);
1149: } else {
1150: /*
1151: * If it's an update, look in the packet to see if
1152: * we already have an update for the state.
1153: */
1154: if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) {
1155: struct pfsync_state *usp =
1156: (void *)((char *)h + PFSYNC_HDRLEN);
1157:
1158: for (i = 0; i < h->count; i++) {
1159: if (!memcmp(usp->id, &st->id,
1160: PFSYNC_ID_LEN) &&
1161: usp->creatorid == st->creatorid) {
1162: sp = usp;
1163: sp->updates++;
1164: break;
1165: }
1166: usp++;
1167: }
1168: }
1169: }
1170: }
1171:
1172: secs = time_second;
1173:
1174: st->pfsync_time = time_uptime;
1175:
1176: if (sp == NULL) {
1177: /* not a "duplicate" update */
1178: i = 255;
1179: sp = sc->sc_statep.s++;
1180: sc->sc_mbuf->m_pkthdr.len =
1181: sc->sc_mbuf->m_len += sizeof(struct pfsync_state);
1182: h->count++;
1183: bzero(sp, sizeof(*sp));
1184:
1185: bcopy(&st->id, sp->id, sizeof(sp->id));
1186: sp->creatorid = st->creatorid;
1187:
1188: strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
1189: pf_state_host_hton(&sk->lan, &sp->lan);
1190: pf_state_host_hton(&sk->gwy, &sp->gwy);
1191: pf_state_host_hton(&sk->ext, &sp->ext);
1192:
1193: bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
1194:
1195: sp->creation = htonl(secs - st->creation);
1196: pf_state_counter_hton(st->packets[0], sp->packets[0]);
1197: pf_state_counter_hton(st->packets[1], sp->packets[1]);
1198: pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
1199: pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
1200: if ((r = st->rule.ptr) == NULL)
1201: sp->rule = htonl(-1);
1202: else
1203: sp->rule = htonl(r->nr);
1204: if ((r = st->anchor.ptr) == NULL)
1205: sp->anchor = htonl(-1);
1206: else
1207: sp->anchor = htonl(r->nr);
1208: sp->af = sk->af;
1209: sp->proto = sk->proto;
1210: sp->direction = sk->direction;
1211: sp->log = st->log;
1212: sp->allow_opts = st->allow_opts;
1213: sp->timeout = st->timeout;
1214:
1215: if (flags & PFSYNC_FLAG_STALE)
1216: sp->sync_flags |= PFSTATE_STALE;
1217: }
1218:
1219: pf_state_peer_hton(&st->src, &sp->src);
1220: pf_state_peer_hton(&st->dst, &sp->dst);
1221:
1222: if (st->expire <= secs)
1223: sp->expire = htonl(0);
1224: else
1225: sp->expire = htonl(st->expire - secs);
1226:
1227: /* do we need to build "compressed" actions for network transfer? */
1228: if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
1229: switch (action) {
1230: case PFSYNC_ACT_UPD:
1231: newaction = PFSYNC_ACT_UPD_C;
1232: break;
1233: case PFSYNC_ACT_DEL:
1234: newaction = PFSYNC_ACT_DEL_C;
1235: break;
1236: default:
1237: /* by default we just send the uncompressed states */
1238: break;
1239: }
1240: }
1241:
1242: if (newaction) {
1243: if (sc->sc_mbuf_net == NULL) {
1244: if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction,
1245: (void *)&sc->sc_statep_net.s)) == NULL) {
1246: splx(s);
1247: return (ENOMEM);
1248: }
1249: }
1250: h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *);
1251:
1252: switch (newaction) {
1253: case PFSYNC_ACT_UPD_C:
1254: if (i != 255) {
1255: up = (void *)((char *)h_net +
1256: PFSYNC_HDRLEN + (i * sizeof(*up)));
1257: up->updates++;
1258: } else {
1259: h_net->count++;
1260: sc->sc_mbuf_net->m_pkthdr.len =
1261: sc->sc_mbuf_net->m_len += sizeof(*up);
1262: up = sc->sc_statep_net.u++;
1263:
1264: bzero(up, sizeof(*up));
1265: bcopy(&st->id, up->id, sizeof(up->id));
1266: up->creatorid = st->creatorid;
1267: }
1268: up->timeout = st->timeout;
1269: up->expire = sp->expire;
1270: up->src = sp->src;
1271: up->dst = sp->dst;
1272: break;
1273: case PFSYNC_ACT_DEL_C:
1274: sc->sc_mbuf_net->m_pkthdr.len =
1275: sc->sc_mbuf_net->m_len += sizeof(*dp);
1276: dp = sc->sc_statep_net.d++;
1277: h_net->count++;
1278:
1279: bzero(dp, sizeof(*dp));
1280: bcopy(&st->id, dp->id, sizeof(dp->id));
1281: dp->creatorid = st->creatorid;
1282: break;
1283: }
1284: }
1285:
1286: if (h->count == sc->sc_maxcount ||
1287: (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates)))
1288: ret = pfsync_sendout(sc);
1289:
1290: splx(s);
1291: return (ret);
1292: }
1293:
1294: /* This must be called in splnet() */
1295: int
1296: pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
1297: {
1298: struct ifnet *ifp = NULL;
1299: struct pfsync_header *h;
1300: struct pfsync_softc *sc = pfsyncif;
1301: struct pfsync_state_upd_req *rup;
1302: int ret = 0;
1303:
1304: if (sc == NULL)
1305: return (0);
1306:
1307: ifp = &sc->sc_if;
1308: if (sc->sc_mbuf == NULL) {
1309: if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1310: (void *)&sc->sc_statep.s)) == NULL)
1311: return (ENOMEM);
1312: h = mtod(sc->sc_mbuf, struct pfsync_header *);
1313: } else {
1314: h = mtod(sc->sc_mbuf, struct pfsync_header *);
1315: if (h->action != PFSYNC_ACT_UREQ) {
1316: pfsync_sendout(sc);
1317: if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1318: (void *)&sc->sc_statep.s)) == NULL)
1319: return (ENOMEM);
1320: h = mtod(sc->sc_mbuf, struct pfsync_header *);
1321: }
1322: }
1323:
1324: if (src != NULL)
1325: sc->sc_sendaddr = *src;
1326: sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
1327: h->count++;
1328: rup = sc->sc_statep.r++;
1329: bzero(rup, sizeof(*rup));
1330: if (up != NULL) {
1331: bcopy(up->id, rup->id, sizeof(rup->id));
1332: rup->creatorid = up->creatorid;
1333: }
1334:
1335: if (h->count == sc->sc_maxcount)
1336: ret = pfsync_sendout(sc);
1337:
1338: return (ret);
1339: }
1340:
1341: int
1342: pfsync_clear_states(u_int32_t creatorid, char *ifname)
1343: {
1344: struct ifnet *ifp = NULL;
1345: struct pfsync_softc *sc = pfsyncif;
1346: struct pfsync_state_clr *cp;
1347: int s, ret;
1348:
1349: if (sc == NULL)
1350: return (0);
1351:
1352: ifp = &sc->sc_if;
1353: s = splnet();
1354: if (sc->sc_mbuf != NULL)
1355: pfsync_sendout(sc);
1356: if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR,
1357: (void *)&sc->sc_statep.c)) == NULL) {
1358: splx(s);
1359: return (ENOMEM);
1360: }
1361: sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp);
1362: cp = sc->sc_statep.c;
1363: cp->creatorid = creatorid;
1364: if (ifname != NULL)
1365: strlcpy(cp->ifname, ifname, IFNAMSIZ);
1366:
1367: ret = (pfsync_sendout(sc));
1368: splx(s);
1369: return (ret);
1370: }
1371:
1372: void
1373: pfsync_timeout(void *v)
1374: {
1375: struct pfsync_softc *sc = v;
1376: int s;
1377:
1378: s = splnet();
1379: pfsync_sendout(sc);
1380: splx(s);
1381: }
1382:
1383: void
1384: pfsync_tdb_timeout(void *v)
1385: {
1386: struct pfsync_softc *sc = v;
1387: int s;
1388:
1389: s = splnet();
1390: pfsync_tdb_sendout(sc);
1391: splx(s);
1392: }
1393:
1394: /* This must be called in splnet() */
1395: void
1396: pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
1397: {
1398: struct pfsync_state_bus *bus;
1399:
1400: if (sc->sc_mbuf != NULL)
1401: pfsync_sendout(sc);
1402:
1403: if (pfsync_sync_ok &&
1404: (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
1405: (void *)&sc->sc_statep.b)) != NULL) {
1406: sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
1407: bus = sc->sc_statep.b;
1408: bus->creatorid = pf_status.hostid;
1409: bus->status = status;
1410: bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
1411: pfsync_sendout(sc);
1412: }
1413: }
1414:
1415: void
1416: pfsync_bulk_update(void *v)
1417: {
1418: struct pfsync_softc *sc = v;
1419: int s, i = 0;
1420: struct pf_state *state;
1421:
1422: s = splnet();
1423: if (sc->sc_mbuf != NULL)
1424: pfsync_sendout(sc);
1425:
1426: /*
1427: * Grab at most PFSYNC_BULKPACKETS worth of states which have not
1428: * been sent since the latest request was made.
1429: */
1430: state = sc->sc_bulk_send_next;
1431: if (state)
1432: do {
1433: /* send state update if syncable and not already sent */
1434: if (!state->sync_flags
1435: && state->timeout < PFTM_MAX
1436: && state->pfsync_time <= sc->sc_ureq_received) {
1437: pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
1438: i++;
1439: }
1440:
1441: /* figure next state to send */
1442: state = TAILQ_NEXT(state, entry_list);
1443:
1444: /* wrap to start of list if we hit the end */
1445: if (!state)
1446: state = TAILQ_FIRST(&state_list);
1447: } while (i < sc->sc_maxcount * PFSYNC_BULKPACKETS &&
1448: state != sc->sc_bulk_terminator);
1449:
1450: if (!state || state == sc->sc_bulk_terminator) {
1451: /* we're done */
1452: pfsync_send_bus(sc, PFSYNC_BUS_END);
1453: sc->sc_ureq_received = 0;
1454: sc->sc_bulk_send_next = NULL;
1455: sc->sc_bulk_terminator = NULL;
1456: timeout_del(&sc->sc_bulk_tmo);
1457: if (pf_status.debug >= PF_DEBUG_MISC)
1458: printf("pfsync: bulk update complete\n");
1459: } else {
1460: /* look again for more in a bit */
1461: timeout_add(&sc->sc_bulk_tmo, 1);
1462: sc->sc_bulk_send_next = state;
1463: }
1464: if (sc->sc_mbuf != NULL)
1465: pfsync_sendout(sc);
1466: splx(s);
1467: }
1468:
1469: void
1470: pfsync_bulkfail(void *v)
1471: {
1472: struct pfsync_softc *sc = v;
1473: int s, error;
1474:
1475: if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
1476: /* Try again in a bit */
1477: timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
1478: s = splnet();
1479: error = pfsync_request_update(NULL, NULL);
1480: if (error == ENOMEM) {
1481: if (pf_status.debug >= PF_DEBUG_MISC)
1482: printf("pfsync: cannot allocate mbufs for "
1483: "bulk update\n");
1484: } else
1485: pfsync_sendout(sc);
1486: splx(s);
1487: } else {
1488: /* Pretend like the transfer was ok */
1489: sc->sc_ureq_sent = 0;
1490: sc->sc_bulk_tries = 0;
1491: #if NCARP > 0
1492: if (!pfsync_sync_ok)
1493: carp_group_demote_adj(&sc->sc_if, -1);
1494: #endif
1495: pfsync_sync_ok = 1;
1496: if (pf_status.debug >= PF_DEBUG_MISC)
1497: printf("pfsync: failed to receive "
1498: "bulk update status\n");
1499: timeout_del(&sc->sc_bulkfail_tmo);
1500: }
1501: }
1502:
1503: /* This must be called in splnet() */
1504: int
1505: pfsync_sendout(struct pfsync_softc *sc)
1506: {
1507: #if NBPFILTER > 0
1508: struct ifnet *ifp = &sc->sc_if;
1509: #endif
1510: struct mbuf *m;
1511:
1512: timeout_del(&sc->sc_tmo);
1513:
1514: if (sc->sc_mbuf == NULL)
1515: return (0);
1516: m = sc->sc_mbuf;
1517: sc->sc_mbuf = NULL;
1518: sc->sc_statep.s = NULL;
1519:
1520: #if NBPFILTER > 0
1521: if (ifp->if_bpf)
1522: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1523: #endif
1524:
1525: if (sc->sc_mbuf_net) {
1526: m_freem(m);
1527: m = sc->sc_mbuf_net;
1528: sc->sc_mbuf_net = NULL;
1529: sc->sc_statep_net.s = NULL;
1530: }
1531:
1532: return pfsync_sendout_mbuf(sc, m);
1533: }
1534:
1535: int
1536: pfsync_tdb_sendout(struct pfsync_softc *sc)
1537: {
1538: #if NBPFILTER > 0
1539: struct ifnet *ifp = &sc->sc_if;
1540: #endif
1541: struct mbuf *m;
1542:
1543: timeout_del(&sc->sc_tdb_tmo);
1544:
1545: if (sc->sc_mbuf_tdb == NULL)
1546: return (0);
1547: m = sc->sc_mbuf_tdb;
1548: sc->sc_mbuf_tdb = NULL;
1549: sc->sc_statep_tdb.t = NULL;
1550:
1551: #if NBPFILTER > 0
1552: if (ifp->if_bpf)
1553: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1554: #endif
1555:
1556: return pfsync_sendout_mbuf(sc, m);
1557: }
1558:
1559: int
1560: pfsync_sendout_mbuf(struct pfsync_softc *sc, struct mbuf *m)
1561: {
1562: struct sockaddr sa;
1563: struct ip *ip;
1564:
1565: if (sc->sc_sync_ifp ||
1566: sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
1567: M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
1568: if (m == NULL) {
1569: pfsyncstats.pfsyncs_onomem++;
1570: return (0);
1571: }
1572: ip = mtod(m, struct ip *);
1573: ip->ip_v = IPVERSION;
1574: ip->ip_hl = sizeof(*ip) >> 2;
1575: ip->ip_tos = IPTOS_LOWDELAY;
1576: ip->ip_len = htons(m->m_pkthdr.len);
1577: ip->ip_id = htons(ip_randomid());
1578: ip->ip_off = htons(IP_DF);
1579: ip->ip_ttl = PFSYNC_DFLTTL;
1580: ip->ip_p = IPPROTO_PFSYNC;
1581: ip->ip_sum = 0;
1582:
1583: bzero(&sa, sizeof(sa));
1584: ip->ip_src.s_addr = INADDR_ANY;
1585:
1586: if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
1587: m->m_flags |= M_MCAST;
1588: ip->ip_dst = sc->sc_sendaddr;
1589: sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
1590:
1591: pfsyncstats.pfsyncs_opackets++;
1592:
1593: if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
1594: pfsyncstats.pfsyncs_oerrors++;
1595: } else
1596: m_freem(m);
1597:
1598: return (0);
1599: }
1600:
1601: #ifdef IPSEC
1602: /* Update an in-kernel tdb. Silently fail if no tdb is found. */
1603: void
1604: pfsync_update_net_tdb(struct pfsync_tdb *pt)
1605: {
1606: struct tdb *tdb;
1607: int s;
1608:
1609: /* check for invalid values */
1610: if (ntohl(pt->spi) <= SPI_RESERVED_MAX ||
1611: (pt->dst.sa.sa_family != AF_INET &&
1612: pt->dst.sa.sa_family != AF_INET6))
1613: goto bad;
1614:
1615: s = spltdb();
1616: tdb = gettdb(pt->spi, &pt->dst, pt->sproto);
1617: if (tdb) {
1618: pt->rpl = ntohl(pt->rpl);
1619: pt->cur_bytes = betoh64(pt->cur_bytes);
1620:
1621: /* Neither replay nor byte counter should ever decrease. */
1622: if (pt->rpl < tdb->tdb_rpl ||
1623: pt->cur_bytes < tdb->tdb_cur_bytes) {
1624: splx(s);
1625: goto bad;
1626: }
1627:
1628: tdb->tdb_rpl = pt->rpl;
1629: tdb->tdb_cur_bytes = pt->cur_bytes;
1630: }
1631: splx(s);
1632: return;
1633:
1634: bad:
1635: if (pf_status.debug >= PF_DEBUG_MISC)
1636: printf("pfsync_insert: PFSYNC_ACT_TDB_UPD: "
1637: "invalid value\n");
1638: pfsyncstats.pfsyncs_badstate++;
1639: return;
1640: }
1641:
1642: /* One of our local tdbs have been updated, need to sync rpl with others */
1643: int
1644: pfsync_update_tdb(struct tdb *tdb, int output)
1645: {
1646: struct ifnet *ifp = NULL;
1647: struct pfsync_softc *sc = pfsyncif;
1648: struct pfsync_header *h;
1649: struct pfsync_tdb *pt = NULL;
1650: int s, i, ret;
1651:
1652: if (sc == NULL)
1653: return (0);
1654:
1655: ifp = &sc->sc_if;
1656: if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
1657: sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1658: /* Don't leave any stale pfsync packets hanging around. */
1659: if (sc->sc_mbuf_tdb != NULL) {
1660: m_freem(sc->sc_mbuf_tdb);
1661: sc->sc_mbuf_tdb = NULL;
1662: sc->sc_statep_tdb.t = NULL;
1663: }
1664: return (0);
1665: }
1666:
1667: s = splnet();
1668: if (sc->sc_mbuf_tdb == NULL) {
1669: if ((sc->sc_mbuf_tdb = pfsync_get_mbuf(sc, PFSYNC_ACT_TDB_UPD,
1670: (void *)&sc->sc_statep_tdb.t)) == NULL) {
1671: splx(s);
1672: return (ENOMEM);
1673: }
1674: h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
1675: } else {
1676: h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
1677: if (h->action != PFSYNC_ACT_TDB_UPD) {
1678: /*
1679: * XXX will never happen as long as there's
1680: * only one "TDB action".
1681: */
1682: pfsync_tdb_sendout(sc);
1683: sc->sc_mbuf_tdb = pfsync_get_mbuf(sc,
1684: PFSYNC_ACT_TDB_UPD, (void *)&sc->sc_statep_tdb.t);
1685: if (sc->sc_mbuf_tdb == NULL) {
1686: splx(s);
1687: return (ENOMEM);
1688: }
1689: h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
1690: } else if (sc->sc_maxupdates) {
1691: /*
1692: * If it's an update, look in the packet to see if
1693: * we already have an update for the state.
1694: */
1695: struct pfsync_tdb *u =
1696: (void *)((char *)h + PFSYNC_HDRLEN);
1697:
1698: for (i = 0; !pt && i < h->count; i++) {
1699: if (tdb->tdb_spi == u->spi &&
1700: tdb->tdb_sproto == u->sproto &&
1701: !bcmp(&tdb->tdb_dst, &u->dst,
1702: SA_LEN(&u->dst.sa))) {
1703: pt = u;
1704: pt->updates++;
1705: }
1706: u++;
1707: }
1708: }
1709: }
1710:
1711: if (pt == NULL) {
1712: /* not a "duplicate" update */
1713: pt = sc->sc_statep_tdb.t++;
1714: sc->sc_mbuf_tdb->m_pkthdr.len =
1715: sc->sc_mbuf_tdb->m_len += sizeof(struct pfsync_tdb);
1716: h->count++;
1717: bzero(pt, sizeof(*pt));
1718:
1719: pt->spi = tdb->tdb_spi;
1720: memcpy(&pt->dst, &tdb->tdb_dst, sizeof pt->dst);
1721: pt->sproto = tdb->tdb_sproto;
1722: }
1723:
1724: /*
1725: * When a failover happens, the master's rpl is probably above
1726: * what we see here (we may be up to a second late), so
1727: * increase it a bit for outbound tdbs to manage most such
1728: * situations.
1729: *
1730: * For now, just add an offset that is likely to be larger
1731: * than the number of packets we can see in one second. The RFC
1732: * just says the next packet must have a higher seq value.
1733: *
1734: * XXX What is a good algorithm for this? We could use
1735: * a rate-determined increase, but to know it, we would have
1736: * to extend struct tdb.
1737: * XXX pt->rpl can wrap over MAXINT, but if so the real tdb
1738: * will soon be replaced anyway. For now, just don't handle
1739: * this edge case.
1740: */
1741: #define RPL_INCR 16384
1742: pt->rpl = htonl(tdb->tdb_rpl + (output ? RPL_INCR : 0));
1743: pt->cur_bytes = htobe64(tdb->tdb_cur_bytes);
1744:
1745: if (h->count == sc->sc_maxcount ||
1746: (sc->sc_maxupdates && (pt->updates >= sc->sc_maxupdates)))
1747: ret = pfsync_tdb_sendout(sc);
1748:
1749: splx(s);
1750: return (ret);
1751: }
1752: #endif
CVSweb