From nobody Sun Oct 26 11:21:40 2025 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4cvZ390V89z6Cvms; Sun, 26 Oct 2025 11:21:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cvZ386qNNz4JV5; Sun, 26 Oct 2025 11:21:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1761477701; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=x+jJOwWMzU9N6LMa2PxI2CM2yPDaDlP+WHDCvmtsnus=; b=IXlv9GKmZeInm0gXhNVG0AV/cDJV/gUiXu1MLJkFNySVwtlxjNQ2prSa4T5HHZYTuZewed 2UwdVu8nrvXnbWyGdddqqmqTjfUmgKyJ1KoB7u6LGd5Sd7C+21j9fOUCrrGV7Ry8e9TnO1 7oLl8pUACxupKDu9UgMG8iTS+Cdd6wxcm/0gpt8uBqvXDQ9ayYKs01raWm6S1+kJZcgnmR GdZ3URcRwEFp7VZef9FcWRwRtTn5pf15tetIWL580rhbDwjcRuUcx7Jfs+e27wZkrw99rR JBbyRRF6mhsyNBqRDzxVD0d0NiKbTbgt5fUHJxwIQkAS6lqDZ4AGeuQM0XyUhw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1761477701; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=x+jJOwWMzU9N6LMa2PxI2CM2yPDaDlP+WHDCvmtsnus=; b=QgbbKBLSuUlJusstM175RGqFAw8sXPu/pd7icGoTrF0K7jTQXJemHqj4hmoxSodiqsA68K LZd0wO/pgrUKqAXNrcvhDFYmUOlBRNl/uERZkOeqAoQQCUrcrETjdkE04+2x1iTGV76JRX lKvubhnkFFaqqYyYomkuhuUS477b1MJ89tNKnpMQQbd0ETlqilsZvJuSoB6ci/+8zU8XA5 gj9NBRV5o88fgdIlPKSzZ0N1KW7bOIXZWIfqfWaklHaCABfnUp1sfGHzDa/CXoaONTT4wz mQmdSBKAwk+1izD1JhruAMaOR9OdniF6N9ndxE+rPWpVK2a8hGcevcY4Ro7c2w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1761477701; a=rsa-sha256; cv=none; b=Bci7k+73KQ274LJhtzR8F6JY4a5T3//BYuhNXGm/F3ADpOtiLz4PCeUkPIr12slMl6tw2o DTuCKTQ0oc9ixxpUSXsXP2C2k/Urg4V/brmDvs5iOr4vfsv7NB4h4Dik2sM2Pl18TZj+UO 4v9vbN94JICrmQIjeiFwaCwbp9hk3RQyXe+c1N0tG7d1jSkb//UFqp+KycSP2B83hFwgQj DOxGEWEncEIiw8jRE2QL7o0W+27EgJo9QpNsO65VBdbr7cAnZuI0bVp9AANnUM9CAFitO2 4iTDphe2tlZDiOHb2cjRQJScU1IAgPkjv/J+Kt79j3sA7G/I2mqRC5m01mNblg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cvZ386GrnzVld; Sun, 26 Oct 2025 11:21:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 59QBLean076725; Sun, 26 Oct 2025 11:21:40 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 59QBLeXc076722; Sun, 26 Oct 2025 11:21:40 GMT (envelope-from git) Date: Sun, 26 Oct 2025 11:21:40 GMT Message-Id: <202510261121.59QBLeXc076722@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: "Andrey V. Elsukov" Subject: git: f7937053fd08 - stable/14 - arp: fix adding proxy entries for P2P interfaces List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ae X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: f7937053fd0899e7b808bab3a0576ff16f3e943d Auto-Submitted: auto-generated The branch stable/14 has been updated by ae: URL: https://cgit.FreeBSD.org/src/commit/?id=f7937053fd0899e7b808bab3a0576ff16f3e943d commit f7937053fd0899e7b808bab3a0576ff16f3e943d Author: Andrey V. Elsukov AuthorDate: 2025-10-17 07:53:35 +0000 Commit: Andrey V. Elsukov CommitDate: 2025-10-26 11:21:14 +0000 arp: fix adding proxy entries for P2P interfaces The old rtsock implementation used in-kernel workaround to do so. When route to specified destination address used P2P interface, the kernel did the search with ifa_ifwithnet() for most suitable network and then add proxy entry to this interface. Use similar approach with netlink implementation. We already have get_ether_addr() function that does almost the same thing as ifa_ifwithnet(). Use it when we find that destination route uses P2P interface and then try to guess suitable interface. This should fix the use of netlink-based arp(8) in mpd5. Rename get_ether_addr() to get_ifinfo(), since now it is used to find only ifindex in case when hwaddr is specified by user. Also make set_nl() and delete_nl() prototype similar to rtsock. And allow '-i' to be used with '-S', since we already allow the same for '-s'. PR: 290221 Reported by: eugen Reviewed by: eugen Differential Revision: https://reviews.freebsd.org/D53113 (cherry picked from commit c26d6bf9da013e839d9a696746ea1741569e619e) --- usr.sbin/arp/arp.c | 32 ++++++++++++++++++++------------ usr.sbin/arp/arp.h | 9 ++++----- usr.sbin/arp/arp_netlink.c | 20 ++++++++++++++++---- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c index fba6bdd57ed5..8b2cc6f09740 100644 --- a/usr.sbin/arp/arp.c +++ b/usr.sbin/arp/arp.c @@ -93,7 +93,6 @@ static int get(char *host); static int file(char *name); static struct rt_msghdr *rtmsg(int cmd, struct sockaddr_in *dst, struct sockaddr_dl *sdl); -static int get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr); static int set_rtsock(struct sockaddr_in *dst, struct sockaddr_dl *sdl_m, char *host); @@ -155,7 +154,8 @@ main(int argc, char *argv[]) if (!func) func = F_GET; if (opts.rifname) { - if (func != F_GET && func != F_SET && !(func == F_DELETE && opts.aflag)) + if (func != F_GET && func != F_SET && func != F_REPLACE && + !(func == F_DELETE && opts.aflag)) xo_errx(1, "-i not applicable to this operation"); if ((opts.rifindex = if_nametoindex(opts.rifname)) == 0) { if (errno == ENXIO) @@ -285,7 +285,6 @@ getaddr(char *host) return (&reply); } -int valid_type(int type); /* * Returns true if the type is a valid one for ARP. */ @@ -369,11 +368,14 @@ set(int argc, char **argv) } ea = (struct ether_addr *)LLADDR(&sdl_m); if ((opts.flags & RTF_ANNOUNCE) && !strcmp(eaddr, "auto")) { - if (!get_ether_addr(dst->sin_addr.s_addr, ea)) { + uint32_t ifindex; + if (!get_ifinfo(dst->sin_addr.s_addr, ea, &ifindex)) { xo_warnx("no interface found for %s", - inet_ntoa(dst->sin_addr)); + inet_ntoa(dst->sin_addr)); return (1); } + if (opts.rifindex == 0) + opts.rifindex = ifindex; sdl_m.sdl_alen = ETHER_ADDR_LEN; } else { struct ether_addr *ea1 = ether_aton(eaddr); @@ -387,7 +389,7 @@ set(int argc, char **argv) } } #ifndef WITHOUT_NETLINK - return (set_nl(opts.rifindex, dst, &sdl_m, host)); + return (set_nl(dst, &sdl_m, host)); #else return (set_rtsock(dst, &sdl_m, host)); #endif @@ -534,7 +536,7 @@ delete(char *host) #ifdef WITHOUT_NETLINK return (delete_rtsock(host)); #else - return (delete_nl(0, host)); + return (delete_nl(host)); #endif } @@ -831,11 +833,11 @@ doit: } /* - * get_ether_addr - get the hardware address of an interface on the - * same subnet as ipaddr. + * get_ifinfo - get the hardware address and if_index of an interface + * on the same subnet as ipaddr. */ -static int -get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr) +int +get_ifinfo(in_addr_t ipaddr, struct ether_addr *hwaddr, uint32_t *pifindex) { struct ifaddrs *ifa, *ifd, *ifas = NULL; in_addr_t ina, mask; @@ -874,7 +876,13 @@ get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr) } if (ifa == NULL) goto done; - + if (pifindex != NULL) + *pifindex = if_nametoindex(ifa->ifa_name); + if (hwaddr == NULL) { + /* ether addr is not required */ + retval = ETHER_ADDR_LEN; + goto done; + } /* * Now scan through again looking for a link-level address * for this interface. diff --git a/usr.sbin/arp/arp.h b/usr.sbin/arp/arp.h index 487863be43e7..512a238df425 100644 --- a/usr.sbin/arp/arp.h +++ b/usr.sbin/arp/arp.h @@ -2,8 +2,8 @@ #define _USR_SBIN_ARP_ARP_H_ int valid_type(int type); +int get_ifinfo(in_addr_t ipaddr, struct ether_addr *hwaddr, uint32_t *pifindex); struct sockaddr_in *getaddr(char *host); -int print_entries_nl(uint32_t ifindex, struct in_addr addr); struct arp_opts { bool aflag; @@ -11,13 +11,12 @@ struct arp_opts { time_t expire_time; int flags; char *rifname; - unsigned int rifindex; + uint32_t rifindex; }; extern struct arp_opts opts; int print_entries_nl(uint32_t ifindex, struct in_addr addr); -int delete_nl(uint32_t ifindex, char *host); -int set_nl(uint32_t ifindex, struct sockaddr_in *dst, struct sockaddr_dl *sdl, - char *host); +int delete_nl(char *host); +int set_nl(struct sockaddr_in *dst, struct sockaddr_dl *sdl, char *host); #endif diff --git a/usr.sbin/arp/arp_netlink.c b/usr.sbin/arp/arp_netlink.c index db1ef775dea2..34f21cf96f4f 100644 --- a/usr.sbin/arp/arp_netlink.c +++ b/usr.sbin/arp/arp_netlink.c @@ -79,13 +79,15 @@ get_link_info(struct snl_state *ss, uint32_t ifindex, static bool -has_l2(struct snl_state *ss, uint32_t ifindex) +has_l2(struct snl_state *ss, uint32_t ifindex, uint32_t *pflags) { struct snl_parsed_link_simple link = {}; + *pflags = 0; if (!get_link_info(ss, ifindex, &link)) return (false); + *pflags = link.ifi_flags; return (valid_type(link.ifi_type) != 0); } @@ -104,6 +106,7 @@ static int guess_ifindex(struct snl_state *ss, uint32_t fibnum, struct in_addr addr) { struct snl_writer nw; + uint32_t ifindex, ifflags; snl_init_writer(ss, &nw); @@ -133,9 +136,16 @@ guess_ifindex(struct snl_state *ss, uint32_t fibnum, struct in_addr addr) return (0); /* Check if the interface is of supported type */ - if (has_l2(ss, r.rta_oif)) + if (has_l2(ss, r.rta_oif, &ifflags)) return (r.rta_oif); + /* Check if we are doing proxy arp for P2P interface */ + if (ifflags & IFF_POINTOPOINT) { + /* Guess interface by dst prefix */ + if (get_ifinfo(addr.s_addr, NULL, &ifindex)) + return (ifindex); + } + /* Check the case when we matched the loopback route for P2P */ snl_init_writer(ss, &nw); hdr = snl_create_msg_request(&nw, RTM_GETNEXTHOP); @@ -326,11 +336,12 @@ print_entries_nl(uint32_t ifindex, struct in_addr addr) } int -delete_nl(uint32_t ifindex, char *host) +delete_nl(char *host) { struct snl_state ss = {}; struct snl_writer nw; struct sockaddr_in *dst; + uint32_t ifindex = opts.rifindex; dst = getaddr(host); if (dst == NULL) @@ -375,10 +386,11 @@ delete_nl(uint32_t ifindex, char *host) } int -set_nl(uint32_t ifindex, struct sockaddr_in *dst, struct sockaddr_dl *sdl, char *host) +set_nl(struct sockaddr_in *dst, struct sockaddr_dl *sdl, char *host) { struct snl_state ss = {}; struct snl_writer nw; + uint32_t ifindex = opts.rifindex; nl_init_socket(&ss);