From: YASUOKA Masahiko Subject: carp: arp request or nd for unicast when not using virtual mac To: tech@openbsd.org Date: Tue, 26 Nov 2024 09:17:11 +0900 Hello, This should have been included when I made carp(4) work without a virtual mac. carp doesn't reply for unicast ARP or ND on that config. ok? ARP request or neighbor solicitation was dropped mistakenly if it's sent for a unicast address and the resolving target is an address of carp interface configured without virtual MAC. Add check for arp_input() and nd6_ns_input() to handle such requests. Index: sys/netinet/if_ether.c =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.c,v diff -u -p -r1.267 if_ether.c --- sys/netinet/if_ether.c 18 Dec 2023 13:30:44 -0000 1.267 +++ sys/netinet/if_ether.c 26 Nov 2024 00:08:37 -0000 @@ -586,9 +586,27 @@ in_arpinput(struct ifnet *ifp, struct mb /* Check target against our interface addresses. */ sin.sin_addr = itaddr; rt = rtalloc(sintosa(&sin), 0, rdomain); - if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && - rt->rt_ifidx == ifp->if_index) - target = 1; + if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL)) { + if (rt->rt_ifidx == ifp->if_index) + target = 1; +#if NCARP > 0 + /* + * Pass if the request is for unicast and the target address is + * configured for a carp but received on the parent interface. + * This happens if the carp is configured without a virtual mac. + */ + else if ((m->m_flags & M_BCAST) == 0) { + struct ifnet *ifp0; + + ifp0 = if_get(rt->rt_ifidx); + if (ifp0->if_type == IFT_CARP && + ifp0->if_carpdevidx == ifp->if_index && + carp_iamatch(ifp0)) + target = 1; + if_put(ifp0); + } +#endif + } rtfree(rt); rt = NULL; Index: sys/netinet6/nd6_nbr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v diff -u -p -r1.153 nd6_nbr.c --- sys/netinet6/nd6_nbr.c 14 Jul 2024 18:53:39 -0000 1.153 +++ sys/netinet6/nd6_nbr.c 26 Nov 2024 00:08:37 -0000 @@ -247,6 +247,26 @@ nd6_ns_input(struct mbuf *m, int off, in i_am_router = 0; /* XXX */ } } +#if NCARP > 0 + /* + * Pass if the request is for unicast and the target address is + * configured for a carp but received on the parent interface. + * This happens if the carp is configured without a virtual mac. + */ + if ((m->m_flags & M_MCAST) == 0 && + rt && (rt->rt_flags & RTF_LOCAL) != 0 && + rt->rt_gateway->sa_family == AF_LINK) { + struct ifnet *ifp0; + + ifp0 = if_get(rt->rt_ifidx); + if (ifp0->if_type == IFT_CARP && + ifp0->if_carpdevidx == ifp->if_index && + carp_iamatch(ifp0)) + ifa = &in6ifa_ifpwithaddr( + ifp0, &taddr6)->ia_ifa; + if_put(ifp0); + } +#endif if (rt) rtfree(rt); }