FreeBSD : patch pour la gestion des alias IPv6 sur interface CARP

Boris HUISGEN June 26, 2012

administration réseau freebsd carp ipv6

Le driver CARP de FreeBSD 8.x contient un bug au niveau de la gestion IPv6. Au lieu d’ajouter chaque adresse IPv6 de l’interface CARP au groupe multicast ff02::1, le driver n’ajoute que la première adresse. Ainsi la prise en compte des alias n’est pas effective et la découverte du voisinage IPv6 n’aboutit pas :

ipv6_ifconfig_carp0="2001:1610:4::102 prefixlen 64"
ipv6_ifconfig_carp0_alias0="2001:1610:4::113 prefixlen 64"

Par capture réseau :

0.000000 fe80::223:4ff:fe17:f840 -> ff02::1:ff00:113 ICMPv6 86 Neighbor Solicitation
0.999052 fe80::223:4ff:fe17:f840 -> ff02::1:ff00:113 ICMPv6 86 Neighbor Solicitation
1.999103 fe80::223:4ff:fe17:f840 -> ff02::1:ff00:113 ICMPv6 86 Neighbor Solicitation
3.000220 fe80::223:4ff:fe17:f840 -> ff02::1:ff00:113 ICMPv6 86 Neighbor Solicitation

Pour corriger ce bug, Paul Herman propose un patch à appliquer aux sources de FreeBSD :

# cd /usr/src
# zcat /path/to/carp_ip6_alias.patch.gz | patch

--- sys/netinet6/in6.c.orig    2011-08-19 07:08:30.000000000 +0000
+++ sys/netinet6/in6.c    2011-08-19 07:09:53.000000000 +0000
@@ -1743,7 +1743,7 @@

ia->ia_addr = *sin6;

-    if (ifacount <= 1 && ifp->if_ioctl) {
+    if ((ifacount <= 1 || ifp->if_type == IFT_CARP) && ifp->if_ioctl) {
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
if (error) {
splx(s);
--- sys/netinet/ip_carp.c.orig    2011-08-19 07:52:56.000000000 +0000
+++ sys/netinet/ip_carp.c    2011-08-19 07:15:03.000000000 +0000
@@ -1670,9 +1670,11 @@
struct carp_if *cif;
struct in6_ifaddr *ia, *ia_if;
struct ip6_moptions *im6o = &sc->sc_im6o;
+    struct in6_multi *in6m;
struct in6_addr in6;
int own, error;

+
error = 0;

if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
@@ -1729,8 +1731,6 @@
}

if (!sc->sc_naddrs6) {
-        struct in6_multi *in6m;
-
im6o->im6o_multicast_ifp = ifp;

/* join CARP multicast address */
@@ -1745,24 +1745,24 @@
goto cleanup;
im6o->im6o_membership[0] = in6m;
im6o->im6o_num_memberships++;
-
-        /* join solicited multicast address */
-        bzero(&in6, sizeof(in6));
-        in6.s6_addr16[0] = htons(0xff02);
-        in6.s6_addr32[1] = 0;
-        in6.s6_addr32[2] = htonl(1);
-        in6.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3];
-        in6.s6_addr8[12] = 0xff;
-        if (in6_setscope(&in6, ifp, NULL) != 0)
-            goto cleanup;
-        in6m = NULL;
-        error = in6_mc_join(ifp, &in6, NULL, &in6m, 0);
-        if (error)
-            goto cleanup;
-        im6o->im6o_membership[1] = in6m;
-        im6o->im6o_num_memberships++;
}

+    /* join solicited multicast address */
+    bzero(&in6, sizeof(in6));
+    in6.s6_addr16[0] = htons(0xff02);
+    in6.s6_addr32[1] = 0;
+    in6.s6_addr32[2] = htonl(1);
+    in6.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3];
+    in6.s6_addr8[12] = 0xff;
+    if (in6_setscope(&in6, ifp, NULL) != 0)
+        goto cleanup;
+    in6m = NULL;
+    error = in6_mc_join(ifp, &in6, NULL, &in6m, 0);
+    if (error)
+        goto cleanup;
+    im6o->im6o_membership[1] = in6m;
+    im6o->im6o_num_memberships++;
+
if (!ifp->if_carp) {
cif = malloc(sizeof(*cif), M_CARP,
M_WAITOK|M_ZERO);

Une fois le noyau de l’hôte patché, le test par ping externe est concluant.

Patch : [download id="16” ]

See also

FreeBSD : redondance IPv6 avec CARP et VLAN
Read more
FreeBSD : redondance réseau CARP et VLAN
Read more
Xen 4 : patch pour une configuration bridge IPv6
Read more