Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163275553
D23475.id67677.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D23475.id67677.diff
View Options
Index: /usr/src/sys/netinet/ip_carp.h
===================================================================
--- /usr/src/sys/netinet/ip_carp.h
+++ /usr/src/sys/netinet/ip_carp.h
@@ -92,6 +92,8 @@
#define CARP_KEY_LEN 20 /* a sha1 hash of a passphrase */
+#define CARP_AUTHLEN 7
+
/* carp_advbase */
#define CARP_DFLTINTV 1
@@ -110,6 +112,7 @@
uint64_t carps_badauth; /* bad authentication */
uint64_t carps_badvhid; /* bad VHID */
uint64_t carps_badaddrs; /* bad address list */
+ uint64_t carps_dups; /* duplicate packets */
uint64_t carps_opackets; /* total output packets, IPv4 */
uint64_t carps_opackets6; /* total output packets, IPv6 */
Index: /usr/src/sys/netinet/ip_carp.c
===================================================================
--- /usr/src/sys/netinet/ip_carp.c
+++ /usr/src/sys/netinet/ip_carp.c
@@ -115,7 +115,6 @@
int sc_sendad_success;
#define CARP_SENDAD_MIN_SUCCESS 3
- int sc_init_counter;
uint64_t sc_counter;
/* authentication */
@@ -416,7 +415,7 @@
/* fetch first half of inner hash */
bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx));
- SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter));
+ SHA1Update(&sha1ctx, (void *)counter, (sizeof(uint32_t) * 2));
SHA1Final(md, &sha1ctx);
/* outer hash */
@@ -594,110 +593,48 @@
}
#endif /* INET6 */
-/*
- * This routine should not be necessary at all, but some switches
- * (VMWare ESX vswitches) can echo our own packets back at us,
- * and we must ignore them or they will cause us to drop out of
- * MASTER mode.
- *
- * We cannot catch all cases of network loops. Instead, what we
- * do here is catch any packet that arrives with a carp header
- * with a VHID of 0, that comes from an address that is our own.
- * These packets are by definition "from us" (even if they are from
- * a misconfigured host that is pretending to be us).
- *
- * The VHID test is outside this mini-function.
- */
-static int
-carp_source_is_self(struct mbuf *m, struct ifaddr *ifa, sa_family_t af)
-{
-#ifdef INET
- struct ip *ip4;
- struct in_addr in4;
-#endif
-#ifdef INET6
- struct ip6_hdr *ip6;
- struct in6_addr in6;
-#endif
-
- switch (af) {
-#ifdef INET
- case AF_INET:
- ip4 = mtod(m, struct ip *);
- in4 = ifatoia(ifa)->ia_addr.sin_addr;
- return (in4.s_addr == ip4->ip_src.s_addr);
-#endif
-#ifdef INET6
- case AF_INET6:
- ip6 = mtod(m, struct ip6_hdr *);
- in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
- return (memcmp(&in6, &ip6->ip6_src, sizeof(in6)) == 0);
-#endif
- default:
- break;
- }
- return (0);
-}
-
static void
carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
{
struct ifnet *ifp = m->m_pkthdr.rcvif;
- struct ifaddr *ifa, *match;
+ struct ifaddr *ifa;
struct carp_softc *sc;
uint64_t tmp_counter;
struct timeval sc_tv, ch_tv;
- int error;
- /*
- * Verify that the VHID is valid on the receiving interface.
- *
- * There should be just one match. If there are none
- * the VHID is not valid and we drop the packet. If
- * there are multiple VHID matches, take just the first
- * one, for compatibility with previous code. While we're
- * scanning, check for obvious loops in the network topology
- * (these should never happen, and as noted above, we may
- * miss real loops; this is just a double-check).
- */
- IF_ADDR_RLOCK(ifp);
- error = 0;
- match = NULL;
- IFNET_FOREACH_IFA(ifp, ifa) {
- if (match == NULL && ifa->ifa_carp != NULL &&
- ifa->ifa_addr->sa_family == af &&
- ifa->ifa_carp->sc_vhid == ch->carp_vhid)
- match = ifa;
- if (ch->carp_vhid == 0 && carp_source_is_self(m, ifa, af))
- error = ELOOP;
- }
- ifa = error ? NULL : match;
- if (ifa != NULL)
- ifa_ref(ifa);
- IF_ADDR_RUNLOCK(ifp);
-
- if (ifa == NULL) {
- if (error == ELOOP) {
- CARP_DEBUG("dropping looped packet on interface %s\n",
- ifp->if_xname);
- CARPSTATS_INC(carps_badif); /* ??? */
- } else {
- CARPSTATS_INC(carps_badvhid);
- }
+ /* Is VHID valid? */
+ if (ch->carp_vhid == 0) {
+ CARP_DEBUG("%s: invalid VHID: 0@%s\n", __func__,
+ ifp->if_xname);
+err_badvhid:
+ CARPSTATS_INC(carps_badvhid);
m_freem(m);
return;
}
-
- /* verify the CARP version. */
- if (ch->carp_version != CARP_VERSION) {
+ /* Verify the CARP version. */
+ if (ch->carp_version != CARP_VERSION ||
+ ch->carp_authlen != CARP_AUTHLEN) {
CARPSTATS_INC(carps_badver);
- CARP_DEBUG("%s: invalid version %d\n", ifp->if_xname,
- ch->carp_version);
- ifa_free(ifa);
m_freem(m);
+ CARP_DEBUG("%s: invalid version %d at %s\n", __func__,
+ ch->carp_version, ifp->if_xname);
return;
}
+ /* Verify that the VHID is valid on the receiving interface. */
+ IF_ADDR_RLOCK(ifp);
+ IFNET_FOREACH_IFA(ifp, ifa) {
+ if (ifa->ifa_addr->sa_family == af &&
+ ifa->ifa_carp != NULL &&
+ ifa->ifa_carp->sc_vhid == ch->carp_vhid) {
+ ifa_ref(ifa);
+ break;
+ }
+ }
+ IF_ADDR_RUNLOCK(ifp);
+ if (ifa == NULL)
+ goto err_badvhid;
+
sc = ifa->ifa_carp;
CARP_LOCK(sc);
ifa_free(ifa);
@@ -714,8 +651,12 @@
tmp_counter += ntohl(ch->carp_counter[1]);
/* XXX Replay protection goes here */
-
- sc->sc_init_counter = 0;
+ if (sc->sc_counter == tmp_counter) {
+ CARPSTATS_INC(carps_dups);
+ CARP_DEBUG("%s: dropping duplicated packet for VHID %u@%s\n",
+ __func__, sc->sc_vhid, ifp->if_xname);
+ goto out;
+ }
sc->sc_counter = tmp_counter;
sc_tv.tv_sec = sc->sc_advbase;
@@ -780,14 +721,7 @@
{
struct m_tag *mtag;
- if (sc->sc_init_counter) {
- /* this could also be seconds since unix epoch */
- sc->sc_counter = arc4random();
- sc->sc_counter = sc->sc_counter << 32;
- sc->sc_counter += arc4random();
- } else
- sc->sc_counter++;
-
+ sc->sc_counter++;
ch->carp_counter[0] = htonl((sc->sc_counter>>32)&0xffffffff);
ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff);
@@ -920,7 +854,7 @@
ch.carp_vhid = sc->sc_vhid;
ch.carp_advbase = sc->sc_advbase;
ch.carp_advskew = advskew;
- ch.carp_authlen = 7; /* XXX DEFINE */
+ ch.carp_authlen = CARP_AUTHLEN;
ch.carp_pad1 = 0; /* must be zero */
ch.carp_cksum = 0;
@@ -1569,8 +1503,11 @@
sc->sc_advbase = CARP_DFLTINTV;
sc->sc_vhid = -1; /* required setting */
- sc->sc_init_counter = 1;
sc->sc_state = INIT;
+ /* this could also be seconds since unix epoch */
+ sc->sc_counter = arc4random();
+ sc->sc_counter = sc->sc_counter << 32;
+ sc->sc_counter += arc4random();
sc->sc_ifasiz = sizeof(struct ifaddr *);
sc->sc_ifas = malloc(sc->sc_ifasiz, M_CARP, M_WAITOK|M_ZERO);
@@ -2028,7 +1965,7 @@
const char *carp_states[] = { CARP_STATES };
char subsys[IFNAMSIZ+5];
- snprintf(subsys, IFNAMSIZ+5, "%u@%s", sc->sc_vhid,
+ snprintf(subsys, sizeof(subsys), "%u@%s", sc->sc_vhid,
sc->sc_carpdev->if_xname);
CARP_LOG("%s: %s -> %s (%s)\n", subsys,
Index: /usr/src/usr.bin/netstat/inet.c
===================================================================
--- /usr/src/usr.bin/netstat/inet.c
+++ /usr/src/usr.bin/netstat/inet.c
@@ -907,6 +907,8 @@
"{N:/packet%s received (IPv4)}\n");
p(carps_ipackets6, "\t{:received-inet6-packets/%ju} "
"{N:/packet%s received (IPv6)}\n");
+ p(carps_badif, "\t\t{:dropped-bad-if/%ju} "
+ "{N:/packet%s discarded for wrong interface}\n");
p(carps_badttl, "\t\t{:dropped-wrong-ttl/%ju} "
"{N:/packet%s discarded for wrong TTL}\n");
p(carps_hdrops, "\t\t{:dropped-short-header/%ju} "
@@ -923,6 +925,8 @@
"{N:/discarded for bad vhid}\n");
p2(carps_badaddrs, "\t\t{:dropped-bad-address-list/%ju} "
"{N:/discarded because of a bad address list}\n");
+ p2(carps_dups, "\t\t{:dropped-duplicates/%ju} "
+ "{N:/discarded because packet is duplicate}\n");
p(carps_opackets, "\t{:sent-inet-packets/%ju} "
"{N:/packet%s sent (IPv4)}\n");
p(carps_opackets6, "\t{:sent-inet6-packets/%ju} "
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jul 22, 3:57 PM (3 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35329056
Default Alt Text
D23475.id67677.diff (7 KB)
Attached To
Mode
D23475: CARP: proper loopback detection and few improvements
Attached
Detach File
Event Timeline
Log In to Comment