Date: Sat, 22 Feb 2025 02:12:45 GMT From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 3b281d1421a7 - main - netinet: enforce broadcast mode for all-ones and all-zeroes destinations Message-ID: <202502220212.51M2CjUT099250@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=3b281d1421a78b588c5fc4182009ce62d8823d95 commit 3b281d1421a78b588c5fc4182009ce62d8823d95 Author: Gleb Smirnoff <glebius@FreeBSD.org> AuthorDate: 2025-02-22 02:11:00 +0000 Commit: Gleb Smirnoff <glebius@FreeBSD.org> CommitDate: 2025-02-22 02:11:00 +0000 netinet: enforce broadcast mode for all-ones and all-zeroes destinations When a socket has SO_BROADCAST set and destination address is INADDR_ANY or INADDR_BROADCAST, the kernel shall pick up first broadcast capable interface and broadcast the packet out of it. Since this API is not reliable on a machine with > 1 broadcast capable interfaces, all practical software seems to use IP_ONESBCAST or other mechanisms to send broadcasts. This has been broken at least since FreeBSD 6.0, see bug 99558. Back then the problem was in the fact that in_broadcast() check was always done against the gateway address, not the destination address. Later, with 90cc51a1ab4be, a second problem piled on top - we aren't checking for INADDR_ANY and INADDR_BROADCAST at all. Better late than never, fix that by checking destination address. PR: 99558 Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D49042 --- sys/netinet/in.h | 7 +++++++ sys/netinet/ip_output.c | 15 ++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 0ee4200017b5..fa710af7cd58 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -686,6 +686,13 @@ char *inet_ntop(int, const void *, char *, socklen_t); /* in libkern */ int inet_pton(int af, const char *, void *); /* in libkern */ void in_ifdetach(struct ifnet *); +static inline bool +in_broadcast(struct in_addr in) +{ + return (in.s_addr == htonl(INADDR_BROADCAST) || + in.s_addr == htonl(INADDR_ANY)); +} + #define in_hosteq(s, t) ((s).s_addr == (t).s_addr) #define in_nullhost(x) ((x).s_addr == INADDR_ANY) #define in_allhosts(x) ((x).s_addr == htonl(INADDR_ALLHOSTS_GROUP)) diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 1811becbf387..35aaf85d6a4e 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -449,7 +449,8 @@ again: mtu = ifp->if_mtu; ip->ip_ttl = 1; isbroadcast = ifp->if_flags & IFF_BROADCAST ? - in_ifaddr_broadcast(dst->sin_addr, ia) : 0; + (in_broadcast(ip->ip_dst) || + in_ifaddr_broadcast(dst->sin_addr, ia)) : 0; src = IA_SIN(ia)->sin_addr; } else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) && imo != NULL && imo->imo_multicast_ifp != NULL) { @@ -502,8 +503,11 @@ again: gw = &nh->gw_sa; if (nh->nh_flags & NHF_HOST) isbroadcast = (nh->nh_flags & NHF_BROADCAST); - else if ((ifp->if_flags & IFF_BROADCAST) && (gw->sa_family == AF_INET)) - isbroadcast = in_ifaddr_broadcast(((const struct sockaddr_in *)gw)->sin_addr, ia); + else if ((ifp->if_flags & IFF_BROADCAST) && + (gw->sa_family == AF_INET)) + isbroadcast = in_broadcast(ip->ip_dst) || + in_ifaddr_broadcast( + ((const struct sockaddr_in *)gw)->sin_addr, ia); else isbroadcast = false; mtu = nh->nh_mtu; @@ -533,11 +537,12 @@ again: gw = &nh->gw_sa; ia = ifatoia(nh->nh_ifa); src = IA_SIN(ia)->sin_addr; - isbroadcast = (((nh->nh_flags & (NHF_HOST | NHF_BROADCAST)) == + isbroadcast = ((nh->nh_flags & (NHF_HOST | NHF_BROADCAST)) == (NHF_HOST | NHF_BROADCAST)) || ((ifp->if_flags & IFF_BROADCAST) && (gw->sa_family == AF_INET) && - in_ifaddr_broadcast(((const struct sockaddr_in *)gw)->sin_addr, ia))); + (in_broadcast(ip->ip_dst) || in_ifaddr_broadcast( + ((const struct sockaddr_in *)gw)->sin_addr, ia))); } /* Catch a possible divide by zero later. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502220212.51M2CjUT099250>