From: Ido Subject: Re: ia_sockmask.sin_family is not set correctly To: Claudio Jeker Cc: tech@openbsd.org Date: Mon, 22 Jun 2026 13:06:24 -0400 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; }