carp: refactor packet tagging for ether_output()

- Separate HMAC preparation (CARP specific) from tagging.
- In unicast mode (CARP specific) don't put tag at all.
- Don't put pointer to software context into the tag.  Putting just vhid,
  an integer value, is a safer design.

Reviewed by:	kp
Differential Revision:	https://reviews.freebsd.org/D45038
This commit is contained in:
Gleb Smirnoff 2024-04-29 19:36:42 -07:00 committed by Kristof Provost
parent cda57d955b
commit 601438fbfa

View file

@ -1055,22 +1055,24 @@ carp_tag(struct carp_softc *sc, struct mbuf *m)
struct m_tag *mtag;
/* Tag packet for carp_output */
if ((mtag = m_tag_get(PACKET_TAG_CARP, sizeof(struct carp_softc *),
if ((mtag = m_tag_get(PACKET_TAG_CARP, sizeof(sc->sc_vhid),
M_NOWAIT)) == NULL) {
m_freem(m);
CARPSTATS_INC(carps_onomem);
return (ENOMEM);
}
bcopy(&sc, mtag + 1, sizeof(sc));
bcopy(&sc->sc_vhid, mtag + 1, sizeof(sc->sc_vhid));
m_tag_prepend(m, mtag);
return (0);
}
static int
static void
carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch)
{
MPASS(sc->sc_version == CARP_VERSION_CARP);
if (sc->sc_init_counter) {
/* this could also be seconds since unix epoch */
sc->sc_counter = arc4random();
@ -1083,8 +1085,6 @@ carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch)
ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff);
carp_hmac_generate(sc, ch->carp_counter, ch->carp_md);
return (carp_tag(sc, m));
}
static inline void
@ -1273,7 +1273,9 @@ carp_send_ad_locked(struct carp_softc *sc)
ch_ptr = (struct carp_header *)(&ip[1]);
bcopy(&ch, ch_ptr, sizeof(ch));
if (carp_prepare_ad(m, sc, ch_ptr))
carp_prepare_ad(m, sc, ch_ptr);
if (IN_MULTICAST(ntohl(sc->sc_carpaddr.s_addr)) &&
carp_tag(sc, m) != 0)
goto resched;
m->m_data += sizeof(*ip);
@ -1333,7 +1335,9 @@ carp_send_ad_locked(struct carp_softc *sc)
ch_ptr = (struct carp_header *)(&ip6[1]);
bcopy(&ch, ch_ptr, sizeof(ch));
if (carp_prepare_ad(m, sc, ch_ptr))
carp_prepare_ad(m, sc, ch_ptr);
if (IN6_IS_ADDR_MULTICAST(&sc->sc_carpaddr6) &&
carp_tag(sc, m) != 0)
goto resched;
m->m_data += sizeof(*ip6);
@ -2019,7 +2023,7 @@ int
carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
{
struct m_tag *mtag;
struct carp_softc *sc;
int vhid;
if (!sa)
return (0);
@ -2041,20 +2045,7 @@ carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
if (mtag == NULL)
return (0);
bcopy(mtag + 1, &sc, sizeof(sc));
switch (sa->sa_family) {
case AF_INET:
if (! IN_MULTICAST(ntohl(sc->sc_carpaddr.s_addr)))
return (0);
break;
case AF_INET6:
if (! IN6_IS_ADDR_MULTICAST(&sc->sc_carpaddr6))
return (0);
break;
default:
panic("Unknown af");
}
bcopy(mtag + 1, &vhid, sizeof(vhid));
/* Set the source MAC address to the Virtual Router MAC Address. */
switch (ifp->if_type) {
@ -2069,7 +2060,7 @@ carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
eh->ether_shost[2] = 0x5e;
eh->ether_shost[3] = 0;
eh->ether_shost[4] = 1;
eh->ether_shost[5] = sc->sc_vhid;
eh->ether_shost[5] = vhid;
}
break;
default: