in.c revision 191443
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 191443 2009-04-23 21:41:37Z rwatson $");
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>
44186948Sbz#include <sys/jail.h>
4512704Sphk#include <sys/kernel.h>
46186948Sbz#include <sys/proc.h>
4712704Sphk#include <sys/sysctl.h>
48181803Sbz#include <sys/vimage.h>
491541Srgrimes
501541Srgrimes#include <net/if.h>
51186119Sqingli#include <net/if_llatbl.h>
5255009Sshin#include <net/if_types.h>
531541Srgrimes#include <net/route.h>
541541Srgrimes
551541Srgrimes#include <netinet/in.h>
561541Srgrimes#include <netinet/in_var.h>
5781127Sume#include <netinet/in_pcb.h>
58170613Sbms#include <netinet/ip_var.h>
59185571Sbz#include <netinet/vinet.h>
60189592Sbms#include <netinet/igmp_var.h>
611541Srgrimes
6292723Salfredstatic int in_mask2len(struct in_addr *);
6392723Salfredstatic void in_len2mask(struct in_addr *, int);
6492723Salfredstatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
6592723Salfred	struct ifnet *, struct thread *);
6655009Sshin
67137628Smlaierstatic int	in_addprefix(struct in_ifaddr *, int);
68137628Smlaierstatic int	in_scrubprefix(struct in_ifaddr *);
6992723Salfredstatic void	in_socktrim(struct sockaddr_in *);
7092723Salfredstatic int	in_ifinit(struct ifnet *,
7192723Salfred	    struct in_ifaddr *, struct sockaddr_in *, int);
72167729Sbmsstatic void	in_purgemaddrs(struct ifnet *);
731541Srgrimes
74185088Szec#ifdef VIMAGE_GLOBALS
75185088Szecstatic int subnetsarelocal;
76185088Szecstatic int sameprefixcarponly;
77185088Szecextern struct inpcbinfo ripcbinfo;
78185088Szec#endif
79185088Szec
80183550SzecSYSCTL_V_INT(V_NET, vnet_inet, _net_inet_ip, OID_AUTO, subnets_are_local,
81183550Szec	CTLFLAG_RW, subnetsarelocal, 0,
82183550Szec	"Treat all subnets as directly connected");
83183550SzecSYSCTL_V_INT(V_NET, vnet_inet, _net_inet_ip, OID_AUTO, same_prefix_carp_only,
84183550Szec	CTLFLAG_RW, sameprefixcarponly, 0,
85149221Sglebius	"Refuse to create same prefixes on different interfaces");
8621666Swollman
871541Srgrimes/*
881541Srgrimes * Return 1 if an internet address is for a ``local'' host
891541Srgrimes * (one to which we have a connection).  If subnetsarelocal
901541Srgrimes * is true, this includes other subnets of the local net.
911541Srgrimes * Otherwise, it includes only the directly-connected (sub)nets.
921541Srgrimes */
931549Srgrimesint
94169454Srwatsonin_localaddr(struct in_addr in)
951541Srgrimes{
96183550Szec	INIT_VNET_INET(curvnet);
971541Srgrimes	register u_long i = ntohl(in.s_addr);
981541Srgrimes	register struct in_ifaddr *ia;
991541Srgrimes
100181803Sbz	if (V_subnetsarelocal) {
101181803Sbz		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
1021541Srgrimes			if ((i & ia->ia_netmask) == ia->ia_net)
1031541Srgrimes				return (1);
1041541Srgrimes	} else {
105181803Sbz		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
1061541Srgrimes			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
1071541Srgrimes				return (1);
1081541Srgrimes	}
1091541Srgrimes	return (0);
1101541Srgrimes}
1111541Srgrimes
1121541Srgrimes/*
113133486Sandre * Return 1 if an internet address is for the local host and configured
114133486Sandre * on one of its interfaces.
115133486Sandre */
116133486Sandreint
117169454Srwatsonin_localip(struct in_addr in)
118133486Sandre{
119183550Szec	INIT_VNET_INET(curvnet);
120133486Sandre	struct in_ifaddr *ia;
121133486Sandre
122133486Sandre	LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
123133486Sandre		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr)
124184295Sbz			return (1);
125133486Sandre	}
126184295Sbz	return (0);
127133486Sandre}
128133486Sandre
129133486Sandre/*
1301541Srgrimes * Determine whether an IP address is in a reserved set of addresses
1311541Srgrimes * that may not be forwarded, or whether datagrams to that destination
1321541Srgrimes * may be forwarded.
1331541Srgrimes */
1341549Srgrimesint
135169454Srwatsonin_canforward(struct in_addr in)
1361541Srgrimes{
1371541Srgrimes	register u_long i = ntohl(in.s_addr);
1381541Srgrimes	register u_long net;
1391541Srgrimes
140166450Sbms	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i))
1411541Srgrimes		return (0);
1421541Srgrimes	if (IN_CLASSA(i)) {
1431541Srgrimes		net = i & IN_CLASSA_NET;
1441541Srgrimes		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
1451541Srgrimes			return (0);
1461541Srgrimes	}
1471541Srgrimes	return (1);
1481541Srgrimes}
1491541Srgrimes
1501541Srgrimes/*
1511541Srgrimes * Trim a mask in a sockaddr
1521541Srgrimes */
15312296Sphkstatic void
154169454Srwatsonin_socktrim(struct sockaddr_in *ap)
1551541Srgrimes{
1561541Srgrimes    register char *cplim = (char *) &ap->sin_addr;
1571541Srgrimes    register char *cp = (char *) (&ap->sin_addr + 1);
1581541Srgrimes
1591541Srgrimes    ap->sin_len = 0;
1604127Swollman    while (--cp >= cplim)
161133874Srwatson	if (*cp) {
1621541Srgrimes	    (ap)->sin_len = cp - (char *) (ap) + 1;
1631541Srgrimes	    break;
1641541Srgrimes	}
1651541Srgrimes}
1661541Srgrimes
16755009Sshinstatic int
16855009Sshinin_mask2len(mask)
16955009Sshin	struct in_addr *mask;
17055009Sshin{
17155009Sshin	int x, y;
17255009Sshin	u_char *p;
17355009Sshin
17455009Sshin	p = (u_char *)mask;
17555009Sshin	for (x = 0; x < sizeof(*mask); x++) {
17655009Sshin		if (p[x] != 0xff)
17755009Sshin			break;
17855009Sshin	}
17955009Sshin	y = 0;
18055009Sshin	if (x < sizeof(*mask)) {
18155009Sshin		for (y = 0; y < 8; y++) {
18255009Sshin			if ((p[x] & (0x80 >> y)) == 0)
18355009Sshin				break;
18455009Sshin		}
18555009Sshin	}
186184295Sbz	return (x * 8 + y);
18755009Sshin}
18855009Sshin
18955009Sshinstatic void
190169454Srwatsonin_len2mask(struct in_addr *mask, int len)
19155009Sshin{
19255009Sshin	int i;
19355009Sshin	u_char *p;
19455009Sshin
19555009Sshin	p = (u_char *)mask;
19655009Sshin	bzero(mask, sizeof(*mask));
19755009Sshin	for (i = 0; i < len / 8; i++)
19855009Sshin		p[i] = 0xff;
19955009Sshin	if (len % 8)
20055009Sshin		p[i] = (0xff00 >> (len % 8)) & 0xff;
20155009Sshin}
20255009Sshin
2031541Srgrimes/*
2041541Srgrimes * Generic internet control operations (ioctl's).
205191443Srwatson *
206191443Srwatson * ifp is NULL if not an interface-specific ioctl.
2071541Srgrimes */
2081541Srgrimes/* ARGSUSED */
2091549Srgrimesint
210169454Srwatsonin_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
211169454Srwatson    struct thread *td)
2121541Srgrimes{
213183550Szec	INIT_VNET_INET(curvnet); /* both so and ifp can be NULL here! */
2141541Srgrimes	register struct ifreq *ifr = (struct ifreq *)data;
215184295Sbz	register struct in_ifaddr *ia, *iap;
2161541Srgrimes	register struct ifaddr *ifa;
217168032Sbms	struct in_addr allhosts_addr;
21884102Sjlemon	struct in_addr dst;
2191541Srgrimes	struct in_ifaddr *oia;
220189592Sbms	struct in_ifinfo *ii;
2211541Srgrimes	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
2221541Srgrimes	struct sockaddr_in oldaddr;
22387124Sbrian	int error, hostIsNew, iaIsNew, maskIsNew, s;
224168032Sbms	int iaIsFirst;
2251541Srgrimes
226184295Sbz	ia = NULL;
227168032Sbms	iaIsFirst = 0;
22887124Sbrian	iaIsNew = 0;
229168032Sbms	allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
23087124Sbrian
231191443Srwatson	/*
232191443Srwatson	 * Filter out ioctls we implement directly; forward the rest on to
233191443Srwatson	 * in_lifaddr_ioctl() and ifp->if_ioctl().
234191443Srwatson	 */
23555009Sshin	switch (cmd) {
236191443Srwatson	case SIOCAIFADDR:
237191443Srwatson	case SIOCDIFADDR:
238191443Srwatson	case SIOCGIFADDR:
239191443Srwatson	case SIOCGIFBRDADDR:
240191443Srwatson	case SIOCGIFDSTADDR:
241191443Srwatson	case SIOCGIFNETMASK:
242191443Srwatson	case SIOCSIFADDR:
243191443Srwatson	case SIOCSIFBRDADDR:
244191443Srwatson	case SIOCSIFDSTADDR:
245191443Srwatson	case SIOCSIFNETMASK:
246191443Srwatson		break;
247191443Srwatson
24855009Sshin	case SIOCALIFADDR:
249164033Srwatson		if (td != NULL) {
250164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
251164033Srwatson			if (error)
252164033Srwatson				return (error);
253164033Srwatson		}
254184295Sbz		if (ifp == NULL)
255184295Sbz			return (EINVAL);
256164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
257164033Srwatson
25855009Sshin	case SIOCDLIFADDR:
259164033Srwatson		if (td != NULL) {
260164033Srwatson			error = priv_check(td, PRIV_NET_DELIFADDR);
261164033Srwatson			if (error)
262164033Srwatson				return (error);
263164033Srwatson		}
264184295Sbz		if (ifp == NULL)
265184295Sbz			return (EINVAL);
266164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
267164033Srwatson
26855009Sshin	case SIOCGLIFADDR:
269184295Sbz		if (ifp == NULL)
270184295Sbz			return (EINVAL);
27183366Sjulian		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
272191443Srwatson
273191443Srwatson	default:
274191443Srwatson		if (ifp == NULL || ifp->if_ioctl == NULL)
275191443Srwatson			return (EOPNOTSUPP);
276191443Srwatson		return ((*ifp->if_ioctl)(ifp, cmd, data));
27755009Sshin	}
27855009Sshin
279191443Srwatson	if (ifp == NULL)
280191443Srwatson		return (EADDRNOTAVAIL);
281191443Srwatson
2821541Srgrimes	/*
2831541Srgrimes	 * Find address for this interface, if it exists.
28414632Sfenner	 *
285191443Srwatson	 * If an alias address was specified, find that one instead of the
286191443Srwatson	 * first one on the interface, if possible.
2871541Srgrimes	 */
288191443Srwatson	dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
289191443Srwatson	LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) {
290191443Srwatson		if (iap->ia_ifp == ifp &&
291191443Srwatson		    iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
292191443Srwatson			if (td == NULL || prison_check_ip4(td->td_ucred,
293191443Srwatson			    &dst) == 0)
294191443Srwatson				ia = iap;
295191443Srwatson			break;
296191443Srwatson		}
297191443Srwatson	}
298191443Srwatson	if (ia == NULL) {
299191443Srwatson		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
300191443Srwatson			iap = ifatoia(ifa);
301191443Srwatson			if (iap->ia_addr.sin_family == AF_INET) {
302191443Srwatson				if (td != NULL &&
303191443Srwatson				    prison_check_ip4(td->td_ucred,
304191443Srwatson				    &iap->ia_addr.sin_addr) != 0)
305191443Srwatson					continue;
306191443Srwatson				ia = iap;
30784102Sjlemon				break;
30884102Sjlemon			}
309191443Srwatson		}
31084102Sjlemon	}
311191443Srwatson	if (ia == NULL)
312191443Srwatson		iaIsFirst = 1;
3131541Srgrimes
3141541Srgrimes	switch (cmd) {
3151541Srgrimes	case SIOCAIFADDR:
3161541Srgrimes	case SIOCDIFADDR:
3178071Swollman		if (ifra->ifra_addr.sin_family == AF_INET) {
31871999Sphk			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
3198071Swollman				if (ia->ia_ifp == ifp  &&
3208071Swollman				    ia->ia_addr.sin_addr.s_addr ==
3218071Swollman				    ifra->ifra_addr.sin_addr.s_addr)
3228071Swollman					break;
3238071Swollman			}
3248876Srgrimes			if ((ifp->if_flags & IFF_POINTOPOINT)
3258071Swollman			    && (cmd == SIOCAIFADDR)
3268071Swollman			    && (ifra->ifra_dstaddr.sin_addr.s_addr
3278071Swollman				== INADDR_ANY)) {
328184295Sbz				return (EDESTADDRREQ);
3298071Swollman			}
3301541Srgrimes		}
331184295Sbz		if (cmd == SIOCDIFADDR && ia == NULL)
3321541Srgrimes			return (EADDRNOTAVAIL);
3331541Srgrimes		/* FALLTHROUGH */
3341541Srgrimes	case SIOCSIFADDR:
3351541Srgrimes	case SIOCSIFNETMASK:
3361541Srgrimes	case SIOCSIFDSTADDR:
337164033Srwatson		if (td != NULL) {
338175626Sbz			error = priv_check(td, (cmd == SIOCDIFADDR) ?
339175626Sbz			    PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR);
340164033Srwatson			if (error)
341164033Srwatson				return (error);
342164033Srwatson		}
3431541Srgrimes
344184295Sbz		if (ia == NULL) {
34520407Swollman			ia = (struct in_ifaddr *)
346111119Simp				malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
347184295Sbz			if (ia == NULL)
3481541Srgrimes				return (ENOBUFS);
34915092Sdg			/*
35015092Sdg			 * Protect from ipintr() traversing address list
35115092Sdg			 * while we're modifying it.
35215092Sdg			 */
35320407Swollman			ifa = &ia->ia_ifa;
354108033Shsu			IFA_LOCK_INIT(ifa);
35520407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
35620407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
35720407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
358108033Shsu			ifa->ifa_refcnt = 1;
359108033Shsu
3601541Srgrimes			ia->ia_sockmask.sin_len = 8;
36185740Sdes			ia->ia_sockmask.sin_family = AF_INET;
3621541Srgrimes			if (ifp->if_flags & IFF_BROADCAST) {
3631541Srgrimes				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
3641541Srgrimes				ia->ia_broadaddr.sin_family = AF_INET;
3651541Srgrimes			}
3661541Srgrimes			ia->ia_ifp = ifp;
367151824Sglebius
368191285Srwatson			IF_ADDR_LOCK(ifp);
369191285Srwatson			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
370191285Srwatson			IF_ADDR_UNLOCK(ifp);
371191285Srwatson			s = splnet();
372181803Sbz			TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
37315092Sdg			splx(s);
37487124Sbrian			iaIsNew = 1;
3751541Srgrimes		}
3761541Srgrimes		break;
3771541Srgrimes
3781541Srgrimes	case SIOCSIFBRDADDR:
379164033Srwatson		if (td != NULL) {
380164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
381164033Srwatson			if (error)
382164033Srwatson				return (error);
383164033Srwatson		}
3841541Srgrimes		/* FALLTHROUGH */
3851541Srgrimes
3861541Srgrimes	case SIOCGIFADDR:
3871541Srgrimes	case SIOCGIFNETMASK:
3881541Srgrimes	case SIOCGIFDSTADDR:
3891541Srgrimes	case SIOCGIFBRDADDR:
390184295Sbz		if (ia == NULL)
3911541Srgrimes			return (EADDRNOTAVAIL);
3921541Srgrimes		break;
3931541Srgrimes	}
3941541Srgrimes	switch (cmd) {
3951541Srgrimes
3961541Srgrimes	case SIOCGIFADDR:
3971541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
39887124Sbrian		return (0);
3991541Srgrimes
4001541Srgrimes	case SIOCGIFBRDADDR:
4011541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
4021541Srgrimes			return (EINVAL);
4031541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
40487124Sbrian		return (0);
4051541Srgrimes
4061541Srgrimes	case SIOCGIFDSTADDR:
4071541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
4081541Srgrimes			return (EINVAL);
4091541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
41087124Sbrian		return (0);
4111541Srgrimes
4121541Srgrimes	case SIOCGIFNETMASK:
4131541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
41487124Sbrian		return (0);
4151541Srgrimes
4161541Srgrimes	case SIOCSIFDSTADDR:
4171541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
4181541Srgrimes			return (EINVAL);
4191541Srgrimes		oldaddr = ia->ia_dstaddr;
4201541Srgrimes		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
421184295Sbz		if (ifp->if_ioctl != NULL) {
422146883Siedowse			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
423146883Siedowse			    (caddr_t)ia);
424146883Siedowse			if (error) {
425146883Siedowse				ia->ia_dstaddr = oldaddr;
426146883Siedowse				return (error);
427146883Siedowse			}
4281541Srgrimes		}
4291541Srgrimes		if (ia->ia_flags & IFA_ROUTE) {
4301541Srgrimes			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
4311541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
4321541Srgrimes			ia->ia_ifa.ifa_dstaddr =
4331541Srgrimes					(struct sockaddr *)&ia->ia_dstaddr;
4341541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
4351541Srgrimes		}
43687124Sbrian		return (0);
4371541Srgrimes
4381541Srgrimes	case SIOCSIFBRDADDR:
4391541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
4401541Srgrimes			return (EINVAL);
4411541Srgrimes		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
44287124Sbrian		return (0);
4431541Srgrimes
4441541Srgrimes	case SIOCSIFADDR:
44587124Sbrian		error = in_ifinit(ifp, ia,
44687124Sbrian		    (struct sockaddr_in *) &ifr->ifr_addr, 1);
44787124Sbrian		if (error != 0 && iaIsNew)
44887124Sbrian			break;
449168032Sbms		if (error == 0) {
450189603Sbms			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
451189592Sbms			if (iaIsFirst &&
452189592Sbms			    (ifp->if_flags & IFF_MULTICAST) != 0) {
453189592Sbms				error = in_joingroup(ifp, &allhosts_addr,
454189592Sbms				    NULL, &ii->ii_allhosts);
455189592Sbms			}
456126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
457168032Sbms		}
45887124Sbrian		return (0);
4591541Srgrimes
4601541Srgrimes	case SIOCSIFNETMASK:
46185740Sdes		ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
46285740Sdes		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
46387124Sbrian		return (0);
4641541Srgrimes
4651541Srgrimes	case SIOCAIFADDR:
4661541Srgrimes		maskIsNew = 0;
4671541Srgrimes		hostIsNew = 1;
4681541Srgrimes		error = 0;
4691541Srgrimes		if (ia->ia_addr.sin_family == AF_INET) {
4701541Srgrimes			if (ifra->ifra_addr.sin_len == 0) {
4711541Srgrimes				ifra->ifra_addr = ia->ia_addr;
4721541Srgrimes				hostIsNew = 0;
4731541Srgrimes			} else if (ifra->ifra_addr.sin_addr.s_addr ==
4741541Srgrimes					       ia->ia_addr.sin_addr.s_addr)
4751541Srgrimes				hostIsNew = 0;
4761541Srgrimes		}
4771541Srgrimes		if (ifra->ifra_mask.sin_len) {
4781541Srgrimes			in_ifscrub(ifp, ia);
4791541Srgrimes			ia->ia_sockmask = ifra->ifra_mask;
48085740Sdes			ia->ia_sockmask.sin_family = AF_INET;
4811541Srgrimes			ia->ia_subnetmask =
4821541Srgrimes			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
4831541Srgrimes			maskIsNew = 1;
4841541Srgrimes		}
4851541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) &&
4861541Srgrimes		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
4871541Srgrimes			in_ifscrub(ifp, ia);
4881541Srgrimes			ia->ia_dstaddr = ifra->ifra_dstaddr;
4891541Srgrimes			maskIsNew  = 1; /* We lie; but the effect's the same */
4901541Srgrimes		}
4911541Srgrimes		if (ifra->ifra_addr.sin_family == AF_INET &&
4921541Srgrimes		    (hostIsNew || maskIsNew))
4931541Srgrimes			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
49487124Sbrian		if (error != 0 && iaIsNew)
49587124Sbrian			break;
49687124Sbrian
4971541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) &&
4981541Srgrimes		    (ifra->ifra_broadaddr.sin_family == AF_INET))
4991541Srgrimes			ia->ia_broadaddr = ifra->ifra_broadaddr;
500168032Sbms		if (error == 0) {
501189603Sbms			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
502189592Sbms			if (iaIsFirst &&
503189592Sbms			    (ifp->if_flags & IFF_MULTICAST) != 0) {
504189592Sbms				error = in_joingroup(ifp, &allhosts_addr,
505189592Sbms				    NULL, &ii->ii_allhosts);
506189592Sbms			}
507126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
508168032Sbms		}
5091541Srgrimes		return (error);
5101541Srgrimes
5111541Srgrimes	case SIOCDIFADDR:
51274299Sru		/*
51374299Sru		 * in_ifscrub kills the interface route.
51474299Sru		 */
5151541Srgrimes		in_ifscrub(ifp, ia);
51615092Sdg		/*
51774299Sru		 * in_ifadown gets rid of all the rest of
51874299Sru		 * the routes.  This is not quite the right
51974299Sru		 * thing to do, but at least if we are running
52074299Sru		 * a routing process they will come back.
52174299Sru		 */
52276469Sru		in_ifadown(&ia->ia_ifa, 1);
523126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
52487124Sbrian		error = 0;
5251541Srgrimes		break;
5261541Srgrimes
5271541Srgrimes	default:
528191443Srwatson		panic("in_control: unsupported ioctl");
5291541Srgrimes	}
53087124Sbrian
53187124Sbrian	/*
53287124Sbrian	 * Protect from ipintr() traversing address list while we're modifying
53387124Sbrian	 * it.
53487124Sbrian	 */
535191285Srwatson	IF_ADDR_LOCK(ifp);
536191285Srwatson	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
537191285Srwatson	IF_ADDR_UNLOCK(ifp);
53887124Sbrian	s = splnet();
539181803Sbz	TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
540168032Sbms	if (ia->ia_addr.sin_family == AF_INET) {
541154777Sandre		LIST_REMOVE(ia, ia_hash);
542168032Sbms		/*
543168032Sbms		 * If this is the last IPv4 address configured on this
544168032Sbms		 * interface, leave the all-hosts group.
545189592Sbms		 * No state-change report need be transmitted.
546168032Sbms		 */
547168032Sbms		oia = NULL;
548168032Sbms		IFP_TO_IA(ifp, oia);
549168032Sbms		if (oia == NULL) {
550189603Sbms			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
551168032Sbms			IN_MULTI_LOCK();
552189592Sbms			if (ii->ii_allhosts) {
553189592Sbms				(void)in_leavegroup_locked(ii->ii_allhosts,
554189592Sbms				    NULL);
555189592Sbms				ii->ii_allhosts = NULL;
556189592Sbms			}
557168032Sbms			IN_MULTI_UNLOCK();
558168032Sbms		}
559168032Sbms	}
56087124Sbrian	IFAFREE(&ia->ia_ifa);
56187124Sbrian	splx(s);
56287124Sbrian
56387124Sbrian	return (error);
5641541Srgrimes}
5651541Srgrimes
5661541Srgrimes/*
56755009Sshin * SIOC[GAD]LIFADDR.
56855009Sshin *	SIOCGLIFADDR: get first address. (?!?)
56955009Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
57055009Sshin *		get first address that matches the specified prefix.
57155009Sshin *	SIOCALIFADDR: add the specified address.
57255009Sshin *	SIOCALIFADDR with IFLR_PREFIX:
57355009Sshin *		EINVAL since we can't deduce hostid part of the address.
57455009Sshin *	SIOCDLIFADDR: delete the specified address.
57555009Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
57655009Sshin *		delete the first address that matches the specified prefix.
57755009Sshin * return values:
57855009Sshin *	EINVAL on invalid parameters
57955009Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
58055009Sshin *	other values may be returned from in_ioctl()
58155009Sshin */
58255009Sshinstatic int
583169454Srwatsonin_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
584169454Srwatson    struct ifnet *ifp, struct thread *td)
58555009Sshin{
58655009Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
58755009Sshin	struct ifaddr *ifa;
58855009Sshin
58955009Sshin	/* sanity checks */
590184295Sbz	if (data == NULL || ifp == NULL) {
59155009Sshin		panic("invalid argument to in_lifaddr_ioctl");
59255009Sshin		/*NOTRECHED*/
59355009Sshin	}
59455009Sshin
59555009Sshin	switch (cmd) {
59655009Sshin	case SIOCGLIFADDR:
59755009Sshin		/* address must be specified on GET with IFLR_PREFIX */
59855009Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
59955009Sshin			break;
60055009Sshin		/*FALLTHROUGH*/
60155009Sshin	case SIOCALIFADDR:
60255009Sshin	case SIOCDLIFADDR:
60355009Sshin		/* address must be specified on ADD and DELETE */
60455917Sshin		if (iflr->addr.ss_family != AF_INET)
605184295Sbz			return (EINVAL);
60655917Sshin		if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
607184295Sbz			return (EINVAL);
60855009Sshin		/* XXX need improvement */
60955917Sshin		if (iflr->dstaddr.ss_family
61055917Sshin		 && iflr->dstaddr.ss_family != AF_INET)
611184295Sbz			return (EINVAL);
61255917Sshin		if (iflr->dstaddr.ss_family
61355917Sshin		 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
614184295Sbz			return (EINVAL);
61555009Sshin		break;
61655009Sshin	default: /*shouldn't happen*/
617184295Sbz		return (EOPNOTSUPP);
61855009Sshin	}
61955009Sshin	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
620184295Sbz		return (EINVAL);
62155009Sshin
62255009Sshin	switch (cmd) {
62355009Sshin	case SIOCALIFADDR:
62455009Sshin	    {
62555009Sshin		struct in_aliasreq ifra;
62655009Sshin
62755009Sshin		if (iflr->flags & IFLR_PREFIX)
628184295Sbz			return (EINVAL);
62955009Sshin
63055009Sshin		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
63155009Sshin		bzero(&ifra, sizeof(ifra));
63255009Sshin		bcopy(iflr->iflr_name, ifra.ifra_name,
63355009Sshin			sizeof(ifra.ifra_name));
63455009Sshin
63555917Sshin		bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
63655009Sshin
63755917Sshin		if (iflr->dstaddr.ss_family) {	/*XXX*/
63855009Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
63955917Sshin				iflr->dstaddr.ss_len);
64055009Sshin		}
64155009Sshin
64255009Sshin		ifra.ifra_mask.sin_family = AF_INET;
64355009Sshin		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
64455009Sshin		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
64555009Sshin
646184295Sbz		return (in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td));
64755009Sshin	    }
64855009Sshin	case SIOCGLIFADDR:
64955009Sshin	case SIOCDLIFADDR:
65055009Sshin	    {
65155009Sshin		struct in_ifaddr *ia;
65255009Sshin		struct in_addr mask, candidate, match;
65355009Sshin		struct sockaddr_in *sin;
65455009Sshin
65555009Sshin		bzero(&mask, sizeof(mask));
656170855Smjacob		bzero(&match, sizeof(match));
65755009Sshin		if (iflr->flags & IFLR_PREFIX) {
65855009Sshin			/* lookup a prefix rather than address. */
65955009Sshin			in_len2mask(&mask, iflr->prefixlen);
66055009Sshin
66155009Sshin			sin = (struct sockaddr_in *)&iflr->addr;
66255009Sshin			match.s_addr = sin->sin_addr.s_addr;
66355009Sshin			match.s_addr &= mask.s_addr;
66455009Sshin
66555009Sshin			/* if you set extra bits, that's wrong */
66655009Sshin			if (match.s_addr != sin->sin_addr.s_addr)
667184295Sbz				return (EINVAL);
66855009Sshin
66955009Sshin		} else {
670170855Smjacob			/* on getting an address, take the 1st match */
671170855Smjacob			/* on deleting an address, do exact match */
672170855Smjacob			if (cmd != SIOCGLIFADDR) {
67355009Sshin				in_len2mask(&mask, 32);
67455009Sshin				sin = (struct sockaddr_in *)&iflr->addr;
67555009Sshin				match.s_addr = sin->sin_addr.s_addr;
67655009Sshin			}
67755009Sshin		}
67855009Sshin
67955009Sshin		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)	{
68055009Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
68155009Sshin				continue;
682170855Smjacob			if (match.s_addr == 0)
68355009Sshin				break;
68455009Sshin			candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
68555009Sshin			candidate.s_addr &= mask.s_addr;
68655009Sshin			if (candidate.s_addr == match.s_addr)
68755009Sshin				break;
68855009Sshin		}
689184295Sbz		if (ifa == NULL)
690184295Sbz			return (EADDRNOTAVAIL);
69155009Sshin		ia = (struct in_ifaddr *)ifa;
69255009Sshin
69355009Sshin		if (cmd == SIOCGLIFADDR) {
69455009Sshin			/* fill in the if_laddrreq structure */
69555009Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
69655009Sshin
69755009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
69855009Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
69955009Sshin					ia->ia_dstaddr.sin_len);
70055009Sshin			} else
70155009Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
70255009Sshin
70355009Sshin			iflr->prefixlen =
70455009Sshin				in_mask2len(&ia->ia_sockmask.sin_addr);
70555009Sshin
70655009Sshin			iflr->flags = 0;	/*XXX*/
70755009Sshin
708184295Sbz			return (0);
70955009Sshin		} else {
71055009Sshin			struct in_aliasreq ifra;
71155009Sshin
71255009Sshin			/* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
71355009Sshin			bzero(&ifra, sizeof(ifra));
71455009Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
71555009Sshin				sizeof(ifra.ifra_name));
71655009Sshin
71755009Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
71855009Sshin				ia->ia_addr.sin_len);
71955009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
72055009Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
72155009Sshin					ia->ia_dstaddr.sin_len);
72255009Sshin			}
72355009Sshin			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
72455009Sshin				ia->ia_sockmask.sin_len);
72555009Sshin
726184295Sbz			return (in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
727184295Sbz			    ifp, td));
72855009Sshin		}
72955009Sshin	    }
73055009Sshin	}
73155009Sshin
732184295Sbz	return (EOPNOTSUPP);	/*just for safety*/
73355009Sshin}
73455009Sshin
73555009Sshin/*
7361541Srgrimes * Delete any existing route for an interface.
7371541Srgrimes */
73822672Swollmanvoid
739169454Srwatsonin_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
7401541Srgrimes{
741169454Srwatson
742137628Smlaier	in_scrubprefix(ia);
7431541Srgrimes}
7441541Srgrimes
7451541Srgrimes/*
7461541Srgrimes * Initialize an interface's internet address
7471541Srgrimes * and routing table entry.
7481541Srgrimes */
74912296Sphkstatic int
750169454Srwatsonin_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
751169454Srwatson    int scrub)
7521541Srgrimes{
753183550Szec	INIT_VNET_INET(ifp->if_vnet);
7541541Srgrimes	register u_long i = ntohl(sin->sin_addr.s_addr);
7551541Srgrimes	struct sockaddr_in oldaddr;
75694326Sbrian	int s = splimp(), flags = RTF_UP, error = 0;
7571541Srgrimes
7581541Srgrimes	oldaddr = ia->ia_addr;
759105748Ssuz	if (oldaddr.sin_family == AF_INET)
760105748Ssuz		LIST_REMOVE(ia, ia_hash);
7611541Srgrimes	ia->ia_addr = *sin;
762105748Ssuz	if (ia->ia_addr.sin_family == AF_INET)
763105748Ssuz		LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
764105748Ssuz		    ia, ia_hash);
7651541Srgrimes	/*
7661541Srgrimes	 * Give the interface a chance to initialize
7671541Srgrimes	 * if this is its first address,
7681541Srgrimes	 * and to validate the address if necessary.
7691541Srgrimes	 */
770184295Sbz	if (ifp->if_ioctl != NULL) {
771146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
772146883Siedowse		if (error) {
773146883Siedowse			splx(s);
774146883Siedowse			/* LIST_REMOVE(ia, ia_hash) is done in in_control */
775146883Siedowse			ia->ia_addr = oldaddr;
776146883Siedowse			if (ia->ia_addr.sin_family == AF_INET)
777146883Siedowse				LIST_INSERT_HEAD(INADDR_HASH(
778146883Siedowse				    ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
779179971Sgonzo			else
780179971Sgonzo				/*
781179971Sgonzo				 * If oldaddr family is not AF_INET (e.g.
782179971Sgonzo				 * interface has been just created) in_control
783179971Sgonzo				 * does not call LIST_REMOVE, and we end up
784179971Sgonzo				 * with bogus ia entries in hash
785179971Sgonzo				 */
786179971Sgonzo				LIST_REMOVE(ia, ia_hash);
787146883Siedowse			return (error);
788146883Siedowse		}
7891541Srgrimes	}
7901541Srgrimes	splx(s);
7911541Srgrimes	if (scrub) {
7921541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
7931541Srgrimes		in_ifscrub(ifp, ia);
7941541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
7951541Srgrimes	}
7961541Srgrimes	if (IN_CLASSA(i))
7971541Srgrimes		ia->ia_netmask = IN_CLASSA_NET;
7981541Srgrimes	else if (IN_CLASSB(i))
7991541Srgrimes		ia->ia_netmask = IN_CLASSB_NET;
8001541Srgrimes	else
8011541Srgrimes		ia->ia_netmask = IN_CLASSC_NET;
8021541Srgrimes	/*
8031541Srgrimes	 * The subnet mask usually includes at least the standard network part,
8041541Srgrimes	 * but may may be smaller in the case of supernetting.
8051541Srgrimes	 * If it is set, we believe it.
8061541Srgrimes	 */
8071541Srgrimes	if (ia->ia_subnetmask == 0) {
8081541Srgrimes		ia->ia_subnetmask = ia->ia_netmask;
8091541Srgrimes		ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
8101541Srgrimes	} else
8111541Srgrimes		ia->ia_netmask &= ia->ia_subnetmask;
8121541Srgrimes	ia->ia_net = i & ia->ia_netmask;
8131541Srgrimes	ia->ia_subnet = i & ia->ia_subnetmask;
8141541Srgrimes	in_socktrim(&ia->ia_sockmask);
815143868Sglebius#ifdef DEV_CARP
8161541Srgrimes	/*
817143868Sglebius	 * XXX: carp(4) does not have interface route
818143868Sglebius	 */
819143868Sglebius	if (ifp->if_type == IFT_CARP)
820143868Sglebius		return (0);
821143868Sglebius#endif
822143868Sglebius	/*
8231541Srgrimes	 * Add route for the network.
8241541Srgrimes	 */
8251541Srgrimes	ia->ia_ifa.ifa_metric = ifp->if_metric;
8261541Srgrimes	if (ifp->if_flags & IFF_BROADCAST) {
8271541Srgrimes		ia->ia_broadaddr.sin_addr.s_addr =
8281541Srgrimes			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
8291541Srgrimes		ia->ia_netbroadcast.s_addr =
8301541Srgrimes			htonl(ia->ia_net | ~ ia->ia_netmask);
8311541Srgrimes	} else if (ifp->if_flags & IFF_LOOPBACK) {
832137833Smlaier		ia->ia_dstaddr = ia->ia_addr;
8331541Srgrimes		flags |= RTF_HOST;
8341541Srgrimes	} else if (ifp->if_flags & IFF_POINTOPOINT) {
8351541Srgrimes		if (ia->ia_dstaddr.sin_family != AF_INET)
8361541Srgrimes			return (0);
8371541Srgrimes		flags |= RTF_HOST;
8381541Srgrimes	}
839137628Smlaier	if ((error = in_addprefix(ia, flags)) != 0)
840137628Smlaier		return (error);
84194326Sbrian
8421541Srgrimes	return (error);
8431541Srgrimes}
8441541Srgrimes
845137628Smlaier#define rtinitflags(x) \
846137628Smlaier	((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
847137628Smlaier	    ? RTF_HOST : 0)
848137628Smlaier/*
849170855Smjacob * Check if we have a route for the given prefix already or add one accordingly.
850137628Smlaier */
851137628Smlaierstatic int
852169454Srwatsonin_addprefix(struct in_ifaddr *target, int flags)
853137628Smlaier{
854183550Szec	INIT_VNET_INET(curvnet);
855137628Smlaier	struct in_ifaddr *ia;
856151555Sglebius	struct in_addr prefix, mask, p, m;
857137628Smlaier	int error;
8581541Srgrimes
859170855Smjacob	if ((flags & RTF_HOST) != 0) {
860137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
861170855Smjacob		mask.s_addr = 0;
862170855Smjacob	} else {
863137628Smlaier		prefix = target->ia_addr.sin_addr;
864137628Smlaier		mask = target->ia_sockmask.sin_addr;
865137628Smlaier		prefix.s_addr &= mask.s_addr;
866137628Smlaier	}
867137628Smlaier
868181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
869151555Sglebius		if (rtinitflags(ia)) {
870137628Smlaier			p = ia->ia_addr.sin_addr;
871151555Sglebius
872151555Sglebius			if (prefix.s_addr != p.s_addr)
873151555Sglebius				continue;
874151555Sglebius		} else {
875151555Sglebius			p = ia->ia_addr.sin_addr;
876151555Sglebius			m = ia->ia_sockmask.sin_addr;
877151555Sglebius			p.s_addr &= m.s_addr;
878151555Sglebius
879151555Sglebius			if (prefix.s_addr != p.s_addr ||
880151555Sglebius			    mask.s_addr != m.s_addr)
881151555Sglebius				continue;
882137628Smlaier		}
883137628Smlaier
884137628Smlaier		/*
885137628Smlaier		 * If we got a matching prefix route inserted by other
886137628Smlaier		 * interface address, we are done here.
887137628Smlaier		 */
888149221Sglebius		if (ia->ia_flags & IFA_ROUTE) {
889181803Sbz			if (V_sameprefixcarponly &&
890149221Sglebius			    target->ia_ifp->if_type != IFT_CARP &&
891149221Sglebius			    ia->ia_ifp->if_type != IFT_CARP)
892149221Sglebius				return (EEXIST);
893149221Sglebius			else
894149221Sglebius				return (0);
895149221Sglebius		}
896137628Smlaier	}
897137628Smlaier
898137628Smlaier	/*
899137628Smlaier	 * No-one seem to have this prefix route, so we try to insert it.
900137628Smlaier	 */
901137628Smlaier	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
902137628Smlaier	if (!error)
903137628Smlaier		target->ia_flags |= IFA_ROUTE;
904184295Sbz	return (error);
905137628Smlaier}
906137628Smlaier
907186119Sqingliextern void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
908186119Sqingli
9091541Srgrimes/*
910137628Smlaier * If there is no other address in the system that can serve a route to the
911137628Smlaier * same prefix, remove the route.  Hand over the route to the new address
912137628Smlaier * otherwise.
913137628Smlaier */
914137628Smlaierstatic int
915169454Srwatsonin_scrubprefix(struct in_ifaddr *target)
916137628Smlaier{
917183550Szec	INIT_VNET_INET(curvnet);
918137628Smlaier	struct in_ifaddr *ia;
919137628Smlaier	struct in_addr prefix, mask, p;
920137628Smlaier	int error;
921137628Smlaier
922137628Smlaier	if ((target->ia_flags & IFA_ROUTE) == 0)
923184295Sbz		return (0);
924137628Smlaier
925137628Smlaier	if (rtinitflags(target))
926137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
927137628Smlaier	else {
928137628Smlaier		prefix = target->ia_addr.sin_addr;
929137628Smlaier		mask = target->ia_sockmask.sin_addr;
930137628Smlaier		prefix.s_addr &= mask.s_addr;
931186119Sqingli		/* remove arp cache */
932186119Sqingli		arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
933137628Smlaier	}
934137628Smlaier
935181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
936137628Smlaier		if (rtinitflags(ia))
937137628Smlaier			p = ia->ia_dstaddr.sin_addr;
938137628Smlaier		else {
939137628Smlaier			p = ia->ia_addr.sin_addr;
940137628Smlaier			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
941137628Smlaier		}
942137628Smlaier
943137628Smlaier		if (prefix.s_addr != p.s_addr)
944137628Smlaier			continue;
945137628Smlaier
946137628Smlaier		/*
947137628Smlaier		 * If we got a matching prefix address, move IFA_ROUTE and
948137628Smlaier		 * the route itself to it.  Make sure that routing daemons
949137628Smlaier		 * get a heads-up.
950143868Sglebius		 *
951143868Sglebius		 * XXX: a special case for carp(4) interface
952137628Smlaier		 */
953143868Sglebius		if ((ia->ia_flags & IFA_ROUTE) == 0
954143868Sglebius#ifdef DEV_CARP
955143868Sglebius		    && (ia->ia_ifp->if_type != IFT_CARP)
956143868Sglebius#endif
957143868Sglebius							) {
958137628Smlaier			rtinit(&(target->ia_ifa), (int)RTM_DELETE,
959137628Smlaier			    rtinitflags(target));
960137628Smlaier			target->ia_flags &= ~IFA_ROUTE;
961137628Smlaier
962137628Smlaier			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
963137628Smlaier			    rtinitflags(ia) | RTF_UP);
964137628Smlaier			if (error == 0)
965137628Smlaier				ia->ia_flags |= IFA_ROUTE;
966184295Sbz			return (error);
967137628Smlaier		}
968137628Smlaier	}
969137628Smlaier
970137628Smlaier	/*
971137628Smlaier	 * As no-one seem to have this prefix, we can remove the route.
972137628Smlaier	 */
973137628Smlaier	rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
974137628Smlaier	target->ia_flags &= ~IFA_ROUTE;
975184295Sbz	return (0);
976137628Smlaier}
977137628Smlaier
978137628Smlaier#undef rtinitflags
979137628Smlaier
980137628Smlaier/*
9811541Srgrimes * Return 1 if the address might be a local broadcast address.
9821541Srgrimes */
9831549Srgrimesint
984169454Srwatsonin_broadcast(struct in_addr in, struct ifnet *ifp)
9851541Srgrimes{
9861541Srgrimes	register struct ifaddr *ifa;
9871541Srgrimes	u_long t;
9881541Srgrimes
9891541Srgrimes	if (in.s_addr == INADDR_BROADCAST ||
9901541Srgrimes	    in.s_addr == INADDR_ANY)
991184295Sbz		return (1);
9921541Srgrimes	if ((ifp->if_flags & IFF_BROADCAST) == 0)
993184295Sbz		return (0);
9941541Srgrimes	t = ntohl(in.s_addr);
9951541Srgrimes	/*
9961541Srgrimes	 * Look through the list of addresses for a match
9971541Srgrimes	 * with a broadcast address.
9981541Srgrimes	 */
9991541Srgrimes#define ia ((struct in_ifaddr *)ifa)
100074362Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
10011541Srgrimes		if (ifa->ifa_addr->sa_family == AF_INET &&
10021541Srgrimes		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
10031541Srgrimes		     in.s_addr == ia->ia_netbroadcast.s_addr ||
10041541Srgrimes		     /*
10051541Srgrimes		      * Check for old-style (host 0) broadcast.
10061541Srgrimes		      */
100713351Sguido		     t == ia->ia_subnet || t == ia->ia_net) &&
100813351Sguido		     /*
100913351Sguido		      * Check for an all one subnetmask. These
101013351Sguido		      * only exist when an interface gets a secondary
101113351Sguido		      * address.
101213351Sguido		      */
101313351Sguido		     ia->ia_subnetmask != (u_long)0xffffffff)
1014184295Sbz			    return (1);
10151541Srgrimes	return (0);
10161541Srgrimes#undef ia
10171541Srgrimes}
1018167729Sbms
10191541Srgrimes/*
1020189592Sbms * On interface removal, clean up IPv4 data structures hung off of the ifnet.
1021189592Sbms */
1022189592Sbmsvoid
1023189592Sbmsin_ifdetach(struct ifnet *ifp)
1024189592Sbms{
1025189592Sbms	INIT_VNET_INET(ifp->if_vnet);
1026189592Sbms
1027189592Sbms	in_pcbpurgeif0(&V_ripcbinfo, ifp);
1028189592Sbms	in_pcbpurgeif0(&V_udbinfo, ifp);
1029189592Sbms	in_purgemaddrs(ifp);
1030189592Sbms}
1031189592Sbms
1032189592Sbms/*
1033167729Sbms * Delete all IPv4 multicast address records, and associated link-layer
1034167729Sbms * multicast address records, associated with ifp.
1035189592Sbms * XXX It looks like domifdetach runs AFTER the link layer cleanup.
1036189931Sbms * XXX This should not race with ifma_protospec being set during
1037189931Sbms * a new allocation, if it does, we have bigger problems.
1038162718Sbms */
1039167729Sbmsstatic void
1040167729Sbmsin_purgemaddrs(struct ifnet *ifp)
1041162718Sbms{
1042183550Szec	INIT_VNET_INET(ifp->if_vnet);
1043189592Sbms	LIST_HEAD(,in_multi) purgeinms;
1044189592Sbms	struct in_multi		*inm, *tinm;
1045189592Sbms	struct ifmultiaddr	*ifma;
1046162718Sbms
1047189592Sbms	LIST_INIT(&purgeinms);
1048162718Sbms	IN_MULTI_LOCK();
1049189592Sbms
1050189592Sbms	/*
1051189592Sbms	 * Extract list of in_multi associated with the detaching ifp
1052189592Sbms	 * which the PF_INET layer is about to release.
1053189592Sbms	 * We need to do this as IF_ADDR_LOCK() may be re-acquired
1054189592Sbms	 * by code further down.
1055189592Sbms	 */
1056189592Sbms	IF_ADDR_LOCK(ifp);
1057189592Sbms	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1058189931Sbms		if (ifma->ifma_addr->sa_family != AF_INET ||
1059189931Sbms		    ifma->ifma_protospec == NULL)
1060189592Sbms			continue;
1061189931Sbms#if 0
1062189931Sbms		KASSERT(ifma->ifma_protospec != NULL,
1063189931Sbms		    ("%s: ifma_protospec is NULL", __func__));
1064189931Sbms#endif
1065189592Sbms		inm = (struct in_multi *)ifma->ifma_protospec;
1066189592Sbms		LIST_INSERT_HEAD(&purgeinms, inm, inm_link);
1067162718Sbms	}
1068189592Sbms	IF_ADDR_UNLOCK(ifp);
1069150296Srwatson
1070189592Sbms	LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) {
1071189592Sbms		inm_release_locked(inm);
1072189592Sbms		LIST_REMOVE(inm, inm_link);
1073189592Sbms	}
1074189592Sbms	igmp_ifdetach(ifp);
1075150296Srwatson
1076189592Sbms	IN_MULTI_UNLOCK();
1077150296Srwatson}
1078186119Sqingli
1079186119Sqingli#include <sys/syslog.h>
1080186119Sqingli#include <net/if_dl.h>
1081186119Sqingli#include <netinet/if_ether.h>
1082186119Sqingli
1083186119Sqinglistruct in_llentry {
1084186119Sqingli	struct llentry		base;
1085186119Sqingli	struct sockaddr_in	l3_addr4;
1086186119Sqingli};
1087186119Sqingli
1088186119Sqinglistatic struct llentry *
1089186119Sqingliin_lltable_new(const struct sockaddr *l3addr, u_int flags)
1090186119Sqingli{
1091186119Sqingli	struct in_llentry *lle;
1092186119Sqingli
1093186119Sqingli	lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_DONTWAIT | M_ZERO);
1094186119Sqingli	if (lle == NULL)		/* NB: caller generates msg */
1095186119Sqingli		return NULL;
1096186119Sqingli
1097186119Sqingli	callout_init(&lle->base.la_timer, CALLOUT_MPSAFE);
1098186119Sqingli	/*
1099186119Sqingli	 * For IPv4 this will trigger "arpresolve" to generate
1100186119Sqingli	 * an ARP request.
1101186119Sqingli	 */
1102186119Sqingli	lle->base.la_expire = time_second; /* mark expired */
1103186119Sqingli	lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
1104186119Sqingli	lle->base.lle_refcnt = 1;
1105186119Sqingli	LLE_LOCK_INIT(&lle->base);
1106186119Sqingli	return &lle->base;
1107186119Sqingli}
1108186119Sqingli
1109186119Sqingli/*
1110186119Sqingli * Deletes an address from the address table.
1111186119Sqingli * This function is called by the timer functions
1112186119Sqingli * such as arptimer() and nd6_llinfo_timer(), and
1113186119Sqingli * the caller does the locking.
1114186119Sqingli */
1115186119Sqinglistatic void
1116186119Sqingliin_lltable_free(struct lltable *llt, struct llentry *lle)
1117186119Sqingli{
1118186150Skmacy	LLE_WUNLOCK(lle);
1119186150Skmacy	LLE_LOCK_DESTROY(lle);
1120186119Sqingli	free(lle, M_LLTABLE);
1121186119Sqingli}
1122186119Sqingli
1123186119Sqinglistatic int
1124186119Sqingliin_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
1125186119Sqingli{
1126186119Sqingli	struct rtentry *rt;
1127186119Sqingli
1128186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1129186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1130186119Sqingli
1131186119Sqingli	/* XXX rtalloc1 should take a const param */
1132186119Sqingli	rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
1133186119Sqingli	if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
1134186119Sqingli		log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
1135186119Sqingli		    inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
1136186119Sqingli		if (rt != NULL)
1137186119Sqingli			RTFREE_LOCKED(rt);
1138186119Sqingli		return (EINVAL);
1139186119Sqingli	}
1140186119Sqingli	RTFREE_LOCKED(rt);
1141186119Sqingli	return 0;
1142186119Sqingli}
1143186119Sqingli
1144186119Sqingli/*
1145186119Sqingli * Return NULL if not found or marked for deletion.
1146186119Sqingli * If found return lle read locked.
1147186119Sqingli */
1148186119Sqinglistatic struct llentry *
1149186119Sqingliin_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
1150186119Sqingli{
1151186119Sqingli	const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
1152186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1153186119Sqingli	struct llentry *lle;
1154186119Sqingli	struct llentries *lleh;
1155186119Sqingli	u_int hashkey;
1156186119Sqingli
1157186119Sqingli	IF_AFDATA_LOCK_ASSERT(ifp);
1158186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1159186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1160186119Sqingli
1161186119Sqingli	hashkey = sin->sin_addr.s_addr;
1162186119Sqingli	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
1163186119Sqingli	LIST_FOREACH(lle, lleh, lle_next) {
1164186708Sqingli		struct sockaddr_in *sa2 = (struct sockaddr_in *)L3_ADDR(lle);
1165186119Sqingli		if (lle->la_flags & LLE_DELETED)
1166186119Sqingli			continue;
1167186708Sqingli		if (sa2->sin_addr.s_addr == sin->sin_addr.s_addr)
1168186119Sqingli			break;
1169186119Sqingli	}
1170186119Sqingli	if (lle == NULL) {
1171186119Sqingli#ifdef DIAGNOSTICS
1172186119Sqingli		if (flags & LLE_DELETE)
1173186119Sqingli			log(LOG_INFO, "interface address is missing from cache = %p  in delete\n", lle);
1174186119Sqingli#endif
1175186119Sqingli		if (!(flags & LLE_CREATE))
1176186119Sqingli			return (NULL);
1177186119Sqingli		/*
1178186119Sqingli		 * A route that covers the given address must have
1179186119Sqingli		 * been installed 1st because we are doing a resolution,
1180186119Sqingli		 * verify this.
1181186119Sqingli		 */
1182186119Sqingli		if (!(flags & LLE_IFADDR) &&
1183186119Sqingli		    in_lltable_rtcheck(ifp, l3addr) != 0)
1184186119Sqingli			goto done;
1185186119Sqingli
1186186119Sqingli		lle = in_lltable_new(l3addr, flags);
1187186119Sqingli		if (lle == NULL) {
1188186119Sqingli			log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
1189186119Sqingli			goto done;
1190186119Sqingli		}
1191186119Sqingli		lle->la_flags = flags & ~LLE_CREATE;
1192186119Sqingli		if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
1193186119Sqingli			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
1194186119Sqingli			lle->la_flags |= (LLE_VALID | LLE_STATIC);
1195186119Sqingli		}
1196186119Sqingli
1197186119Sqingli		lle->lle_tbl  = llt;
1198186119Sqingli		lle->lle_head = lleh;
1199186119Sqingli		LIST_INSERT_HEAD(lleh, lle, lle_next);
1200186119Sqingli	} else if (flags & LLE_DELETE) {
1201186119Sqingli		if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
1202186119Sqingli			LLE_WLOCK(lle);
1203186119Sqingli			lle->la_flags = LLE_DELETED;
1204186119Sqingli			LLE_WUNLOCK(lle);
1205186119Sqingli#ifdef DIAGNOSTICS
1206186119Sqingli			log(LOG_INFO, "ifaddr cache = %p  is deleted\n", lle);
1207186119Sqingli#endif
1208186119Sqingli		}
1209186119Sqingli		lle = (void *)-1;
1210186119Sqingli
1211186119Sqingli	}
1212186544Sbz	if (LLE_IS_VALID(lle)) {
1213186119Sqingli		if (flags & LLE_EXCLUSIVE)
1214186119Sqingli			LLE_WLOCK(lle);
1215186119Sqingli		else
1216186119Sqingli			LLE_RLOCK(lle);
1217186119Sqingli	}
1218186119Sqinglidone:
1219186119Sqingli	return (lle);
1220186119Sqingli}
1221186119Sqingli
1222186119Sqinglistatic int
1223186119Sqingliin_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
1224186119Sqingli{
1225186119Sqingli#define	SIN(lle)	((struct sockaddr_in *) L3_ADDR(lle))
1226186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1227186119Sqingli	struct llentry *lle;
1228186119Sqingli	/* XXX stack use */
1229186119Sqingli	struct {
1230186119Sqingli		struct rt_msghdr	rtm;
1231186119Sqingli		struct sockaddr_inarp	sin;
1232186119Sqingli		struct sockaddr_dl	sdl;
1233186119Sqingli	} arpc;
1234186119Sqingli	int error, i;
1235186119Sqingli
1236186119Sqingli	/* XXXXX
1237186119Sqingli	 * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
1238186119Sqingli	 * so it is okay to use this ASSERT, change it when
1239186119Sqingli	 * IFNET lock is finalized
1240186119Sqingli	 */
1241186119Sqingli	IFNET_WLOCK_ASSERT();
1242186119Sqingli
1243186119Sqingli	error = 0;
1244186119Sqingli	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
1245186119Sqingli		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
1246186119Sqingli			struct sockaddr_dl *sdl;
1247186119Sqingli
1248186119Sqingli			/* skip deleted entries */
1249186119Sqingli			if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
1250186119Sqingli				continue;
1251186980Sbz			/* Skip if jailed and not a valid IP of the prison. */
1252188144Sjamie			if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
1253186980Sbz				continue;
1254186119Sqingli			/*
1255186119Sqingli			 * produce a msg made of:
1256186119Sqingli			 *  struct rt_msghdr;
1257186119Sqingli			 *  struct sockaddr_inarp; (IPv4)
1258186119Sqingli			 *  struct sockaddr_dl;
1259186119Sqingli			 */
1260186119Sqingli			bzero(&arpc, sizeof(arpc));
1261186119Sqingli			arpc.rtm.rtm_msglen = sizeof(arpc);
1262186935Sharti			arpc.rtm.rtm_version = RTM_VERSION;
1263186935Sharti			arpc.rtm.rtm_type = RTM_GET;
1264186935Sharti			arpc.rtm.rtm_flags = RTF_UP;
1265186935Sharti			arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
1266186119Sqingli			arpc.sin.sin_family = AF_INET;
1267186119Sqingli			arpc.sin.sin_len = sizeof(arpc.sin);
1268186119Sqingli			arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
1269186119Sqingli
1270186119Sqingli			/* publish */
1271186119Sqingli			if (lle->la_flags & LLE_PUB) {
1272186119Sqingli				arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
1273186119Sqingli				/* proxy only */
1274186119Sqingli				if (lle->la_flags & LLE_PROXY)
1275186119Sqingli					arpc.sin.sin_other = SIN_PROXY;
1276186119Sqingli			}
1277186119Sqingli
1278186119Sqingli			sdl = &arpc.sdl;
1279186119Sqingli			sdl->sdl_family = AF_LINK;
1280186119Sqingli			sdl->sdl_len = sizeof(*sdl);
1281186119Sqingli			sdl->sdl_alen = ifp->if_addrlen;
1282186119Sqingli			sdl->sdl_index = ifp->if_index;
1283186119Sqingli			sdl->sdl_type = ifp->if_type;
1284186119Sqingli			bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
1285186119Sqingli
1286186119Sqingli			arpc.rtm.rtm_rmx.rmx_expire =
1287186119Sqingli			    lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
1288186500Sqingli			arpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
1289186119Sqingli			if (lle->la_flags & LLE_STATIC)
1290186119Sqingli				arpc.rtm.rtm_flags |= RTF_STATIC;
1291186119Sqingli			arpc.rtm.rtm_index = ifp->if_index;
1292186119Sqingli			error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
1293186119Sqingli			if (error)
1294186119Sqingli				break;
1295186119Sqingli		}
1296186119Sqingli	}
1297186119Sqingli	return error;
1298186119Sqingli#undef SIN
1299186119Sqingli}
1300186119Sqingli
1301186119Sqinglivoid *
1302186119Sqingliin_domifattach(struct ifnet *ifp)
1303189592Sbms{
1304189592Sbms	struct in_ifinfo *ii;
1305189592Sbms	struct lltable *llt;
1306189592Sbms
1307189592Sbms	ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO);
1308189592Sbms
1309189592Sbms	llt = lltable_init(ifp, AF_INET);
1310186119Sqingli	if (llt != NULL) {
1311186119Sqingli		llt->llt_new = in_lltable_new;
1312186119Sqingli		llt->llt_free = in_lltable_free;
1313186119Sqingli		llt->llt_rtcheck = in_lltable_rtcheck;
1314186119Sqingli		llt->llt_lookup = in_lltable_lookup;
1315186119Sqingli		llt->llt_dump = in_lltable_dump;
1316186119Sqingli	}
1317189592Sbms	ii->ii_llt = llt;
1318189592Sbms
1319189592Sbms	ii->ii_igmp = igmp_domifattach(ifp);
1320189592Sbms
1321189592Sbms	return ii;
1322186119Sqingli}
1323186119Sqingli
1324186119Sqinglivoid
1325189592Sbmsin_domifdetach(struct ifnet *ifp, void *aux)
1326186119Sqingli{
1327189592Sbms	struct in_ifinfo *ii = (struct in_ifinfo *)aux;
1328186119Sqingli
1329189592Sbms	igmp_domifdetach(ifp);
1330189592Sbms	lltable_free(ii->ii_llt);
1331189592Sbms	free(ii, M_IFADDR);
1332186119Sqingli}
1333