Index | Thread | Search

From:
Ido <ido@wireplug.org>
Subject:
Re: ia_sockmask.sin_family is not set correctly
To:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Cc:
tech@openbsd.org
Date:
Mon, 22 Jun 2026 13:06:24 -0400

Download raw body.

Thread
On 2026-06-18, Claudio Jeker wrote:
> In BSD the netmask was normally all 0xff apart from the sa_len.
> This comes from the time where all netmasks were shared amongst all
> address families.
> 
> In general the sa_family value of the address should be used for the
> netmask sockaddr. Also be aware that on some systems the returned buffer
> may be shorter than the AF specific sockaddr struct.
> 
> So if you really want cross platform then you need to handle that in
> userland. It may still make sense to improve the exported values by
> getifaddrs(3).

Thanks for the explanation and for taking the time to look into this.

> Your diff is certainly not complete. There are a fair amount of other
> places where ia_sockmask is adjusted that would also need such a fix.

The updated diff below covers all the assignments of ia_sockmask, apart from
the one in if_pppx.c which already sets the sin_family field correctly.

However, I suspect it might actually be sufficient to set it only in the two
	if (ai == NULL) {
	}
blocks, in in_ioctl_set_ifaddr() and in_ioctl_change_ifaddr() where we allocate
a new in_ifaddr. I'll follow up with an alternative diff that does just that.

---
Ido

diff --git sys/netinet/in.c sys/netinet/in.c
index 4edd8573071..7199345e3f7 100644
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -345,6 +345,7 @@ in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged)
 			error = EINVAL;
 			break;
 		}
+		ia->ia_sockmask.sin_family = AF_INET;
 		ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
 		    sin->sin_addr.s_addr;
 		break;
@@ -390,7 +391,9 @@ in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
 		ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
 		ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
 		ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
+		ia->ia_sockmask.sin_family = AF_INET;
 		ia->ia_sockmask.sin_len = 8;
+
 		if (ifp->if_flags & IFF_BROADCAST) {
 			ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
 			ia->ia_broadaddr.sin_family = AF_INET;
@@ -484,6 +487,7 @@ in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
 			ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
 			ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
 			ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
+			ia->ia_sockmask.sin_family = AF_INET;
 			ia->ia_sockmask.sin_len = 8;
 			if (ifp->if_flags & IFF_BROADCAST) {
 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
@@ -503,6 +507,7 @@ in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
 		}
 		if (masksin != NULL) {
 			in_ifscrub(ifp, ia);
+			ia->ia_sockmask.sin_family = AF_INET;
 			ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
 			    masksin->sin_addr.s_addr;
 			needinit = 1;
@@ -668,6 +673,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
 			ia->ia_netmask = IN_CLASSB_NET;
 		else
 			ia->ia_netmask = IN_CLASSC_NET;
+		ia->ia_sockmask.sin_family = AF_INET;
 		ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask;
 	}