summaryrefslogtreecommitdiff
path: root/sys/net/if_pfsync.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2008-12-21 23:41:27 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2008-12-21 23:41:27 +0000
commit8482147d4961544e40c1b715bdc8b9638431c0a8 (patch)
tree271eaa7c00564b2a9c699a1720147bf937403cb9 /sys/net/if_pfsync.c
parent3b98634342abb6af329171a6b09f89482cb4ed88 (diff)
split the pfsync input routine up so that each action has its own function
to handle it. this is to modularise it in preparation for further changes. in my opinion it also makes the code a lot easier to read and to maintain. tested by sthen@ johan@
Diffstat (limited to 'sys/net/if_pfsync.c')
-rw-r--r--sys/net/if_pfsync.c1005
1 files changed, 585 insertions, 420 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c
index 33bc4fb0101..ae5216edb84 100644
--- a/sys/net/if_pfsync.c
+++ b/sys/net/if_pfsync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pfsync.c,v 1.101 2008/09/17 20:10:37 chl Exp $ */
+/* $OpenBSD: if_pfsync.c,v 1.102 2008/12/21 23:41:26 dlg Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff
@@ -106,6 +106,40 @@ void pfsync_send_bus(struct pfsync_softc *, u_int8_t);
void pfsync_bulk_update(void *);
void pfsync_bulkfail(void *);
+struct pfsync_pkt {
+ struct ip *ip;
+ struct in_addr src;
+ u_int8_t flags;
+};
+
+void pfsync4_input(struct pfsync_pkt *, struct mbuf *);
+
+int pfsync4_in_clr(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_ins(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_upd(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_del(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_upd_c(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_del_c(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_ureq(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_bus(struct pfsync_pkt *, struct mbuf *, int, int);
+int pfsync4_in_tdb_upd(struct pfsync_pkt *, struct mbuf *, int, int);
+
+int pfsync4_in_error(struct pfsync_pkt *, struct mbuf *, int, int);
+
+int (*pfsync4_acts[])(struct pfsync_pkt *, struct mbuf *, int, int) = {
+ pfsync4_in_clr, /* PFSYNC_ACT_CLR */
+ pfsync4_in_ins, /* PFSYNC_ACT_INS */
+ pfsync4_in_upd, /* PFSYNC_ACT_UPD */
+ pfsync4_in_del, /* PFSYNC_ACT_DEL */
+ pfsync4_in_upd_c, /* PFSYNC_ACT_UPD_C */
+ pfsync4_in_del_c, /* PFSYNC_ACT_DEL_C */
+ pfsync4_in_error, /* PFSYNC_ACT_INS_F */
+ pfsync4_in_error, /* PFSYNC_ACT_DEL_F */
+ pfsync4_in_ureq, /* PFSYNC_ACT_UREQ */
+ pfsync4_in_bus, /* PFSYNC_ACT_BUS */
+ pfsync4_in_tdb_upd /* PFSYNC_ACT_TDB_UPD */
+};
+
int pfsync_sync_ok;
struct if_clone pfsync_cloner =
@@ -440,26 +474,14 @@ pfsync_state_import(struct pfsync_state *sp, u_int8_t flags)
void
pfsync_input(struct mbuf *m, ...)
{
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_pkt pkt;
struct ip *ip = mtod(m, struct ip *);
struct pfsync_header *ph;
- struct pfsync_softc *sc = pfsyncif;
- struct pf_state *st;
- struct pf_state_key *sk;
- struct pf_state_item *si;
- struct pf_state_cmp id_key;
- struct pfsync_state *sp;
- struct pfsync_state_upd *up;
- struct pfsync_state_del *dp;
- struct pfsync_state_clr *cp;
- struct pfsync_state_upd_req *rup;
- struct pfsync_state_bus *bus;
-#ifdef IPSEC
- struct pfsync_tdb *pt;
-#endif
- struct in_addr src;
- struct mbuf *mp;
- int iplen, action, error, i, s, count, offp, sfail, stale = 0;
- u_int8_t flags = 0;
+
+ int offset;
+ int action, count;
+ int rv;
pfsyncstats.pfsyncs_ipackets++;
@@ -479,21 +501,21 @@ pfsync_input(struct mbuf *m, ...)
goto done;
}
- iplen = ip->ip_hl << 2;
+ offset = ip->ip_hl << 2;
- if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
+ if (m->m_pkthdr.len < offset + sizeof(*ph)) {
pfsyncstats.pfsyncs_hdrops++;
goto done;
}
- if (iplen + sizeof(*ph) > m->m_len) {
- if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
+ if (offset + sizeof(*ph) > m->m_len) {
+ if (m_pullup(m, offset + sizeof(*ph)) == NULL) {
pfsyncstats.pfsyncs_hdrops++;
- goto done;
+ return;
}
ip = mtod(m, struct ip *);
}
- ph = (struct pfsync_header *)((char *)ip + iplen);
+ ph = (struct pfsync_header *)((char *)ip + offset);
/* verify the version */
if (ph->version != PFSYNC_VERSION) {
@@ -511,453 +533,596 @@ pfsync_input(struct mbuf *m, ...)
}
/* Cheaper to grab this now than having to mess with mbufs later */
- src = ip->ip_src;
+ pkt.ip = ip;
+ pkt.src = ip->ip_src;
+ pkt.flags = 0;
if (!bcmp(&ph->pf_chksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
- flags |= PFSYNC_SI_CKSUM;
+ pkt.flags |= PFSYNC_SI_CKSUM;
- switch (action) {
- case PFSYNC_ACT_CLR: {
- struct pf_state *nexts;
- struct pf_state_key *nextsk;
- u_int32_t creatorid;
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- sizeof(*cp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
- cp = (struct pfsync_state_clr *)(mp->m_data + offp);
- creatorid = cp->creatorid;
-
- s = splsoftnet();
- if (cp->ifname[0] == '\0') {
- for (st = RB_MIN(pf_state_tree_id, &tree_id);
- st; st = nexts) {
- nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
- if (st->creatorid == creatorid) {
- st->sync_flags |= PFSTATE_FROMSYNC;
- pf_unlink_state(st);
- }
- }
- } else {
- if (pfi_kif_get(cp->ifname) == NULL) {
- splx(s);
- return;
+ offset += sizeof(*ph);
+ rv = (*pfsync4_acts[action])(&pkt, m, offset, count);
+ if (rv == -1)
+ return;
+
+done:
+ m_freem(m);
+}
+
+int
+pfsync4_in_clr(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct mbuf *mp;
+ int offp;
+
+ struct pfsync_state_clr *cp;
+ struct pf_state *nexts;
+ struct pf_state_key *sk, *nextsk;
+ struct pf_state_item *si;
+ struct pf_state *st;
+ struct pfi_kif *kif;
+ u_int32_t creatorid;
+ int s;
+
+ mp = m_pulldown(m, offset, sizeof(*cp), &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ cp = (struct pfsync_state_clr *)(mp->m_data + offp);
+
+ s = splsoftnet();
+ if (cp->ifname[0] == '\0') {
+ for (st = RB_MIN(pf_state_tree_id, &tree_id); st; st = nexts) {
+ nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
+ if (st->creatorid == creatorid) {
+ st->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(st);
}
- /* XXX correct? */
- for (sk = RB_MIN(pf_state_tree,
- &pf_statetbl); sk; sk = nextsk) {
- nextsk = RB_NEXT(pf_state_tree,
- &pf_statetbl, sk);
- TAILQ_FOREACH(si, &sk->states, entry) {
- if (si->s->creatorid == creatorid) {
- si->s->sync_flags |=
- PFSTATE_FROMSYNC;
- pf_unlink_state(si->s);
- }
+ }
+ } else if ((kif = pfi_kif_get(cp->ifname)) != NULL) {
+ /* XXX correct? */
+ for (sk = RB_MIN(pf_state_tree, &pf_statetbl);
+ sk; sk = nextsk) {
+ nextsk = RB_NEXT(pf_state_tree, &pf_statetbl, sk);
+ TAILQ_FOREACH(si, &sk->states, entry) {
+ if (si->s->creatorid == creatorid &&
+ si->s->kif == kif) {
+ si->s->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(si->s);
}
}
}
- splx(s);
-
- break;
}
- case PFSYNC_ACT_INS:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*sp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
+ splx(s);
- s = splsoftnet();
- for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
- i < count; i++, sp++) {
- /* check for invalid values */
- if (sp->timeout >= PFTM_MAX ||
- sp->src.state > PF_TCPS_PROXY_DST ||
- sp->dst.state > PF_TCPS_PROXY_DST ||
- sp->direction > PF_OUT ||
- (sp->af != AF_INET && sp->af != AF_INET6)) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_input: PFSYNC_ACT_INS: "
- "invalid value\n");
- pfsyncstats.pfsyncs_badval++;
- continue;
- }
+ return (sizeof(*cp));
+}
- if ((error = pfsync_state_import(sp, flags))) {
- if (error == ENOMEM) {
- splx(s);
- goto done;
- }
- continue;
+int
+pfsync4_in_ins(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct pfsync_state *sp, *spa;
+ int s;
+
+ struct mbuf *mp;
+ int len = count * sizeof(*sp);
+ int offp;
+ int i;
+
+ mp = m_pulldown(m, offset, len, &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ spa = (struct pfsync_state *)(mp->m_data + offp);
+
+ s = splsoftnet();
+ for (i = 0; i < count; i++) {
+ sp = &spa[i];
+
+ /* check for invalid values */
+ if (sp->timeout >= PFTM_MAX ||
+ sp->src.state > PF_TCPS_PROXY_DST ||
+ sp->dst.state > PF_TCPS_PROXY_DST ||
+ sp->direction > PF_OUT ||
+ (sp->af != AF_INET && sp->af != AF_INET6)) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pfsync_input: PFSYNC_ACT_INS: "
+ "invalid value\n");
}
+ pfsyncstats.pfsyncs_badval++;
+ continue;
}
- splx(s);
- break;
- case PFSYNC_ACT_UPD:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*sp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
+
+ if (pfsync_state_import(sp, pkt->flags) == ENOMEM) {
+ /* drop out */
+ break;
}
+ }
+ splx(s);
- s = splsoftnet();
- for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
- i < count; i++, sp++) {
- int flags = PFSYNC_FLAG_STALE;
-
- /* check for invalid values */
- if (sp->timeout >= PFTM_MAX ||
- sp->src.state > PF_TCPS_PROXY_DST ||
- sp->dst.state > PF_TCPS_PROXY_DST) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_input: PFSYNC_ACT_UPD: "
- "invalid value\n");
- pfsyncstats.pfsyncs_badval++;
- continue;
- }
+ return (len);
+}
+
+int
+pfsync4_in_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_state *sp, *spa;
+ struct pf_state_cmp id_key;
+ struct pf_state_key *sk;
+ struct pf_state *st;
+ int stale, sfail;
+ int flags;
+ int s;
- bcopy(sp->id, &id_key.id, sizeof(id_key.id));
- id_key.creatorid = sp->creatorid;
+ struct mbuf *mp;
+ int len = count * sizeof(*sp);
+ int offp;
+ int i;
+
+ mp = m_pulldown(m, offset, len, &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ spa = (struct pfsync_state *)(mp->m_data + offp);
- st = pf_find_state_byid(&id_key);
- if (st == NULL) {
- /* insert the update */
- if (pfsync_state_import(sp, flags))
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- sk = st->key[PF_SK_WIRE]; /* XXX right one? */
- sfail = 0;
- if (sk->proto == IPPROTO_TCP) {
- /*
- * The state should never go backwards except
- * for syn-proxy states. Neither should the
- * sequence window slide backwards.
- */
- if (st->src.state > sp->src.state &&
- (st->src.state < PF_TCPS_PROXY_SRC ||
- sp->src.state >= PF_TCPS_PROXY_SRC))
- sfail = 1;
- else if (SEQ_GT(st->src.seqlo,
- ntohl(sp->src.seqlo)))
- sfail = 3;
- else if (st->dst.state > sp->dst.state) {
- /* There might still be useful
- * information about the src state here,
- * so import that part of the update,
- * then "fail" so we send the updated
- * state back to the peer who is missing
- * our what we know. */
- pf_state_peer_ntoh(&sp->src, &st->src);
- /* XXX do anything with timeouts? */
- sfail = 7;
- flags = 0;
- } else if (st->dst.state >= TCPS_SYN_SENT &&
- SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
- sfail = 4;
- } else {
- /*
- * Non-TCP protocol state machine always go
- * forwards
- */
- if (st->src.state > sp->src.state)
- sfail = 5;
- else if (st->dst.state > sp->dst.state)
- sfail = 6;
- }
- if (sfail) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: %s stale update "
- "(%d) id: %016llx "
- "creatorid: %08x\n",
- (sfail < 7 ? "ignoring"
- : "partial"), sfail,
- betoh64(st->id),
- ntohl(st->creatorid));
- pfsyncstats.pfsyncs_stale++;
-
- if (!(sp->sync_flags & PFSTATE_STALE)) {
- /* we have a better state, send it */
- if (sc->sc_mbuf != NULL && !stale)
- pfsync_sendout(sc);
- stale++;
- if (!st->sync_flags)
- pfsync_pack_state(
- PFSYNC_ACT_UPD, st, flags);
- }
- continue;
+ s = splsoftnet();
+ for (i = 0; i < count; i++) {
+ sp = &spa[i];
+
+ flags = PFSYNC_FLAG_STALE;
+
+ /* check for invalid values */
+ if (sp->timeout >= PFTM_MAX ||
+ sp->src.state > PF_TCPS_PROXY_DST ||
+ sp->dst.state > PF_TCPS_PROXY_DST) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pfsync_input: PFSYNC_ACT_UPD: "
+ "invalid value\n");
}
- pfsync_alloc_scrub_memory(&sp->dst, &st->dst);
- pf_state_peer_ntoh(&sp->src, &st->src);
- pf_state_peer_ntoh(&sp->dst, &st->dst);
- st->expire = ntohl(sp->expire) + time_second;
- st->timeout = sp->timeout;
- }
- if (stale && sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
- splx(s);
- break;
- /*
- * It's not strictly necessary for us to support the "uncompressed"
- * delete action, but it's relatively simple and maintains consistency.
- */
- case PFSYNC_ACT_DEL:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*sp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
+ pfsyncstats.pfsyncs_badval++;
+ continue;
}
- s = splsoftnet();
- for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
- i < count; i++, sp++) {
- bcopy(sp->id, &id_key.id, sizeof(id_key.id));
- id_key.creatorid = sp->creatorid;
+ bcopy(sp->id, &id_key.id, sizeof(id_key.id));
+ id_key.creatorid = sp->creatorid;
- st = pf_find_state_byid(&id_key);
- if (st == NULL) {
+ st = pf_find_state_byid(&id_key);
+ if (st == NULL) {
+ /* insert the update */
+ if (pfsync_state_import(sp, flags))
pfsyncstats.pfsyncs_badstate++;
- continue;
+ continue;
+ }
+ sk = st->key[PF_SK_WIRE]; /* XXX right one? */
+
+ sfail = 0;
+ if (sk->proto == IPPROTO_TCP) {
+ /*
+ * The state should never go backwards except
+ * for syn-proxy states. Neither should the
+ * sequence window slide backwards.
+ */
+ if (st->src.state > sp->src.state &&
+ (st->src.state < PF_TCPS_PROXY_SRC ||
+ sp->src.state >= PF_TCPS_PROXY_SRC))
+ sfail = 1;
+ else if (SEQ_GT(st->src.seqlo, ntohl(sp->src.seqlo)))
+ sfail = 3;
+ else if (st->dst.state > sp->dst.state) {
+ /* There might still be useful
+ * information about the src state here,
+ * so import that part of the update,
+ * then "fail" so we send the updated
+ * state back to the peer who is missing
+ * our what we know. */
+ pf_state_peer_ntoh(&sp->src, &st->src);
+ /* XXX do anything with timeouts? */
+ sfail = 7;
+ flags = 0;
+ } else if (st->dst.state >= TCPS_SYN_SENT &&
+ SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
+ sfail = 4;
+ } else {
+ /*
+ * Non-TCP protocol state machine always go
+ * forwards
+ */
+ if (st->src.state > sp->src.state)
+ sfail = 5;
+ else if (st->dst.state > sp->dst.state)
+ sfail = 6;
+ }
+ if (sfail) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: %s stale update "
+ "(%d) id: %016llx "
+ "creatorid: %08x\n",
+ (sfail < 7 ? "ignoring"
+ : "partial"), sfail,
+ betoh64(st->id),
+ ntohl(st->creatorid));
+ pfsyncstats.pfsyncs_stale++;
+
+ if (!(sp->sync_flags & PFSTATE_STALE)) {
+ /* we have a better state, send it */
+ if (sc->sc_mbuf != NULL && !stale)
+ pfsync_sendout(sc);
+ stale++;
+ if (!st->sync_flags)
+ pfsync_pack_state( PFSYNC_ACT_UPD,
+ st, flags);
}
- st->sync_flags |= PFSTATE_FROMSYNC;
- pf_unlink_state(st);
+ continue;
}
- splx(s);
- break;
- case PFSYNC_ACT_UPD_C: {
- int update_requested = 0;
+ pfsync_alloc_scrub_memory(&sp->dst, &st->dst);
+ pf_state_peer_ntoh(&sp->src, &st->src);
+ pf_state_peer_ntoh(&sp->dst, &st->dst);
+ st->expire = ntohl(sp->expire) + time_second;
+ st->timeout = sp->timeout;
+ }
+ if (stale && sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+ splx(s);
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*up), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
+ return (len);
+}
+
+int
+pfsync4_in_del(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct pfsync_state *sp, *spa;
+ struct pf_state_cmp id_key;
+ struct pf_state *st;
+ int s;
+
+ struct mbuf *mp;
+ int len = count * sizeof(*sp);
+ int offp;
+ int i;
+
+ mp = m_pulldown(m, offset, len, &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ spa = (struct pfsync_state *)(mp->m_data + offp);
+
+ s = splsoftnet();
+ for (i = 0; i < count; i++) {
+ sp = &spa[i];
+
+ bcopy(sp->id, &id_key.id, sizeof(id_key.id));
+ id_key.creatorid = sp->creatorid;
+
+ st = pf_find_state_byid(&id_key);
+ if (st == NULL) {
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
}
+ st->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(st);
+ }
+ splx(s);
- s = splsoftnet();
- for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
- i < count; i++, up++) {
- /* check for invalid values */
- if (up->timeout >= PFTM_MAX ||
- up->src.state > PF_TCPS_PROXY_DST ||
- up->dst.state > PF_TCPS_PROXY_DST) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_input: "
- "PFSYNC_ACT_UPD_C: "
- "invalid value\n");
- pfsyncstats.pfsyncs_badval++;
- continue;
- }
+ return (len);
+}
- bcopy(up->id, &id_key.id, sizeof(id_key.id));
- id_key.creatorid = up->creatorid;
+int
+pfsync4_in_upd_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_state_upd *up, *upa;
+ struct pf_state_cmp id_key;
+ struct pf_state_key *sk;
+ struct pf_state *st;
+ int stale, sfail;
+ int update_requested;
+ int s;
- st = pf_find_state_byid(&id_key);
- if (st == NULL) {
- /* We don't have this state. Ask for it. */
- error = pfsync_request_update(up, &src);
- if (error == ENOMEM) {
- splx(s);
- goto done;
- }
+ struct mbuf *mp;
+ int len = count * sizeof(*up);
+ int offp;
+ int i;
+
+ mp = m_pulldown(m, offset, len, &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ upa = (struct pfsync_state_upd *)(mp->m_data + offp);
+
+ s = splnet();
+ for (i = 0; i < count; i++) {
+ up = &upa[i];
+
+ /* check for invalid values */
+ if (up->timeout >= PFTM_MAX ||
+ up->src.state > PF_TCPS_PROXY_DST ||
+ up->dst.state > PF_TCPS_PROXY_DST) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync_input: "
+ "PFSYNC_ACT_UPD_C: "
+ "invalid value\n");
+ pfsyncstats.pfsyncs_badval++;
+ continue;
+ }
+
+ bcopy(up->id, &id_key.id, sizeof(id_key.id));
+ id_key.creatorid = up->creatorid;
+
+ st = pf_find_state_byid(&id_key);
+ if (st == NULL) {
+ /* We don't have this state. Ask for it. */
+ switch (pfsync_request_update(up, &pkt->src)) {
+ case 0:
update_requested = 1;
+ break;
+ case ENOMEM:
+ break;
+ default:
pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- sk = st->key[PF_SK_WIRE]; /* XXX right one? */
- sfail = 0;
- if (sk->proto == IPPROTO_TCP) {
- /*
- * The state should never go backwards except
- * for syn-proxy states. Neither should the
- * sequence window slide backwards.
- */
- if (st->src.state > up->src.state &&
- (st->src.state < PF_TCPS_PROXY_SRC ||
- up->src.state >= PF_TCPS_PROXY_SRC))
- sfail = 1;
- else if (st->dst.state > up->dst.state)
- sfail = 2;
- else if (SEQ_GT(st->src.seqlo,
- ntohl(up->src.seqlo)))
- sfail = 3;
- else if (st->dst.state >= TCPS_SYN_SENT &&
- SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
- sfail = 4;
- } else {
- /*
- * Non-TCP protocol state machine always go
- * forwards
- */
- if (st->src.state > up->src.state)
- sfail = 5;
- else if (st->dst.state > up->dst.state)
- sfail = 6;
+ break;
}
- if (sfail) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: ignoring stale update "
- "(%d) id: %016llx "
- "creatorid: %08x\n", sfail,
- betoh64(st->id),
- ntohl(st->creatorid));
- pfsyncstats.pfsyncs_stale++;
-
- /* we have a better state, send it out */
- if ((!stale || update_requested) &&
- sc->sc_mbuf != NULL) {
- pfsync_sendout(sc);
- update_requested = 0;
- }
- stale++;
- if (!st->sync_flags)
- pfsync_pack_state(PFSYNC_ACT_UPD, st,
- PFSYNC_FLAG_STALE);
- continue;
+ continue;
+ }
+
+ sk = st->key[PF_SK_WIRE]; /* XXX right one? */
+ sfail = 0;
+ if (sk->proto == IPPROTO_TCP) {
+ /*
+ * The state should never go backwards except
+ * for syn-proxy states. Neither should the
+ * sequence window slide backwards.
+ */
+ if (st->src.state > up->src.state &&
+ (st->src.state < PF_TCPS_PROXY_SRC ||
+ up->src.state >= PF_TCPS_PROXY_SRC))
+ sfail = 1;
+ else if (st->dst.state > up->dst.state)
+ sfail = 2;
+ else if (SEQ_GT(st->src.seqlo, ntohl(up->src.seqlo)))
+ sfail = 3;
+ else if (st->dst.state >= TCPS_SYN_SENT &&
+ SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
+ sfail = 4;
+ } else {
+ /*
+ * Non-TCP protocol state machine always go
+ * forwards
+ */
+ if (st->src.state > up->src.state)
+ sfail = 5;
+ else if (st->dst.state > up->dst.state)
+ sfail = 6;
+ }
+ if (sfail) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: ignoring stale update "
+ "(%d) id: %016llx "
+ "creatorid: %08x\n", sfail,
+ betoh64(st->id),
+ ntohl(st->creatorid));
+ pfsyncstats.pfsyncs_stale++;
+
+ /* we have a better state, send it out */
+ if ((!stale || update_requested) &&
+ sc->sc_mbuf != NULL) {
+ pfsync_sendout(sc);
+ update_requested = 0;
}
- pfsync_alloc_scrub_memory(&up->dst, &st->dst);
- pf_state_peer_ntoh(&up->src, &st->src);
- pf_state_peer_ntoh(&up->dst, &st->dst);
- st->expire = ntohl(up->expire) + time_second;
- st->timeout = up->timeout;
+ stale++;
+ if (!st->sync_flags)
+ pfsync_pack_state(PFSYNC_ACT_UPD, st,
+ PFSYNC_FLAG_STALE);
+ continue;
}
- if ((update_requested || stale) && sc->sc_mbuf)
- pfsync_sendout(sc);
- splx(s);
- break;
+ pfsync_alloc_scrub_memory(&up->dst, &st->dst);
+ pf_state_peer_ntoh(&up->src, &st->src);
+ pf_state_peer_ntoh(&up->dst, &st->dst);
+ st->expire = ntohl(up->expire) + time_second;
+ st->timeout = up->timeout;
}
- case PFSYNC_ACT_DEL_C:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*dp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
+ if ((update_requested || stale) && sc->sc_mbuf)
+ pfsync_sendout(sc);
+ splx(s);
+
+ return (len);
+}
+
+int
+pfsync4_in_del_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct pfsync_state_del *dp, *dpa;
+ struct pf_state_cmp id_key;
+ struct pf_state *st;
+ int s;
+
+ struct mbuf *mp;
+ int len = count * sizeof(*dp);
+ int offp;
+ int i;
+
+ mp = m_pulldown(m, offset, len, &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ dpa = (struct pfsync_state_del *)(mp->m_data + offp);
+
+ s = splsoftnet();
+ for (i = 0; i < count; i++) {
+ dp = &dpa[i];
+
+ bcopy(dp->id, &id_key.id, sizeof(id_key.id));
+ id_key.creatorid = dp->creatorid;
+
+ st = pf_find_state_byid(&id_key);
+ if (st == NULL) {
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
}
+ st->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(st);
+ }
+ splx(s);
+
+ return (len);
+}
+
+int
+pfsync4_in_error(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ m_freem(m);
+ return (-1);
+}
+
+int
+pfsync4_in_ureq(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_state_upd_req *rup, *rupa;
+ struct pf_state_cmp id_key;
+ struct pf_state *st;
+ int s;
+
+ struct mbuf *mp;
+ int len = count * sizeof(*rup);
+ int offp;
+ int i;
+
+ mp = m_pulldown(m, offset, len, &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ rupa = (struct pfsync_state_upd_req *)(mp->m_data + offp);
+
+ s = splsoftnet();
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
- s = splsoftnet();
- for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
- i < count; i++, dp++) {
- bcopy(dp->id, &id_key.id, sizeof(id_key.id));
- id_key.creatorid = dp->creatorid;
+ for (i = 0; i < count; i++) {
+ rup = &rupa[i];
+ bcopy(rup->id, &id_key.id, sizeof(id_key.id));
+ id_key.creatorid = rup->creatorid;
+
+ if (id_key.id == 0 && id_key.creatorid == 0) {
+ sc->sc_ureq_received = time_uptime;
+ if (sc->sc_bulk_send_next == NULL)
+ sc->sc_bulk_send_next =
+ TAILQ_FIRST(&state_list);
+ sc->sc_bulk_terminator = sc->sc_bulk_send_next;
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received "
+ "bulk update request\n");
+ pfsync_send_bus(sc, PFSYNC_BUS_START);
+ timeout_add_sec(&sc->sc_bulk_tmo, 1);
+ } else {
st = pf_find_state_byid(&id_key);
if (st == NULL) {
pfsyncstats.pfsyncs_badstate++;
continue;
}
- st->sync_flags |= PFSTATE_FROMSYNC;
- pf_unlink_state(st);
- }
- splx(s);
- break;
- case PFSYNC_ACT_INS_F:
- case PFSYNC_ACT_DEL_F:
- /* not implemented */
- break;
- case PFSYNC_ACT_UREQ:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*rup), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
+ if (!st->sync_flags)
+ pfsync_pack_state(PFSYNC_ACT_UPD, st, 0);
}
+ }
- s = splsoftnet();
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
- for (i = 0,
- rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
- i < count; i++, rup++) {
- bcopy(rup->id, &id_key.id, sizeof(id_key.id));
- id_key.creatorid = rup->creatorid;
-
- if (id_key.id == 0 && id_key.creatorid == 0) {
- sc->sc_ureq_received = time_uptime;
- if (sc->sc_bulk_send_next == NULL)
- sc->sc_bulk_send_next =
- TAILQ_FIRST(&state_list);
- sc->sc_bulk_terminator = sc->sc_bulk_send_next;
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received "
- "bulk update request\n");
- pfsync_send_bus(sc, PFSYNC_BUS_START);
- timeout_add_sec(&sc->sc_bulk_tmo, 1);
- } else {
- st = pf_find_state_byid(&id_key);
- if (st == NULL) {
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- if (!st->sync_flags)
- pfsync_pack_state(PFSYNC_ACT_UPD,
- st, 0);
- }
- }
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
- splx(s);
- break;
- case PFSYNC_ACT_BUS:
- /* If we're not waiting for a bulk update, who cares. */
- if (sc->sc_ureq_sent == 0)
- break;
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+ splx(s);
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- sizeof(*bus), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
- bus = (struct pfsync_state_bus *)(mp->m_data + offp);
- switch (bus->status) {
- case PFSYNC_BUS_START:
- timeout_add(&sc->sc_bulkfail_tmo,
- pf_pool_limits[PF_LIMIT_STATES].limit /
- (PFSYNC_BULKPACKETS * sc->sc_maxcount));
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received bulk "
- "update start\n");
- break;
- case PFSYNC_BUS_END:
- if (time_uptime - ntohl(bus->endtime) >=
- sc->sc_ureq_sent) {
- /* that's it, we're happy */
- sc->sc_ureq_sent = 0;
- sc->sc_bulk_tries = 0;
- timeout_del(&sc->sc_bulkfail_tmo);
+ return (len);
+}
+
+int
+pfsync4_in_bus(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_state_bus *bus;
+
+ struct mbuf *mp;
+ int offp;
+
+ /* If we're not waiting for a bulk update, who cares. */
+ if (sc->sc_ureq_sent == 0)
+ return (sizeof(*bus));
+
+ mp = m_pulldown(m, offset, sizeof(*bus), &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
+ }
+ bus = (struct pfsync_state_bus *)(mp->m_data + offp);
+
+ switch (bus->status) {
+ case PFSYNC_BUS_START:
+ timeout_add(&sc->sc_bulkfail_tmo,
+ pf_pool_limits[PF_LIMIT_STATES].limit /
+ (PFSYNC_BULKPACKETS * sc->sc_maxcount));
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received bulk "
+ "update start\n");
+ break;
+ case PFSYNC_BUS_END:
+ if (time_uptime - ntohl(bus->endtime) >=
+ sc->sc_ureq_sent) {
+ /* that's it, we're happy */
+ sc->sc_ureq_sent = 0;
+ sc->sc_bulk_tries = 0;
+ timeout_del(&sc->sc_bulkfail_tmo);
#if NCARP > 0
- if (!pfsync_sync_ok)
- carp_group_demote_adj(&sc->sc_if, -1);
+ if (!pfsync_sync_ok)
+ carp_group_demote_adj(&sc->sc_if, -1);
#endif
- pfsync_sync_ok = 1;
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received valid "
- "bulk update end\n");
- } else {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received invalid "
- "bulk update end: bad timestamp\n");
- }
- break;
+ pfsync_sync_ok = 1;
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received valid "
+ "bulk update end\n");
+ } else {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received invalid "
+ "bulk update end: bad timestamp\n");
}
break;
+ }
+
+ return (sizeof(*bus));
+}
+
+int
+pfsync4_in_tdb_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset,
+ int count)
+{
+ struct pfsync_tdb *pt;
+ int len = count * sizeof(*pt);
+
#ifdef IPSEC
- case PFSYNC_ACT_TDB_UPD:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*pt), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
- s = splsoftnet();
- for (i = 0, pt = (struct pfsync_tdb *)(mp->m_data + offp);
- i < count; i++, pt++)
- pfsync_update_net_tdb(pt);
- splx(s);
- break;
-#endif
+ int s;
+
+ struct mbuf *mp;
+ int offp;
+ int i;
+
+ mp = m_pulldown(m, offset, len, &offp);
+ if (mp == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return (-1);
}
+ pt = (struct pfsync_tdb *)(mp->m_data + offp);
-done:
- if (m)
- m_freem(m);
+ s = splsoftnet();
+ for (i = 0; i < count; i++)
+ pfsync_update_net_tdb(&pt[i]);
+ splx(s);
+#endif
+
+ return (len);
}
int