in.c revision 126264
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1982, 1986, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes * 3310939Swollman * @(#)in.c 8.4 (Berkeley) 1/9/95 3450477Speter * $FreeBSD: head/sys/netinet/in.c 126264 2004-02-26 04:27:55Z mlaier $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes#include <sys/param.h> 381549Srgrimes#include <sys/systm.h> 3924204Sbde#include <sys/sockio.h> 401541Srgrimes#include <sys/malloc.h> 411541Srgrimes#include <sys/socket.h> 4212704Sphk#include <sys/kernel.h> 4312704Sphk#include <sys/sysctl.h> 441541Srgrimes 451541Srgrimes#include <net/if.h> 4655009Sshin#include <net/if_types.h> 471541Srgrimes#include <net/route.h> 481541Srgrimes 491541Srgrimes#include <netinet/in.h> 501541Srgrimes#include <netinet/in_var.h> 5181127Sume#include <netinet/in_pcb.h> 521541Srgrimes 536363Sphk#include <netinet/igmp_var.h> 546363Sphk 5530354Sphkstatic MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address"); 5630309Sphk 5792723Salfredstatic int in_mask2len(struct in_addr *); 5892723Salfredstatic void in_len2mask(struct in_addr *, int); 5992723Salfredstatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t, 6092723Salfred struct ifnet *, struct thread *); 6155009Sshin 6292723Salfredstatic void in_socktrim(struct sockaddr_in *); 6392723Salfredstatic int in_ifinit(struct ifnet *, 6492723Salfred struct in_ifaddr *, struct sockaddr_in *, int); 651541Srgrimes 6618193Swollmanstatic int subnetsarelocal = 0; 6712704SphkSYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, 68123998Sru &subnetsarelocal, 0, "Treat all subnets as directly connected"); 6921666Swollman 7021666Swollmanstruct in_multihead in_multihead; /* XXX BSS initialization */ 7121666Swollman 7281127Sumeextern struct inpcbinfo ripcbinfo; 7381127Sumeextern struct inpcbinfo udbinfo; 7481127Sume 751541Srgrimes/* 761541Srgrimes * Return 1 if an internet address is for a ``local'' host 771541Srgrimes * (one to which we have a connection). If subnetsarelocal 781541Srgrimes * is true, this includes other subnets of the local net. 791541Srgrimes * Otherwise, it includes only the directly-connected (sub)nets. 801541Srgrimes */ 811549Srgrimesint 821541Srgrimesin_localaddr(in) 831541Srgrimes struct in_addr in; 841541Srgrimes{ 851541Srgrimes register u_long i = ntohl(in.s_addr); 861541Srgrimes register struct in_ifaddr *ia; 871541Srgrimes 881541Srgrimes if (subnetsarelocal) { 8974362Sphk TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) 901541Srgrimes if ((i & ia->ia_netmask) == ia->ia_net) 911541Srgrimes return (1); 921541Srgrimes } else { 9372012Sphk TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) 941541Srgrimes if ((i & ia->ia_subnetmask) == ia->ia_subnet) 951541Srgrimes return (1); 961541Srgrimes } 971541Srgrimes return (0); 981541Srgrimes} 991541Srgrimes 1001541Srgrimes/* 1011541Srgrimes * Determine whether an IP address is in a reserved set of addresses 1021541Srgrimes * that may not be forwarded, or whether datagrams to that destination 1031541Srgrimes * may be forwarded. 1041541Srgrimes */ 1051549Srgrimesint 1061541Srgrimesin_canforward(in) 1071541Srgrimes struct in_addr in; 1081541Srgrimes{ 1091541Srgrimes register u_long i = ntohl(in.s_addr); 1101541Srgrimes register u_long net; 1111541Srgrimes 1121541Srgrimes if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i)) 1131541Srgrimes return (0); 1141541Srgrimes if (IN_CLASSA(i)) { 1151541Srgrimes net = i & IN_CLASSA_NET; 1161541Srgrimes if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) 1171541Srgrimes return (0); 1181541Srgrimes } 1191541Srgrimes return (1); 1201541Srgrimes} 1211541Srgrimes 1221541Srgrimes/* 1231541Srgrimes * Trim a mask in a sockaddr 1241541Srgrimes */ 12512296Sphkstatic void 1261541Srgrimesin_socktrim(ap) 1271541Srgrimesstruct sockaddr_in *ap; 1281541Srgrimes{ 1291541Srgrimes register char *cplim = (char *) &ap->sin_addr; 1301541Srgrimes register char *cp = (char *) (&ap->sin_addr + 1); 1311541Srgrimes 1321541Srgrimes ap->sin_len = 0; 1334127Swollman while (--cp >= cplim) 1341541Srgrimes if (*cp) { 1351541Srgrimes (ap)->sin_len = cp - (char *) (ap) + 1; 1361541Srgrimes break; 1371541Srgrimes } 1381541Srgrimes} 1391541Srgrimes 14055009Sshinstatic int 14155009Sshinin_mask2len(mask) 14255009Sshin struct in_addr *mask; 14355009Sshin{ 14455009Sshin int x, y; 14555009Sshin u_char *p; 14655009Sshin 14755009Sshin p = (u_char *)mask; 14855009Sshin for (x = 0; x < sizeof(*mask); x++) { 14955009Sshin if (p[x] != 0xff) 15055009Sshin break; 15155009Sshin } 15255009Sshin y = 0; 15355009Sshin if (x < sizeof(*mask)) { 15455009Sshin for (y = 0; y < 8; y++) { 15555009Sshin if ((p[x] & (0x80 >> y)) == 0) 15655009Sshin break; 15755009Sshin } 15855009Sshin } 15955009Sshin return x * 8 + y; 16055009Sshin} 16155009Sshin 16255009Sshinstatic void 16355009Sshinin_len2mask(mask, len) 16455009Sshin struct in_addr *mask; 16555009Sshin int len; 16655009Sshin{ 16755009Sshin int i; 16855009Sshin u_char *p; 16955009Sshin 17055009Sshin p = (u_char *)mask; 17155009Sshin bzero(mask, sizeof(*mask)); 17255009Sshin for (i = 0; i < len / 8; i++) 17355009Sshin p[i] = 0xff; 17455009Sshin if (len % 8) 17555009Sshin p[i] = (0xff00 >> (len % 8)) & 0xff; 17655009Sshin} 17755009Sshin 1781541Srgrimes/* 1791541Srgrimes * Generic internet control operations (ioctl's). 1801541Srgrimes * Ifp is 0 if not an interface-specific ioctl. 1811541Srgrimes */ 1821541Srgrimes/* ARGSUSED */ 1831549Srgrimesint 18483366Sjulianin_control(so, cmd, data, ifp, td) 1851541Srgrimes struct socket *so; 18636735Sdfr u_long cmd; 1871541Srgrimes caddr_t data; 1881541Srgrimes register struct ifnet *ifp; 18983366Sjulian struct thread *td; 1901541Srgrimes{ 1911541Srgrimes register struct ifreq *ifr = (struct ifreq *)data; 19214632Sfenner register struct in_ifaddr *ia = 0, *iap; 1931541Srgrimes register struct ifaddr *ifa; 19484102Sjlemon struct in_addr dst; 1951541Srgrimes struct in_ifaddr *oia; 1961541Srgrimes struct in_aliasreq *ifra = (struct in_aliasreq *)data; 1971541Srgrimes struct sockaddr_in oldaddr; 19887124Sbrian int error, hostIsNew, iaIsNew, maskIsNew, s; 1991541Srgrimes 20087124Sbrian iaIsNew = 0; 20187124Sbrian 20255009Sshin switch (cmd) { 20355009Sshin case SIOCALIFADDR: 20455009Sshin case SIOCDLIFADDR: 20593593Sjhb if (td && (error = suser(td)) != 0) 20655009Sshin return error; 20755009Sshin /*fall through*/ 20855009Sshin case SIOCGLIFADDR: 20955009Sshin if (!ifp) 21055009Sshin return EINVAL; 21183366Sjulian return in_lifaddr_ioctl(so, cmd, data, ifp, td); 21255009Sshin } 21355009Sshin 2141541Srgrimes /* 2151541Srgrimes * Find address for this interface, if it exists. 21614632Sfenner * 21714632Sfenner * If an alias address was specified, find that one instead of 21884102Sjlemon * the first one on the interface, if possible. 2191541Srgrimes */ 22084102Sjlemon if (ifp) { 22184102Sjlemon dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; 22284102Sjlemon LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) 22384102Sjlemon if (iap->ia_ifp == ifp && 22484102Sjlemon iap->ia_addr.sin_addr.s_addr == dst.s_addr) { 22584102Sjlemon ia = iap; 22684102Sjlemon break; 22784102Sjlemon } 22884102Sjlemon if (ia == NULL) 22984102Sjlemon TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 23084102Sjlemon iap = ifatoia(ifa); 23184102Sjlemon if (iap->ia_addr.sin_family == AF_INET) { 23214632Sfenner ia = iap; 23314632Sfenner break; 23414632Sfenner } 23514632Sfenner } 23684102Sjlemon } 2371541Srgrimes 2381541Srgrimes switch (cmd) { 2391541Srgrimes 2401541Srgrimes case SIOCAIFADDR: 2411541Srgrimes case SIOCDIFADDR: 24241575Seivind if (ifp == 0) 24341575Seivind return (EADDRNOTAVAIL); 2448071Swollman if (ifra->ifra_addr.sin_family == AF_INET) { 24571999Sphk for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) { 2468071Swollman if (ia->ia_ifp == ifp && 2478071Swollman ia->ia_addr.sin_addr.s_addr == 2488071Swollman ifra->ifra_addr.sin_addr.s_addr) 2498071Swollman break; 2508071Swollman } 2518876Srgrimes if ((ifp->if_flags & IFF_POINTOPOINT) 2528071Swollman && (cmd == SIOCAIFADDR) 2538071Swollman && (ifra->ifra_dstaddr.sin_addr.s_addr 2548071Swollman == INADDR_ANY)) { 2559563Swollman return EDESTADDRREQ; 2568071Swollman } 2571541Srgrimes } 2581541Srgrimes if (cmd == SIOCDIFADDR && ia == 0) 2591541Srgrimes return (EADDRNOTAVAIL); 2601541Srgrimes /* FALLTHROUGH */ 2611541Srgrimes case SIOCSIFADDR: 2621541Srgrimes case SIOCSIFNETMASK: 2631541Srgrimes case SIOCSIFDSTADDR: 26493593Sjhb if (td && (error = suser(td)) != 0) 26525201Swollman return error; 2661541Srgrimes 2671541Srgrimes if (ifp == 0) 26841575Seivind return (EADDRNOTAVAIL); 2691541Srgrimes if (ia == (struct in_ifaddr *)0) { 27020407Swollman ia = (struct in_ifaddr *) 271111119Simp malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); 27220407Swollman if (ia == (struct in_ifaddr *)NULL) 2731541Srgrimes return (ENOBUFS); 27415092Sdg /* 27515092Sdg * Protect from ipintr() traversing address list 27615092Sdg * while we're modifying it. 27715092Sdg */ 27815092Sdg s = splnet(); 27920407Swollman TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link); 280108033Shsu 28120407Swollman ifa = &ia->ia_ifa; 282108033Shsu IFA_LOCK_INIT(ifa); 28320407Swollman ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr; 28420407Swollman ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; 28520407Swollman ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask; 286108033Shsu ifa->ifa_refcnt = 1; 287108033Shsu TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); 288108033Shsu 2891541Srgrimes ia->ia_sockmask.sin_len = 8; 29085740Sdes ia->ia_sockmask.sin_family = AF_INET; 2911541Srgrimes if (ifp->if_flags & IFF_BROADCAST) { 2921541Srgrimes ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 2931541Srgrimes ia->ia_broadaddr.sin_family = AF_INET; 2941541Srgrimes } 2951541Srgrimes ia->ia_ifp = ifp; 29615092Sdg splx(s); 29787124Sbrian iaIsNew = 1; 2981541Srgrimes } 2991541Srgrimes break; 3001541Srgrimes 3011541Srgrimes case SIOCSIFBRDADDR: 30293593Sjhb if (td && (error = suser(td)) != 0) 30325201Swollman return error; 3041541Srgrimes /* FALLTHROUGH */ 3051541Srgrimes 3061541Srgrimes case SIOCGIFADDR: 3071541Srgrimes case SIOCGIFNETMASK: 3081541Srgrimes case SIOCGIFDSTADDR: 3091541Srgrimes case SIOCGIFBRDADDR: 3101541Srgrimes if (ia == (struct in_ifaddr *)0) 3111541Srgrimes return (EADDRNOTAVAIL); 3121541Srgrimes break; 3131541Srgrimes } 3141541Srgrimes switch (cmd) { 3151541Srgrimes 3161541Srgrimes case SIOCGIFADDR: 3171541Srgrimes *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 31887124Sbrian return (0); 3191541Srgrimes 3201541Srgrimes case SIOCGIFBRDADDR: 3211541Srgrimes if ((ifp->if_flags & IFF_BROADCAST) == 0) 3221541Srgrimes return (EINVAL); 3231541Srgrimes *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 32487124Sbrian return (0); 3251541Srgrimes 3261541Srgrimes case SIOCGIFDSTADDR: 3271541Srgrimes if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 3281541Srgrimes return (EINVAL); 3291541Srgrimes *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 33087124Sbrian return (0); 3311541Srgrimes 3321541Srgrimes case SIOCGIFNETMASK: 3331541Srgrimes *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 33487124Sbrian return (0); 3351541Srgrimes 3361541Srgrimes case SIOCSIFDSTADDR: 3371541Srgrimes if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 3381541Srgrimes return (EINVAL); 3391541Srgrimes oldaddr = ia->ia_dstaddr; 3401541Srgrimes ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 3411541Srgrimes if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 3421541Srgrimes (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 3431541Srgrimes ia->ia_dstaddr = oldaddr; 3441541Srgrimes return (error); 3451541Srgrimes } 3461541Srgrimes if (ia->ia_flags & IFA_ROUTE) { 3471541Srgrimes ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 3481541Srgrimes rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 3491541Srgrimes ia->ia_ifa.ifa_dstaddr = 3501541Srgrimes (struct sockaddr *)&ia->ia_dstaddr; 3511541Srgrimes rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 3521541Srgrimes } 35387124Sbrian return (0); 3541541Srgrimes 3551541Srgrimes case SIOCSIFBRDADDR: 3561541Srgrimes if ((ifp->if_flags & IFF_BROADCAST) == 0) 3571541Srgrimes return (EINVAL); 3581541Srgrimes ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 35987124Sbrian return (0); 3601541Srgrimes 3611541Srgrimes case SIOCSIFADDR: 36287124Sbrian error = in_ifinit(ifp, ia, 36387124Sbrian (struct sockaddr_in *) &ifr->ifr_addr, 1); 36487124Sbrian if (error != 0 && iaIsNew) 36587124Sbrian break; 366126264Smlaier if (error == 0) 367126264Smlaier EVENTHANDLER_INVOKE(ifaddr_event, ifp); 36887124Sbrian return (0); 3691541Srgrimes 3701541Srgrimes case SIOCSIFNETMASK: 37185740Sdes ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr; 37285740Sdes ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr); 37387124Sbrian return (0); 3741541Srgrimes 3751541Srgrimes case SIOCAIFADDR: 3761541Srgrimes maskIsNew = 0; 3771541Srgrimes hostIsNew = 1; 3781541Srgrimes error = 0; 3791541Srgrimes if (ia->ia_addr.sin_family == AF_INET) { 3801541Srgrimes if (ifra->ifra_addr.sin_len == 0) { 3811541Srgrimes ifra->ifra_addr = ia->ia_addr; 3821541Srgrimes hostIsNew = 0; 3831541Srgrimes } else if (ifra->ifra_addr.sin_addr.s_addr == 3841541Srgrimes ia->ia_addr.sin_addr.s_addr) 3851541Srgrimes hostIsNew = 0; 3861541Srgrimes } 3871541Srgrimes if (ifra->ifra_mask.sin_len) { 3881541Srgrimes in_ifscrub(ifp, ia); 3891541Srgrimes ia->ia_sockmask = ifra->ifra_mask; 39085740Sdes ia->ia_sockmask.sin_family = AF_INET; 3911541Srgrimes ia->ia_subnetmask = 3921541Srgrimes ntohl(ia->ia_sockmask.sin_addr.s_addr); 3931541Srgrimes maskIsNew = 1; 3941541Srgrimes } 3951541Srgrimes if ((ifp->if_flags & IFF_POINTOPOINT) && 3961541Srgrimes (ifra->ifra_dstaddr.sin_family == AF_INET)) { 3971541Srgrimes in_ifscrub(ifp, ia); 3981541Srgrimes ia->ia_dstaddr = ifra->ifra_dstaddr; 3991541Srgrimes maskIsNew = 1; /* We lie; but the effect's the same */ 4001541Srgrimes } 4011541Srgrimes if (ifra->ifra_addr.sin_family == AF_INET && 4021541Srgrimes (hostIsNew || maskIsNew)) 4031541Srgrimes error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 40487124Sbrian if (error != 0 && iaIsNew) 40587124Sbrian break; 40687124Sbrian 4071541Srgrimes if ((ifp->if_flags & IFF_BROADCAST) && 4081541Srgrimes (ifra->ifra_broadaddr.sin_family == AF_INET)) 4091541Srgrimes ia->ia_broadaddr = ifra->ifra_broadaddr; 410126264Smlaier if (error == 0) 411126264Smlaier EVENTHANDLER_INVOKE(ifaddr_event, ifp); 4121541Srgrimes return (error); 4131541Srgrimes 4141541Srgrimes case SIOCDIFADDR: 41574299Sru /* 41674299Sru * in_ifscrub kills the interface route. 41774299Sru */ 4181541Srgrimes in_ifscrub(ifp, ia); 41915092Sdg /* 42074299Sru * in_ifadown gets rid of all the rest of 42174299Sru * the routes. This is not quite the right 42274299Sru * thing to do, but at least if we are running 42374299Sru * a routing process they will come back. 42474299Sru */ 42576469Sru in_ifadown(&ia->ia_ifa, 1); 42681127Sume /* 42781127Sume * XXX horrible hack to detect that we are being called 42881127Sume * from if_detach() 42981127Sume */ 430121922Ssam if (ifaddr_byindex(ifp->if_index) == NULL) { 43198102Shsu in_pcbpurgeif0(&ripcbinfo, ifp); 43298102Shsu in_pcbpurgeif0(&udbinfo, ifp); 43381127Sume } 434126264Smlaier EVENTHANDLER_INVOKE(ifaddr_event, ifp); 43587124Sbrian error = 0; 4361541Srgrimes break; 4371541Srgrimes 4381541Srgrimes default: 4391541Srgrimes if (ifp == 0 || ifp->if_ioctl == 0) 4401541Srgrimes return (EOPNOTSUPP); 4411541Srgrimes return ((*ifp->if_ioctl)(ifp, cmd, data)); 4421541Srgrimes } 44387124Sbrian 44487124Sbrian /* 44587124Sbrian * Protect from ipintr() traversing address list while we're modifying 44687124Sbrian * it. 44787124Sbrian */ 44887124Sbrian s = splnet(); 44987124Sbrian TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); 45087124Sbrian TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link); 45187124Sbrian LIST_REMOVE(ia, ia_hash); 45287124Sbrian IFAFREE(&ia->ia_ifa); 45387124Sbrian splx(s); 45487124Sbrian 45587124Sbrian return (error); 4561541Srgrimes} 4571541Srgrimes 4581541Srgrimes/* 45955009Sshin * SIOC[GAD]LIFADDR. 46055009Sshin * SIOCGLIFADDR: get first address. (?!?) 46155009Sshin * SIOCGLIFADDR with IFLR_PREFIX: 46255009Sshin * get first address that matches the specified prefix. 46355009Sshin * SIOCALIFADDR: add the specified address. 46455009Sshin * SIOCALIFADDR with IFLR_PREFIX: 46555009Sshin * EINVAL since we can't deduce hostid part of the address. 46655009Sshin * SIOCDLIFADDR: delete the specified address. 46755009Sshin * SIOCDLIFADDR with IFLR_PREFIX: 46855009Sshin * delete the first address that matches the specified prefix. 46955009Sshin * return values: 47055009Sshin * EINVAL on invalid parameters 47155009Sshin * EADDRNOTAVAIL on prefix match failed/specified address not found 47255009Sshin * other values may be returned from in_ioctl() 47355009Sshin */ 47455009Sshinstatic int 47583366Sjulianin_lifaddr_ioctl(so, cmd, data, ifp, td) 47655009Sshin struct socket *so; 47755009Sshin u_long cmd; 47855009Sshin caddr_t data; 47955009Sshin struct ifnet *ifp; 48083366Sjulian struct thread *td; 48155009Sshin{ 48255009Sshin struct if_laddrreq *iflr = (struct if_laddrreq *)data; 48355009Sshin struct ifaddr *ifa; 48455009Sshin 48555009Sshin /* sanity checks */ 48655009Sshin if (!data || !ifp) { 48755009Sshin panic("invalid argument to in_lifaddr_ioctl"); 48855009Sshin /*NOTRECHED*/ 48955009Sshin } 49055009Sshin 49155009Sshin switch (cmd) { 49255009Sshin case SIOCGLIFADDR: 49355009Sshin /* address must be specified on GET with IFLR_PREFIX */ 49455009Sshin if ((iflr->flags & IFLR_PREFIX) == 0) 49555009Sshin break; 49655009Sshin /*FALLTHROUGH*/ 49755009Sshin case SIOCALIFADDR: 49855009Sshin case SIOCDLIFADDR: 49955009Sshin /* address must be specified on ADD and DELETE */ 50055917Sshin if (iflr->addr.ss_family != AF_INET) 50155009Sshin return EINVAL; 50255917Sshin if (iflr->addr.ss_len != sizeof(struct sockaddr_in)) 50355009Sshin return EINVAL; 50455009Sshin /* XXX need improvement */ 50555917Sshin if (iflr->dstaddr.ss_family 50655917Sshin && iflr->dstaddr.ss_family != AF_INET) 50755009Sshin return EINVAL; 50855917Sshin if (iflr->dstaddr.ss_family 50955917Sshin && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in)) 51055009Sshin return EINVAL; 51155009Sshin break; 51255009Sshin default: /*shouldn't happen*/ 51355009Sshin return EOPNOTSUPP; 51455009Sshin } 51555009Sshin if (sizeof(struct in_addr) * 8 < iflr->prefixlen) 51655009Sshin return EINVAL; 51755009Sshin 51855009Sshin switch (cmd) { 51955009Sshin case SIOCALIFADDR: 52055009Sshin { 52155009Sshin struct in_aliasreq ifra; 52255009Sshin 52355009Sshin if (iflr->flags & IFLR_PREFIX) 52455009Sshin return EINVAL; 52555009Sshin 52655009Sshin /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */ 52755009Sshin bzero(&ifra, sizeof(ifra)); 52855009Sshin bcopy(iflr->iflr_name, ifra.ifra_name, 52955009Sshin sizeof(ifra.ifra_name)); 53055009Sshin 53155917Sshin bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len); 53255009Sshin 53355917Sshin if (iflr->dstaddr.ss_family) { /*XXX*/ 53455009Sshin bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr, 53555917Sshin iflr->dstaddr.ss_len); 53655009Sshin } 53755009Sshin 53855009Sshin ifra.ifra_mask.sin_family = AF_INET; 53955009Sshin ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in); 54055009Sshin in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen); 54155009Sshin 54283366Sjulian return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td); 54355009Sshin } 54455009Sshin case SIOCGLIFADDR: 54555009Sshin case SIOCDLIFADDR: 54655009Sshin { 54755009Sshin struct in_ifaddr *ia; 54855009Sshin struct in_addr mask, candidate, match; 54955009Sshin struct sockaddr_in *sin; 55055009Sshin int cmp; 55155009Sshin 55255009Sshin bzero(&mask, sizeof(mask)); 55355009Sshin if (iflr->flags & IFLR_PREFIX) { 55455009Sshin /* lookup a prefix rather than address. */ 55555009Sshin in_len2mask(&mask, iflr->prefixlen); 55655009Sshin 55755009Sshin sin = (struct sockaddr_in *)&iflr->addr; 55855009Sshin match.s_addr = sin->sin_addr.s_addr; 55955009Sshin match.s_addr &= mask.s_addr; 56055009Sshin 56155009Sshin /* if you set extra bits, that's wrong */ 56255009Sshin if (match.s_addr != sin->sin_addr.s_addr) 56355009Sshin return EINVAL; 56455009Sshin 56555009Sshin cmp = 1; 56655009Sshin } else { 56755009Sshin if (cmd == SIOCGLIFADDR) { 56855009Sshin /* on getting an address, take the 1st match */ 56955009Sshin cmp = 0; /*XXX*/ 57055009Sshin } else { 57155009Sshin /* on deleting an address, do exact match */ 57255009Sshin in_len2mask(&mask, 32); 57355009Sshin sin = (struct sockaddr_in *)&iflr->addr; 57455009Sshin match.s_addr = sin->sin_addr.s_addr; 57555009Sshin 57655009Sshin cmp = 1; 57755009Sshin } 57855009Sshin } 57955009Sshin 58055009Sshin TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 58155009Sshin if (ifa->ifa_addr->sa_family != AF_INET6) 58255009Sshin continue; 58355009Sshin if (!cmp) 58455009Sshin break; 58555009Sshin candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr; 58655009Sshin candidate.s_addr &= mask.s_addr; 58755009Sshin if (candidate.s_addr == match.s_addr) 58855009Sshin break; 58955009Sshin } 59055009Sshin if (!ifa) 59155009Sshin return EADDRNOTAVAIL; 59255009Sshin ia = (struct in_ifaddr *)ifa; 59355009Sshin 59455009Sshin if (cmd == SIOCGLIFADDR) { 59555009Sshin /* fill in the if_laddrreq structure */ 59655009Sshin bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len); 59755009Sshin 59855009Sshin if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { 59955009Sshin bcopy(&ia->ia_dstaddr, &iflr->dstaddr, 60055009Sshin ia->ia_dstaddr.sin_len); 60155009Sshin } else 60255009Sshin bzero(&iflr->dstaddr, sizeof(iflr->dstaddr)); 60355009Sshin 60455009Sshin iflr->prefixlen = 60555009Sshin in_mask2len(&ia->ia_sockmask.sin_addr); 60655009Sshin 60755009Sshin iflr->flags = 0; /*XXX*/ 60855009Sshin 60955009Sshin return 0; 61055009Sshin } else { 61155009Sshin struct in_aliasreq ifra; 61255009Sshin 61355009Sshin /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */ 61455009Sshin bzero(&ifra, sizeof(ifra)); 61555009Sshin bcopy(iflr->iflr_name, ifra.ifra_name, 61655009Sshin sizeof(ifra.ifra_name)); 61755009Sshin 61855009Sshin bcopy(&ia->ia_addr, &ifra.ifra_addr, 61955009Sshin ia->ia_addr.sin_len); 62055009Sshin if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { 62155009Sshin bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr, 62255009Sshin ia->ia_dstaddr.sin_len); 62355009Sshin } 62455009Sshin bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr, 62555009Sshin ia->ia_sockmask.sin_len); 62655009Sshin 62755009Sshin return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, 62883366Sjulian ifp, td); 62955009Sshin } 63055009Sshin } 63155009Sshin } 63255009Sshin 63355009Sshin return EOPNOTSUPP; /*just for safety*/ 63455009Sshin} 63555009Sshin 63655009Sshin/* 6371541Srgrimes * Delete any existing route for an interface. 6381541Srgrimes */ 63922672Swollmanvoid 6401541Srgrimesin_ifscrub(ifp, ia) 6411541Srgrimes register struct ifnet *ifp; 6421541Srgrimes register struct in_ifaddr *ia; 6431541Srgrimes{ 6441541Srgrimes 6451541Srgrimes if ((ia->ia_flags & IFA_ROUTE) == 0) 6461541Srgrimes return; 6471541Srgrimes if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 6481541Srgrimes rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 6491541Srgrimes else 6501541Srgrimes rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 6511541Srgrimes ia->ia_flags &= ~IFA_ROUTE; 6521541Srgrimes} 6531541Srgrimes 6541541Srgrimes/* 6551541Srgrimes * Initialize an interface's internet address 6561541Srgrimes * and routing table entry. 6571541Srgrimes */ 65812296Sphkstatic int 6591541Srgrimesin_ifinit(ifp, ia, sin, scrub) 6601541Srgrimes register struct ifnet *ifp; 6611541Srgrimes register struct in_ifaddr *ia; 6621541Srgrimes struct sockaddr_in *sin; 6631541Srgrimes int scrub; 6641541Srgrimes{ 6651541Srgrimes register u_long i = ntohl(sin->sin_addr.s_addr); 6661541Srgrimes struct sockaddr_in oldaddr; 66794326Sbrian int s = splimp(), flags = RTF_UP, error = 0; 6681541Srgrimes 6691541Srgrimes oldaddr = ia->ia_addr; 670105748Ssuz if (oldaddr.sin_family == AF_INET) 671105748Ssuz LIST_REMOVE(ia, ia_hash); 6721541Srgrimes ia->ia_addr = *sin; 673105748Ssuz if (ia->ia_addr.sin_family == AF_INET) 674105748Ssuz LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), 675105748Ssuz ia, ia_hash); 6761541Srgrimes /* 6771541Srgrimes * Give the interface a chance to initialize 6781541Srgrimes * if this is its first address, 6791541Srgrimes * and to validate the address if necessary. 6801541Srgrimes */ 6811541Srgrimes if (ifp->if_ioctl && 6821541Srgrimes (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 6831541Srgrimes splx(s); 684105748Ssuz /* LIST_REMOVE(ia, ia_hash) is done in in_control */ 6851541Srgrimes ia->ia_addr = oldaddr; 686105748Ssuz if (ia->ia_addr.sin_family == AF_INET) 687105748Ssuz LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), 688105748Ssuz ia, ia_hash); 6891541Srgrimes return (error); 6901541Srgrimes } 6911541Srgrimes splx(s); 6921541Srgrimes if (scrub) { 6931541Srgrimes ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 6941541Srgrimes in_ifscrub(ifp, ia); 6951541Srgrimes ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 6961541Srgrimes } 6971541Srgrimes if (IN_CLASSA(i)) 6981541Srgrimes ia->ia_netmask = IN_CLASSA_NET; 6991541Srgrimes else if (IN_CLASSB(i)) 7001541Srgrimes ia->ia_netmask = IN_CLASSB_NET; 7011541Srgrimes else 7021541Srgrimes ia->ia_netmask = IN_CLASSC_NET; 7031541Srgrimes /* 7041541Srgrimes * The subnet mask usually includes at least the standard network part, 7051541Srgrimes * but may may be smaller in the case of supernetting. 7061541Srgrimes * If it is set, we believe it. 7071541Srgrimes */ 7081541Srgrimes if (ia->ia_subnetmask == 0) { 7091541Srgrimes ia->ia_subnetmask = ia->ia_netmask; 7101541Srgrimes ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 7111541Srgrimes } else 7121541Srgrimes ia->ia_netmask &= ia->ia_subnetmask; 7131541Srgrimes ia->ia_net = i & ia->ia_netmask; 7141541Srgrimes ia->ia_subnet = i & ia->ia_subnetmask; 7151541Srgrimes in_socktrim(&ia->ia_sockmask); 7161541Srgrimes /* 7171541Srgrimes * Add route for the network. 7181541Srgrimes */ 7191541Srgrimes ia->ia_ifa.ifa_metric = ifp->if_metric; 7201541Srgrimes if (ifp->if_flags & IFF_BROADCAST) { 7211541Srgrimes ia->ia_broadaddr.sin_addr.s_addr = 7221541Srgrimes htonl(ia->ia_subnet | ~ia->ia_subnetmask); 7231541Srgrimes ia->ia_netbroadcast.s_addr = 7241541Srgrimes htonl(ia->ia_net | ~ ia->ia_netmask); 7251541Srgrimes } else if (ifp->if_flags & IFF_LOOPBACK) { 7261541Srgrimes ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 7271541Srgrimes flags |= RTF_HOST; 7281541Srgrimes } else if (ifp->if_flags & IFF_POINTOPOINT) { 7291541Srgrimes if (ia->ia_dstaddr.sin_family != AF_INET) 7301541Srgrimes return (0); 7311541Srgrimes flags |= RTF_HOST; 7321541Srgrimes } 73394326Sbrian 73494326Sbrian /*- 73594326Sbrian * Don't add host routes for interface addresses of 73694326Sbrian * 0.0.0.0 --> 0.255.255.255 netmask 255.0.0.0. This makes it 73794326Sbrian * possible to assign several such address pairs with consistent 73894326Sbrian * results (no host route) and is required by BOOTP. 73994326Sbrian * 74094326Sbrian * XXX: This is ugly ! There should be a way for the caller to 74194326Sbrian * say that they don't want a host route. 74294326Sbrian */ 74394326Sbrian if (ia->ia_addr.sin_addr.s_addr != INADDR_ANY || 74494326Sbrian ia->ia_netmask != IN_CLASSA_NET || 74594326Sbrian ia->ia_dstaddr.sin_addr.s_addr != htonl(IN_CLASSA_HOST)) { 74694326Sbrian if ((error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags)) != 0) { 74794326Sbrian ia->ia_addr = oldaddr; 74894326Sbrian return (error); 74994326Sbrian } 7501541Srgrimes ia->ia_flags |= IFA_ROUTE; 75187124Sbrian } 75287124Sbrian 7531541Srgrimes /* 7541541Srgrimes * If the interface supports multicast, join the "all hosts" 7551541Srgrimes * multicast group on that interface. 7561541Srgrimes */ 7571541Srgrimes if (ifp->if_flags & IFF_MULTICAST) { 7581541Srgrimes struct in_addr addr; 7591541Srgrimes 7601541Srgrimes addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 7611541Srgrimes in_addmulti(&addr, ifp); 7621541Srgrimes } 7631541Srgrimes return (error); 7641541Srgrimes} 7651541Srgrimes 7661541Srgrimes 7671541Srgrimes/* 7681541Srgrimes * Return 1 if the address might be a local broadcast address. 7691541Srgrimes */ 7701549Srgrimesint 7711541Srgrimesin_broadcast(in, ifp) 7721541Srgrimes struct in_addr in; 7731541Srgrimes struct ifnet *ifp; 7741541Srgrimes{ 7751541Srgrimes register struct ifaddr *ifa; 7761541Srgrimes u_long t; 7771541Srgrimes 7781541Srgrimes if (in.s_addr == INADDR_BROADCAST || 7791541Srgrimes in.s_addr == INADDR_ANY) 7801541Srgrimes return 1; 7811541Srgrimes if ((ifp->if_flags & IFF_BROADCAST) == 0) 7821541Srgrimes return 0; 7831541Srgrimes t = ntohl(in.s_addr); 7841541Srgrimes /* 7851541Srgrimes * Look through the list of addresses for a match 7861541Srgrimes * with a broadcast address. 7871541Srgrimes */ 7881541Srgrimes#define ia ((struct in_ifaddr *)ifa) 78974362Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 7901541Srgrimes if (ifa->ifa_addr->sa_family == AF_INET && 7911541Srgrimes (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr || 7921541Srgrimes in.s_addr == ia->ia_netbroadcast.s_addr || 7931541Srgrimes /* 7941541Srgrimes * Check for old-style (host 0) broadcast. 7951541Srgrimes */ 79613351Sguido t == ia->ia_subnet || t == ia->ia_net) && 79713351Sguido /* 79813351Sguido * Check for an all one subnetmask. These 79913351Sguido * only exist when an interface gets a secondary 80013351Sguido * address. 80113351Sguido */ 80213351Sguido ia->ia_subnetmask != (u_long)0xffffffff) 8031541Srgrimes return 1; 8041541Srgrimes return (0); 8051541Srgrimes#undef ia 8061541Srgrimes} 8071541Srgrimes/* 8081541Srgrimes * Add an address to the list of IP multicast addresses for a given interface. 8091541Srgrimes */ 8101541Srgrimesstruct in_multi * 8111541Srgrimesin_addmulti(ap, ifp) 8121541Srgrimes register struct in_addr *ap; 8131541Srgrimes register struct ifnet *ifp; 8141541Srgrimes{ 8151541Srgrimes register struct in_multi *inm; 81621666Swollman int error; 81721666Swollman struct sockaddr_in sin; 81821666Swollman struct ifmultiaddr *ifma; 8191541Srgrimes int s = splnet(); 8201541Srgrimes 8211541Srgrimes /* 82221666Swollman * Call generic routine to add membership or increment 82321666Swollman * refcount. It wants addresses in the form of a sockaddr, 82421666Swollman * so we build one here (being careful to zero the unused bytes). 8251541Srgrimes */ 82621666Swollman bzero(&sin, sizeof sin); 82721666Swollman sin.sin_family = AF_INET; 82821666Swollman sin.sin_len = sizeof sin; 82921666Swollman sin.sin_addr = *ap; 83021666Swollman error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma); 83121666Swollman if (error) { 83221666Swollman splx(s); 83321666Swollman return 0; 8341541Srgrimes } 8357280Swollman 83621666Swollman /* 83721666Swollman * If ifma->ifma_protospec is null, then if_addmulti() created 83821666Swollman * a new record. Otherwise, we are done. 83921666Swollman */ 84064853Sbde if (ifma->ifma_protospec != 0) { 84164853Sbde splx(s); 84221666Swollman return ifma->ifma_protospec; 84364853Sbde } 84421666Swollman 845111119Simp /* XXX - if_addmulti uses M_WAITOK. Can this really be called 84621666Swollman at interrupt time? If so, need to fix if_addmulti. XXX */ 84769781Sdwmalone inm = (struct in_multi *)malloc(sizeof(*inm), M_IPMADDR, 84869781Sdwmalone M_NOWAIT | M_ZERO); 84921666Swollman if (inm == NULL) { 85021666Swollman splx(s); 85121666Swollman return (NULL); 8521541Srgrimes } 85321666Swollman 85421666Swollman inm->inm_addr = *ap; 85521666Swollman inm->inm_ifp = ifp; 85621666Swollman inm->inm_ifma = ifma; 85721666Swollman ifma->ifma_protospec = inm; 85821666Swollman LIST_INSERT_HEAD(&in_multihead, inm, inm_link); 85921666Swollman 86021666Swollman /* 86121666Swollman * Let IGMP know that we have joined a new IP multicast group. 86221666Swollman */ 86321666Swollman igmp_joingroup(inm); 8641541Srgrimes splx(s); 8651541Srgrimes return (inm); 8661541Srgrimes} 8671541Srgrimes 8681541Srgrimes/* 8691541Srgrimes * Delete a multicast address record. 8701541Srgrimes */ 8711549Srgrimesvoid 8721541Srgrimesin_delmulti(inm) 8731541Srgrimes register struct in_multi *inm; 8741541Srgrimes{ 87521666Swollman struct ifmultiaddr *ifma = inm->inm_ifma; 87645997Sluigi struct in_multi my_inm; 8771541Srgrimes int s = splnet(); 8781541Srgrimes 87945997Sluigi my_inm.inm_ifp = NULL ; /* don't send the leave msg */ 88021666Swollman if (ifma->ifma_refcount == 1) { 8811541Srgrimes /* 8821541Srgrimes * No remaining claims to this record; let IGMP know that 8831541Srgrimes * we are leaving the multicast group. 88445997Sluigi * But do it after the if_delmulti() which might reset 88545997Sluigi * the interface and nuke the packet. 8861541Srgrimes */ 88745997Sluigi my_inm = *inm ; 88821666Swollman ifma->ifma_protospec = 0; 88921666Swollman LIST_REMOVE(inm, inm_link); 8901541Srgrimes free(inm, M_IPMADDR); 8911541Srgrimes } 89221666Swollman /* XXX - should be separate API for when we have an ifma? */ 89321666Swollman if_delmulti(ifma->ifma_ifp, ifma->ifma_addr); 89445997Sluigi if (my_inm.inm_ifp != NULL) 89545997Sluigi igmp_leavegroup(&my_inm); 8961541Srgrimes splx(s); 8971541Srgrimes} 898