in.c revision 260504
12088Ssos/*- 2228976Suqs * Copyright (c) 1982, 1986, 1991, 1993 32088Ssos * The Regents of the University of California. All rights reserved. 42088Ssos * Copyright (C) 2001 WIDE Project. All rights reserved. 52088Ssos * 62088Ssos * Redistribution and use in source and binary forms, with or without 72088Ssos * modification, are permitted provided that the following conditions 82088Ssos * are met: 95994Ssos * 1. Redistributions of source code must retain the above copyright 105994Ssos * notice, this list of conditions and the following disclaimer. 112088Ssos * 2. Redistributions in binary form must reproduce the above copyright 122088Ssos * notice, this list of conditions and the following disclaimer in the 132088Ssos * documentation and/or other materials provided with the distribution. 142088Ssos * 4. Neither the name of the University nor the names of its contributors 1597748Sschweikh * may be used to endorse or promote products derived from this software 162088Ssos * without specific prior written permission. 172088Ssos * 182088Ssos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 192088Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202088Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 212088Ssos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 222088Ssos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 232088Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 242088Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 252088Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 262088Ssos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 272088Ssos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 282088Ssos * SUCH DAMAGE. 29114601Sobrien * 30114601Sobrien * @(#)in.c 8.4 (Berkeley) 1/9/95 3129603Scharnier */ 322088Ssos 3329603Scharnier#include <sys/cdefs.h> 342088Ssos__FBSDID("$FreeBSD: stable/10/sys/netinet/in.c 260504 2014-01-10 09:45:28Z ae $"); 3529603Scharnier 363864Sswallace#include "opt_mpath.h" 3729603Scharnier 3842505Syokota#include <sys/param.h> 3966834Sphk#include <sys/systm.h> 4066834Sphk#include <sys/sockio.h> 41298297Semaste#include <sys/malloc.h> 42267540Sray#include <sys/priv.h> 432088Ssos#include <sys/socket.h> 442088Ssos#include <sys/jail.h> 452088Ssos#include <sys/kernel.h> 4676643Simp#include <sys/proc.h> 4790394Sru#include <sys/sysctl.h> 4890394Sru#include <sys/syslog.h> 4976643Simp 5090394Sru#include <net/if.h> 5190394Sru#include <net/if_var.h> 5290394Sru#include <net/if_arp.h> 5390394Sru#include <net/if_dl.h> 5490394Sru#include <net/if_llatbl.h> 5590394Sru#include <net/if_types.h> 5676643Simp#include <net/route.h> 5776643Simp#include <net/vnet.h> 5876643Simp 5976643Simp#include <netinet/if_ether.h> 60196500Sed#include <netinet/in.h> 61196500Sed#include <netinet/in_var.h> 62228437Sed#include <netinet/in_pcb.h> 638857Srgrimes#include <netinet/ip_var.h> 642088Ssos#include <netinet/ip_carp.h> 652088Ssos#include <netinet/igmp_var.h> 6638139Syokota#include <netinet/udp.h> 672088Ssos#include <netinet/udp_var.h> 682088Ssos 69228437Sedstatic int in_mask2len(struct in_addr *); 7032316Syokotastatic void in_len2mask(struct in_addr *, int); 7132316Syokotastatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t, 7232316Syokota struct ifnet *, struct thread *); 7332316Syokota 7432316Syokotastatic void in_socktrim(struct sockaddr_in *); 75228437Sedstatic int in_ifinit(struct ifnet *, struct in_ifaddr *, 7632316Syokota struct sockaddr_in *, int, int); 7732316Syokotastatic void in_purgemaddrs(struct ifnet *); 7832316Syokota 7932316Syokotastatic VNET_DEFINE(int, nosameprefix); 8032316Syokota#define V_nosameprefix VNET(nosameprefix) 81228437SedSYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_RW, 825994Ssos &VNET_NAME(nosameprefix), 0, 835994Ssos "Refuse to create same prefixes on different interfaces"); 845994Ssos 855994SsosVNET_DECLARE(struct inpcbinfo, ripcbinfo); 865994Ssos#define V_ripcbinfo VNET(ripcbinfo) 875994Ssos 885994Ssos/* 895994Ssos * Return 1 if an internet address is for a ``local'' host 905994Ssos * (one to which we have a connection). 915994Ssos */ 925994Ssosint 939202Srgrimesin_localaddr(struct in_addr in) 945994Ssos{ 955994Ssos register u_long i = ntohl(in.s_addr); 965994Ssos register struct in_ifaddr *ia; 979202Srgrimes 985994Ssos IN_IFADDR_RLOCK(); 995994Ssos TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { 1005994Ssos if ((i & ia->ia_subnetmask) == ia->ia_subnet) { 1015994Ssos IN_IFADDR_RUNLOCK(); 1025994Ssos return (1); 1035994Ssos } 1045994Ssos } 1055994Ssos IN_IFADDR_RUNLOCK(); 1062088Ssos return (0); 1072088Ssos} 108228437Sed 109228437Sed/* 110228437Sed * Return 1 if an internet address is for the local host and configured 111228437Sed * on one of its interfaces. 112228437Sed */ 113228437Sedint 114228437Sedin_localip(struct in_addr in) 115228437Sed{ 116298297Semaste struct in_ifaddr *ia; 117228437Sed 1182088Ssos IN_IFADDR_RLOCK(); 119228437Sed LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) { 120228437Sed if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) { 1212088Ssos IN_IFADDR_RUNLOCK(); 122298297Semaste return (1); 123228437Sed } 124228437Sed } 125228437Sed IN_IFADDR_RUNLOCK(); 126228437Sed return (0); 127228437Sed} 128228437Sed 129228437Sed/* 130228437Sed * Determine whether an IP address is in a reserved set of addresses 131228437Sed * that may not be forwarded, or whether datagrams to that destination 132228437Sed * may be forwarded. 133228437Sed */ 134228437Sedint 135228437Sedin_canforward(struct in_addr in) 136228437Sed{ 137228437Sed register u_long i = ntohl(in.s_addr); 138228437Sed register u_long net; 139228437Sed 140228437Sed if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i)) 141228437Sed return (0); 142228437Sed if (IN_CLASSA(i)) { 143228437Sed net = i & IN_CLASSA_NET; 144228437Sed if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) 145228437Sed return (0); 146228437Sed } 147228437Sed return (1); 148298297Semaste} 149298297Semaste 150298297Semaste/* 151298297Semaste * Trim a mask in a sockaddr 152298297Semaste */ 153298297Semastestatic void 154267540Srayin_socktrim(struct sockaddr_in *ap) 155267540Sray{ 156267540Sray register char *cplim = (char *) &ap->sin_addr; 157267540Sray register char *cp = (char *) (&ap->sin_addr + 1); 158268366Sray 159268366Sray ap->sin_len = 0; 160267540Sray while (--cp >= cplim) 161268366Sray if (*cp) { 162268366Sray (ap)->sin_len = cp - (char *) (ap) + 1; 163268366Sray break; 164267540Sray } 165267540Sray} 166228437Sed 1672088Ssosstatic int 1682088Ssosin_mask2len(mask) 1692088Ssos struct in_addr *mask; 1702088Ssos{ 17129603Scharnier int x, y; 1722088Ssos u_char *p; 1732088Ssos 1742088Ssos p = (u_char *)mask; 1752088Ssos for (x = 0; x < sizeof(*mask); x++) { 176228437Sed if (p[x] != 0xff) 1772088Ssos break; 1782088Ssos } 1795536Ssos y = 0; 1805536Ssos if (x < sizeof(*mask)) { 1815536Ssos for (y = 0; y < 8; y++) { 1822088Ssos if ((p[x] & (0x80 >> y)) == 0) 1832088Ssos break; 18477394Ssobomax } 1852088Ssos } 1862088Ssos return (x * 8 + y); 1872088Ssos} 1882088Ssos 18977394Ssobomaxstatic void 1902088Ssosin_len2mask(struct in_addr *mask, int len) 1912088Ssos{ 1922088Ssos int i; 1932088Ssos u_char *p; 1942088Ssos 1952088Ssos p = (u_char *)mask; 1962088Ssos bzero(mask, sizeof(*mask)); 1972088Ssos for (i = 0; i < len / 8; i++) 1982088Ssos p[i] = 0xff; 1992088Ssos if (len % 8) 2002088Ssos p[i] = (0xff00 >> (len % 8)) & 0xff; 2012088Ssos} 2022088Ssos 203228437Sed/* 20499816Salfred * Generic internet control operations (ioctl's). 2052088Ssos * 20632316Syokota * ifp is NULL if not an interface-specific ioctl. 2072088Ssos */ 208196500Sed/* ARGSUSED */ 2092088Ssosint 210196500Sedin_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, 2112088Ssos struct thread *td) 212196500Sed{ 2132088Ssos register struct ifreq *ifr = (struct ifreq *)data; 214196500Sed register struct in_ifaddr *ia, *iap; 2152088Ssos register struct ifaddr *ifa; 216196500Sed struct in_addr allhosts_addr; 2172088Ssos struct in_addr dst; 218196500Sed struct in_ifinfo *ii; 2192088Ssos struct in_aliasreq *ifra = (struct in_aliasreq *)data; 220196500Sed int error, hostIsNew, iaIsNew, maskIsNew; 2212088Ssos int iaIsFirst; 222196500Sed u_long ocmd = cmd; 2232088Ssos 224196500Sed /* 2252088Ssos * Pre-10.x compat: OSIOCAIFADDR passes a shorter 226196500Sed * struct in_aliasreq, without ifra_vhid. 22748105Syokota */ 228196500Sed if (cmd == OSIOCAIFADDR) 2292088Ssos cmd = SIOCAIFADDR; 230196500Sed 2312088Ssos ia = NULL; 232196500Sed iaIsFirst = 0; 2332088Ssos iaIsNew = 0; 234196500Sed allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 2352088Ssos 236196500Sed /* 2372088Ssos * Filter out ioctls we implement directly; forward the rest on to 238196500Sed * in_lifaddr_ioctl() and ifp->if_ioctl(). 2392088Ssos */ 240196500Sed switch (cmd) { 2412088Ssos case SIOCGIFADDR: 242196500Sed case SIOCGIFBRDADDR: 2435994Ssos case SIOCGIFDSTADDR: 244196500Sed case SIOCGIFNETMASK: 24538053Syokota case SIOCDIFADDR: 246196500Sed break; 24754380Syokota case SIOCAIFADDR: 248196500Sed /* 24954380Syokota * ifra_addr must be present and be of INET family. 250196500Sed * ifra_broadaddr and ifra_mask are optional. 25154380Syokota */ 252196500Sed if (ifra->ifra_addr.sin_len != sizeof(struct sockaddr_in) || 25354380Syokota ifra->ifra_addr.sin_family != AF_INET) 254196500Sed return (EINVAL); 25554380Syokota if (ifra->ifra_broadaddr.sin_len != 0 && 256196500Sed (ifra->ifra_broadaddr.sin_len != 25754380Syokota sizeof(struct sockaddr_in) || 258196500Sed ifra->ifra_broadaddr.sin_family != AF_INET)) 25954380Syokota return (EINVAL); 260196500Sed#if 0 26165759Sdwmalone /* 262196500Sed * ifconfig(8) in pre-10.x doesn't set sin_family for the 26365759Sdwmalone * mask. The code is disabled for the 10.x timeline, to 264196500Sed * make SIOCAIFADDR compatible with 9.x ifconfig(8). 26574118Sache * The code should be enabled in 11.x 266196500Sed */ 26732316Syokota if (ifra->ifra_mask.sin_len != 0 && 26832316Syokota (ifra->ifra_mask.sin_len != sizeof(struct sockaddr_in) || 26932316Syokota ifra->ifra_mask.sin_family != AF_INET)) 270196500Sed return (EINVAL); 2712088Ssos#endif 2722088Ssos break; 2732088Ssos case SIOCSIFADDR: 274196500Sed case SIOCSIFBRDADDR: 2752088Ssos case SIOCSIFDSTADDR: 2762088Ssos case SIOCSIFNETMASK: 2772088Ssos /* We no longer support that old commands. */ 278196500Sed return (EINVAL); 2792088Ssos 2802088Ssos case SIOCALIFADDR: 2812088Ssos if (td != NULL) { 282197330Sed error = priv_check(td, PRIV_NET_ADDIFADDR); 2832088Ssos if (error) 2842088Ssos return (error); 2852088Ssos } 2862088Ssos if (ifp == NULL) 2872088Ssos return (EINVAL); 2882088Ssos return in_lifaddr_ioctl(so, cmd, data, ifp, td); 2892088Ssos 29077394Ssobomax case SIOCDLIFADDR: 291298297Semaste if (td != NULL) { 2922088Ssos error = priv_check(td, PRIV_NET_DELIFADDR); 29332316Syokota if (error) 2942088Ssos return (error); 295298297Semaste } 2962088Ssos if (ifp == NULL) 29732316Syokota return (EINVAL); 29832316Syokota return in_lifaddr_ioctl(so, cmd, data, ifp, td); 29932316Syokota 30032316Syokota case SIOCGLIFADDR: 30132316Syokota if (ifp == NULL) 30232316Syokota return (EINVAL); 30332316Syokota return in_lifaddr_ioctl(so, cmd, data, ifp, td); 30432316Syokota 30532316Syokota default: 30632316Syokota if (ifp == NULL || ifp->if_ioctl == NULL) 30732316Syokota return (EOPNOTSUPP); 30832316Syokota return ((*ifp->if_ioctl)(ifp, cmd, data)); 30932316Syokota } 31032316Syokota 31132316Syokota if (ifp == NULL) 31232316Syokota return (EADDRNOTAVAIL); 31332316Syokota 31432316Syokota /* 31532316Syokota * Security checks before we get involved in any work. 3162088Ssos */ 31732316Syokota switch (cmd) { 31832316Syokota case SIOCAIFADDR: 31932316Syokota if (td != NULL) { 32032316Syokota error = priv_check(td, PRIV_NET_ADDIFADDR); 32132316Syokota if (error) 32232316Syokota return (error); 323228437Sed } 32432316Syokota break; 32532316Syokota 32632316Syokota case SIOCDIFADDR: 32732316Syokota if (td != NULL) { 32832316Syokota error = priv_check(td, PRIV_NET_DELIFADDR); 3292088Ssos if (error) 3302088Ssos return (error); 3312088Ssos } 3322088Ssos break; 3332088Ssos } 3342088Ssos 3352088Ssos /* 3362088Ssos * Find address for this interface, if it exists. 3372088Ssos * 338196500Sed * If an alias address was specified, find that one instead of the 3392088Ssos * first one on the interface, if possible. 340196500Sed */ 3412088Ssos dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; 3422088Ssos IN_IFADDR_RLOCK(); 34332316Syokota LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) { 3442088Ssos if (iap->ia_ifp == ifp && 3452088Ssos iap->ia_addr.sin_addr.s_addr == dst.s_addr) { 34632316Syokota if (td == NULL || prison_check_ip4(td->td_ucred, 34732316Syokota &dst) == 0) 3482088Ssos ia = iap; 3492088Ssos break; 350228437Sed } 35132316Syokota } 35232316Syokota if (ia != NULL) 35332316Syokota ifa_ref(&ia->ia_ifa); 35432316Syokota IN_IFADDR_RUNLOCK(); 35532316Syokota if (ia == NULL) { 3562088Ssos IF_ADDR_RLOCK(ifp); 35732316Syokota TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 35832316Syokota iap = ifatoia(ifa); 35932316Syokota if (iap->ia_addr.sin_family == AF_INET) { 36032316Syokota if (td != NULL && 36132316Syokota prison_check_ip4(td->td_ucred, 36232316Syokota &iap->ia_addr.sin_addr) != 0) 36332316Syokota continue; 36432316Syokota ia = iap; 36532316Syokota break; 36632316Syokota } 36732316Syokota } 36832316Syokota if (ia != NULL) 36932316Syokota ifa_ref(&ia->ia_ifa); 37032316Syokota IF_ADDR_RUNLOCK(ifp); 37132316Syokota } 37232316Syokota if (ia == NULL) 37332316Syokota iaIsFirst = 1; 37432316Syokota 37532316Syokota error = 0; 37632316Syokota switch (cmd) { 37732316Syokota case SIOCAIFADDR: 37832316Syokota case SIOCDIFADDR: 37932316Syokota if (ifra->ifra_addr.sin_family == AF_INET) { 38032316Syokota struct in_ifaddr *oia; 38132316Syokota 38232316Syokota IN_IFADDR_RLOCK(); 38332316Syokota for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) { 38432316Syokota if (ia->ia_ifp == ifp && 38532316Syokota ia->ia_addr.sin_addr.s_addr == 38632316Syokota ifra->ifra_addr.sin_addr.s_addr) 38732316Syokota break; 38832316Syokota } 38932316Syokota if (ia != NULL && ia != oia) 39032316Syokota ifa_ref(&ia->ia_ifa); 39132316Syokota if (oia != NULL && ia != oia) 39232316Syokota ifa_free(&oia->ia_ifa); 39332316Syokota IN_IFADDR_RUNLOCK(); 39432316Syokota if ((ifp->if_flags & IFF_POINTOPOINT) 39532316Syokota && (cmd == SIOCAIFADDR) 39632316Syokota && (ifra->ifra_dstaddr.sin_addr.s_addr 39732316Syokota == INADDR_ANY)) { 39832316Syokota error = EDESTADDRREQ; 39932316Syokota goto out; 40032316Syokota } 40132316Syokota } 40232316Syokota if (cmd == SIOCDIFADDR && ia == NULL) { 40332316Syokota error = EADDRNOTAVAIL; 40432316Syokota goto out; 40532316Syokota } 40632316Syokota if (ia == NULL) { 40732316Syokota ia = (struct in_ifaddr *) 40832316Syokota malloc(sizeof *ia, M_IFADDR, M_NOWAIT | 40932316Syokota M_ZERO); 41032316Syokota if (ia == NULL) { 411228437Sed error = ENOBUFS; 4122088Ssos goto out; 4132088Ssos } 414196500Sed 4152088Ssos ifa = &ia->ia_ifa; 4162088Ssos ifa_init(ifa); 417196500Sed ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr; 4188857Srgrimes ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; 4192088Ssos ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask; 420196500Sed 4212088Ssos ia->ia_sockmask.sin_len = 8; 4222088Ssos ia->ia_sockmask.sin_family = AF_INET; 423196500Sed if (ifp->if_flags & IFF_BROADCAST) { 4242088Ssos ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 4252088Ssos ia->ia_broadaddr.sin_family = AF_INET; 426196500Sed } 4272088Ssos ia->ia_ifp = ifp; 4282088Ssos 429196500Sed ifa_ref(ifa); /* if_addrhead */ 4302088Ssos IF_ADDR_WLOCK(ifp); 4312088Ssos TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); 432196500Sed IF_ADDR_WUNLOCK(ifp); 4332088Ssos ifa_ref(ifa); /* in_ifaddrhead */ 4342088Ssos IN_IFADDR_WLOCK(); 435196500Sed TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link); 4362088Ssos IN_IFADDR_WUNLOCK(); 4372088Ssos iaIsNew = 1; 438196500Sed } 4392088Ssos break; 4402088Ssos 441196500Sed case SIOCGIFADDR: 4422088Ssos case SIOCGIFNETMASK: 4432088Ssos case SIOCGIFDSTADDR: 444196500Sed case SIOCGIFBRDADDR: 4452088Ssos if (ia == NULL) { 4462088Ssos error = EADDRNOTAVAIL; 447196500Sed goto out; 44848105Syokota } 44948105Syokota break; 450196500Sed } 4512088Ssos 4522088Ssos /* 453196500Sed * Most paths in this switch return directly or via out. Only paths 4542088Ssos * that remove the address break in order to hit common removal code. 4552088Ssos */ 456196500Sed switch (cmd) { 4572088Ssos case SIOCGIFADDR: 4582088Ssos *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 459196500Sed goto out; 4602088Ssos 4612088Ssos case SIOCGIFBRDADDR: 462196500Sed if ((ifp->if_flags & IFF_BROADCAST) == 0) { 4632088Ssos error = EINVAL; 4642088Ssos goto out; 465196500Sed } 4662088Ssos *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 4672088Ssos goto out; 468196500Sed 4692088Ssos case SIOCGIFDSTADDR: 4702088Ssos if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 471196500Sed error = EINVAL; 47232316Syokota goto out; 47332316Syokota } 474196500Sed *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 47538053Syokota goto out; 47638053Syokota 477196500Sed case SIOCGIFNETMASK: 47854380Syokota *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 47954380Syokota goto out; 480196500Sed 48154380Syokota case SIOCAIFADDR: 48254380Syokota maskIsNew = 0; 483196500Sed hostIsNew = 1; 48454380Syokota error = 0; 48554380Syokota if (ifra->ifra_addr.sin_addr.s_addr == 486196500Sed ia->ia_addr.sin_addr.s_addr) 48754380Syokota hostIsNew = 0; 48854380Syokota if (ifra->ifra_mask.sin_len) { 489196500Sed /* 49054380Syokota * QL: XXX 49154380Syokota * Need to scrub the prefix here in case 492196500Sed * the issued command is SIOCAIFADDR with 49354380Syokota * the same address, but with a different 49454380Syokota * prefix length. And if the prefix length 495196500Sed * is the same as before, then the call is 49654380Syokota * un-necessarily executed here. 49754380Syokota */ 498196500Sed in_ifscrub(ifp, ia, LLE_STATIC); 49965759Sdwmalone ia->ia_sockmask = ifra->ifra_mask; 50065759Sdwmalone ia->ia_sockmask.sin_family = AF_INET; 501196500Sed ia->ia_subnetmask = 50265759Sdwmalone ntohl(ia->ia_sockmask.sin_addr.s_addr); 50365759Sdwmalone maskIsNew = 1; 504196500Sed } 50574118Sache if ((ifp->if_flags & IFF_POINTOPOINT) && 50674118Sache (ifra->ifra_dstaddr.sin_family == AF_INET)) { 5072088Ssos in_ifscrub(ifp, ia, LLE_STATIC); 508196500Sed ia->ia_dstaddr = ifra->ifra_dstaddr; 5098857Srgrimes maskIsNew = 1; /* We lie; but the effect's the same */ 5102088Ssos } 5118857Srgrimes if (hostIsNew || maskIsNew) 5122088Ssos error = in_ifinit(ifp, ia, &ifra->ifra_addr, maskIsNew, 51332316Syokota (ocmd == cmd ? ifra->ifra_vhid : 0)); 51432316Syokota if (error != 0 && iaIsNew) 5152088Ssos break; 5168857Srgrimes 5172088Ssos if ((ifp->if_flags & IFF_BROADCAST) && 51832316Syokota ifra->ifra_broadaddr.sin_len) 5192088Ssos ia->ia_broadaddr = ifra->ifra_broadaddr; 5202088Ssos if (error == 0) { 5212088Ssos ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]); 5228857Srgrimes if (iaIsFirst && 5232088Ssos (ifp->if_flags & IFF_MULTICAST) != 0) { 5248857Srgrimes error = in_joingroup(ifp, &allhosts_addr, 5259202Srgrimes NULL, &ii->ii_allhosts); 5268857Srgrimes } 5272088Ssos EVENTHANDLER_INVOKE(ifaddr_event, ifp); 5288857Srgrimes } 5292088Ssos goto out; 5308857Srgrimes 5312088Ssos case SIOCDIFADDR: 5322088Ssos /* 5332088Ssos * in_ifscrub kills the interface route. 5342088Ssos */ 535228437Sed in_ifscrub(ifp, ia, LLE_STATIC); 53642505Syokota 5372088Ssos /* 53829603Scharnier * in_ifadown gets rid of all the rest of 5392088Ssos * the routes. This is not quite the right 5402088Ssos * thing to do, but at least if we are running 5412088Ssos * a routing process they will come back. 5422088Ssos */ 5432088Ssos in_ifadown(&ia->ia_ifa, 1); 5442088Ssos EVENTHANDLER_INVOKE(ifaddr_event, ifp); 5452088Ssos error = 0; 5462088Ssos break; 5472088Ssos 5482088Ssos default: 549196500Sed panic("in_control: unsupported ioctl"); 5502088Ssos } 5518857Srgrimes 5522088Ssos if (ia->ia_ifa.ifa_carp) 5532088Ssos (*carp_detach_p)(&ia->ia_ifa); 5542088Ssos 5552088Ssos IF_ADDR_WLOCK(ifp); 5562088Ssos /* Re-check that ia is still part of the list. */ 5572088Ssos TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 5582088Ssos if (ifa == &ia->ia_ifa) 5592088Ssos break; 5602088Ssos } 5612088Ssos if (ifa == NULL) { 5622088Ssos /* 5632088Ssos * If we lost the race with another thread, there is no need to 5642088Ssos * try it again for the next loop as there is no other exit 5656046Ssos * path between here and out. 5666046Ssos */ 5676046Ssos IF_ADDR_WUNLOCK(ifp); 5688857Srgrimes error = EADDRNOTAVAIL; 5692088Ssos goto out; 5702088Ssos } 571228437Sed TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); 57232316Syokota IF_ADDR_WUNLOCK(ifp); 57332316Syokota ifa_free(&ia->ia_ifa); /* if_addrhead */ 57432316Syokota 57532316Syokota IN_IFADDR_WLOCK(); 5762088Ssos TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link); 57732316Syokota 57832316Syokota LIST_REMOVE(ia, ia_hash); 57932316Syokota IN_IFADDR_WUNLOCK(); 58032316Syokota /* 58132316Syokota * If this is the last IPv4 address configured on this 58232316Syokota * interface, leave the all-hosts group. 58332316Syokota * No state-change report need be transmitted. 58432316Syokota */ 58532316Syokota IFP_TO_IA(ifp, iap); 58632316Syokota if (iap == NULL) { 58732316Syokota ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]); 58832316Syokota IN_MULTI_LOCK(); 58932316Syokota if (ii->ii_allhosts) { 59032316Syokota (void)in_leavegroup_locked(ii->ii_allhosts, NULL); 59132316Syokota ii->ii_allhosts = NULL; 59232316Syokota } 59332316Syokota IN_MULTI_UNLOCK(); 59432316Syokota } else 59532316Syokota ifa_free(&iap->ia_ifa); 59632316Syokota 59732316Syokota ifa_free(&ia->ia_ifa); /* in_ifaddrhead */ 59832316Syokotaout: 59932316Syokota if (ia != NULL) 60032316Syokota ifa_free(&ia->ia_ifa); 60132316Syokota return (error); 60232316Syokota} 60332316Syokota 60432316Syokota/* 60532316Syokota * SIOC[GAD]LIFADDR. 60632316Syokota * SIOCGLIFADDR: get first address. (?!?) 60732316Syokota * SIOCGLIFADDR with IFLR_PREFIX: 60832316Syokota * get first address that matches the specified prefix. 60932316Syokota * SIOCALIFADDR: add the specified address. 61032316Syokota * SIOCALIFADDR with IFLR_PREFIX: 61132316Syokota * EINVAL since we can't deduce hostid part of the address. 612228437Sed * SIOCDLIFADDR: delete the specified address. 61332316Syokota * SIOCDLIFADDR with IFLR_PREFIX: 61432316Syokota * delete the first address that matches the specified prefix. 615196500Sed * return values: 616196500Sed * EINVAL on invalid parameters 61732316Syokota * EADDRNOTAVAIL on prefix match failed/specified address not found 61832316Syokota * other values may be returned from in_ioctl() 61932316Syokota */ 62032316Syokotastatic int 62132316Syokotain_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data, 62232316Syokota struct ifnet *ifp, struct thread *td) 62332316Syokota{ 62432316Syokota struct if_laddrreq *iflr = (struct if_laddrreq *)data; 62532316Syokota struct ifaddr *ifa; 62632316Syokota 62732316Syokota /* sanity checks */ 62832316Syokota if (data == NULL || ifp == NULL) { 62932316Syokota panic("invalid argument to in_lifaddr_ioctl"); 63032316Syokota /*NOTRECHED*/ 63132316Syokota } 63232316Syokota 63332316Syokota switch (cmd) { 63432316Syokota case SIOCGLIFADDR: 63532316Syokota /* address must be specified on GET with IFLR_PREFIX */ 63632316Syokota if ((iflr->flags & IFLR_PREFIX) == 0) 63732316Syokota break; 63832316Syokota /*FALLTHROUGH*/ 63932316Syokota case SIOCALIFADDR: 64032316Syokota case SIOCDLIFADDR: 64132316Syokota /* address must be specified on ADD and DELETE */ 64232316Syokota if (iflr->addr.ss_family != AF_INET) 64332316Syokota return (EINVAL); 64432316Syokota if (iflr->addr.ss_len != sizeof(struct sockaddr_in)) 64532316Syokota return (EINVAL); 64632316Syokota /* XXX need improvement */ 64732316Syokota if (iflr->dstaddr.ss_family 64848105Syokota && iflr->dstaddr.ss_family != AF_INET) 64948105Syokota return (EINVAL); 65048105Syokota if (iflr->dstaddr.ss_family 65132316Syokota && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in)) 65232316Syokota return (EINVAL); 65332316Syokota break; 65432316Syokota default: /*shouldn't happen*/ 65532316Syokota return (EOPNOTSUPP); 65632316Syokota } 65732316Syokota if (sizeof(struct in_addr) * 8 < iflr->prefixlen) 65832316Syokota return (EINVAL); 65932316Syokota 66032316Syokota switch (cmd) { 66132316Syokota case SIOCALIFADDR: 66232316Syokota { 66332316Syokota struct in_aliasreq ifra; 66432316Syokota 66532316Syokota if (iflr->flags & IFLR_PREFIX) 66632316Syokota return (EINVAL); 66732316Syokota 66832316Syokota /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */ 66932316Syokota bzero(&ifra, sizeof(ifra)); 67032316Syokota bcopy(iflr->iflr_name, ifra.ifra_name, 67132316Syokota sizeof(ifra.ifra_name)); 67232316Syokota 67332316Syokota bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len); 67432316Syokota 67538053Syokota if (iflr->dstaddr.ss_family) { /*XXX*/ 67638053Syokota bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr, 67738053Syokota iflr->dstaddr.ss_len); 67854380Syokota } 67954380Syokota 68054380Syokota ifra.ifra_mask.sin_family = AF_INET; 68154380Syokota ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in); 68254380Syokota in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen); 68354380Syokota 68454380Syokota return (in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td)); 68554380Syokota } 68654380Syokota case SIOCGLIFADDR: 68754380Syokota case SIOCDLIFADDR: 68854380Syokota { 68954380Syokota struct in_ifaddr *ia; 69054380Syokota struct in_addr mask, candidate, match; 69154380Syokota struct sockaddr_in *sin; 69254380Syokota 69354380Syokota bzero(&mask, sizeof(mask)); 69454380Syokota bzero(&match, sizeof(match)); 69554380Syokota if (iflr->flags & IFLR_PREFIX) { 69654380Syokota /* lookup a prefix rather than address. */ 69754380Syokota in_len2mask(&mask, iflr->prefixlen); 69854380Syokota 69965759Sdwmalone sin = (struct sockaddr_in *)&iflr->addr; 70065759Sdwmalone match.s_addr = sin->sin_addr.s_addr; 70165759Sdwmalone match.s_addr &= mask.s_addr; 70265759Sdwmalone 70365759Sdwmalone /* if you set extra bits, that's wrong */ 70465759Sdwmalone if (match.s_addr != sin->sin_addr.s_addr) 70574118Sache return (EINVAL); 70674118Sache 70774118Sache } else { 70832316Syokota /* on getting an address, take the 1st match */ 70932316Syokota /* on deleting an address, do exact match */ 71032316Syokota if (cmd != SIOCGLIFADDR) { 71132316Syokota in_len2mask(&mask, 32); 71232486Syokota sin = (struct sockaddr_in *)&iflr->addr; 71332316Syokota match.s_addr = sin->sin_addr.s_addr; 71432316Syokota } 71532316Syokota } 71632316Syokota 71732316Syokota IF_ADDR_RLOCK(ifp); 71832316Syokota TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 71932316Syokota if (ifa->ifa_addr->sa_family != AF_INET) 72032316Syokota continue; 72132316Syokota if (match.s_addr == 0) 72232316Syokota break; 72332316Syokota sin = (struct sockaddr_in *)&ifa->ifa_addr; 72432316Syokota candidate.s_addr = sin->sin_addr.s_addr; 72532316Syokota candidate.s_addr &= mask.s_addr; 72632316Syokota if (candidate.s_addr == match.s_addr) 72732316Syokota break; 72832316Syokota } 72932316Syokota if (ifa != NULL) 730228437Sed ifa_ref(ifa); 73132316Syokota IF_ADDR_RUNLOCK(ifp); 73232316Syokota if (ifa == NULL) 73332316Syokota return (EADDRNOTAVAIL); 73432316Syokota ia = (struct in_ifaddr *)ifa; 73532486Syokota 73632316Syokota if (cmd == SIOCGLIFADDR) { 73732316Syokota /* fill in the if_laddrreq structure */ 73832486Syokota bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len); 73932486Syokota 74032486Syokota if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { 74132316Syokota bcopy(&ia->ia_dstaddr, &iflr->dstaddr, 74232316Syokota ia->ia_dstaddr.sin_len); 74332316Syokota } else 74432486Syokota bzero(&iflr->dstaddr, sizeof(iflr->dstaddr)); 74532316Syokota 74632316Syokota iflr->prefixlen = 747196500Sed in_mask2len(&ia->ia_sockmask.sin_addr); 74832316Syokota 74932316Syokota iflr->flags = 0; /*XXX*/ 75032316Syokota ifa_free(ifa); 75132486Syokota 75232316Syokota return (0); 75332316Syokota } else { 75432316Syokota struct in_aliasreq ifra; 75532486Syokota 75632316Syokota /* fill in_aliasreq and do ioctl(SIOCDIFADDR) */ 75732316Syokota bzero(&ifra, sizeof(ifra)); 758228437Sed bcopy(iflr->iflr_name, ifra.ifra_name, 75932316Syokota sizeof(ifra.ifra_name)); 76032316Syokota 76132316Syokota bcopy(&ia->ia_addr, &ifra.ifra_addr, 76232316Syokota ia->ia_addr.sin_len); 76332316Syokota if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { 76432486Syokota bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr, 76532316Syokota ia->ia_dstaddr.sin_len); 76632486Syokota } 76732486Syokota bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr, 76832486Syokota ia->ia_sockmask.sin_len); 76932486Syokota ifa_free(ifa); 77032486Syokota 77132316Syokota return (in_control(so, SIOCDIFADDR, (caddr_t)&ifra, 77232316Syokota ifp, td)); 77332316Syokota } 77432316Syokota } 77532316Syokota } 77632316Syokota 77732316Syokota return (EOPNOTSUPP); /*just for safety*/ 77832316Syokota} 77932316Syokota 78032316Syokota/* 78132316Syokota * Delete any existing route for an interface. 78232316Syokota */ 78332316Syokotavoid 78432316Syokotain_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, u_int flags) 78532316Syokota{ 78632316Syokota 78732316Syokota in_scrubprefix(ia, flags); 78832316Syokota} 78932316Syokota 79032316Syokota/* 79132316Syokota * Initialize an interface's internet address 79232316Syokota * and routing table entry. 79332316Syokota */ 79432316Syokotastatic int 79532316Syokotain_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, 79632316Syokota int masksupplied, int vhid) 79732316Syokota{ 79832316Syokota register u_long i = ntohl(sin->sin_addr.s_addr); 79932486Syokota int flags, error = 0; 80032316Syokota 80132316Syokota IN_IFADDR_WLOCK(); 802228437Sed if (ia->ia_addr.sin_family == AF_INET) 803298297Semaste LIST_REMOVE(ia, ia_hash); 804298297Semaste ia->ia_addr = *sin; 805298297Semaste LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), 806298297Semaste ia, ia_hash); 807298297Semaste IN_IFADDR_WUNLOCK(); 808298297Semaste 809298297Semaste if (vhid > 0) { 810298297Semaste if (carp_attach_p != NULL) 811298297Semaste error = (*carp_attach_p)(&ia->ia_ifa, vhid); 812298297Semaste else 813298297Semaste error = EPROTONOSUPPORT; 814298297Semaste } 815298297Semaste if (error) 816298297Semaste return (error); 817298297Semaste 818298297Semaste /* 819298297Semaste * Give the interface a chance to initialize 82019569Sjoerg * if this is its first address, 8212088Ssos * and to validate the address if necessary. 82232316Syokota */ 82332316Syokota if (ifp->if_ioctl != NULL && 824298297Semaste (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) != 0) 825298297Semaste /* LIST_REMOVE(ia, ia_hash) is done in in_control */ 826298297Semaste return (error); 82719569Sjoerg 828267540Sray /* 829267540Sray * Be compatible with network classes, if netmask isn't supplied, 83099816Salfred * guess it based on classes. 8312088Ssos */ 832298297Semaste if (!masksupplied) { 833298297Semaste if (IN_CLASSA(i)) 834298297Semaste ia->ia_subnetmask = IN_CLASSA_NET; 835298297Semaste else if (IN_CLASSB(i)) 836298297Semaste ia->ia_subnetmask = IN_CLASSB_NET; 837298297Semaste else 838298297Semaste ia->ia_subnetmask = IN_CLASSC_NET; 839298297Semaste ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 840298297Semaste } 841298297Semaste ia->ia_subnet = i & ia->ia_subnetmask; 842298297Semaste in_socktrim(&ia->ia_sockmask); 84376502Ssobomax 844298297Semaste /* 845298297Semaste * Add route for the network. 846298297Semaste */ 847298297Semaste flags = RTF_UP; 848298297Semaste ia->ia_ifa.ifa_metric = ifp->if_metric; 849298297Semaste if (ifp->if_flags & IFF_BROADCAST) { 850298297Semaste if (ia->ia_subnetmask == IN_RFC3021_MASK) 85176502Ssobomax ia->ia_broadaddr.sin_addr.s_addr = INADDR_BROADCAST; 85276643Simp else 853298297Semaste ia->ia_broadaddr.sin_addr.s_addr = 85479677Sobrien htonl(ia->ia_subnet | ~ia->ia_subnetmask); 8552088Ssos } else if (ifp->if_flags & IFF_LOOPBACK) { 8562088Ssos ia->ia_dstaddr = ia->ia_addr; 85732316Syokota flags |= RTF_HOST; 85832316Syokota } else if (ifp->if_flags & IFF_POINTOPOINT) { 85932316Syokota if (ia->ia_dstaddr.sin_family != AF_INET) 8602088Ssos return (0); 861298297Semaste flags |= RTF_HOST; 8622088Ssos } 8632088Ssos if (!vhid && (error = in_addprefix(ia, flags)) != 0) 86419569Sjoerg return (error); 86519569Sjoerg 86619569Sjoerg if (ia->ia_addr.sin_addr.s_addr == INADDR_ANY) 86719569Sjoerg return (0); 86832316Syokota 86932316Syokota if (ifp->if_flags & IFF_POINTOPOINT && 87032316Syokota ia->ia_dstaddr.sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr) 87132316Syokota return (0); 87232316Syokota 87332316Syokota /* 87419569Sjoerg * add a loopback route to self 87519569Sjoerg */ 87632316Syokota if (V_useloopback && !vhid && !(ifp->if_flags & IFF_LOOPBACK)) { 87729603Scharnier struct route ia_ro; 878298297Semaste 8792088Ssos bzero(&ia_ro, sizeof(ia_ro)); 8802088Ssos *((struct sockaddr_in *)(&ia_ro.ro_dst)) = ia->ia_addr; 88132316Syokota rtalloc_ign_fib(&ia_ro, 0, RT_DEFAULT_FIB); 88232316Syokota if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) && 88332316Syokota (ia_ro.ro_rt->rt_ifp == V_loif)) { 884298297Semaste RT_LOCK(ia_ro.ro_rt); 88532316Syokota RT_ADDREF(ia_ro.ro_rt); 88632316Syokota RTFREE_LOCKED(ia_ro.ro_rt); 8872088Ssos } else 8882088Ssos error = ifa_add_loopback_route((struct ifaddr *)ia, 889228437Sed (struct sockaddr *)&ia->ia_addr); 89099816Salfred if (error == 0) 8912088Ssos ia->ia_flags |= IFA_RTSELF; 89232316Syokota if (ia_ro.ro_rt != NULL) 89332316Syokota RTFREE(ia_ro.ro_rt); 8942088Ssos } 8952088Ssos 89632316Syokota return (error); 89729603Scharnier} 89832316Syokota 89932316Syokota#define rtinitflags(x) \ 9002088Ssos ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \ 9012088Ssos ? RTF_HOST : 0) 9022088Ssos 9032088Ssos/* 9042088Ssos * Generate a routing message when inserting or deleting 9052088Ssos * an interface address alias. 90632316Syokota */ 90732316Syokotastatic void in_addralias_rtmsg(int cmd, struct in_addr *prefix, 90832316Syokota struct in_ifaddr *target) 90932316Syokota{ 91032316Syokota struct route pfx_ro; 91132316Syokota struct sockaddr_in *pfx_addr; 91232316Syokota struct rtentry msg_rt; 9132088Ssos 9142088Ssos /* QL: XXX 915228437Sed * This is a bit questionable because there is no 91699816Salfred * additional route entry added/deleted for an address 9172088Ssos * alias. Therefore this route report is inaccurate. 9182088Ssos */ 9192088Ssos bzero(&pfx_ro, sizeof(pfx_ro)); 9202088Ssos pfx_addr = (struct sockaddr_in *)(&pfx_ro.ro_dst); 9212088Ssos pfx_addr->sin_len = sizeof(*pfx_addr); 9222088Ssos pfx_addr->sin_family = AF_INET; 9232088Ssos pfx_addr->sin_addr = *prefix; 9242088Ssos rtalloc_ign_fib(&pfx_ro, 0, 0); 9252088Ssos if (pfx_ro.ro_rt != NULL) { 92629603Scharnier msg_rt = *pfx_ro.ro_rt; 9272088Ssos 9282088Ssos /* QL: XXX 9292088Ssos * Point the gateway to the new interface 930228437Sed * address as if a new prefix route entry has 9312088Ssos * been added through the new address alias. 9322088Ssos * All other parts of the rtentry is accurate, 9332088Ssos * e.g., rt_key, rt_mask, rt_ifp etc. 9342088Ssos */ 9352088Ssos msg_rt.rt_gateway = (struct sockaddr *)&target->ia_addr; 9362088Ssos rt_newaddrmsg(cmd, (struct ifaddr *)target, 0, &msg_rt); 9372088Ssos RTFREE(pfx_ro.ro_rt); 9382088Ssos } 9392088Ssos return; 9402088Ssos} 94129603Scharnier 9422088Ssos/* 9432088Ssos * Check if we have a route for the given prefix already or add one accordingly. 9442088Ssos */ 9452088Ssosint 94629603Scharnierin_addprefix(struct in_ifaddr *target, int flags) 9472088Ssos{ 9482088Ssos struct in_ifaddr *ia; 9492088Ssos struct in_addr prefix, mask, p, m; 950133353Sjmg int error; 9512088Ssos 9522088Ssos if ((flags & RTF_HOST) != 0) { 95329603Scharnier prefix = target->ia_dstaddr.sin_addr; 9542088Ssos mask.s_addr = 0; 9552088Ssos } else { 956228437Sed prefix = target->ia_addr.sin_addr; 9572088Ssos mask = target->ia_sockmask.sin_addr; 9582088Ssos prefix.s_addr &= mask.s_addr; 9595536Ssos } 9602088Ssos 96138044Syokota IN_IFADDR_RLOCK(); 96238044Syokota TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { 963164333Sru if (rtinitflags(ia)) { 96438044Syokota p = ia->ia_dstaddr.sin_addr; 96538044Syokota 9668857Srgrimes if (prefix.s_addr != p.s_addr) 967164333Sru continue; 9685536Ssos } else { 96938044Syokota p = ia->ia_addr.sin_addr; 97048982Syokota m = ia->ia_sockmask.sin_addr; 97148982Syokota p.s_addr &= m.s_addr; 9722088Ssos 9732088Ssos if (prefix.s_addr != p.s_addr || 9748857Srgrimes mask.s_addr != m.s_addr) 9755536Ssos continue; 9762088Ssos } 9772088Ssos 9782088Ssos /* 9792088Ssos * If we got a matching prefix route inserted by other 9802088Ssos * interface address, we are done here. 9812088Ssos */ 9822088Ssos if (ia->ia_flags & IFA_ROUTE) { 98377394Ssobomax#ifdef RADIX_MPATH 9842088Ssos if (ia->ia_addr.sin_addr.s_addr == 9852088Ssos target->ia_addr.sin_addr.s_addr) { 98638044Syokota IN_IFADDR_RUNLOCK(); 98738044Syokota return (EEXIST); 98838044Syokota } else 9892088Ssos break; 9902088Ssos#endif 9915536Ssos if (V_nosameprefix) { 992164333Sru IN_IFADDR_RUNLOCK(); 9935536Ssos return (EEXIST); 9942088Ssos } else { 9952088Ssos in_addralias_rtmsg(RTM_ADD, &prefix, target); 996228437Sed IN_IFADDR_RUNLOCK(); 9972088Ssos return (0); 9982088Ssos } 99944628Syokota } 100039047Syokota } 100139047Syokota IN_IFADDR_RUNLOCK(); 100246761Syokota 10032088Ssos /* 100446761Syokota * No-one seem to have this prefix route, so we try to insert it. 100544628Syokota */ 100646761Syokota error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags); 100746761Syokota if (!error) 100844628Syokota target->ia_flags |= IFA_ROUTE; 100946761Syokota return (error); 101046761Syokota} 101139047Syokota 101246761Syokota/* 101346761Syokota * If there is no other address in the system that can serve a route to the 10142088Ssos * same prefix, remove the route. Hand over the route to the new address 10152088Ssos * otherwise. 10162088Ssos */ 10172088Ssosint 10182088Ssosin_scrubprefix(struct in_ifaddr *target, u_int flags) 10192088Ssos{ 10202088Ssos struct in_ifaddr *ia; 10212088Ssos struct in_addr prefix, mask, p, m; 10222088Ssos int error = 0; 10232088Ssos struct sockaddr_in prefix0, mask0; 102477394Ssobomax 10252088Ssos /* 10262088Ssos * Remove the loopback route to the interface address. 102746761Syokota * The "useloopback" setting is not consulted because if the 102846761Syokota * user configures an interface address, turns off this 102946761Syokota * setting, and then tries to delete that interface address, 103046761Syokota * checking the current setting of "useloopback" would leave 103146761Syokota * that interface address loopback route untouched, which 103246761Syokota * would be wrong. Therefore the interface address loopback route 103346761Syokota * deletion is unconditional. 103446761Syokota */ 10352088Ssos if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) && 10362088Ssos !(target->ia_ifp->if_flags & IFF_LOOPBACK) && 103744628Syokota (target->ia_flags & IFA_RTSELF)) { 103844628Syokota struct route ia_ro; 103946761Syokota int freeit = 0; 104046761Syokota 104146761Syokota bzero(&ia_ro, sizeof(ia_ro)); 104246761Syokota *((struct sockaddr_in *)(&ia_ro.ro_dst)) = target->ia_addr; 10432088Ssos rtalloc_ign_fib(&ia_ro, 0, 0); 10442088Ssos if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) && 104599816Salfred (ia_ro.ro_rt->rt_ifp == V_loif)) { 104699816Salfred RT_LOCK(ia_ro.ro_rt); 104742505Syokota if (ia_ro.ro_rt->rt_refcnt <= 1) 104842505Syokota freeit = 1; 104942505Syokota else if (flags & LLE_STATIC) { 105099816Salfred RT_REMREF(ia_ro.ro_rt); 105142505Syokota target->ia_flags &= ~IFA_RTSELF; 105242505Syokota } 105342505Syokota RTFREE_LOCKED(ia_ro.ro_rt); 105442505Syokota } 105542505Syokota if (freeit && (flags & LLE_STATIC)) { 105699816Salfred error = ifa_del_loopback_route((struct ifaddr *)target, 10576046Ssos (struct sockaddr *)&target->ia_addr); 105842505Syokota if (error == 0) 105942505Syokota target->ia_flags &= ~IFA_RTSELF; 106042505Syokota } 106142505Syokota if ((flags & LLE_STATIC) && 106242505Syokota !(target->ia_ifp->if_flags & IFF_NOARP)) 106342505Syokota /* remove arp cache */ 106442505Syokota arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr); 1065228437Sed } 106642505Syokota 106742505Syokota if (rtinitflags(target)) { 106842505Syokota prefix = target->ia_dstaddr.sin_addr; 106942505Syokota mask.s_addr = 0; 107042505Syokota } else { 107142505Syokota prefix = target->ia_addr.sin_addr; 107242505Syokota mask = target->ia_sockmask.sin_addr; 107342505Syokota prefix.s_addr &= mask.s_addr; 107442505Syokota } 107542505Syokota 107677394Ssobomax if ((target->ia_flags & IFA_ROUTE) == 0) { 107742505Syokota in_addralias_rtmsg(RTM_DELETE, &prefix, target); 107842505Syokota return (0); 107942505Syokota } 1080228437Sed 108142505Syokota IN_IFADDR_RLOCK(); 108242505Syokota TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { 108342505Syokota if (rtinitflags(ia)) { 108442505Syokota p = ia->ia_dstaddr.sin_addr; 108542505Syokota 108642505Syokota if (prefix.s_addr != p.s_addr) 108742505Syokota continue; 108842505Syokota } else { 108942505Syokota p = ia->ia_addr.sin_addr; 109042505Syokota m = ia->ia_sockmask.sin_addr; 109142505Syokota p.s_addr &= m.s_addr; 109242505Syokota 109342505Syokota if (prefix.s_addr != p.s_addr || 109442505Syokota mask.s_addr != m.s_addr) 109542505Syokota continue; 109642505Syokota } 109742505Syokota 109842505Syokota if ((ia->ia_ifp->if_flags & IFF_UP) == 0) 109942505Syokota continue; 110042505Syokota 110142505Syokota /* 110242505Syokota * If we got a matching prefix address, move IFA_ROUTE and 110342505Syokota * the route itself to it. Make sure that routing daemons 110442505Syokota * get a heads-up. 110542505Syokota */ 110677394Ssobomax if ((ia->ia_flags & IFA_ROUTE) == 0) { 110742505Syokota ifa_ref(&ia->ia_ifa); 110842505Syokota IN_IFADDR_RUNLOCK(); 110942505Syokota error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, 111042505Syokota rtinitflags(target)); 111142505Syokota if (error == 0) 111242505Syokota target->ia_flags &= ~IFA_ROUTE; 111342505Syokota else 1114228437Sed log(LOG_INFO, "in_scrubprefix: err=%d, old prefix delete failed\n", 111542505Syokota error); 111642505Syokota error = rtinit(&ia->ia_ifa, (int)RTM_ADD, 111742505Syokota rtinitflags(ia) | RTF_UP); 111842505Syokota if (error == 0) 111942505Syokota ia->ia_flags |= IFA_ROUTE; 112042505Syokota else 112142505Syokota log(LOG_INFO, "in_scrubprefix: err=%d, new prefix add failed\n", 112242505Syokota error); 112342505Syokota ifa_free(&ia->ia_ifa); 112442505Syokota return (error); 112542505Syokota } 112642505Syokota } 112742505Syokota IN_IFADDR_RUNLOCK(); 112842505Syokota 112942505Syokota /* 113077394Ssobomax * remove all L2 entries on the given prefix 113142505Syokota */ 113242505Syokota bzero(&prefix0, sizeof(prefix0)); 113342505Syokota prefix0.sin_len = sizeof(prefix0); 113442505Syokota prefix0.sin_family = AF_INET; 113542505Syokota prefix0.sin_addr.s_addr = target->ia_subnet; 113642505Syokota bzero(&mask0, sizeof(mask0)); 1137228437Sed mask0.sin_len = sizeof(mask0); 1138162327Semax mask0.sin_family = AF_INET; 1139148017Semax mask0.sin_addr.s_addr = target->ia_subnetmask; 1140148017Semax lltable_prefix_free(AF_INET, (struct sockaddr *)&prefix0, 1141148017Semax (struct sockaddr *)&mask0, flags); 114242505Syokota 1143148017Semax /* 1144148017Semax * As no-one seem to have this prefix, we can remove the route. 1145148017Semax */ 1146148017Semax error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target)); 1147148017Semax if (error == 0) 1148148017Semax target->ia_flags &= ~IFA_ROUTE; 1149148017Semax else 1150148017Semax log(LOG_INFO, "in_scrubprefix: err=%d, prefix delete failed\n", error); 1151148017Semax return (error); 1152148017Semax} 1153148017Semax 1154148017Semax#undef rtinitflags 1155148017Semax 1156148017Semax/* 1157148017Semax * Return 1 if the address might be a local broadcast address. 1158148017Semax */ 1159148017Semaxint 1160148017Semaxin_broadcast(struct in_addr in, struct ifnet *ifp) 1161148017Semax{ 1162148017Semax register struct ifaddr *ifa; 1163148017Semax u_long t; 1164148017Semax 1165148017Semax if (in.s_addr == INADDR_BROADCAST || 1166148017Semax in.s_addr == INADDR_ANY) 1167148017Semax return (1); 1168148017Semax if ((ifp->if_flags & IFF_BROADCAST) == 0) 1169148017Semax return (0); 1170148017Semax t = ntohl(in.s_addr); 1171148017Semax /* 1172148017Semax * Look through the list of addresses for a match 1173148017Semax * with a broadcast address. 1174148017Semax */ 1175148017Semax#define ia ((struct in_ifaddr *)ifa) 1176148017Semax TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 1177148017Semax if (ifa->ifa_addr->sa_family == AF_INET && 1178148017Semax (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr || 1179148017Semax /* 1180148017Semax * Check for old-style (host 0) broadcast, but 1181148017Semax * taking into account that RFC 3021 obsoletes it. 1182148017Semax */ 1183148017Semax (ia->ia_subnetmask != IN_RFC3021_MASK && 1184148017Semax t == ia->ia_subnet)) && 1185148017Semax /* 1186148017Semax * Check for an all one subnetmask. These 1187148017Semax * only exist when an interface gets a secondary 1188148017Semax * address. 1189148017Semax */ 1190148017Semax ia->ia_subnetmask != (u_long)0xffffffff) 1191148017Semax return (1); 1192148017Semax return (0); 1193148017Semax#undef ia 1194148017Semax} 1195148017Semax 1196148017Semax/* 1197148017Semax * On interface removal, clean up IPv4 data structures hung off of the ifnet. 1198148017Semax */ 1199148017Semaxvoid 1200148017Semaxin_ifdetach(struct ifnet *ifp) 1201228437Sed{ 1202201387Sed 12032088Ssos in_pcbpurgeif0(&V_ripcbinfo, ifp); 120429603Scharnier in_pcbpurgeif0(&V_udbinfo, ifp); 1205148017Semax in_purgemaddrs(ifp); 120629603Scharnier} 1207298297Semaste 120829603Scharnier/* 12092088Ssos * Delete all IPv4 multicast address records, and associated link-layer 12102088Ssos * multicast address records, associated with ifp. 12112088Ssos * XXX It looks like domifdetach runs AFTER the link layer cleanup. 121251287Speter * XXX This should not race with ifma_protospec being set during 12132088Ssos * a new allocation, if it does, we have bigger problems. 12142088Ssos */ 1215298297Semastestatic void 12162088Ssosin_purgemaddrs(struct ifnet *ifp) 12172088Ssos{ 1218298297Semaste LIST_HEAD(,in_multi) purgeinms; 1219298297Semaste struct in_multi *inm, *tinm; 1220298297Semaste struct ifmultiaddr *ifma; 1221298297Semaste 1222298297Semaste LIST_INIT(&purgeinms); 1223298297Semaste IN_MULTI_LOCK(); 1224298297Semaste 12252088Ssos /* 1226148017Semax * Extract list of in_multi associated with the detaching ifp 1227148017Semax * which the PF_INET layer is about to release. 1228148017Semax * We need to do this as IF_ADDR_LOCK() may be re-acquired 1229148017Semax * by code further down. 123077329Sdes */ 123177329Sdes IF_ADDR_RLOCK(ifp); 123277329Sdes TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 123377329Sdes if (ifma->ifma_addr->sa_family != AF_INET || 123477329Sdes ifma->ifma_protospec == NULL) 123577329Sdes continue; 123677329Sdes#if 0 123777329Sdes KASSERT(ifma->ifma_protospec != NULL, 123877329Sdes ("%s: ifma_protospec is NULL", __func__)); 123977329Sdes#endif 124077329Sdes inm = (struct in_multi *)ifma->ifma_protospec; 124177329Sdes LIST_INSERT_HEAD(&purgeinms, inm, inm_link); 1242298297Semaste } 1243298297Semaste IF_ADDR_RUNLOCK(ifp); 124477329Sdes 124577329Sdes LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) { 124677329Sdes LIST_REMOVE(inm, inm_link); 124777329Sdes inm_release_locked(inm); 124877329Sdes } 124977329Sdes igmp_ifdetach(ifp); 125077329Sdes 125177329Sdes IN_MULTI_UNLOCK(); 125277329Sdes} 125377329Sdes 125477329Sdesstruct in_llentry { 125577329Sdes struct llentry base; 125677329Sdes struct sockaddr_in l3_addr4; 125777329Sdes}; 125877329Sdes 125977329Sdes/* 126077329Sdes * Deletes an address from the address table. 126177329Sdes * This function is called by the timer functions 126277329Sdes * such as arptimer() and nd6_llinfo_timer(), and 126377329Sdes * the caller does the locking. 126477329Sdes */ 126577329Sdesstatic void 126677329Sdesin_lltable_free(struct lltable *llt, struct llentry *lle) 126777329Sdes{ 12682088Ssos LLE_WUNLOCK(lle); 126929603Scharnier LLE_LOCK_DESTROY(lle); 12702088Ssos free(lle, M_LLTABLE); 12712088Ssos} 12722088Ssos 1273static struct llentry * 1274in_lltable_new(const struct sockaddr *l3addr, u_int flags) 1275{ 1276 struct in_llentry *lle; 1277 1278 lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_NOWAIT | M_ZERO); 1279 if (lle == NULL) /* NB: caller generates msg */ 1280 return NULL; 1281 1282 /* 1283 * For IPv4 this will trigger "arpresolve" to generate 1284 * an ARP request. 1285 */ 1286 lle->base.la_expire = time_uptime; /* mark expired */ 1287 lle->l3_addr4 = *(const struct sockaddr_in *)l3addr; 1288 lle->base.lle_refcnt = 1; 1289 lle->base.lle_free = in_lltable_free; 1290 LLE_LOCK_INIT(&lle->base); 1291 callout_init_rw(&lle->base.la_timer, &lle->base.lle_lock, 1292 CALLOUT_RETURNUNLOCKED); 1293 1294 return (&lle->base); 1295} 1296 1297#define IN_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \ 1298 (((ntohl((d)->sin_addr.s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 ) 1299 1300static void 1301in_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix, 1302 const struct sockaddr *mask, u_int flags) 1303{ 1304 const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix; 1305 const struct sockaddr_in *msk = (const struct sockaddr_in *)mask; 1306 struct llentry *lle, *next; 1307 int i; 1308 size_t pkts_dropped; 1309 1310 IF_AFDATA_WLOCK(llt->llt_ifp); 1311 for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { 1312 LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { 1313 /* 1314 * (flags & LLE_STATIC) means deleting all entries 1315 * including static ARP entries. 1316 */ 1317 if (IN_ARE_MASKED_ADDR_EQUAL(satosin(L3_ADDR(lle)), 1318 pfx, msk) && ((flags & LLE_STATIC) || 1319 !(lle->la_flags & LLE_STATIC))) { 1320 LLE_WLOCK(lle); 1321 if (callout_stop(&lle->la_timer)) 1322 LLE_REMREF(lle); 1323 pkts_dropped = llentry_free(lle); 1324 ARPSTAT_ADD(dropped, pkts_dropped); 1325 } 1326 } 1327 } 1328 IF_AFDATA_WUNLOCK(llt->llt_ifp); 1329} 1330 1331 1332static int 1333in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr) 1334{ 1335 struct rtentry *rt; 1336 1337 KASSERT(l3addr->sa_family == AF_INET, 1338 ("sin_family %d", l3addr->sa_family)); 1339 1340 /* XXX rtalloc1 should take a const param */ 1341 rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0); 1342 1343 if (rt == NULL) 1344 return (EINVAL); 1345 1346 /* 1347 * If the gateway for an existing host route matches the target L3 1348 * address, which is a special route inserted by some implementation 1349 * such as MANET, and the interface is of the correct type, then 1350 * allow for ARP to proceed. 1351 */ 1352 if (rt->rt_flags & RTF_GATEWAY) { 1353 if (!(rt->rt_flags & RTF_HOST) || !rt->rt_ifp || 1354 rt->rt_ifp->if_type != IFT_ETHER || 1355 (rt->rt_ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) != 0 || 1356 memcmp(rt->rt_gateway->sa_data, l3addr->sa_data, 1357 sizeof(in_addr_t)) != 0) { 1358 RTFREE_LOCKED(rt); 1359 return (EINVAL); 1360 } 1361 } 1362 1363 /* 1364 * Make sure that at least the destination address is covered 1365 * by the route. This is for handling the case where 2 or more 1366 * interfaces have the same prefix. An incoming packet arrives 1367 * on one interface and the corresponding outgoing packet leaves 1368 * another interface. 1369 */ 1370 if (!(rt->rt_flags & RTF_HOST) && rt->rt_ifp != ifp) { 1371 const char *sa, *mask, *addr, *lim; 1372 int len; 1373 1374 mask = (const char *)rt_mask(rt); 1375 /* 1376 * Just being extra cautious to avoid some custom 1377 * code getting into trouble. 1378 */ 1379 if (mask == NULL) { 1380 RTFREE_LOCKED(rt); 1381 return (EINVAL); 1382 } 1383 1384 sa = (const char *)rt_key(rt); 1385 addr = (const char *)l3addr; 1386 len = ((const struct sockaddr_in *)l3addr)->sin_len; 1387 lim = addr + len; 1388 1389 for ( ; addr < lim; sa++, mask++, addr++) { 1390 if ((*sa ^ *addr) & *mask) { 1391#ifdef DIAGNOSTIC 1392 log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n", 1393 inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr)); 1394#endif 1395 RTFREE_LOCKED(rt); 1396 return (EINVAL); 1397 } 1398 } 1399 } 1400 1401 RTFREE_LOCKED(rt); 1402 return (0); 1403} 1404 1405/* 1406 * Return NULL if not found or marked for deletion. 1407 * If found return lle read locked. 1408 */ 1409static struct llentry * 1410in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) 1411{ 1412 const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr; 1413 struct ifnet *ifp = llt->llt_ifp; 1414 struct llentry *lle; 1415 struct llentries *lleh; 1416 u_int hashkey; 1417 1418 IF_AFDATA_LOCK_ASSERT(ifp); 1419 KASSERT(l3addr->sa_family == AF_INET, 1420 ("sin_family %d", l3addr->sa_family)); 1421 1422 hashkey = sin->sin_addr.s_addr; 1423 lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)]; 1424 LIST_FOREACH(lle, lleh, lle_next) { 1425 struct sockaddr_in *sa2 = satosin(L3_ADDR(lle)); 1426 if (lle->la_flags & LLE_DELETED) 1427 continue; 1428 if (sa2->sin_addr.s_addr == sin->sin_addr.s_addr) 1429 break; 1430 } 1431 if (lle == NULL) { 1432#ifdef DIAGNOSTIC 1433 if (flags & LLE_DELETE) 1434 log(LOG_INFO, "interface address is missing from cache = %p in delete\n", lle); 1435#endif 1436 if (!(flags & LLE_CREATE)) 1437 return (NULL); 1438 IF_AFDATA_WLOCK_ASSERT(ifp); 1439 /* 1440 * A route that covers the given address must have 1441 * been installed 1st because we are doing a resolution, 1442 * verify this. 1443 */ 1444 if (!(flags & LLE_IFADDR) && 1445 in_lltable_rtcheck(ifp, flags, l3addr) != 0) 1446 goto done; 1447 1448 lle = in_lltable_new(l3addr, flags); 1449 if (lle == NULL) { 1450 log(LOG_INFO, "lla_lookup: new lle malloc failed\n"); 1451 goto done; 1452 } 1453 lle->la_flags = flags & ~LLE_CREATE; 1454 if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) { 1455 bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen); 1456 lle->la_flags |= (LLE_VALID | LLE_STATIC); 1457 } 1458 1459 lle->lle_tbl = llt; 1460 lle->lle_head = lleh; 1461 lle->la_flags |= LLE_LINKED; 1462 LIST_INSERT_HEAD(lleh, lle, lle_next); 1463 } else if (flags & LLE_DELETE) { 1464 if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) { 1465 LLE_WLOCK(lle); 1466 lle->la_flags |= LLE_DELETED; 1467 EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); 1468#ifdef DIAGNOSTIC 1469 log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); 1470#endif 1471 if ((lle->la_flags & 1472 (LLE_STATIC | LLE_IFADDR)) == LLE_STATIC) 1473 llentry_free(lle); 1474 else 1475 LLE_WUNLOCK(lle); 1476 } 1477 lle = (void *)-1; 1478 1479 } 1480 if (LLE_IS_VALID(lle)) { 1481 if (flags & LLE_EXCLUSIVE) 1482 LLE_WLOCK(lle); 1483 else 1484 LLE_RLOCK(lle); 1485 } 1486done: 1487 return (lle); 1488} 1489 1490static int 1491in_lltable_dump(struct lltable *llt, struct sysctl_req *wr) 1492{ 1493#define SIN(lle) ((struct sockaddr_in *) L3_ADDR(lle)) 1494 struct ifnet *ifp = llt->llt_ifp; 1495 struct llentry *lle; 1496 /* XXX stack use */ 1497 struct { 1498 struct rt_msghdr rtm; 1499 struct sockaddr_in sin; 1500 struct sockaddr_dl sdl; 1501 } arpc; 1502 int error, i; 1503 1504 LLTABLE_LOCK_ASSERT(); 1505 1506 error = 0; 1507 for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { 1508 LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { 1509 struct sockaddr_dl *sdl; 1510 1511 /* skip deleted entries */ 1512 if ((lle->la_flags & LLE_DELETED) == LLE_DELETED) 1513 continue; 1514 /* Skip if jailed and not a valid IP of the prison. */ 1515 if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0) 1516 continue; 1517 /* 1518 * produce a msg made of: 1519 * struct rt_msghdr; 1520 * struct sockaddr_in; (IPv4) 1521 * struct sockaddr_dl; 1522 */ 1523 bzero(&arpc, sizeof(arpc)); 1524 arpc.rtm.rtm_msglen = sizeof(arpc); 1525 arpc.rtm.rtm_version = RTM_VERSION; 1526 arpc.rtm.rtm_type = RTM_GET; 1527 arpc.rtm.rtm_flags = RTF_UP; 1528 arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY; 1529 arpc.sin.sin_family = AF_INET; 1530 arpc.sin.sin_len = sizeof(arpc.sin); 1531 arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr; 1532 1533 /* publish */ 1534 if (lle->la_flags & LLE_PUB) 1535 arpc.rtm.rtm_flags |= RTF_ANNOUNCE; 1536 1537 sdl = &arpc.sdl; 1538 sdl->sdl_family = AF_LINK; 1539 sdl->sdl_len = sizeof(*sdl); 1540 sdl->sdl_index = ifp->if_index; 1541 sdl->sdl_type = ifp->if_type; 1542 if ((lle->la_flags & LLE_VALID) == LLE_VALID) { 1543 sdl->sdl_alen = ifp->if_addrlen; 1544 bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen); 1545 } else { 1546 sdl->sdl_alen = 0; 1547 bzero(LLADDR(sdl), ifp->if_addrlen); 1548 } 1549 1550 arpc.rtm.rtm_rmx.rmx_expire = 1551 lle->la_flags & LLE_STATIC ? 0 : lle->la_expire; 1552 arpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA); 1553 if (lle->la_flags & LLE_STATIC) 1554 arpc.rtm.rtm_flags |= RTF_STATIC; 1555 arpc.rtm.rtm_index = ifp->if_index; 1556 error = SYSCTL_OUT(wr, &arpc, sizeof(arpc)); 1557 if (error) 1558 break; 1559 } 1560 } 1561 return error; 1562#undef SIN 1563} 1564 1565void * 1566in_domifattach(struct ifnet *ifp) 1567{ 1568 struct in_ifinfo *ii; 1569 struct lltable *llt; 1570 1571 ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO); 1572 1573 llt = lltable_init(ifp, AF_INET); 1574 if (llt != NULL) { 1575 llt->llt_prefix_free = in_lltable_prefix_free; 1576 llt->llt_lookup = in_lltable_lookup; 1577 llt->llt_dump = in_lltable_dump; 1578 } 1579 ii->ii_llt = llt; 1580 1581 ii->ii_igmp = igmp_domifattach(ifp); 1582 1583 return ii; 1584} 1585 1586void 1587in_domifdetach(struct ifnet *ifp, void *aux) 1588{ 1589 struct in_ifinfo *ii = (struct in_ifinfo *)aux; 1590 1591 igmp_domifdetach(ifp); 1592 lltable_free(ii->ii_llt); 1593 free(ii, M_IFADDR); 1594} 1595