diff options
-rw-r--r-- | sys/net/if_pfsync.c | 140 |
1 files changed, 80 insertions, 60 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c index fd84d3a3ba3..c6629152755 100644 --- a/sys/net/if_pfsync.c +++ b/sys/net/if_pfsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.138 2010/01/12 02:47:07 claudio Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.139 2010/01/12 10:21:38 dlg Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -114,22 +114,40 @@ int pfsync_in_eof(struct pfsync_pkt *, struct mbuf *, int, int); int pfsync_in_error(struct pfsync_pkt *, struct mbuf *, int, int); -int (*pfsync_acts[])(struct pfsync_pkt *, struct mbuf *, int, int) = { - pfsync_in_clr, /* PFSYNC_ACT_CLR */ - pfsync_in_error, /* PFSYNC_ACT_OINS */ - pfsync_in_iack, /* PFSYNC_ACT_INS_ACK */ - pfsync_in_error, /* PFSYNC_ACT_OUPD */ - pfsync_in_upd_c, /* PFSYNC_ACT_UPD_C */ - pfsync_in_ureq, /* PFSYNC_ACT_UPD_REQ */ - pfsync_in_del, /* PFSYNC_ACT_DEL */ - pfsync_in_del_c, /* PFSYNC_ACT_DEL_C */ - pfsync_in_error, /* PFSYNC_ACT_INS_F */ - pfsync_in_error, /* PFSYNC_ACT_DEL_F */ - pfsync_in_bus, /* PFSYNC_ACT_BUS */ - pfsync_in_tdb, /* PFSYNC_ACT_TDB */ - pfsync_in_eof, /* PFSYNC_ACT_EOF */ - pfsync_in_ins, /* PFSYNC_ACT_INS */ - pfsync_in_upd /* PFSYNC_ACT_UPD */ +struct { + int (*in)(struct pfsync_pkt *, struct mbuf *, int, int); + size_t len; +} pfsync_acts[] = { + /* PFSYNC_ACT_CLR */ + { pfsync_in_clr, sizeof(struct pfsync_clr) }, + /* PFSYNC_ACT_OINS */ + { pfsync_in_error, 0 }, + /* PFSYNC_ACT_INS_ACK */ + { pfsync_in_iack, sizeof(struct pfsync_ins_ack) }, + /* PFSYNC_ACT_OUPD */ + { pfsync_in_error, 0 }, + /* PFSYNC_ACT_UPD_C */ + { pfsync_in_upd_c, sizeof(struct pfsync_upd_c) }, + /* PFSYNC_ACT_UPD_REQ */ + { pfsync_in_ureq, sizeof(struct pfsync_upd_req) }, + /* PFSYNC_ACT_DEL */ + { pfsync_in_del, sizeof(struct pfsync_state) }, + /* PFSYNC_ACT_DEL_C */ + { pfsync_in_del_c, sizeof(struct pfsync_del_c) }, + /* PFSYNC_ACT_INS_F */ + { pfsync_in_error, 0 }, + /* PFSYNC_ACT_DEL_F */ + { pfsync_in_error, 0 }, + /* PFSYNC_ACT_BUS */ + { pfsync_in_bus, sizeof(struct pfsync_bus) }, + /* PFSYNC_ACT_TDB */ + { pfsync_in_tdb, sizeof(struct pfsync_tdb) }, + /* PFSYNC_ACT_EOF */ + { pfsync_in_eof, 0 }, + /* PFSYNC_ACT_INS */ + { pfsync_in_ins, sizeof(struct pfsync_state) }, + /* PFSYNC_ACT_UPD */ + { pfsync_in_upd, sizeof(struct pfsync_state) } }; struct pfsync_q { @@ -335,6 +353,9 @@ pfsync_clone_destroy(struct ifnet *ifp) if (!pfsync_sync_ok) carp_group_demote_adj(&sc->sc_if, -1); #endif +#if NBPFILTER > 0 + bpfdetach(ifp); +#endif if_detach(ifp); pfsync_drop(sc); @@ -625,8 +646,7 @@ pfsync_input(struct mbuf *m, ...) struct pfsync_header *ph; struct pfsync_subheader subh; - int offset, len; - int rv; + int offset, len, count, mlen; pfsyncstats.pfsyncs_ipackets++; @@ -689,18 +709,30 @@ pfsync_input(struct mbuf *m, ...) m_copydata(m, offset, sizeof(subh), (caddr_t)&subh); offset += sizeof(subh); + mlen = subh.len << 2; + count = ntohs(subh.count); + if (subh.action >= PFSYNC_ACT_MAX || - subh.action >= nitems(pfsync_acts)) { + subh.action >= nitems(pfsync_acts) || + mlen < pfsync_acts[subh.action].len) { + /* + * subheaders are always followed by at least one + * message (except for EOF), so if the peer is new + * enough to tell us how big its messages are then we + * know enough to skip them. + */ + if (count > 0 && mlen > 0) { + offset += count * mlen; + continue; + } pfsyncstats.pfsyncs_badact++; goto done; } - rv = (*pfsync_acts[subh.action])(&pkt, m, offset, - ntohs(subh.count)); - if (rv == -1) + if (pfsync_acts[subh.action].in(&pkt, m, offset, count) == -1) return; - offset += rv; + offset += mlen * count; } done: @@ -712,7 +744,6 @@ pfsync_in_clr(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) { struct pfsync_clr *clr; struct mbuf *mp; - int len = sizeof(*clr) * count; int i, offp; struct pf_state *st, *nexts; @@ -721,7 +752,7 @@ pfsync_in_clr(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) u_int32_t creatorid; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, sizeof(*clr) * count, &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -762,7 +793,7 @@ pfsync_in_clr(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } splx(s); - return (len); + return (0); } int @@ -770,12 +801,11 @@ pfsync_in_ins(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) { struct mbuf *mp; struct pfsync_state *sa, *sp; - int len = sizeof(*sp) * count; int i, offp; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, sizeof(*sp) * count, &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -807,7 +837,7 @@ pfsync_in_ins(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } splx(s); - return (len); + return (0); } int @@ -818,11 +848,10 @@ pfsync_in_iack(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) struct pf_state *st; struct mbuf *mp; - int len = count * sizeof(*ia); int offp, i; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(*ia), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -845,7 +874,7 @@ pfsync_in_iack(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } splx(s); - return (len); + return (0); } int @@ -889,11 +918,10 @@ pfsync_in_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) int sync; struct mbuf *mp; - int len = count * sizeof(*sp); int offp, i; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(*sp), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -967,7 +995,7 @@ pfsync_in_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } splx(s); - return (len); + return (0); } int @@ -977,14 +1005,13 @@ pfsync_in_upd_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) struct pf_state_cmp id_key; struct pf_state *st; - int len = count * sizeof(*up); int sync; struct mbuf *mp; int offp, i; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(*up), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -1056,7 +1083,7 @@ pfsync_in_upd_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } splx(s); - return (len); + return (0); } int @@ -1064,13 +1091,12 @@ pfsync_in_ureq(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) { struct pfsync_upd_req *ur, *ura; struct mbuf *mp; - int len = count * sizeof(*ur); int i, offp; struct pf_state_cmp id_key; struct pf_state *st; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(*ur), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -1098,7 +1124,7 @@ pfsync_in_ureq(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } } - return (len); + return (0); } int @@ -1108,11 +1134,10 @@ pfsync_in_del(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) struct pfsync_state *sa, *sp; struct pf_state_cmp id_key; struct pf_state *st; - int len = count * sizeof(*sp); int offp, i; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(*sp), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -1136,7 +1161,7 @@ pfsync_in_del(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } splx(s); - return (len); + return (0); } int @@ -1146,11 +1171,10 @@ pfsync_in_del_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) struct pfsync_del_c *sa, *sp; struct pf_state_cmp id_key; struct pf_state *st; - int len = count * sizeof(*sp); int offp, i; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(*sp), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -1175,7 +1199,7 @@ pfsync_in_del_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) } splx(s); - return (len); + return (0); } int @@ -1184,14 +1208,13 @@ pfsync_in_bus(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) struct pfsync_softc *sc = pfsyncif; struct pfsync_bus *bus; struct mbuf *mp; - int len = count * sizeof(*bus); int offp; /* If we're not waiting for a bulk update, who cares. */ if (sc->sc_ureq_sent == 0) - return (len); + return (0); - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(*bus), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -1231,14 +1254,12 @@ pfsync_in_bus(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) break; } - return (len); + return (0); } int pfsync_in_tdb(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) { - int len = count * sizeof(struct pfsync_tdb); - #if defined(IPSEC) struct pfsync_tdb *tp; struct mbuf *mp; @@ -1246,7 +1267,7 @@ pfsync_in_tdb(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) int i; int s; - mp = m_pulldown(m, offset, len, &offp); + mp = m_pulldown(m, offset, count * sizeof(struct pfsync_tdb), &offp); if (mp == NULL) { pfsyncstats.pfsyncs_badlen++; return (-1); @@ -1259,7 +1280,7 @@ pfsync_in_tdb(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) splx(s); #endif - return (len); + return (0); } #if defined(IPSEC) @@ -1312,9 +1333,8 @@ pfsync_in_eof(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) if (offset != m->m_pkthdr.len) pfsyncstats.pfsyncs_badlen++; - /* we're done. free and let the caller return */ - m_freem(m); - return (-1); + /* we're done. let the caller return */ + return (0); } int @@ -1731,7 +1751,7 @@ pfsync_sendout(void) bzero(subh, sizeof(*subh)); subh->action = PFSYNC_ACT_EOF; subh->len = 0 >> 2; - subh->count = htons(1); + subh->count = htons(0); /* we're done, let's put it on the wire */ #if NBPFILTER > 0 |