in.c revision 186708
1139823Simp/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
4137668Smlaier * Copyright (C) 2001 WIDE Project.  All rights reserved.
51541Srgrimes *
61541Srgrimes * Redistribution and use in source and binary forms, with or without
71541Srgrimes * modification, are permitted provided that the following conditions
81541Srgrimes * are met:
91541Srgrimes * 1. Redistributions of source code must retain the above copyright
101541Srgrimes *    notice, this list of conditions and the following disclaimer.
111541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer in the
131541Srgrimes *    documentation and/or other materials provided with the distribution.
141541Srgrimes * 4. Neither the name of the University nor the names of its contributors
151541Srgrimes *    may be used to endorse or promote products derived from this software
161541Srgrimes *    without specific prior written permission.
171541Srgrimes *
181541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
191541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
221541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281541Srgrimes * SUCH DAMAGE.
291541Srgrimes *
3010939Swollman *	@(#)in.c	8.4 (Berkeley) 1/9/95
311541Srgrimes */
321541Srgrimes
33172467Ssilby#include <sys/cdefs.h>
34172467Ssilby__FBSDID("$FreeBSD: head/sys/netinet/in.c 186708 2009-01-03 00:27:28Z qingli $");
35172467Ssilby
36143868Sglebius#include "opt_carp.h"
37143868Sglebius
381541Srgrimes#include <sys/param.h>
391549Srgrimes#include <sys/systm.h>
4024204Sbde#include <sys/sockio.h>
411541Srgrimes#include <sys/malloc.h>
42164033Srwatson#include <sys/priv.h>
431541Srgrimes#include <sys/socket.h>
4412704Sphk#include <sys/kernel.h>
4512704Sphk#include <sys/sysctl.h>
46181803Sbz#include <sys/vimage.h>
471541Srgrimes
481541Srgrimes#include <net/if.h>
49186119Sqingli#include <net/if_llatbl.h>
5055009Sshin#include <net/if_types.h>
511541Srgrimes#include <net/route.h>
521541Srgrimes
531541Srgrimes#include <netinet/in.h>
541541Srgrimes#include <netinet/in_var.h>
5581127Sume#include <netinet/in_pcb.h>
56170613Sbms#include <netinet/ip_var.h>
57185571Sbz#include <netinet/vinet.h>
581541Srgrimes
5992723Salfredstatic int in_mask2len(struct in_addr *);
6092723Salfredstatic void in_len2mask(struct in_addr *, int);
6192723Salfredstatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
6292723Salfred	struct ifnet *, struct thread *);
6355009Sshin
64137628Smlaierstatic int	in_addprefix(struct in_ifaddr *, int);
65137628Smlaierstatic int	in_scrubprefix(struct in_ifaddr *);
6692723Salfredstatic void	in_socktrim(struct sockaddr_in *);
6792723Salfredstatic int	in_ifinit(struct ifnet *,
6892723Salfred	    struct in_ifaddr *, struct sockaddr_in *, int);
69167729Sbmsstatic void	in_purgemaddrs(struct ifnet *);
701541Srgrimes
71185088Szec#ifdef VIMAGE_GLOBALS
72185088Szecstatic int subnetsarelocal;
73185088Szecstatic int sameprefixcarponly;
74185088Szecextern struct inpcbinfo ripcbinfo;
75185088Szec#endif
76185088Szec
77183550SzecSYSCTL_V_INT(V_NET, vnet_inet, _net_inet_ip, OID_AUTO, subnets_are_local,
78183550Szec	CTLFLAG_RW, subnetsarelocal, 0,
79183550Szec	"Treat all subnets as directly connected");
80183550SzecSYSCTL_V_INT(V_NET, vnet_inet, _net_inet_ip, OID_AUTO, same_prefix_carp_only,
81183550Szec	CTLFLAG_RW, sameprefixcarponly, 0,
82149221Sglebius	"Refuse to create same prefixes on different interfaces");
8321666Swollman
841541Srgrimes/*
851541Srgrimes * Return 1 if an internet address is for a ``local'' host
861541Srgrimes * (one to which we have a connection).  If subnetsarelocal
871541Srgrimes * is true, this includes other subnets of the local net.
881541Srgrimes * Otherwise, it includes only the directly-connected (sub)nets.
891541Srgrimes */
901549Srgrimesint
91169454Srwatsonin_localaddr(struct in_addr in)
921541Srgrimes{
93183550Szec	INIT_VNET_INET(curvnet);
941541Srgrimes	register u_long i = ntohl(in.s_addr);
951541Srgrimes	register struct in_ifaddr *ia;
961541Srgrimes
97181803Sbz	if (V_subnetsarelocal) {
98181803Sbz		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
991541Srgrimes			if ((i & ia->ia_netmask) == ia->ia_net)
1001541Srgrimes				return (1);
1011541Srgrimes	} else {
102181803Sbz		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
1031541Srgrimes			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
1041541Srgrimes				return (1);
1051541Srgrimes	}
1061541Srgrimes	return (0);
1071541Srgrimes}
1081541Srgrimes
1091541Srgrimes/*
110133486Sandre * Return 1 if an internet address is for the local host and configured
111133486Sandre * on one of its interfaces.
112133486Sandre */
113133486Sandreint
114169454Srwatsonin_localip(struct in_addr in)
115133486Sandre{
116183550Szec	INIT_VNET_INET(curvnet);
117133486Sandre	struct in_ifaddr *ia;
118133486Sandre
119133486Sandre	LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
120133486Sandre		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr)
121184295Sbz			return (1);
122133486Sandre	}
123184295Sbz	return (0);
124133486Sandre}
125133486Sandre
126133486Sandre/*
1271541Srgrimes * Determine whether an IP address is in a reserved set of addresses
1281541Srgrimes * that may not be forwarded, or whether datagrams to that destination
1291541Srgrimes * may be forwarded.
1301541Srgrimes */
1311549Srgrimesint
132169454Srwatsonin_canforward(struct in_addr in)
1331541Srgrimes{
1341541Srgrimes	register u_long i = ntohl(in.s_addr);
1351541Srgrimes	register u_long net;
1361541Srgrimes
137166450Sbms	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i))
1381541Srgrimes		return (0);
1391541Srgrimes	if (IN_CLASSA(i)) {
1401541Srgrimes		net = i & IN_CLASSA_NET;
1411541Srgrimes		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
1421541Srgrimes			return (0);
1431541Srgrimes	}
1441541Srgrimes	return (1);
1451541Srgrimes}
1461541Srgrimes
1471541Srgrimes/*
1481541Srgrimes * Trim a mask in a sockaddr
1491541Srgrimes */
15012296Sphkstatic void
151169454Srwatsonin_socktrim(struct sockaddr_in *ap)
1521541Srgrimes{
1531541Srgrimes    register char *cplim = (char *) &ap->sin_addr;
1541541Srgrimes    register char *cp = (char *) (&ap->sin_addr + 1);
1551541Srgrimes
1561541Srgrimes    ap->sin_len = 0;
1574127Swollman    while (--cp >= cplim)
158133874Srwatson	if (*cp) {
1591541Srgrimes	    (ap)->sin_len = cp - (char *) (ap) + 1;
1601541Srgrimes	    break;
1611541Srgrimes	}
1621541Srgrimes}
1631541Srgrimes
16455009Sshinstatic int
16555009Sshinin_mask2len(mask)
16655009Sshin	struct in_addr *mask;
16755009Sshin{
16855009Sshin	int x, y;
16955009Sshin	u_char *p;
17055009Sshin
17155009Sshin	p = (u_char *)mask;
17255009Sshin	for (x = 0; x < sizeof(*mask); x++) {
17355009Sshin		if (p[x] != 0xff)
17455009Sshin			break;
17555009Sshin	}
17655009Sshin	y = 0;
17755009Sshin	if (x < sizeof(*mask)) {
17855009Sshin		for (y = 0; y < 8; y++) {
17955009Sshin			if ((p[x] & (0x80 >> y)) == 0)
18055009Sshin				break;
18155009Sshin		}
18255009Sshin	}
183184295Sbz	return (x * 8 + y);
18455009Sshin}
18555009Sshin
18655009Sshinstatic void
187169454Srwatsonin_len2mask(struct in_addr *mask, int len)
18855009Sshin{
18955009Sshin	int i;
19055009Sshin	u_char *p;
19155009Sshin
19255009Sshin	p = (u_char *)mask;
19355009Sshin	bzero(mask, sizeof(*mask));
19455009Sshin	for (i = 0; i < len / 8; i++)
19555009Sshin		p[i] = 0xff;
19655009Sshin	if (len % 8)
19755009Sshin		p[i] = (0xff00 >> (len % 8)) & 0xff;
19855009Sshin}
19955009Sshin
2001541Srgrimes/*
2011541Srgrimes * Generic internet control operations (ioctl's).
2021541Srgrimes * Ifp is 0 if not an interface-specific ioctl.
2031541Srgrimes */
2041541Srgrimes/* ARGSUSED */
2051549Srgrimesint
206169454Srwatsonin_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
207169454Srwatson    struct thread *td)
2081541Srgrimes{
209183550Szec	INIT_VNET_INET(curvnet); /* both so and ifp can be NULL here! */
2101541Srgrimes	register struct ifreq *ifr = (struct ifreq *)data;
211184295Sbz	register struct in_ifaddr *ia, *iap;
2121541Srgrimes	register struct ifaddr *ifa;
213168032Sbms	struct in_addr allhosts_addr;
21484102Sjlemon	struct in_addr dst;
2151541Srgrimes	struct in_ifaddr *oia;
2161541Srgrimes	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
2171541Srgrimes	struct sockaddr_in oldaddr;
21887124Sbrian	int error, hostIsNew, iaIsNew, maskIsNew, s;
219168032Sbms	int iaIsFirst;
2201541Srgrimes
221184295Sbz	ia = NULL;
222168032Sbms	iaIsFirst = 0;
22387124Sbrian	iaIsNew = 0;
224168032Sbms	allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
22587124Sbrian
22655009Sshin	switch (cmd) {
22755009Sshin	case SIOCALIFADDR:
228164033Srwatson		if (td != NULL) {
229164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
230164033Srwatson			if (error)
231164033Srwatson				return (error);
232164033Srwatson		}
233184295Sbz		if (ifp == NULL)
234184295Sbz			return (EINVAL);
235164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
236164033Srwatson
23755009Sshin	case SIOCDLIFADDR:
238164033Srwatson		if (td != NULL) {
239164033Srwatson			error = priv_check(td, PRIV_NET_DELIFADDR);
240164033Srwatson			if (error)
241164033Srwatson				return (error);
242164033Srwatson		}
243184295Sbz		if (ifp == NULL)
244184295Sbz			return (EINVAL);
245164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
246164033Srwatson
24755009Sshin	case SIOCGLIFADDR:
248184295Sbz		if (ifp == NULL)
249184295Sbz			return (EINVAL);
25083366Sjulian		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
25155009Sshin	}
25255009Sshin
2531541Srgrimes	/*
2541541Srgrimes	 * Find address for this interface, if it exists.
25514632Sfenner	 *
25614632Sfenner	 * If an alias address was specified, find that one instead of
25784102Sjlemon	 * the first one on the interface, if possible.
2581541Srgrimes	 */
259184295Sbz	if (ifp != NULL) {
26084102Sjlemon		dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
26184102Sjlemon		LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash)
26284102Sjlemon			if (iap->ia_ifp == ifp &&
26384102Sjlemon			    iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
26484102Sjlemon				ia = iap;
26584102Sjlemon				break;
26684102Sjlemon			}
26784102Sjlemon		if (ia == NULL)
26884102Sjlemon			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
26984102Sjlemon				iap = ifatoia(ifa);
27084102Sjlemon				if (iap->ia_addr.sin_family == AF_INET) {
27114632Sfenner					ia = iap;
27214632Sfenner					break;
27314632Sfenner				}
27414632Sfenner			}
275168032Sbms		if (ia == NULL)
276168032Sbms			iaIsFirst = 1;
27784102Sjlemon	}
2781541Srgrimes
2791541Srgrimes	switch (cmd) {
2801541Srgrimes
2811541Srgrimes	case SIOCAIFADDR:
2821541Srgrimes	case SIOCDIFADDR:
283184295Sbz		if (ifp == NULL)
28441575Seivind			return (EADDRNOTAVAIL);
2858071Swollman		if (ifra->ifra_addr.sin_family == AF_INET) {
28671999Sphk			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
2878071Swollman				if (ia->ia_ifp == ifp  &&
2888071Swollman				    ia->ia_addr.sin_addr.s_addr ==
2898071Swollman				    ifra->ifra_addr.sin_addr.s_addr)
2908071Swollman					break;
2918071Swollman			}
2928876Srgrimes			if ((ifp->if_flags & IFF_POINTOPOINT)
2938071Swollman			    && (cmd == SIOCAIFADDR)
2948071Swollman			    && (ifra->ifra_dstaddr.sin_addr.s_addr
2958071Swollman				== INADDR_ANY)) {
296184295Sbz				return (EDESTADDRREQ);
2978071Swollman			}
2981541Srgrimes		}
299184295Sbz		if (cmd == SIOCDIFADDR && ia == NULL)
3001541Srgrimes			return (EADDRNOTAVAIL);
3011541Srgrimes		/* FALLTHROUGH */
3021541Srgrimes	case SIOCSIFADDR:
3031541Srgrimes	case SIOCSIFNETMASK:
3041541Srgrimes	case SIOCSIFDSTADDR:
305164033Srwatson		if (td != NULL) {
306175626Sbz			error = priv_check(td, (cmd == SIOCDIFADDR) ?
307175626Sbz			    PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR);
308164033Srwatson			if (error)
309164033Srwatson				return (error);
310164033Srwatson		}
3111541Srgrimes
312184295Sbz		if (ifp == NULL)
31341575Seivind			return (EADDRNOTAVAIL);
314184295Sbz		if (ia == NULL) {
31520407Swollman			ia = (struct in_ifaddr *)
316111119Simp				malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
317184295Sbz			if (ia == NULL)
3181541Srgrimes				return (ENOBUFS);
31915092Sdg			/*
32015092Sdg			 * Protect from ipintr() traversing address list
32115092Sdg			 * while we're modifying it.
32215092Sdg			 */
32315092Sdg			s = splnet();
32420407Swollman			ifa = &ia->ia_ifa;
325108033Shsu			IFA_LOCK_INIT(ifa);
32620407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
32720407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
32820407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
329108033Shsu			ifa->ifa_refcnt = 1;
330108033Shsu			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
331108033Shsu
3321541Srgrimes			ia->ia_sockmask.sin_len = 8;
33385740Sdes			ia->ia_sockmask.sin_family = AF_INET;
3341541Srgrimes			if (ifp->if_flags & IFF_BROADCAST) {
3351541Srgrimes				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
3361541Srgrimes				ia->ia_broadaddr.sin_family = AF_INET;
3371541Srgrimes			}
3381541Srgrimes			ia->ia_ifp = ifp;
339151824Sglebius
340181803Sbz			TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
34115092Sdg			splx(s);
34287124Sbrian			iaIsNew = 1;
3431541Srgrimes		}
3441541Srgrimes		break;
3451541Srgrimes
3461541Srgrimes	case SIOCSIFBRDADDR:
347164033Srwatson		if (td != NULL) {
348164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
349164033Srwatson			if (error)
350164033Srwatson				return (error);
351164033Srwatson		}
3521541Srgrimes		/* FALLTHROUGH */
3531541Srgrimes
3541541Srgrimes	case SIOCGIFADDR:
3551541Srgrimes	case SIOCGIFNETMASK:
3561541Srgrimes	case SIOCGIFDSTADDR:
3571541Srgrimes	case SIOCGIFBRDADDR:
358184295Sbz		if (ia == NULL)
3591541Srgrimes			return (EADDRNOTAVAIL);
3601541Srgrimes		break;
3611541Srgrimes	}
3621541Srgrimes	switch (cmd) {
3631541Srgrimes
3641541Srgrimes	case SIOCGIFADDR:
3651541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
36687124Sbrian		return (0);
3671541Srgrimes
3681541Srgrimes	case SIOCGIFBRDADDR:
3691541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
3701541Srgrimes			return (EINVAL);
3711541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
37287124Sbrian		return (0);
3731541Srgrimes
3741541Srgrimes	case SIOCGIFDSTADDR:
3751541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
3761541Srgrimes			return (EINVAL);
3771541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
37887124Sbrian		return (0);
3791541Srgrimes
3801541Srgrimes	case SIOCGIFNETMASK:
3811541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
38287124Sbrian		return (0);
3831541Srgrimes
3841541Srgrimes	case SIOCSIFDSTADDR:
3851541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
3861541Srgrimes			return (EINVAL);
3871541Srgrimes		oldaddr = ia->ia_dstaddr;
3881541Srgrimes		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
389184295Sbz		if (ifp->if_ioctl != NULL) {
390146883Siedowse			IFF_LOCKGIANT(ifp);
391146883Siedowse			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
392146883Siedowse			    (caddr_t)ia);
393146883Siedowse			IFF_UNLOCKGIANT(ifp);
394146883Siedowse			if (error) {
395146883Siedowse				ia->ia_dstaddr = oldaddr;
396146883Siedowse				return (error);
397146883Siedowse			}
3981541Srgrimes		}
3991541Srgrimes		if (ia->ia_flags & IFA_ROUTE) {
4001541Srgrimes			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
4011541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
4021541Srgrimes			ia->ia_ifa.ifa_dstaddr =
4031541Srgrimes					(struct sockaddr *)&ia->ia_dstaddr;
4041541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
4051541Srgrimes		}
40687124Sbrian		return (0);
4071541Srgrimes
4081541Srgrimes	case SIOCSIFBRDADDR:
4091541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
4101541Srgrimes			return (EINVAL);
4111541Srgrimes		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
41287124Sbrian		return (0);
4131541Srgrimes
4141541Srgrimes	case SIOCSIFADDR:
41587124Sbrian		error = in_ifinit(ifp, ia,
41687124Sbrian		    (struct sockaddr_in *) &ifr->ifr_addr, 1);
41787124Sbrian		if (error != 0 && iaIsNew)
41887124Sbrian			break;
419168032Sbms		if (error == 0) {
420168032Sbms			if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
421168032Sbms				in_addmulti(&allhosts_addr, ifp);
422126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
423168032Sbms		}
42487124Sbrian		return (0);
4251541Srgrimes
4261541Srgrimes	case SIOCSIFNETMASK:
42785740Sdes		ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
42885740Sdes		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
42987124Sbrian		return (0);
4301541Srgrimes
4311541Srgrimes	case SIOCAIFADDR:
4321541Srgrimes		maskIsNew = 0;
4331541Srgrimes		hostIsNew = 1;
4341541Srgrimes		error = 0;
4351541Srgrimes		if (ia->ia_addr.sin_family == AF_INET) {
4361541Srgrimes			if (ifra->ifra_addr.sin_len == 0) {
4371541Srgrimes				ifra->ifra_addr = ia->ia_addr;
4381541Srgrimes				hostIsNew = 0;
4391541Srgrimes			} else if (ifra->ifra_addr.sin_addr.s_addr ==
4401541Srgrimes					       ia->ia_addr.sin_addr.s_addr)
4411541Srgrimes				hostIsNew = 0;
4421541Srgrimes		}
4431541Srgrimes		if (ifra->ifra_mask.sin_len) {
4441541Srgrimes			in_ifscrub(ifp, ia);
4451541Srgrimes			ia->ia_sockmask = ifra->ifra_mask;
44685740Sdes			ia->ia_sockmask.sin_family = AF_INET;
4471541Srgrimes			ia->ia_subnetmask =
4481541Srgrimes			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
4491541Srgrimes			maskIsNew = 1;
4501541Srgrimes		}
4511541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) &&
4521541Srgrimes		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
4531541Srgrimes			in_ifscrub(ifp, ia);
4541541Srgrimes			ia->ia_dstaddr = ifra->ifra_dstaddr;
4551541Srgrimes			maskIsNew  = 1; /* We lie; but the effect's the same */
4561541Srgrimes		}
4571541Srgrimes		if (ifra->ifra_addr.sin_family == AF_INET &&
4581541Srgrimes		    (hostIsNew || maskIsNew))
4591541Srgrimes			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
46087124Sbrian		if (error != 0 && iaIsNew)
46187124Sbrian			break;
46287124Sbrian
4631541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) &&
4641541Srgrimes		    (ifra->ifra_broadaddr.sin_family == AF_INET))
4651541Srgrimes			ia->ia_broadaddr = ifra->ifra_broadaddr;
466168032Sbms		if (error == 0) {
467168032Sbms			if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
468168032Sbms				in_addmulti(&allhosts_addr, ifp);
469126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
470168032Sbms		}
4711541Srgrimes		return (error);
4721541Srgrimes
4731541Srgrimes	case SIOCDIFADDR:
47474299Sru		/*
47574299Sru		 * in_ifscrub kills the interface route.
47674299Sru		 */
4771541Srgrimes		in_ifscrub(ifp, ia);
47815092Sdg		/*
47974299Sru		 * in_ifadown gets rid of all the rest of
48074299Sru		 * the routes.  This is not quite the right
48174299Sru		 * thing to do, but at least if we are running
48274299Sru		 * a routing process they will come back.
48374299Sru		 */
48476469Sru		in_ifadown(&ia->ia_ifa, 1);
485126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
48687124Sbrian		error = 0;
4871541Srgrimes		break;
4881541Srgrimes
4891541Srgrimes	default:
490184295Sbz		if (ifp == NULL || ifp->if_ioctl == NULL)
4911541Srgrimes			return (EOPNOTSUPP);
492146883Siedowse		IFF_LOCKGIANT(ifp);
493146883Siedowse		error = (*ifp->if_ioctl)(ifp, cmd, data);
494146883Siedowse		IFF_UNLOCKGIANT(ifp);
495146883Siedowse		return (error);
4961541Srgrimes	}
49787124Sbrian
49887124Sbrian	/*
49987124Sbrian	 * Protect from ipintr() traversing address list while we're modifying
50087124Sbrian	 * it.
50187124Sbrian	 */
50287124Sbrian	s = splnet();
50387124Sbrian	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
504181803Sbz	TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
505168032Sbms	if (ia->ia_addr.sin_family == AF_INET) {
506154777Sandre		LIST_REMOVE(ia, ia_hash);
507168032Sbms		/*
508168032Sbms		 * If this is the last IPv4 address configured on this
509168032Sbms		 * interface, leave the all-hosts group.
510168032Sbms		 * XXX: This is quite ugly because of locking and structure.
511168032Sbms		 */
512168032Sbms		oia = NULL;
513168032Sbms		IFP_TO_IA(ifp, oia);
514168032Sbms		if (oia == NULL) {
515168032Sbms			struct in_multi *inm;
516168032Sbms
517168032Sbms			IFF_LOCKGIANT(ifp);
518168032Sbms			IN_MULTI_LOCK();
519168032Sbms			IN_LOOKUP_MULTI(allhosts_addr, ifp, inm);
520168032Sbms			if (inm != NULL)
521168032Sbms				in_delmulti_locked(inm);
522168032Sbms			IN_MULTI_UNLOCK();
523168032Sbms			IFF_UNLOCKGIANT(ifp);
524168032Sbms		}
525168032Sbms	}
52687124Sbrian	IFAFREE(&ia->ia_ifa);
52787124Sbrian	splx(s);
52887124Sbrian
52987124Sbrian	return (error);
5301541Srgrimes}
5311541Srgrimes
5321541Srgrimes/*
53355009Sshin * SIOC[GAD]LIFADDR.
53455009Sshin *	SIOCGLIFADDR: get first address. (?!?)
53555009Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
53655009Sshin *		get first address that matches the specified prefix.
53755009Sshin *	SIOCALIFADDR: add the specified address.
53855009Sshin *	SIOCALIFADDR with IFLR_PREFIX:
53955009Sshin *		EINVAL since we can't deduce hostid part of the address.
54055009Sshin *	SIOCDLIFADDR: delete the specified address.
54155009Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
54255009Sshin *		delete the first address that matches the specified prefix.
54355009Sshin * return values:
54455009Sshin *	EINVAL on invalid parameters
54555009Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
54655009Sshin *	other values may be returned from in_ioctl()
54755009Sshin */
54855009Sshinstatic int
549169454Srwatsonin_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
550169454Srwatson    struct ifnet *ifp, struct thread *td)
55155009Sshin{
55255009Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
55355009Sshin	struct ifaddr *ifa;
55455009Sshin
55555009Sshin	/* sanity checks */
556184295Sbz	if (data == NULL || ifp == NULL) {
55755009Sshin		panic("invalid argument to in_lifaddr_ioctl");
55855009Sshin		/*NOTRECHED*/
55955009Sshin	}
56055009Sshin
56155009Sshin	switch (cmd) {
56255009Sshin	case SIOCGLIFADDR:
56355009Sshin		/* address must be specified on GET with IFLR_PREFIX */
56455009Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
56555009Sshin			break;
56655009Sshin		/*FALLTHROUGH*/
56755009Sshin	case SIOCALIFADDR:
56855009Sshin	case SIOCDLIFADDR:
56955009Sshin		/* address must be specified on ADD and DELETE */
57055917Sshin		if (iflr->addr.ss_family != AF_INET)
571184295Sbz			return (EINVAL);
57255917Sshin		if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
573184295Sbz			return (EINVAL);
57455009Sshin		/* XXX need improvement */
57555917Sshin		if (iflr->dstaddr.ss_family
57655917Sshin		 && iflr->dstaddr.ss_family != AF_INET)
577184295Sbz			return (EINVAL);
57855917Sshin		if (iflr->dstaddr.ss_family
57955917Sshin		 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
580184295Sbz			return (EINVAL);
58155009Sshin		break;
58255009Sshin	default: /*shouldn't happen*/
583184295Sbz		return (EOPNOTSUPP);
58455009Sshin	}
58555009Sshin	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
586184295Sbz		return (EINVAL);
58755009Sshin
58855009Sshin	switch (cmd) {
58955009Sshin	case SIOCALIFADDR:
59055009Sshin	    {
59155009Sshin		struct in_aliasreq ifra;
59255009Sshin
59355009Sshin		if (iflr->flags & IFLR_PREFIX)
594184295Sbz			return (EINVAL);
59555009Sshin
59655009Sshin		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
59755009Sshin		bzero(&ifra, sizeof(ifra));
59855009Sshin		bcopy(iflr->iflr_name, ifra.ifra_name,
59955009Sshin			sizeof(ifra.ifra_name));
60055009Sshin
60155917Sshin		bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
60255009Sshin
60355917Sshin		if (iflr->dstaddr.ss_family) {	/*XXX*/
60455009Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
60555917Sshin				iflr->dstaddr.ss_len);
60655009Sshin		}
60755009Sshin
60855009Sshin		ifra.ifra_mask.sin_family = AF_INET;
60955009Sshin		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
61055009Sshin		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
61155009Sshin
612184295Sbz		return (in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td));
61355009Sshin	    }
61455009Sshin	case SIOCGLIFADDR:
61555009Sshin	case SIOCDLIFADDR:
61655009Sshin	    {
61755009Sshin		struct in_ifaddr *ia;
61855009Sshin		struct in_addr mask, candidate, match;
61955009Sshin		struct sockaddr_in *sin;
62055009Sshin
62155009Sshin		bzero(&mask, sizeof(mask));
622170855Smjacob		bzero(&match, sizeof(match));
62355009Sshin		if (iflr->flags & IFLR_PREFIX) {
62455009Sshin			/* lookup a prefix rather than address. */
62555009Sshin			in_len2mask(&mask, iflr->prefixlen);
62655009Sshin
62755009Sshin			sin = (struct sockaddr_in *)&iflr->addr;
62855009Sshin			match.s_addr = sin->sin_addr.s_addr;
62955009Sshin			match.s_addr &= mask.s_addr;
63055009Sshin
63155009Sshin			/* if you set extra bits, that's wrong */
63255009Sshin			if (match.s_addr != sin->sin_addr.s_addr)
633184295Sbz				return (EINVAL);
63455009Sshin
63555009Sshin		} else {
636170855Smjacob			/* on getting an address, take the 1st match */
637170855Smjacob			/* on deleting an address, do exact match */
638170855Smjacob			if (cmd != SIOCGLIFADDR) {
63955009Sshin				in_len2mask(&mask, 32);
64055009Sshin				sin = (struct sockaddr_in *)&iflr->addr;
64155009Sshin				match.s_addr = sin->sin_addr.s_addr;
64255009Sshin			}
64355009Sshin		}
64455009Sshin
64555009Sshin		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)	{
64655009Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
64755009Sshin				continue;
648170855Smjacob			if (match.s_addr == 0)
64955009Sshin				break;
65055009Sshin			candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
65155009Sshin			candidate.s_addr &= mask.s_addr;
65255009Sshin			if (candidate.s_addr == match.s_addr)
65355009Sshin				break;
65455009Sshin		}
655184295Sbz		if (ifa == NULL)
656184295Sbz			return (EADDRNOTAVAIL);
65755009Sshin		ia = (struct in_ifaddr *)ifa;
65855009Sshin
65955009Sshin		if (cmd == SIOCGLIFADDR) {
66055009Sshin			/* fill in the if_laddrreq structure */
66155009Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
66255009Sshin
66355009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
66455009Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
66555009Sshin					ia->ia_dstaddr.sin_len);
66655009Sshin			} else
66755009Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
66855009Sshin
66955009Sshin			iflr->prefixlen =
67055009Sshin				in_mask2len(&ia->ia_sockmask.sin_addr);
67155009Sshin
67255009Sshin			iflr->flags = 0;	/*XXX*/
67355009Sshin
674184295Sbz			return (0);
67555009Sshin		} else {
67655009Sshin			struct in_aliasreq ifra;
67755009Sshin
67855009Sshin			/* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
67955009Sshin			bzero(&ifra, sizeof(ifra));
68055009Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
68155009Sshin				sizeof(ifra.ifra_name));
68255009Sshin
68355009Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
68455009Sshin				ia->ia_addr.sin_len);
68555009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
68655009Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
68755009Sshin					ia->ia_dstaddr.sin_len);
68855009Sshin			}
68955009Sshin			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
69055009Sshin				ia->ia_sockmask.sin_len);
69155009Sshin
692184295Sbz			return (in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
693184295Sbz			    ifp, td));
69455009Sshin		}
69555009Sshin	    }
69655009Sshin	}
69755009Sshin
698184295Sbz	return (EOPNOTSUPP);	/*just for safety*/
69955009Sshin}
70055009Sshin
70155009Sshin/*
7021541Srgrimes * Delete any existing route for an interface.
7031541Srgrimes */
70422672Swollmanvoid
705169454Srwatsonin_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
7061541Srgrimes{
707169454Srwatson
708137628Smlaier	in_scrubprefix(ia);
7091541Srgrimes}
7101541Srgrimes
7111541Srgrimes/*
7121541Srgrimes * Initialize an interface's internet address
7131541Srgrimes * and routing table entry.
7141541Srgrimes */
71512296Sphkstatic int
716169454Srwatsonin_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
717169454Srwatson    int scrub)
7181541Srgrimes{
719183550Szec	INIT_VNET_INET(ifp->if_vnet);
7201541Srgrimes	register u_long i = ntohl(sin->sin_addr.s_addr);
7211541Srgrimes	struct sockaddr_in oldaddr;
72294326Sbrian	int s = splimp(), flags = RTF_UP, error = 0;
7231541Srgrimes
7241541Srgrimes	oldaddr = ia->ia_addr;
725105748Ssuz	if (oldaddr.sin_family == AF_INET)
726105748Ssuz		LIST_REMOVE(ia, ia_hash);
7271541Srgrimes	ia->ia_addr = *sin;
728105748Ssuz	if (ia->ia_addr.sin_family == AF_INET)
729105748Ssuz		LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
730105748Ssuz		    ia, ia_hash);
7311541Srgrimes	/*
7321541Srgrimes	 * Give the interface a chance to initialize
7331541Srgrimes	 * if this is its first address,
7341541Srgrimes	 * and to validate the address if necessary.
7351541Srgrimes	 */
736184295Sbz	if (ifp->if_ioctl != NULL) {
737146883Siedowse		IFF_LOCKGIANT(ifp);
738146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
739146883Siedowse		IFF_UNLOCKGIANT(ifp);
740146883Siedowse		if (error) {
741146883Siedowse			splx(s);
742146883Siedowse			/* LIST_REMOVE(ia, ia_hash) is done in in_control */
743146883Siedowse			ia->ia_addr = oldaddr;
744146883Siedowse			if (ia->ia_addr.sin_family == AF_INET)
745146883Siedowse				LIST_INSERT_HEAD(INADDR_HASH(
746146883Siedowse				    ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
747179971Sgonzo			else
748179971Sgonzo				/*
749179971Sgonzo				 * If oldaddr family is not AF_INET (e.g.
750179971Sgonzo				 * interface has been just created) in_control
751179971Sgonzo				 * does not call LIST_REMOVE, and we end up
752179971Sgonzo				 * with bogus ia entries in hash
753179971Sgonzo				 */
754179971Sgonzo				LIST_REMOVE(ia, ia_hash);
755146883Siedowse			return (error);
756146883Siedowse		}
7571541Srgrimes	}
7581541Srgrimes	splx(s);
7591541Srgrimes	if (scrub) {
7601541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
7611541Srgrimes		in_ifscrub(ifp, ia);
7621541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
7631541Srgrimes	}
7641541Srgrimes	if (IN_CLASSA(i))
7651541Srgrimes		ia->ia_netmask = IN_CLASSA_NET;
7661541Srgrimes	else if (IN_CLASSB(i))
7671541Srgrimes		ia->ia_netmask = IN_CLASSB_NET;
7681541Srgrimes	else
7691541Srgrimes		ia->ia_netmask = IN_CLASSC_NET;
7701541Srgrimes	/*
7711541Srgrimes	 * The subnet mask usually includes at least the standard network part,
7721541Srgrimes	 * but may may be smaller in the case of supernetting.
7731541Srgrimes	 * If it is set, we believe it.
7741541Srgrimes	 */
7751541Srgrimes	if (ia->ia_subnetmask == 0) {
7761541Srgrimes		ia->ia_subnetmask = ia->ia_netmask;
7771541Srgrimes		ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
7781541Srgrimes	} else
7791541Srgrimes		ia->ia_netmask &= ia->ia_subnetmask;
7801541Srgrimes	ia->ia_net = i & ia->ia_netmask;
7811541Srgrimes	ia->ia_subnet = i & ia->ia_subnetmask;
7821541Srgrimes	in_socktrim(&ia->ia_sockmask);
783143868Sglebius#ifdef DEV_CARP
7841541Srgrimes	/*
785143868Sglebius	 * XXX: carp(4) does not have interface route
786143868Sglebius	 */
787143868Sglebius	if (ifp->if_type == IFT_CARP)
788143868Sglebius		return (0);
789143868Sglebius#endif
790143868Sglebius	/*
7911541Srgrimes	 * Add route for the network.
7921541Srgrimes	 */
7931541Srgrimes	ia->ia_ifa.ifa_metric = ifp->if_metric;
7941541Srgrimes	if (ifp->if_flags & IFF_BROADCAST) {
7951541Srgrimes		ia->ia_broadaddr.sin_addr.s_addr =
7961541Srgrimes			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
7971541Srgrimes		ia->ia_netbroadcast.s_addr =
7981541Srgrimes			htonl(ia->ia_net | ~ ia->ia_netmask);
7991541Srgrimes	} else if (ifp->if_flags & IFF_LOOPBACK) {
800137833Smlaier		ia->ia_dstaddr = ia->ia_addr;
8011541Srgrimes		flags |= RTF_HOST;
8021541Srgrimes	} else if (ifp->if_flags & IFF_POINTOPOINT) {
8031541Srgrimes		if (ia->ia_dstaddr.sin_family != AF_INET)
8041541Srgrimes			return (0);
8051541Srgrimes		flags |= RTF_HOST;
8061541Srgrimes	}
807137628Smlaier	if ((error = in_addprefix(ia, flags)) != 0)
808137628Smlaier		return (error);
80994326Sbrian
8101541Srgrimes	return (error);
8111541Srgrimes}
8121541Srgrimes
813137628Smlaier#define rtinitflags(x) \
814137628Smlaier	((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
815137628Smlaier	    ? RTF_HOST : 0)
816137628Smlaier/*
817170855Smjacob * Check if we have a route for the given prefix already or add one accordingly.
818137628Smlaier */
819137628Smlaierstatic int
820169454Srwatsonin_addprefix(struct in_ifaddr *target, int flags)
821137628Smlaier{
822183550Szec	INIT_VNET_INET(curvnet);
823137628Smlaier	struct in_ifaddr *ia;
824151555Sglebius	struct in_addr prefix, mask, p, m;
825137628Smlaier	int error;
8261541Srgrimes
827170855Smjacob	if ((flags & RTF_HOST) != 0) {
828137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
829170855Smjacob		mask.s_addr = 0;
830170855Smjacob	} else {
831137628Smlaier		prefix = target->ia_addr.sin_addr;
832137628Smlaier		mask = target->ia_sockmask.sin_addr;
833137628Smlaier		prefix.s_addr &= mask.s_addr;
834137628Smlaier	}
835137628Smlaier
836181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
837151555Sglebius		if (rtinitflags(ia)) {
838137628Smlaier			p = ia->ia_addr.sin_addr;
839151555Sglebius
840151555Sglebius			if (prefix.s_addr != p.s_addr)
841151555Sglebius				continue;
842151555Sglebius		} else {
843151555Sglebius			p = ia->ia_addr.sin_addr;
844151555Sglebius			m = ia->ia_sockmask.sin_addr;
845151555Sglebius			p.s_addr &= m.s_addr;
846151555Sglebius
847151555Sglebius			if (prefix.s_addr != p.s_addr ||
848151555Sglebius			    mask.s_addr != m.s_addr)
849151555Sglebius				continue;
850137628Smlaier		}
851137628Smlaier
852137628Smlaier		/*
853137628Smlaier		 * If we got a matching prefix route inserted by other
854137628Smlaier		 * interface address, we are done here.
855137628Smlaier		 */
856149221Sglebius		if (ia->ia_flags & IFA_ROUTE) {
857181803Sbz			if (V_sameprefixcarponly &&
858149221Sglebius			    target->ia_ifp->if_type != IFT_CARP &&
859149221Sglebius			    ia->ia_ifp->if_type != IFT_CARP)
860149221Sglebius				return (EEXIST);
861149221Sglebius			else
862149221Sglebius				return (0);
863149221Sglebius		}
864137628Smlaier	}
865137628Smlaier
866137628Smlaier	/*
867137628Smlaier	 * No-one seem to have this prefix route, so we try to insert it.
868137628Smlaier	 */
869137628Smlaier	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
870137628Smlaier	if (!error)
871137628Smlaier		target->ia_flags |= IFA_ROUTE;
872184295Sbz	return (error);
873137628Smlaier}
874137628Smlaier
875186119Sqingliextern void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
876186119Sqingli
8771541Srgrimes/*
878137628Smlaier * If there is no other address in the system that can serve a route to the
879137628Smlaier * same prefix, remove the route.  Hand over the route to the new address
880137628Smlaier * otherwise.
881137628Smlaier */
882137628Smlaierstatic int
883169454Srwatsonin_scrubprefix(struct in_ifaddr *target)
884137628Smlaier{
885183550Szec	INIT_VNET_INET(curvnet);
886137628Smlaier	struct in_ifaddr *ia;
887137628Smlaier	struct in_addr prefix, mask, p;
888137628Smlaier	int error;
889137628Smlaier
890137628Smlaier	if ((target->ia_flags & IFA_ROUTE) == 0)
891184295Sbz		return (0);
892137628Smlaier
893137628Smlaier	if (rtinitflags(target))
894137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
895137628Smlaier	else {
896137628Smlaier		prefix = target->ia_addr.sin_addr;
897137628Smlaier		mask = target->ia_sockmask.sin_addr;
898137628Smlaier		prefix.s_addr &= mask.s_addr;
899186119Sqingli		/* remove arp cache */
900186119Sqingli		arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
901137628Smlaier	}
902137628Smlaier
903181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
904137628Smlaier		if (rtinitflags(ia))
905137628Smlaier			p = ia->ia_dstaddr.sin_addr;
906137628Smlaier		else {
907137628Smlaier			p = ia->ia_addr.sin_addr;
908137628Smlaier			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
909137628Smlaier		}
910137628Smlaier
911137628Smlaier		if (prefix.s_addr != p.s_addr)
912137628Smlaier			continue;
913137628Smlaier
914137628Smlaier		/*
915137628Smlaier		 * If we got a matching prefix address, move IFA_ROUTE and
916137628Smlaier		 * the route itself to it.  Make sure that routing daemons
917137628Smlaier		 * get a heads-up.
918143868Sglebius		 *
919143868Sglebius		 * XXX: a special case for carp(4) interface
920137628Smlaier		 */
921143868Sglebius		if ((ia->ia_flags & IFA_ROUTE) == 0
922143868Sglebius#ifdef DEV_CARP
923143868Sglebius		    && (ia->ia_ifp->if_type != IFT_CARP)
924143868Sglebius#endif
925143868Sglebius							) {
926137628Smlaier			rtinit(&(target->ia_ifa), (int)RTM_DELETE,
927137628Smlaier			    rtinitflags(target));
928137628Smlaier			target->ia_flags &= ~IFA_ROUTE;
929137628Smlaier
930137628Smlaier			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
931137628Smlaier			    rtinitflags(ia) | RTF_UP);
932137628Smlaier			if (error == 0)
933137628Smlaier				ia->ia_flags |= IFA_ROUTE;
934184295Sbz			return (error);
935137628Smlaier		}
936137628Smlaier	}
937137628Smlaier
938137628Smlaier	/*
939137628Smlaier	 * As no-one seem to have this prefix, we can remove the route.
940137628Smlaier	 */
941137628Smlaier	rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
942137628Smlaier	target->ia_flags &= ~IFA_ROUTE;
943184295Sbz	return (0);
944137628Smlaier}
945137628Smlaier
946137628Smlaier#undef rtinitflags
947137628Smlaier
948137628Smlaier/*
9491541Srgrimes * Return 1 if the address might be a local broadcast address.
9501541Srgrimes */
9511549Srgrimesint
952169454Srwatsonin_broadcast(struct in_addr in, struct ifnet *ifp)
9531541Srgrimes{
9541541Srgrimes	register struct ifaddr *ifa;
9551541Srgrimes	u_long t;
9561541Srgrimes
9571541Srgrimes	if (in.s_addr == INADDR_BROADCAST ||
9581541Srgrimes	    in.s_addr == INADDR_ANY)
959184295Sbz		return (1);
9601541Srgrimes	if ((ifp->if_flags & IFF_BROADCAST) == 0)
961184295Sbz		return (0);
9621541Srgrimes	t = ntohl(in.s_addr);
9631541Srgrimes	/*
9641541Srgrimes	 * Look through the list of addresses for a match
9651541Srgrimes	 * with a broadcast address.
9661541Srgrimes	 */
9671541Srgrimes#define ia ((struct in_ifaddr *)ifa)
96874362Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
9691541Srgrimes		if (ifa->ifa_addr->sa_family == AF_INET &&
9701541Srgrimes		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
9711541Srgrimes		     in.s_addr == ia->ia_netbroadcast.s_addr ||
9721541Srgrimes		     /*
9731541Srgrimes		      * Check for old-style (host 0) broadcast.
9741541Srgrimes		      */
97513351Sguido		     t == ia->ia_subnet || t == ia->ia_net) &&
97613351Sguido		     /*
97713351Sguido		      * Check for an all one subnetmask. These
97813351Sguido		      * only exist when an interface gets a secondary
97913351Sguido		      * address.
98013351Sguido		      */
98113351Sguido		     ia->ia_subnetmask != (u_long)0xffffffff)
982184295Sbz			    return (1);
9831541Srgrimes	return (0);
9841541Srgrimes#undef ia
9851541Srgrimes}
986167729Sbms
9871541Srgrimes/*
988167729Sbms * Delete all IPv4 multicast address records, and associated link-layer
989167729Sbms * multicast address records, associated with ifp.
990162718Sbms */
991167729Sbmsstatic void
992167729Sbmsin_purgemaddrs(struct ifnet *ifp)
993162718Sbms{
994183550Szec	INIT_VNET_INET(ifp->if_vnet);
995162718Sbms	struct in_multi *inm;
996162718Sbms	struct in_multi *oinm;
997162718Sbms
998168032Sbms#ifdef DIAGNOSTIC
999168032Sbms	printf("%s: purging ifp %p\n", __func__, ifp);
1000168032Sbms#endif
1001162718Sbms	IFF_LOCKGIANT(ifp);
1002162718Sbms	IN_MULTI_LOCK();
1003181803Sbz	LIST_FOREACH_SAFE(inm, &V_in_multihead, inm_link, oinm) {
1004162718Sbms		if (inm->inm_ifp == ifp)
1005162718Sbms			in_delmulti_locked(inm);
1006162718Sbms	}
1007150853Srwatson	IN_MULTI_UNLOCK();
1008150852Srwatson	IFF_UNLOCKGIANT(ifp);
10091541Srgrimes}
1010150296Srwatson
1011150296Srwatson/*
1012150296Srwatson * On interface removal, clean up IPv4 data structures hung off of the ifnet.
1013150296Srwatson */
1014150296Srwatsonvoid
1015169454Srwatsonin_ifdetach(struct ifnet *ifp)
1016150296Srwatson{
1017183550Szec	INIT_VNET_INET(ifp->if_vnet);
1018150296Srwatson
1019181803Sbz	in_pcbpurgeif0(&V_ripcbinfo, ifp);
1020181803Sbz	in_pcbpurgeif0(&V_udbinfo, ifp);
1021167729Sbms	in_purgemaddrs(ifp);
1022150296Srwatson}
1023186119Sqingli
1024186119Sqingli#include <sys/syslog.h>
1025186119Sqingli#include <net/if_dl.h>
1026186119Sqingli#include <netinet/if_ether.h>
1027186119Sqingli
1028186119Sqinglistruct in_llentry {
1029186119Sqingli	struct llentry		base;
1030186119Sqingli	struct sockaddr_in	l3_addr4;
1031186119Sqingli};
1032186119Sqingli
1033186119Sqinglistatic struct llentry *
1034186119Sqingliin_lltable_new(const struct sockaddr *l3addr, u_int flags)
1035186119Sqingli{
1036186119Sqingli	struct in_llentry *lle;
1037186119Sqingli
1038186119Sqingli	lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_DONTWAIT | M_ZERO);
1039186119Sqingli	if (lle == NULL)		/* NB: caller generates msg */
1040186119Sqingli		return NULL;
1041186119Sqingli
1042186119Sqingli	callout_init(&lle->base.la_timer, CALLOUT_MPSAFE);
1043186119Sqingli	/*
1044186119Sqingli	 * For IPv4 this will trigger "arpresolve" to generate
1045186119Sqingli	 * an ARP request.
1046186119Sqingli	 */
1047186119Sqingli	lle->base.la_expire = time_second; /* mark expired */
1048186119Sqingli	lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
1049186119Sqingli	lle->base.lle_refcnt = 1;
1050186119Sqingli	LLE_LOCK_INIT(&lle->base);
1051186119Sqingli	return &lle->base;
1052186119Sqingli}
1053186119Sqingli
1054186119Sqingli/*
1055186119Sqingli * Deletes an address from the address table.
1056186119Sqingli * This function is called by the timer functions
1057186119Sqingli * such as arptimer() and nd6_llinfo_timer(), and
1058186119Sqingli * the caller does the locking.
1059186119Sqingli */
1060186119Sqinglistatic void
1061186119Sqingliin_lltable_free(struct lltable *llt, struct llentry *lle)
1062186119Sqingli{
1063186150Skmacy	LLE_WUNLOCK(lle);
1064186150Skmacy	LLE_LOCK_DESTROY(lle);
1065186119Sqingli	free(lle, M_LLTABLE);
1066186119Sqingli}
1067186119Sqingli
1068186119Sqinglistatic int
1069186119Sqingliin_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
1070186119Sqingli{
1071186119Sqingli	struct rtentry *rt;
1072186119Sqingli
1073186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1074186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1075186119Sqingli
1076186119Sqingli	/* XXX rtalloc1 should take a const param */
1077186119Sqingli	rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
1078186119Sqingli	if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
1079186119Sqingli		log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
1080186119Sqingli		    inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
1081186119Sqingli		if (rt != NULL)
1082186119Sqingli			RTFREE_LOCKED(rt);
1083186119Sqingli		return (EINVAL);
1084186119Sqingli	}
1085186119Sqingli	RTFREE_LOCKED(rt);
1086186119Sqingli	return 0;
1087186119Sqingli}
1088186119Sqingli
1089186119Sqingli/*
1090186119Sqingli * Return NULL if not found or marked for deletion.
1091186119Sqingli * If found return lle read locked.
1092186119Sqingli */
1093186119Sqinglistatic struct llentry *
1094186119Sqingliin_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
1095186119Sqingli{
1096186119Sqingli	const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
1097186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1098186119Sqingli	struct llentry *lle;
1099186119Sqingli	struct llentries *lleh;
1100186119Sqingli	u_int hashkey;
1101186119Sqingli
1102186119Sqingli	IF_AFDATA_LOCK_ASSERT(ifp);
1103186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1104186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1105186119Sqingli
1106186119Sqingli	hashkey = sin->sin_addr.s_addr;
1107186119Sqingli	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
1108186119Sqingli	LIST_FOREACH(lle, lleh, lle_next) {
1109186708Sqingli		struct sockaddr_in *sa2 = (struct sockaddr_in *)L3_ADDR(lle);
1110186119Sqingli		if (lle->la_flags & LLE_DELETED)
1111186119Sqingli			continue;
1112186708Sqingli		if (sa2->sin_addr.s_addr == sin->sin_addr.s_addr)
1113186119Sqingli			break;
1114186119Sqingli	}
1115186119Sqingli	if (lle == NULL) {
1116186119Sqingli#ifdef DIAGNOSTICS
1117186119Sqingli		if (flags & LLE_DELETE)
1118186119Sqingli			log(LOG_INFO, "interface address is missing from cache = %p  in delete\n", lle);
1119186119Sqingli#endif
1120186119Sqingli		if (!(flags & LLE_CREATE))
1121186119Sqingli			return (NULL);
1122186119Sqingli		/*
1123186119Sqingli		 * A route that covers the given address must have
1124186119Sqingli		 * been installed 1st because we are doing a resolution,
1125186119Sqingli		 * verify this.
1126186119Sqingli		 */
1127186119Sqingli		if (!(flags & LLE_IFADDR) &&
1128186119Sqingli		    in_lltable_rtcheck(ifp, l3addr) != 0)
1129186119Sqingli			goto done;
1130186119Sqingli
1131186119Sqingli		lle = in_lltable_new(l3addr, flags);
1132186119Sqingli		if (lle == NULL) {
1133186119Sqingli			log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
1134186119Sqingli			goto done;
1135186119Sqingli		}
1136186119Sqingli		lle->la_flags = flags & ~LLE_CREATE;
1137186119Sqingli		if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
1138186119Sqingli			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
1139186119Sqingli			lle->la_flags |= (LLE_VALID | LLE_STATIC);
1140186119Sqingli		}
1141186119Sqingli
1142186119Sqingli		lle->lle_tbl  = llt;
1143186119Sqingli		lle->lle_head = lleh;
1144186119Sqingli		LIST_INSERT_HEAD(lleh, lle, lle_next);
1145186119Sqingli	} else if (flags & LLE_DELETE) {
1146186119Sqingli		if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
1147186119Sqingli			LLE_WLOCK(lle);
1148186119Sqingli			lle->la_flags = LLE_DELETED;
1149186119Sqingli			LLE_WUNLOCK(lle);
1150186119Sqingli#ifdef DIAGNOSTICS
1151186119Sqingli			log(LOG_INFO, "ifaddr cache = %p  is deleted\n", lle);
1152186119Sqingli#endif
1153186119Sqingli		}
1154186119Sqingli		lle = (void *)-1;
1155186119Sqingli
1156186119Sqingli	}
1157186544Sbz	if (LLE_IS_VALID(lle)) {
1158186119Sqingli		if (flags & LLE_EXCLUSIVE)
1159186119Sqingli			LLE_WLOCK(lle);
1160186119Sqingli		else
1161186119Sqingli			LLE_RLOCK(lle);
1162186119Sqingli	}
1163186119Sqinglidone:
1164186119Sqingli	return (lle);
1165186119Sqingli}
1166186119Sqingli
1167186119Sqinglistatic int
1168186119Sqingliin_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
1169186119Sqingli{
1170186119Sqingli#define	SIN(lle)	((struct sockaddr_in *) L3_ADDR(lle))
1171186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1172186119Sqingli	struct llentry *lle;
1173186119Sqingli	/* XXX stack use */
1174186119Sqingli	struct {
1175186119Sqingli		struct rt_msghdr	rtm;
1176186119Sqingli		struct sockaddr_inarp	sin;
1177186119Sqingli		struct sockaddr_dl	sdl;
1178186119Sqingli	} arpc;
1179186119Sqingli	int error, i;
1180186119Sqingli
1181186119Sqingli	/* XXXXX
1182186119Sqingli	 * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
1183186119Sqingli	 * so it is okay to use this ASSERT, change it when
1184186119Sqingli	 * IFNET lock is finalized
1185186119Sqingli	 */
1186186119Sqingli	IFNET_WLOCK_ASSERT();
1187186119Sqingli
1188186119Sqingli	error = 0;
1189186119Sqingli	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
1190186119Sqingli		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
1191186119Sqingli			struct sockaddr_dl *sdl;
1192186119Sqingli
1193186119Sqingli			/* skip deleted entries */
1194186119Sqingli			if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
1195186119Sqingli				continue;
1196186119Sqingli			/*
1197186119Sqingli			 * produce a msg made of:
1198186119Sqingli			 *  struct rt_msghdr;
1199186119Sqingli			 *  struct sockaddr_inarp; (IPv4)
1200186119Sqingli			 *  struct sockaddr_dl;
1201186119Sqingli			 */
1202186119Sqingli			bzero(&arpc, sizeof(arpc));
1203186119Sqingli			arpc.rtm.rtm_msglen = sizeof(arpc);
1204186119Sqingli			arpc.sin.sin_family = AF_INET;
1205186119Sqingli			arpc.sin.sin_len = sizeof(arpc.sin);
1206186119Sqingli			arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
1207186119Sqingli
1208186119Sqingli			/* publish */
1209186119Sqingli			if (lle->la_flags & LLE_PUB) {
1210186119Sqingli				arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
1211186119Sqingli				/* proxy only */
1212186119Sqingli				if (lle->la_flags & LLE_PROXY)
1213186119Sqingli					arpc.sin.sin_other = SIN_PROXY;
1214186119Sqingli			}
1215186119Sqingli
1216186119Sqingli			sdl = &arpc.sdl;
1217186119Sqingli			sdl->sdl_family = AF_LINK;
1218186119Sqingli			sdl->sdl_len = sizeof(*sdl);
1219186119Sqingli			sdl->sdl_alen = ifp->if_addrlen;
1220186119Sqingli			sdl->sdl_index = ifp->if_index;
1221186119Sqingli			sdl->sdl_type = ifp->if_type;
1222186119Sqingli			bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
1223186119Sqingli
1224186119Sqingli			arpc.rtm.rtm_rmx.rmx_expire =
1225186119Sqingli			    lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
1226186500Sqingli			arpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
1227186119Sqingli			if (lle->la_flags & LLE_STATIC)
1228186119Sqingli				arpc.rtm.rtm_flags |= RTF_STATIC;
1229186119Sqingli			arpc.rtm.rtm_index = ifp->if_index;
1230186119Sqingli			error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
1231186119Sqingli			if (error)
1232186119Sqingli				break;
1233186119Sqingli		}
1234186119Sqingli	}
1235186119Sqingli	return error;
1236186119Sqingli#undef SIN
1237186119Sqingli}
1238186119Sqingli
1239186119Sqinglivoid *
1240186119Sqingliin_domifattach(struct ifnet *ifp)
1241186119Sqingli{
1242186119Sqingli	struct lltable *llt = lltable_init(ifp, AF_INET);
1243186119Sqingli
1244186119Sqingli	if (llt != NULL) {
1245186119Sqingli		llt->llt_new = in_lltable_new;
1246186119Sqingli		llt->llt_free = in_lltable_free;
1247186119Sqingli		llt->llt_rtcheck = in_lltable_rtcheck;
1248186119Sqingli		llt->llt_lookup = in_lltable_lookup;
1249186119Sqingli		llt->llt_dump = in_lltable_dump;
1250186119Sqingli	}
1251186119Sqingli	return (llt);
1252186119Sqingli}
1253186119Sqingli
1254186119Sqinglivoid
1255186119Sqingliin_domifdetach(struct ifnet *ifp __unused, void *aux)
1256186119Sqingli{
1257186119Sqingli	struct lltable *llt = (struct lltable *)aux;
1258186119Sqingli
1259186119Sqingli	lltable_free(llt);
1260186119Sqingli}
1261