40#include <sys/devctl.h>
42#include <sys/kernel.h>
43#include <sys/limits.h>
44#include <sys/malloc.h>
46#include <sys/module.h>
49#include <sys/protosw.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52#include <sys/sysctl.h>
53#include <sys/syslog.h>
54#include <sys/taskqueue.h>
55#include <sys/counter.h>
57#include <net/ethernet.h>
59#include <net/if_var.h>
61#include <net/if_llatbl.h>
62#include <net/if_types.h>
66#if defined(INET) || defined(INET6)
71#include <machine/in_cksum.h>
81#include <netinet6/in6_var.h>
82#include <netinet6/ip6_var.h>
83#include <netinet6/scope6_var.h>
84#include <netinet6/nd6.h>
87#include <crypto/sha1.h>
97 struct callout sc_md_tmo;
100 struct callout sc_md6_tmo;
114#define CARP_SENDAD_MAX_ERRORS 3
116#define CARP_SENDAD_MIN_SUCCESS 3
122#define CARP_HMAC_PAD 64
140 struct ip_moptions cif_imo;
143 struct ip6_moptions cif_im6o;
145 struct ifnet *cif_ifp;
148#define CIF_PROMISC 0x00000001
191#define V_carp_allow VNET(carp_allow)
195#define V_carp_dscp VNET(carp_dscp)
199#define V_carp_preempt VNET(carp_preempt)
203#define V_carp_log VNET(carp_log)
207#define V_carp_demotion VNET(carp_demotion)
211#define V_carp_senderr_adj VNET(carp_senderr_adj)
215#define V_carp_ifdown_adj VNET(carp_ifdown_adj)
221SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
224 CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
226 "Accept incoming CARP packets");
228 CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
230 "DSCP value for carp packets");
231SYSCTL_INT(_net_inet_carp, OID_AUTO, preempt, CTLFLAG_VNET | CTLFLAG_RW,
232 &VNET_NAME(carp_preempt), 0,
"High-priority backup preemption mode");
233SYSCTL_INT(_net_inet_carp, OID_AUTO, log, CTLFLAG_VNET | CTLFLAG_RW,
234 &VNET_NAME(carp_log), 0,
"CARP log level");
236 CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
238 "Adjust demotion factor (skew of advskew)");
240 CTLFLAG_VNET | CTLFLAG_RW,
241 &VNET_NAME(carp_senderr_adj), 0,
"Send error demotion factor adjustment");
243 CTLFLAG_VNET | CTLFLAG_RW,
244 &VNET_NAME(carp_ifdown_adj), 0,
245 "Interface down demotion factor adjustment");
251#define CARPSTATS_ADD(name, val) \
252 counter_u64_add(VNET(carpstats)[offsetof(struct carpstats, name) / \
253 sizeof(uint64_t)], (val))
254#define CARPSTATS_INC(name) CARPSTATS_ADD(name, 1)
257 carpstats,
"CARP statistics (struct carpstats, netinet/ip_carp.h)");
259#define CARP_LOCK_INIT(sc) mtx_init(&(sc)->sc_mtx, "carp_softc", \
261#define CARP_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
262#define CARP_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
263#define CARP_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
264#define CARP_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
265#define CIF_LOCK_INIT(cif) mtx_init(&(cif)->cif_mtx, "carp_if", \
267#define CIF_LOCK_DESTROY(cif) mtx_destroy(&(cif)->cif_mtx)
268#define CIF_LOCK_ASSERT(cif) mtx_assert(&(cif)->cif_mtx, MA_OWNED)
269#define CIF_LOCK(cif) mtx_lock(&(cif)->cif_mtx)
270#define CIF_UNLOCK(cif) mtx_unlock(&(cif)->cif_mtx)
271#define CIF_FREE(cif) do { \
273 if (TAILQ_EMPTY(&(cif)->cif_vrs)) \
279#define CARP_LOG(...) do { \
280 if (V_carp_log > 0) \
281 log(LOG_INFO, "carp: " __VA_ARGS__); \
284#define CARP_DEBUG(...) do { \
285 if (V_carp_log > 1) \
286 log(LOG_DEBUG, __VA_ARGS__); \
289#define IFNET_FOREACH_IFA(ifp, ifa) \
290 CK_STAILQ_FOREACH((ifa), &(ifp)->if_addrhead, ifa_link) \
291 if ((ifa)->ifa_carp != NULL)
293#define CARP_FOREACH_IFA(sc, ifa) \
294 CARP_LOCK_ASSERT(sc); \
296 _i < (sc)->sc_naddrs + (sc)->sc_naddrs6 && \
297 ((ifa) = sc->sc_ifas[_i]) != NULL; \
300#define IFNET_FOREACH_CARP(ifp, sc) \
301 KASSERT(mtx_owned(&ifp->if_carp->cif_mtx) || \
302 sx_xlocked(&carp_sx), ("cif_vrs not locked")); \
303 TAILQ_FOREACH((sc), &(ifp)->if_carp->cif_vrs, sc_list)
305#define DEMOTE_ADVSKEW(sc) \
306 (((sc)->sc_advskew + V_carp_demotion > CARP_MAXSKEW) ? \
308 (((sc)->sc_advskew + V_carp_demotion < 0) ? \
309 0 : ((sc)->sc_advskew + V_carp_demotion)))
334static struct mtx carp_mtx;
335static struct sx carp_sx;
336static struct task carp_sendall_task =
350 struct in6_addr last6, cur6, in6;
358 for (i = 0; i <
sizeof(sc->
sc_pad); i++)
364 SHA1Update(&sc->
sc_sha1, (
void *)&version,
sizeof(version));
365 SHA1Update(&sc->
sc_sha1, (
void *)&type,
sizeof(type));
366 SHA1Update(&sc->
sc_sha1, (
void *)&vhid,
sizeof(vhid));
372 cur.s_addr = 0xffffffff;
374 in.s_addr =
ifatoia(ifa)->ia_addr.sin_addr.s_addr;
375 if (ifa->ifa_addr->sa_family == AF_INET &&
376 ntohl(in.s_addr) > ntohl(last.s_addr) &&
377 ntohl(in.s_addr) < ntohl(cur.s_addr)) {
378 cur.s_addr = in.s_addr;
383 SHA1Update(&sc->
sc_sha1, (
void *)&cur,
sizeof(cur));
387 memset(&cur6, 0,
sizeof(cur6));
391 memset(&cur6, 0xff,
sizeof(cur6));
393 in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
394 if (IN6_IS_SCOPE_EMBED(&in6))
395 in6.s6_addr16[1] = 0;
396 if (ifa->ifa_addr->sa_family == AF_INET6 &&
397 memcmp(&in6, &last6,
sizeof(in6)) > 0 &&
398 memcmp(&in6, &cur6,
sizeof(in6)) < 0) {
404 SHA1Update(&sc->
sc_sha1, (
void *)&cur6,
sizeof(cur6));
409 for (i = 0; i <
sizeof(sc->
sc_pad); i++)
410 sc->
sc_pad[i] ^= 0x36 ^ 0x5c;
415 unsigned char md[20])
422 bcopy(&sc->
sc_sha1, &sha1ctx,
sizeof(sha1ctx));
424 SHA1Update(&sha1ctx, (
void *)counter,
sizeof(sc->
sc_counter));
425 SHA1Final(md, &sha1ctx);
430 SHA1Update(&sha1ctx, md, 20);
431 SHA1Final(md, &sha1ctx);
436 unsigned char md[20])
438 unsigned char md2[20];
444 return (bcmp(md, md2,
sizeof(md2)));
454carp_input(
struct mbuf **mp,
int *offp,
int proto)
456 struct mbuf *m = *mp;
457 struct ip *
ip = mtod(m,
struct ip *);
468 return (IPPROTO_DONE);
474 CARP_DEBUG(
"%s: received ttl %d != 255 on %s\n", __func__,
476 m->m_pkthdr.rcvif->if_xname);
478 return (IPPROTO_DONE);
483 if (m->m_pkthdr.len < iplen +
sizeof(*ch)) {
485 CARP_DEBUG(
"%s: received len %zd < sizeof(struct carp_header) "
486 "on %s\n", __func__, m->m_len -
sizeof(
struct ip),
487 m->m_pkthdr.rcvif->if_xname);
489 return (IPPROTO_DONE);
492 if (iplen +
sizeof(*ch) < m->m_len) {
493 if ((m = m_pullup(m, iplen +
sizeof(*ch))) == NULL) {
496 return (IPPROTO_DONE);
498 ip = mtod(m,
struct ip *);
506 len = iplen +
sizeof(*ch);
507 if (len > m->m_pkthdr.len) {
509 CARP_DEBUG(
"%s: packet too short %d on %s\n", __func__,
511 m->m_pkthdr.rcvif->if_xname);
513 return (IPPROTO_DONE);
516 if ((m = m_pullup(m, len)) == NULL) {
518 return (IPPROTO_DONE);
520 ip = mtod(m,
struct ip *);
525 if (in_cksum(m, len - iplen)) {
527 CARP_DEBUG(
"%s: checksum failed on %s\n", __func__,
528 m->m_pkthdr.rcvif->if_xname);
530 return (IPPROTO_DONE);
535 return (IPPROTO_DONE);
543 struct mbuf *m = *mp;
552 return (IPPROTO_DONE);
556 if (m->m_pkthdr.rcvif->if_carp == NULL) {
558 CARP_DEBUG(
"%s: packet received on non-carp interface: %s\n",
559 __func__, m->m_pkthdr.rcvif->if_xname);
561 return (IPPROTO_DONE);
567 CARP_DEBUG(
"%s: received ttl %d != 255 on %s\n", __func__,
568 ip6->ip6_hlim, m->m_pkthdr.rcvif->if_xname);
570 return (IPPROTO_DONE);
574 if (m->m_len < *offp +
sizeof(*ch)) {
576 m = m_pullup(m, *offp +
sizeof(*ch));
579 CARP_DEBUG(
"%s: packet size %u too small\n", __func__, len);
580 return (IPPROTO_DONE);
583 ch = (
struct carp_header *)(mtod(m,
char *) + *offp);
587 if (in_cksum(m,
sizeof(*ch))) {
589 CARP_DEBUG(
"%s: checksum failed, on %s\n", __func__,
590 m->m_pkthdr.rcvif->if_xname);
592 return (IPPROTO_DONE);
597 return (IPPROTO_DONE);
630 ip4 = mtod(m,
struct ip *);
631 in4 =
ifatoia(ifa)->ia_addr.sin_addr;
632 return (in4.
s_addr == ip4->ip_src.s_addr);
636 ip6 = mtod(m,
struct ip6_hdr *);
637 in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
638 return (memcmp(&in6, &ip6->
ip6_src,
sizeof(in6)) == 0);
649 struct ifnet *ifp = m->m_pkthdr.rcvif;
650 struct ifaddr *ifa, *match;
652 uint64_t tmp_counter;
653 struct timeval sc_tv, ch_tv;
672 if (match == NULL && ifa->ifa_carp != NULL &&
673 ifa->ifa_addr->sa_family == af &&
679 ifa = error ? NULL : match;
684 if (error == ELOOP) {
685 CARP_DEBUG(
"dropping looped packet on interface %s\n",
698 CARP_DEBUG(
"%s: invalid version %d\n", ifp->if_xname,
711 CARP_DEBUG(
"%s: incorrect hash for VHID %u@%s\n", __func__,
717 tmp_counter = tmp_counter<<32;
738 if (timevalcmp(&sc_tv, &ch_tv, >) ||
739 timevalcmp(&sc_tv, &ch_tv, ==)) {
742 "more frequent advertisement received");
754 "preempting a slower master");
764 if (timevalcmp(&sc_tv, &ch_tv, <)) {
801 if ((mtag = m_tag_get(PACKET_TAG_CARP,
sizeof(
struct carp_softc *),
802 M_NOWAIT)) == NULL) {
807 bcopy(&sc, mtag + 1,
sizeof(sc));
808 m_tag_prepend(m, mtag);
821 struct epoch_tracker et;
825 LIST_FOREACH(sc, &carp_list, sc_next)
833 mtx_unlock(&carp_mtx);
842 struct epoch_tracker et;
868 static const char fmt[] =
"send error %d on %s";
869 char msg[
sizeof(fmt) + IFNAMSIZ];
871 sprintf(msg, fmt, error, sc->
sc_carpdev->if_xname);
878 static const char fmt[] =
"send ok on %s";
879 char msg[
sizeof(fmt) + IFNAMSIZ];
899static struct ifaddr *
902 struct ifaddr *ifa, *best;
909 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
910 if (ifa->ifa_addr->sa_family == af &&
911 (best == NULL || ifa_preferred(best, ifa)))
934 tv.tv_usec = advskew * 1000000 / 256;
951 m = m_gethdr(M_NOWAIT, MT_DATA);
956 len =
sizeof(*ip) +
sizeof(ch);
957 m->m_pkthdr.len = len;
958 m->m_pkthdr.rcvif = NULL;
960 M_ALIGN(m, m->m_len);
961 m->m_flags |= M_MCAST;
962 ip = mtod(m,
struct ip *);
976 ifatoia(ifa)->ia_addr.sin_addr.s_addr;
979 ip->ip_src.s_addr = 0;
983 bcopy(&ch, ch_ptr,
sizeof(ch));
987 m->m_data +=
sizeof(*ip);
989 m->m_data -=
sizeof(*ip);
1001 m = m_gethdr(M_NOWAIT, MT_DATA);
1006 len =
sizeof(*ip6) +
sizeof(ch);
1007 m->m_pkthdr.len = len;
1008 m->m_pkthdr.rcvif = NULL;
1010 M_ALIGN(m, m->m_len);
1011 m->m_flags |= M_MCAST;
1012 ip6 = mtod(m,
struct ip6_hdr *);
1013 bzero(ip6,
sizeof(*ip6));
1020 ip6->ip6_nxt = IPPROTO_CARP;
1025 bcopy(IFA_IN6(ifa), &ip6->
ip6_src,
1026 sizeof(
struct in6_addr));
1030 bzero(&ip6->
ip6_src,
sizeof(
struct in6_addr));
1033 ip6->
ip6_dst.s6_addr16[0] = htons(0xff02);
1034 ip6->
ip6_dst.s6_addr8[15] = 0x12;
1037 CARP_DEBUG(
"%s: in6_setscope failed\n", __func__);
1042 bcopy(&ch, ch_ptr,
sizeof(ch));
1046 m->m_data +=
sizeof(*ip6);
1047 ch_ptr->
carp_cksum = in_cksum(m, len -
sizeof(*ip6));
1048 m->m_data -=
sizeof(*ip6);
1053 &sc->
sc_carpdev->if_carp->cif_im6o, NULL, NULL));
1074 switch (ifa->ifa_addr->sa_family) {
1078 ifa_add_loopback_route(ifa,
1079 (
struct sockaddr *)&
ifatoia(ifa)->ia_addr);
1084 ifa_add_loopback_route(ifa,
1085 (
struct sockaddr *)&ifatoia6(ifa)->ia_addr);
1086 nd6_add_ifa_lle(ifatoia6(ifa));
1105 switch (ifa->ifa_addr->sa_family) {
1108 ifa_del_loopback_route(ifa,
1109 (
struct sockaddr *)&
ifatoia(ifa)->ia_addr);
1115 ifa_del_loopback_route(ifa,
1116 (
struct sockaddr *)&ifatoia6(ifa)->ia_addr);
1117 nd6_rem_ifa_lle(ifatoia6(ifa), 1);
1146 if (ifa->ifa_addr->sa_family != AF_INET)
1148 addr = ((
struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
1159 *enaddr = LLADDR(&sc->
sc_addr);
1171 static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
1173 struct in6_addr *in6;
1176 if (ifa->ifa_addr->sa_family != AF_INET6)
1198 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1199 if (ifa->ifa_addr->sa_family != AF_INET6)
1201 if (!IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa)))
1203 if (ifa->ifa_carp && ifa->ifa_carp->sc_state != MASTER)
1214carp_macmatch6(
struct ifnet *ifp,
struct mbuf *m,
const struct in6_addr *taddr)
1221 if (ifa->ifa_addr->sa_family == AF_INET6 &&
1222 IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa))) {
1226 mtag = m_tag_get(PACKET_TAG_CARP,
1230 return (LLADDR(&sc->
sc_addr));
1232 bcopy(&sc, mtag + 1,
sizeof(sc));
1233 m_tag_prepend(m, mtag);
1235 return (LLADDR(&sc->
sc_addr));
1248 if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1)
1273 struct epoch_tracker et;
1275 NET_EPOCH_ENTER(et);
1311 panic(
"carp: VHID %u@%s: master_down event in %s state\n",
1331 if ((sc->
sc_carpdev->if_flags & IFF_UP) == 0 ||
1332 sc->
sc_carpdev->if_link_state != LINK_STATE_UP ||
1349 callout_reset(&sc->sc_md_tmo, tvtohz(&tv),
1355 callout_reset(&sc->sc_md6_tmo, tvtohz(&tv),
1362 callout_reset(&sc->sc_md_tmo, tvtohz(&tv),
1367 callout_reset(&sc->sc_md6_tmo, tvtohz(&tv),
1376 callout_reset(&sc->
sc_ad_tmo, tvtohz(&tv),
1388 struct ifnet *ifp = cif->cif_ifp;
1395 struct ip_moptions *imo = &cif->cif_imo;
1404 imo->imo_multicast_vif = -1;
1406 addr.
s_addr = htonl(INADDR_CARP_GROUP);
1414 imo->imo_multicast_ifp = ifp;
1416 imo->imo_multicast_loop = 0;
1423 struct ip6_moptions *im6o = &cif->cif_im6o;
1424 struct in6_mfilter *im6f[2];
1425 struct in6_addr in6;
1427 if (ip6_mfilter_first(&im6o->im6o_head))
1430 im6f[0] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
1431 im6f[1] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
1433 ip6_mfilter_init(&im6o->im6o_head);
1435 im6o->im6o_multicast_ifp = ifp;
1438 bzero(&in6,
sizeof(in6));
1439 in6.s6_addr16[0] = htons(0xff02);
1440 in6.s6_addr8[15] = 0x12;
1441 if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
1442 ip6_mfilter_free(im6f[0]);
1443 ip6_mfilter_free(im6f[1]);
1446 if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[0]->im6f_in6m, 0)) != 0) {
1447 ip6_mfilter_free(im6f[0]);
1448 ip6_mfilter_free(im6f[1]);
1453 bzero(&in6,
sizeof(in6));
1454 in6.s6_addr16[0] = htons(0xff02);
1455 in6.s6_addr32[1] = 0;
1456 in6.s6_addr32[2] = htonl(1);
1457 in6.s6_addr32[3] = 0;
1458 in6.s6_addr8[12] = 0xff;
1460 if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
1461 ip6_mfilter_free(im6f[0]);
1462 ip6_mfilter_free(im6f[1]);
1466 if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[1]->im6f_in6m, 0)) != 0) {
1467 in6_leavegroup(im6f[0]->im6f_in6m, NULL);
1468 ip6_mfilter_free(im6f[0]);
1469 ip6_mfilter_free(im6f[1]);
1472 ip6_mfilter_insert(&im6o->im6o_head, im6f[0]);
1473 ip6_mfilter_insert(&im6o->im6o_head, im6f[1]);
1489 struct ip_moptions *imo = &cif->cif_imo;
1493 struct ip6_moptions *im6o = &cif->cif_im6o;
1494 struct in6_mfilter *im6f;
1496 sx_assert(&carp_sx, SA_XLOCKED);
1501 if (cif->cif_naddrs != 0)
1513 if (cif->cif_naddrs6 != 0)
1516 while ((im6f = ip6_mfilter_first(&im6o->im6o_head)) != NULL) {
1517 ip6_mfilter_remove(&im6o->im6o_head, im6f);
1518 in6_leavegroup(im6f->im6f_in6m, NULL);
1519 ip6_mfilter_free(im6f);
1527carp_output(
struct ifnet *ifp,
struct mbuf *m,
const struct sockaddr *sa)
1535 switch (sa->sa_family) {
1548 mtag = m_tag_find(m, PACKET_TAG_CARP, NULL);
1552 bcopy(mtag + 1, &sc,
sizeof(sc));
1555 switch (ifp->if_type) {
1559 struct ether_header *eh;
1561 eh = mtod(m,
struct ether_header *);
1562 eh->ether_shost[0] = 0;
1563 eh->ether_shost[1] = 0;
1564 eh->ether_shost[2] = 0x5e;
1565 eh->ether_shost[3] = 0;
1566 eh->ether_shost[4] = 1;
1567 eh->ether_shost[5] = sc->
sc_vhid;
1571 printf(
"%s: carp is not supported for the %d interface type\n",
1572 ifp->if_xname, ifp->if_type);
1573 return (EOPNOTSUPP);
1585 sx_assert(&carp_sx, SA_XLOCKED);
1587 if ((cif = ifp->if_carp) == NULL)
1590 sc = malloc(
sizeof(*sc), M_CARP, M_WAITOK|M_ZERO);
1597 sc->
sc_ifasiz =
sizeof(
struct ifaddr *);
1603 callout_init_mtx(&sc->sc_md_tmo, &sc->
sc_mtx, CALLOUT_RETURNUNLOCKED);
1606 callout_init_mtx(&sc->sc_md6_tmo, &sc->
sc_mtx, CALLOUT_RETURNUNLOCKED);
1608 callout_init_mtx(&sc->
sc_ad_tmo, &sc->
sc_mtx, CALLOUT_RETURNUNLOCKED);
1611 TAILQ_INSERT_TAIL(&cif->cif_vrs, sc, sc_list);
1614 mtx_lock(&carp_mtx);
1615 LIST_INSERT_HEAD(&carp_list, sc, sc_next);
1616 mtx_unlock(&carp_mtx);
1624 struct ifaddr **
new;
1626 new = malloc(sc->
sc_ifasiz * 2, M_CARP, M_WAITOK | M_ZERO);
1639 struct carp_if *cif = ifp->if_carp;
1641 sx_assert(&carp_sx, SA_XLOCKED);
1648 TAILQ_REMOVE(&cif->cif_vrs, sc, sc_list);
1651 mtx_lock(&carp_mtx);
1652 LIST_REMOVE(sc, sc_next);
1653 mtx_unlock(&carp_mtx);
1657 callout_drain(&sc->sc_md_tmo);
1660 callout_drain(&sc->sc_md6_tmo);
1674 cif = malloc(
sizeof(*cif), M_CARP, M_WAITOK|M_ZERO);
1676 if ((error = ifpromisc(ifp, 1)) != 0)
1677 printf(
"%s: ifpromisc(%s) failed: %d\n",
1678 __func__, ifp->if_xname, error);
1684 TAILQ_INIT(&cif->cif_vrs);
1689 IF_ADDR_WUNLOCK(ifp);
1697 struct ifnet *ifp = cif->cif_ifp;
1700 KASSERT(TAILQ_EMPTY(&cif->cif_vrs), (
"%s: softc list not empty",
1704 ifp->if_carp = NULL;
1705 IF_ADDR_WUNLOCK(ifp);
1738 int error = 0, locked = 0;
1740 if ((error = copyin(ifr_data_get_ptr(ifr), &carpr,
sizeof carpr)))
1743 ifp = ifunit_ref(ifr->ifr_name);
1747 switch (ifp->if_type) {
1757 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
1758 error = EADDRNOTAVAIL;
1765 if ((error = priv_check(td, PRIV_NETINET_CARP)))
1784 LLADDR(&sc->
sc_addr)[2] = 0x5e;
1806 carp_hmac_prepare(sc);
1814 "user requested via ifconfig");
1820 "user requested via ifconfig");
1840 if (ifp->if_carp == NULL) {
1845 priveleged = (priv_check(td, PRIV_NETINET_CARP) == 0);
1855 error = copyout(&carpr, ifr_data_get_ptr(ifr),
1874 error = copyout(&carpr,
1875 (
char *)ifr_data_get_ptr(ifr) +
1876 (i *
sizeof(carpr)),
sizeof(carpr));
1889 sx_xunlock(&carp_sx);
1903 if (ifa == NULL || ifa->ifa_carp == NULL)
1906 return (ifa->ifa_carp->sc_vhid);
1912 struct ifnet *ifp = ifa->ifa_ifp;
1913 struct carp_if *cif = ifp->if_carp;
1917 KASSERT(ifa->ifa_carp == NULL, (
"%s: ifa %p attached", __func__, ifa));
1919 switch (ifa->ifa_addr->sa_family) {
1928 return (EPROTOTYPE);
1932 if (ifp->if_carp == NULL) {
1933 sx_xunlock(&carp_sx);
1934 return (ENOPROTOOPT);
1941 sx_xunlock(&carp_sx);
1948 sx_xunlock(&carp_sx);
1953 if (index > sc->
sc_ifasiz /
sizeof(
struct ifaddr *))
1956 switch (ifa->ifa_addr->sa_family) {
1976 carp_hmac_prepare(sc);
1980 sx_xunlock(&carp_sx);
1988 struct ifnet *ifp = ifa->ifa_ifp;
1989 struct carp_if *cif = ifp->if_carp;
1993 KASSERT(sc != NULL, (
"%s: %p not attached", __func__, ifa));
2000 for (i = 0; i < index; i++)
2003 KASSERT(i < index, (
"%s: %p no backref", __func__, ifa));
2004 for (; i < index - 1; i++)
2006 sc->
sc_ifas[index - 1] = NULL;
2008 switch (ifa->ifa_addr->sa_family) {
2026 ifa->ifa_carp = NULL;
2029 carp_hmac_prepare(sc);
2040 sx_xunlock(&carp_sx);
2051 char subsys[IFNAMSIZ+5];
2053 snprintf(subsys, IFNAMSIZ+5,
"%u@%s", sc->
sc_vhid,
2056 CARP_LOG(
"%s: %s -> %s (%s)\n", subsys,
2061 devctl_notify(
"CARP", subsys, carp_states[
state], NULL);
2085 if (sc->
sc_carpdev->if_link_state != LINK_STATE_UP ||
2090 callout_stop(&sc->sc_md_tmo);
2093 callout_stop(&sc->sc_md6_tmo);
2114 taskqueue_enqueue(taskqueue_swi, &carp_sendall_task);
2124 error = sysctl_handle_int(oidp, &
new, 0, req);
2125 if (error || !req->newptr)
2131 mtx_lock(&carp_mtx);
2132 LIST_FOREACH(sc, &carp_list, sc_next) {
2138 mtx_unlock(&carp_mtx);
2150 error = sysctl_handle_int(oidp, &
new, 0, req);
2151 if (error || !req->newptr)
2154 if (new < 0 || new > 63)
2168 error = sysctl_handle_int(oidp, &
new, 0, req);
2169 if (error || !req->newptr)
2179static struct protosw in_carp_protosw = {
2180 .pr_type = SOCK_RAW,
2182 .pr_protocol = IPPROTO_CARP,
2183 .pr_flags = PR_ATOMIC|PR_ADDR,
2192extern struct domain inet6domain;
2193static struct protosw in6_carp_protosw = {
2194 .pr_type = SOCK_RAW,
2195 .pr_domain = &inet6domain,
2196 .pr_protocol = IPPROTO_CARP,
2197 .pr_flags = PR_ATOMIC|PR_ADDR,
2199 .pr_output = rip6_output,
2200 .pr_ctloutput = rip6_ctloutput,
2201 .pr_usrreqs = &rip6_usrreqs
2212 pf_proto_unregister(PF_INET, IPPROTO_CARP, SOCK_RAW);
2215 carp_iamatch_p = NULL;
2219 (void)ip6proto_unregister(IPPROTO_CARP);
2220 pf_proto_unregister(PF_INET6, IPPROTO_CARP, SOCK_RAW);
2223 carp_iamatch6_p = NULL;
2224 carp_macmatch6_p = NULL;
2235 mtx_unlock(&carp_mtx);
2236 taskqueue_drain(taskqueue_swi, &carp_sendall_task);
2237 mtx_destroy(&carp_mtx);
2238 sx_destroy(&carp_sx);
2246 mtx_init(&carp_mtx,
"carp_mtx", NULL, MTX_DEF);
2247 sx_init(&carp_sx,
"carp_sx");
2248 LIST_INIT(&carp_list);
2262 (
struct protosw *)&in6_carp_protosw);
2264 printf(
"carp: error %d attaching to PF_INET6\n",
2269 err = ip6proto_register(IPPROTO_CARP);
2271 printf(
"carp: error %d registering with INET6\n", err);
2280 printf(
"carp: error %d attaching to PF_INET\n",
2287 printf(
"carp: error %d registering with INET\n", err);
2303 mtx_lock(&carp_mtx);
2304 if (LIST_EMPTY(&carp_list))
2307 mtx_unlock(&carp_mtx);
static TAILQ_HEAD(handler_chain, proto_handler)
#define ND_NA_FLAG_OVERRIDE
void arp_announce_ifaddr(struct ifnet *ifp, struct in_addr addr, u_char *enaddr)
int in_scrubprefix(struct in_ifaddr *target, u_int flags)
int in_addprefix(struct in_ifaddr *target)
__sa_family_t sa_family_t
int in_joingroup(struct ifnet *ifp, const struct in_addr *gina, struct in_mfilter *imf, struct in_multi **pinm)
void ip_mfilter_free(struct in_mfilter *imf)
struct in_mfilter * ip_mfilter_alloc(const int mflags, const int st0, const int st1)
int in_leavegroup(struct in_multi *inm, struct in_mfilter *imf)
static void ip_mfilter_insert(struct ip_mfilter_head *head, struct in_mfilter *imf)
static void ip_mfilter_init(struct ip_mfilter_head *head)
static struct in_mfilter * ip_mfilter_first(const struct ip_mfilter_head *head)
static void ip_mfilter_remove(struct ip_mfilter_head *head, struct in_mfilter *imf)
#define IPV6_FLOWLABEL_LEN
#define IPTOS_DSCP_OFFSET
static void carp_carprcp(struct carpreq *carpr, struct carp_softc *sc, int priv)
VNET_PCPUSTAT_DEFINE(struct carpstats, carpstats)
static void carp_grow_ifas(struct carp_softc *sc)
static void carp_set_state(struct carp_softc *, int, const char *reason)
static void carp_ifa_addroute(struct ifaddr *)
#define CARP_FOREACH_IFA(sc, ifa)
SYSCTL_VNET_PCPUSTAT(_net_inet_carp, OID_AUTO, stats, struct carpstats, carpstats, "CARP statistics (struct carpstats, netinet/ip_carp.h)")
int carp_forus(struct ifnet *ifp, u_char *dhost)
static void carp_master_down(void *)
static void carp_linkstate(struct ifnet *ifp)
#define CIF_LOCK_INIT(cif)
static void carp_send_ad_error(struct carp_softc *sc, int error)
#define CARP_SENDAD_MIN_SUCCESS
#define IFNET_FOREACH_CARP(ifp, sc)
VNET_DEFINE_STATIC(int, carp_allow)
int carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
VNET_PCPUSTAT_SYSINIT(carpstats)
static void carp_ifa_delroute(struct ifaddr *)
int carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td)
#define CARP_SENDAD_MAX_ERRORS
static int carp_allow_sysctl(SYSCTL_HANDLER_ARGS)
static void carp_free_if(struct carp_if *)
static void carp_hmac_generate(struct carp_softc *sc, uint32_t counter[2], unsigned char md[20])
static int carp_get_vhid(struct ifaddr *ifa)
static MALLOC_DEFINE(M_CARP, "CARP", "CARP addresses")
static void carp_delroute(struct carp_softc *)
static int carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
#define CARP_LOCK_ASSERT(sc)
#define V_carp_ifdown_adj
static void carp_demote_adj(int, char *)
static void carp_send_ad_locked(struct carp_softc *)
static void carp_destroy(struct carp_softc *)
static void carp_input_c(struct mbuf *, struct carp_header *, sa_family_t)
static void carp_send_ad(void *)
VNET_PCPUSTAT_SYSUNINIT(carpstats)
#define DEMOTE_ADVSKEW(sc)
static int carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch)
static struct ifaddr * carp_best_ifa(int af, struct ifnet *ifp)
static void carp_sc_state(struct carp_softc *)
static int carp_mod_load(void)
static int carp_dscp_sysctl(SYSCTL_HANDLER_ARGS)
static int carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS)
static struct carp_if * carp_alloc_if(struct ifnet *)
SYSCTL_PROC(_net_inet_carp, OID_AUTO, allow, CTLFLAG_VNET|CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_MPSAFE, 0, 0, carp_allow_sysctl, "I", "Accept incoming CARP packets")
static int carp_hmac_verify(struct carp_softc *sc, uint32_t counter[2], unsigned char md[20])
static LIST_HEAD(carp_softc)
void carp_detach(struct ifaddr *ifa, bool keep_cif)
SYSCTL_INT(_net_inet_carp, OID_AUTO, preempt, CTLFLAG_VNET|CTLFLAG_RW, &VNET_NAME(carp_preempt), 0, "High-priority backup preemption mode")
int carp_attach(struct ifaddr *ifa, int vhid)
#define CARPSTATS_INC(name)
#define CIF_LOCK_ASSERT(cif)
static int carp_source_is_self(struct mbuf *m, struct ifaddr *ifa, sa_family_t af)
SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "CARP")
static int carp_modevent(module_t mod, int type, void *data)
static void carp_addroute(struct carp_softc *)
static void carp_master_down_locked(struct carp_softc *, const char *reason)
#define CARP_LOCK_INIT(sc)
static moduledata_t carp_mod
static void carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa)
#define CARP_LOCK_DESTROY(sc)
static void carp_setrun(struct carp_softc *, sa_family_t)
static struct carp_softc * carp_alloc(struct ifnet *)
static void carp_send_ad_all(void *, int)
DECLARE_MODULE(carp, carp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY)
#define CIF_LOCK_DESTROY(cif)
int carp_master(struct ifaddr *ifa)
#define V_carp_senderr_adj
#define IFNET_FOREACH_IFA(ifp, ifa)
static void carp_mod_cleanup(void)
int carp_iamatch(struct ifaddr *, uint8_t **)
int(* carp_output_p)(struct ifnet *, struct mbuf *, const struct sockaddr *)
int carp_input(struct mbuf **, int *, int)
#define CARP_ADVERTISEMENT
int(* carp_ioctl_p)(struct ifreq *, u_long, struct thread *)
int(* carp_get_vhid_p)(struct ifaddr *)
int(* carp_master_p)(struct ifaddr *)
void(* carp_linkstate_p)(struct ifnet *)
char * carp_macmatch6(struct ifnet *, struct mbuf *, const struct in6_addr *)
void(* carp_demote_adj_p)(int, char *)
void(* carp_detach_p)(struct ifaddr *, bool)
int carp6_input(struct mbuf **, int *, int)
struct ifaddr * carp_iamatch6(struct ifnet *, struct in6_addr *)
int(* carp_forus_p)(struct ifnet *, u_char *)
int(* carp_attach_p)(struct ifaddr *, int)
void ip_fillid(struct ip *ip)
int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, struct inpcb *inp)
int rip_output(struct mbuf *, struct socket *,...)
struct pr_usrreqs rip_usrreqs
int rip_ctloutput(struct socket *, struct sockopt *)
struct sockaddr_dl sc_addr
unsigned char sc_pad[CARP_HMAC_PAD]
struct ifnet * sc_carpdev
enum carp_softc::@10 sc_state
unsigned char sc_key[CARP_KEY_LEN]
unsigned char carpr_key[CARP_KEY_LEN]
struct in_multi * imf_inm
struct in_addr ip_src ip_dst
TAILQ_ENTRY(bbr_sendmap) r_next