The second step of merging the two switches in in_ioctl() is to split the six ioctls in this function into two families of three and to start disentangling them. While it is not strictly needed, it seemed cleanest to introduce a new function analogous to what was done in in6_ioctl(). This way we have a clear separation of the two families and we can manipulate them independently. We can easily merge them back together later on if that is desired.
The diff below copies the boiler plate from in_ioctl() to a new function and moves SIOCAIFADDR, SIOCDIFADDR, and SIOCSIFADDR there. The next step will then be to actually merge the two cases per ioctl. Index: sys/netinet/in.c =================================================================== RCS file: /var/cvs/src/sys/netinet/in.c,v retrieving revision 1.152 diff -u -p -r1.152 in.c --- sys/netinet/in.c 25 May 2018 06:05:08 -0000 1.152 +++ sys/netinet/in.c 25 May 2018 06:24:30 -0000 @@ -84,6 +84,7 @@ void in_socktrim(struct sockaddr_in *); +int in_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *, int); int in_ioctl_get(u_long, caddr_t, struct ifnet *); void in_purgeaddr(struct ifaddr *); int in_addhost(struct in_ifaddr *, struct sockaddr_in *); @@ -216,7 +217,6 @@ in_ioctl(u_long cmd, caddr_t data, struc struct in_aliasreq *ifra = (struct in_aliasreq *)data; struct sockaddr_in oldaddr; int error = 0; - int newifaddr; if (ifp == NULL) return (ENXIO); @@ -230,6 +230,7 @@ in_ioctl(u_long cmd, caddr_t data, struc case SIOCAIFADDR: case SIOCDIFADDR: case SIOCSIFADDR: + return in_ioctl_change_ifaddr(cmd, data, ifp, privileged); case SIOCSIFNETMASK: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: @@ -248,47 +249,6 @@ in_ioctl(u_long cmd, caddr_t data, struc } switch (cmd) { - case SIOCAIFADDR: - case SIOCDIFADDR: - if (ifra->ifra_addr.sin_family == AF_INET) { - for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) { - if ((ifa->ifa_addr->sa_family == AF_INET) && - ifatoia(ifa)->ia_addr.sin_addr.s_addr == - ifra->ifra_addr.sin_addr.s_addr) - break; - } - ia = ifatoia(ifa); - } - if (cmd == SIOCDIFADDR && ia == NULL) { - error = EADDRNOTAVAIL; - goto err; - } - /* FALLTHROUGH */ - case SIOCSIFADDR: - if (!privileged) { - error = EPERM; - goto err; - } - - if (ia == NULL) { - ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); - ia->ia_addr.sin_family = AF_INET; - ia->ia_addr.sin_len = sizeof(ia->ia_addr); - 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_len = 8; - if (ifp->if_flags & IFF_BROADCAST) { - ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); - ia->ia_broadaddr.sin_family = AF_INET; - } - ia->ia_ifp = ifp; - - newifaddr = 1; - } else - newifaddr = 0; - break; - case SIOCSIFNETMASK: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: @@ -342,7 +302,76 @@ in_ioctl(u_long cmd, caddr_t data, struc ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr = ifra->ifra_addr.sin_addr.s_addr; break; + } + +err: + NET_UNLOCK(); + return (error); +} + +int +in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp, + int privileged) +{ + struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa; + struct in_ifaddr *ia = NULL; + struct in_aliasreq *ifra = (struct in_aliasreq *)data; + int error = 0; + int newifaddr; + NET_LOCK(); + + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family == AF_INET) { + ia = ifatoia(ifa); + break; + } + } + + switch (cmd) { + case SIOCAIFADDR: + case SIOCDIFADDR: + if (ifra->ifra_addr.sin_family == AF_INET) { + for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) { + if ((ifa->ifa_addr->sa_family == AF_INET) && + ifatoia(ifa)->ia_addr.sin_addr.s_addr == + ifra->ifra_addr.sin_addr.s_addr) + break; + } + ia = ifatoia(ifa); + } + if (cmd == SIOCDIFADDR && ia == NULL) { + error = EADDRNOTAVAIL; + goto err; + } + /* FALLTHROUGH */ + case SIOCSIFADDR: + if (!privileged) { + error = EPERM; + goto err; + } + + if (ia == NULL) { + ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); + ia->ia_addr.sin_family = AF_INET; + ia->ia_addr.sin_len = sizeof(ia->ia_addr); + 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_len = 8; + if (ifp->if_flags & IFF_BROADCAST) { + ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); + ia->ia_broadaddr.sin_family = AF_INET; + } + ia->ia_ifp = ifp; + + newifaddr = 1; + } else + newifaddr = 0; + break; + } + switch(cmd) { case SIOCSIFADDR: in_ifscrub(ifp, ia); error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), newifaddr); @@ -399,6 +428,9 @@ in_ioctl(u_long cmd, caddr_t data, struc in_purgeaddr(&ia->ia_ifa); dohooks(ifp->if_addrhooks, 0); break; + + default: + panic("invalid ioctl %lu", cmd); } err: