in.c revision 223862
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 223862 2011-07-08 09:38:33Z zec $");
35172467Ssilby
36204902Sqingli#include "opt_mpath.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>
48192011Sqingli#include <sys/syslog.h>
491541Srgrimes
501541Srgrimes#include <net/if.h>
51195914Sqingli#include <net/if_var.h>
52215207Sgnn#include <net/if_arp.h>
53192011Sqingli#include <net/if_dl.h>
54186119Sqingli#include <net/if_llatbl.h>
5555009Sshin#include <net/if_types.h>
561541Srgrimes#include <net/route.h>
57192011Sqingli#include <net/vnet.h>
581541Srgrimes
591541Srgrimes#include <netinet/in.h>
601541Srgrimes#include <netinet/in_var.h>
6181127Sume#include <netinet/in_pcb.h>
62170613Sbms#include <netinet/ip_var.h>
63189592Sbms#include <netinet/igmp_var.h>
64195699Srwatson#include <netinet/udp.h>
65195699Srwatson#include <netinet/udp_var.h>
661541Srgrimes
6792723Salfredstatic int in_mask2len(struct in_addr *);
6892723Salfredstatic void in_len2mask(struct in_addr *, int);
6992723Salfredstatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
7092723Salfred	struct ifnet *, struct thread *);
7155009Sshin
72137628Smlaierstatic int	in_addprefix(struct in_ifaddr *, int);
73222143Sqinglistatic int	in_scrubprefix(struct in_ifaddr *, u_int);
7492723Salfredstatic void	in_socktrim(struct sockaddr_in *);
7592723Salfredstatic int	in_ifinit(struct ifnet *,
7692723Salfred	    struct in_ifaddr *, struct sockaddr_in *, int);
77167729Sbmsstatic void	in_purgemaddrs(struct ifnet *);
781541Srgrimes
79215701Sdimstatic VNET_DEFINE(int, subnetsarelocal);
80195727Srwatson#define	V_subnetsarelocal		VNET(subnetsarelocal)
81195699SrwatsonSYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
82195699Srwatson	&VNET_NAME(subnetsarelocal), 0,
83183550Szec	"Treat all subnets as directly connected");
84215701Sdimstatic VNET_DEFINE(int, sameprefixcarponly);
85207369Sbz#define	V_sameprefixcarponly		VNET(sameprefixcarponly)
86195699SrwatsonSYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW,
87195699Srwatson	&VNET_NAME(sameprefixcarponly), 0,
88149221Sglebius	"Refuse to create same prefixes on different interfaces");
8921666Swollman
90207369SbzVNET_DECLARE(struct inpcbinfo, ripcbinfo);
91207369Sbz#define	V_ripcbinfo			VNET(ripcbinfo)
92207369Sbz
93215207SgnnVNET_DECLARE(struct arpstat, arpstat);  /* ARP statistics, see if_arp.h */
94215207Sgnn#define	V_arpstat		VNET(arpstat)
95215207Sgnn
961541Srgrimes/*
971541Srgrimes * Return 1 if an internet address is for a ``local'' host
981541Srgrimes * (one to which we have a connection).  If subnetsarelocal
991541Srgrimes * is true, this includes other subnets of the local net.
1001541Srgrimes * Otherwise, it includes only the directly-connected (sub)nets.
1011541Srgrimes */
1021549Srgrimesint
103169454Srwatsonin_localaddr(struct in_addr in)
1041541Srgrimes{
1051541Srgrimes	register u_long i = ntohl(in.s_addr);
1061541Srgrimes	register struct in_ifaddr *ia;
1071541Srgrimes
108194951Srwatson	IN_IFADDR_RLOCK();
109181803Sbz	if (V_subnetsarelocal) {
110194951Srwatson		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
111194951Srwatson			if ((i & ia->ia_netmask) == ia->ia_net) {
112194951Srwatson				IN_IFADDR_RUNLOCK();
1131541Srgrimes				return (1);
114194951Srwatson			}
115194951Srwatson		}
1161541Srgrimes	} else {
117194951Srwatson		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
118194951Srwatson			if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
119194951Srwatson				IN_IFADDR_RUNLOCK();
1201541Srgrimes				return (1);
121194951Srwatson			}
122194951Srwatson		}
1231541Srgrimes	}
124194951Srwatson	IN_IFADDR_RUNLOCK();
1251541Srgrimes	return (0);
1261541Srgrimes}
1271541Srgrimes
1281541Srgrimes/*
129133486Sandre * Return 1 if an internet address is for the local host and configured
130133486Sandre * on one of its interfaces.
131133486Sandre */
132133486Sandreint
133169454Srwatsonin_localip(struct in_addr in)
134133486Sandre{
135133486Sandre	struct in_ifaddr *ia;
136133486Sandre
137194951Srwatson	IN_IFADDR_RLOCK();
138133486Sandre	LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
139194951Srwatson		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) {
140194951Srwatson			IN_IFADDR_RUNLOCK();
141184295Sbz			return (1);
142194951Srwatson		}
143133486Sandre	}
144194951Srwatson	IN_IFADDR_RUNLOCK();
145184295Sbz	return (0);
146133486Sandre}
147133486Sandre
148133486Sandre/*
1491541Srgrimes * Determine whether an IP address is in a reserved set of addresses
1501541Srgrimes * that may not be forwarded, or whether datagrams to that destination
1511541Srgrimes * may be forwarded.
1521541Srgrimes */
1531549Srgrimesint
154169454Srwatsonin_canforward(struct in_addr in)
1551541Srgrimes{
1561541Srgrimes	register u_long i = ntohl(in.s_addr);
1571541Srgrimes	register u_long net;
1581541Srgrimes
159166450Sbms	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i))
1601541Srgrimes		return (0);
1611541Srgrimes	if (IN_CLASSA(i)) {
1621541Srgrimes		net = i & IN_CLASSA_NET;
1631541Srgrimes		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
1641541Srgrimes			return (0);
1651541Srgrimes	}
1661541Srgrimes	return (1);
1671541Srgrimes}
1681541Srgrimes
1691541Srgrimes/*
1701541Srgrimes * Trim a mask in a sockaddr
1711541Srgrimes */
17212296Sphkstatic void
173169454Srwatsonin_socktrim(struct sockaddr_in *ap)
1741541Srgrimes{
1751541Srgrimes    register char *cplim = (char *) &ap->sin_addr;
1761541Srgrimes    register char *cp = (char *) (&ap->sin_addr + 1);
1771541Srgrimes
1781541Srgrimes    ap->sin_len = 0;
1794127Swollman    while (--cp >= cplim)
180133874Srwatson	if (*cp) {
1811541Srgrimes	    (ap)->sin_len = cp - (char *) (ap) + 1;
1821541Srgrimes	    break;
1831541Srgrimes	}
1841541Srgrimes}
1851541Srgrimes
18655009Sshinstatic int
18755009Sshinin_mask2len(mask)
18855009Sshin	struct in_addr *mask;
18955009Sshin{
19055009Sshin	int x, y;
19155009Sshin	u_char *p;
19255009Sshin
19355009Sshin	p = (u_char *)mask;
19455009Sshin	for (x = 0; x < sizeof(*mask); x++) {
19555009Sshin		if (p[x] != 0xff)
19655009Sshin			break;
19755009Sshin	}
19855009Sshin	y = 0;
19955009Sshin	if (x < sizeof(*mask)) {
20055009Sshin		for (y = 0; y < 8; y++) {
20155009Sshin			if ((p[x] & (0x80 >> y)) == 0)
20255009Sshin				break;
20355009Sshin		}
20455009Sshin	}
205184295Sbz	return (x * 8 + y);
20655009Sshin}
20755009Sshin
20855009Sshinstatic void
209169454Srwatsonin_len2mask(struct in_addr *mask, int len)
21055009Sshin{
21155009Sshin	int i;
21255009Sshin	u_char *p;
21355009Sshin
21455009Sshin	p = (u_char *)mask;
21555009Sshin	bzero(mask, sizeof(*mask));
21655009Sshin	for (i = 0; i < len / 8; i++)
21755009Sshin		p[i] = 0xff;
21855009Sshin	if (len % 8)
21955009Sshin		p[i] = (0xff00 >> (len % 8)) & 0xff;
22055009Sshin}
22155009Sshin
2221541Srgrimes/*
2231541Srgrimes * Generic internet control operations (ioctl's).
224191443Srwatson *
225191443Srwatson * ifp is NULL if not an interface-specific ioctl.
2261541Srgrimes */
2271541Srgrimes/* ARGSUSED */
2281549Srgrimesint
229169454Srwatsonin_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
230169454Srwatson    struct thread *td)
2311541Srgrimes{
2321541Srgrimes	register struct ifreq *ifr = (struct ifreq *)data;
233184295Sbz	register struct in_ifaddr *ia, *iap;
2341541Srgrimes	register struct ifaddr *ifa;
235168032Sbms	struct in_addr allhosts_addr;
23684102Sjlemon	struct in_addr dst;
237189592Sbms	struct in_ifinfo *ii;
2381541Srgrimes	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
2391541Srgrimes	struct sockaddr_in oldaddr;
240194951Srwatson	int error, hostIsNew, iaIsNew, maskIsNew;
241168032Sbms	int iaIsFirst;
2421541Srgrimes
243184295Sbz	ia = NULL;
244168032Sbms	iaIsFirst = 0;
24587124Sbrian	iaIsNew = 0;
246168032Sbms	allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
24787124Sbrian
248191443Srwatson	/*
249191443Srwatson	 * Filter out ioctls we implement directly; forward the rest on to
250191443Srwatson	 * in_lifaddr_ioctl() and ifp->if_ioctl().
251191443Srwatson	 */
25255009Sshin	switch (cmd) {
253191443Srwatson	case SIOCAIFADDR:
254191443Srwatson	case SIOCDIFADDR:
255191443Srwatson	case SIOCGIFADDR:
256191443Srwatson	case SIOCGIFBRDADDR:
257191443Srwatson	case SIOCGIFDSTADDR:
258191443Srwatson	case SIOCGIFNETMASK:
259191443Srwatson	case SIOCSIFADDR:
260191443Srwatson	case SIOCSIFBRDADDR:
261191443Srwatson	case SIOCSIFDSTADDR:
262191443Srwatson	case SIOCSIFNETMASK:
263191443Srwatson		break;
264191443Srwatson
26555009Sshin	case SIOCALIFADDR:
266164033Srwatson		if (td != NULL) {
267164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
268164033Srwatson			if (error)
269164033Srwatson				return (error);
270164033Srwatson		}
271184295Sbz		if (ifp == NULL)
272184295Sbz			return (EINVAL);
273164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
274164033Srwatson
27555009Sshin	case SIOCDLIFADDR:
276164033Srwatson		if (td != NULL) {
277164033Srwatson			error = priv_check(td, PRIV_NET_DELIFADDR);
278164033Srwatson			if (error)
279164033Srwatson				return (error);
280164033Srwatson		}
281184295Sbz		if (ifp == NULL)
282184295Sbz			return (EINVAL);
283164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
284164033Srwatson
28555009Sshin	case SIOCGLIFADDR:
286184295Sbz		if (ifp == NULL)
287184295Sbz			return (EINVAL);
28883366Sjulian		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
289191443Srwatson
290191443Srwatson	default:
291191443Srwatson		if (ifp == NULL || ifp->if_ioctl == NULL)
292191443Srwatson			return (EOPNOTSUPP);
293191443Srwatson		return ((*ifp->if_ioctl)(ifp, cmd, data));
29455009Sshin	}
29555009Sshin
296191443Srwatson	if (ifp == NULL)
297191443Srwatson		return (EADDRNOTAVAIL);
298191443Srwatson
2991541Srgrimes	/*
300191456Srwatson	 * Security checks before we get involved in any work.
301191456Srwatson	 */
302191456Srwatson	switch (cmd) {
303191456Srwatson	case SIOCAIFADDR:
304191456Srwatson	case SIOCSIFADDR:
305191456Srwatson	case SIOCSIFBRDADDR:
306191456Srwatson	case SIOCSIFNETMASK:
307191456Srwatson	case SIOCSIFDSTADDR:
308191456Srwatson		if (td != NULL) {
309191456Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
310191456Srwatson			if (error)
311191456Srwatson				return (error);
312191456Srwatson		}
313191456Srwatson		break;
314191456Srwatson
315191456Srwatson	case SIOCDIFADDR:
316191456Srwatson		if (td != NULL) {
317191456Srwatson			error = priv_check(td, PRIV_NET_DELIFADDR);
318191456Srwatson			if (error)
319191456Srwatson				return (error);
320191456Srwatson		}
321191456Srwatson		break;
322191456Srwatson	}
323191456Srwatson
324191456Srwatson	/*
3251541Srgrimes	 * Find address for this interface, if it exists.
32614632Sfenner	 *
327191443Srwatson	 * If an alias address was specified, find that one instead of the
328191443Srwatson	 * first one on the interface, if possible.
3291541Srgrimes	 */
330191443Srwatson	dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
331194951Srwatson	IN_IFADDR_RLOCK();
332191443Srwatson	LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) {
333191443Srwatson		if (iap->ia_ifp == ifp &&
334191443Srwatson		    iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
335191443Srwatson			if (td == NULL || prison_check_ip4(td->td_ucred,
336191443Srwatson			    &dst) == 0)
337191443Srwatson				ia = iap;
338191443Srwatson			break;
339191443Srwatson		}
340191443Srwatson	}
341194760Srwatson	if (ia != NULL)
342194760Srwatson		ifa_ref(&ia->ia_ifa);
343194951Srwatson	IN_IFADDR_RUNLOCK();
344191443Srwatson	if (ia == NULL) {
345194760Srwatson		IF_ADDR_LOCK(ifp);
346191443Srwatson		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
347191443Srwatson			iap = ifatoia(ifa);
348191443Srwatson			if (iap->ia_addr.sin_family == AF_INET) {
349191443Srwatson				if (td != NULL &&
350191443Srwatson				    prison_check_ip4(td->td_ucred,
351191443Srwatson				    &iap->ia_addr.sin_addr) != 0)
352191443Srwatson					continue;
353191443Srwatson				ia = iap;
35484102Sjlemon				break;
35584102Sjlemon			}
356191443Srwatson		}
357194760Srwatson		if (ia != NULL)
358194760Srwatson			ifa_ref(&ia->ia_ifa);
359194760Srwatson		IF_ADDR_UNLOCK(ifp);
36084102Sjlemon	}
361191443Srwatson	if (ia == NULL)
362191443Srwatson		iaIsFirst = 1;
3631541Srgrimes
364191500Srwatson	error = 0;
3651541Srgrimes	switch (cmd) {
3661541Srgrimes	case SIOCAIFADDR:
3671541Srgrimes	case SIOCDIFADDR:
3688071Swollman		if (ifra->ifra_addr.sin_family == AF_INET) {
369194760Srwatson			struct in_ifaddr *oia;
370194760Srwatson
371194951Srwatson			IN_IFADDR_RLOCK();
37271999Sphk			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
3738071Swollman				if (ia->ia_ifp == ifp  &&
3748071Swollman				    ia->ia_addr.sin_addr.s_addr ==
3758071Swollman				    ifra->ifra_addr.sin_addr.s_addr)
3768071Swollman					break;
3778071Swollman			}
378194760Srwatson			if (ia != NULL && ia != oia)
379194760Srwatson				ifa_ref(&ia->ia_ifa);
380194760Srwatson			if (oia != NULL && ia != oia)
381194760Srwatson				ifa_free(&oia->ia_ifa);
382194951Srwatson			IN_IFADDR_RUNLOCK();
3838876Srgrimes			if ((ifp->if_flags & IFF_POINTOPOINT)
3848071Swollman			    && (cmd == SIOCAIFADDR)
3858071Swollman			    && (ifra->ifra_dstaddr.sin_addr.s_addr
3868071Swollman				== INADDR_ANY)) {
387191500Srwatson				error = EDESTADDRREQ;
388194760Srwatson				goto out;
3898071Swollman			}
3901541Srgrimes		}
391191500Srwatson		if (cmd == SIOCDIFADDR && ia == NULL) {
392191500Srwatson			error = EADDRNOTAVAIL;
393194760Srwatson			goto out;
394191500Srwatson		}
3951541Srgrimes		/* FALLTHROUGH */
3961541Srgrimes	case SIOCSIFADDR:
3971541Srgrimes	case SIOCSIFNETMASK:
3981541Srgrimes	case SIOCSIFDSTADDR:
399184295Sbz		if (ia == NULL) {
40020407Swollman			ia = (struct in_ifaddr *)
401191500Srwatson				malloc(sizeof *ia, M_IFADDR, M_NOWAIT |
402191500Srwatson				    M_ZERO);
403191500Srwatson			if (ia == NULL) {
404191500Srwatson				error = ENOBUFS;
405194760Srwatson				goto out;
406191500Srwatson			}
407191500Srwatson
40820407Swollman			ifa = &ia->ia_ifa;
409194602Srwatson			ifa_init(ifa);
41020407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
41120407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
41220407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
413108033Shsu
4141541Srgrimes			ia->ia_sockmask.sin_len = 8;
41585740Sdes			ia->ia_sockmask.sin_family = AF_INET;
4161541Srgrimes			if (ifp->if_flags & IFF_BROADCAST) {
4171541Srgrimes				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
4181541Srgrimes				ia->ia_broadaddr.sin_family = AF_INET;
4191541Srgrimes			}
4201541Srgrimes			ia->ia_ifp = ifp;
421151824Sglebius
422194760Srwatson			ifa_ref(ifa);			/* if_addrhead */
423194760Srwatson			IF_ADDR_LOCK(ifp);
424191285Srwatson			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
425194760Srwatson			IF_ADDR_UNLOCK(ifp);
426194760Srwatson			ifa_ref(ifa);			/* in_ifaddrhead */
427194951Srwatson			IN_IFADDR_WLOCK();
428181803Sbz			TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
429194951Srwatson			IN_IFADDR_WUNLOCK();
43087124Sbrian			iaIsNew = 1;
4311541Srgrimes		}
4321541Srgrimes		break;
4331541Srgrimes
4341541Srgrimes	case SIOCSIFBRDADDR:
4351541Srgrimes	case SIOCGIFADDR:
4361541Srgrimes	case SIOCGIFNETMASK:
4371541Srgrimes	case SIOCGIFDSTADDR:
4381541Srgrimes	case SIOCGIFBRDADDR:
439191500Srwatson		if (ia == NULL) {
440191500Srwatson			error = EADDRNOTAVAIL;
441194760Srwatson			goto out;
442191500Srwatson		}
4431541Srgrimes		break;
4441541Srgrimes	}
445191500Srwatson
446191500Srwatson	/*
447194760Srwatson	 * Most paths in this switch return directly or via out.  Only paths
448194760Srwatson	 * that remove the address break in order to hit common removal code.
449191500Srwatson	 */
4501541Srgrimes	switch (cmd) {
4511541Srgrimes	case SIOCGIFADDR:
4521541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
453194760Srwatson		goto out;
4541541Srgrimes
4551541Srgrimes	case SIOCGIFBRDADDR:
456191500Srwatson		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
457191500Srwatson			error = EINVAL;
458194760Srwatson			goto out;
459191500Srwatson		}
4601541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
461194760Srwatson		goto out;
4621541Srgrimes
4631541Srgrimes	case SIOCGIFDSTADDR:
464191500Srwatson		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
465191500Srwatson			error = EINVAL;
466194760Srwatson			goto out;
467191500Srwatson		}
4681541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
469194760Srwatson		goto out;
4701541Srgrimes
4711541Srgrimes	case SIOCGIFNETMASK:
4721541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
473194760Srwatson		goto out;
4741541Srgrimes
4751541Srgrimes	case SIOCSIFDSTADDR:
476191500Srwatson		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
477191500Srwatson			error = EINVAL;
478194760Srwatson			goto out;
479191500Srwatson		}
4801541Srgrimes		oldaddr = ia->ia_dstaddr;
4811541Srgrimes		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
482184295Sbz		if (ifp->if_ioctl != NULL) {
483146883Siedowse			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
484146883Siedowse			    (caddr_t)ia);
485146883Siedowse			if (error) {
486146883Siedowse				ia->ia_dstaddr = oldaddr;
487194760Srwatson				goto out;
488146883Siedowse			}
4891541Srgrimes		}
4901541Srgrimes		if (ia->ia_flags & IFA_ROUTE) {
4911541Srgrimes			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
4921541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
4931541Srgrimes			ia->ia_ifa.ifa_dstaddr =
4941541Srgrimes					(struct sockaddr *)&ia->ia_dstaddr;
4951541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
4961541Srgrimes		}
497194760Srwatson		goto out;
4981541Srgrimes
4991541Srgrimes	case SIOCSIFBRDADDR:
500191500Srwatson		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
501191500Srwatson			error = EINVAL;
502194760Srwatson			goto out;
503191500Srwatson		}
5041541Srgrimes		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
505194760Srwatson		goto out;
5061541Srgrimes
5071541Srgrimes	case SIOCSIFADDR:
50887124Sbrian		error = in_ifinit(ifp, ia,
50987124Sbrian		    (struct sockaddr_in *) &ifr->ifr_addr, 1);
51087124Sbrian		if (error != 0 && iaIsNew)
51187124Sbrian			break;
512168032Sbms		if (error == 0) {
513189603Sbms			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
514189592Sbms			if (iaIsFirst &&
515189592Sbms			    (ifp->if_flags & IFF_MULTICAST) != 0) {
516189592Sbms				error = in_joingroup(ifp, &allhosts_addr,
517189592Sbms				    NULL, &ii->ii_allhosts);
518189592Sbms			}
519126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
520168032Sbms		}
521194760Srwatson		error = 0;
522194760Srwatson		goto out;
5231541Srgrimes
5241541Srgrimes	case SIOCSIFNETMASK:
52585740Sdes		ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
52685740Sdes		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
527194760Srwatson		goto out;
5281541Srgrimes
5291541Srgrimes	case SIOCAIFADDR:
5301541Srgrimes		maskIsNew = 0;
5311541Srgrimes		hostIsNew = 1;
5321541Srgrimes		error = 0;
5331541Srgrimes		if (ia->ia_addr.sin_family == AF_INET) {
5341541Srgrimes			if (ifra->ifra_addr.sin_len == 0) {
5351541Srgrimes				ifra->ifra_addr = ia->ia_addr;
5361541Srgrimes				hostIsNew = 0;
5371541Srgrimes			} else if (ifra->ifra_addr.sin_addr.s_addr ==
5381541Srgrimes					       ia->ia_addr.sin_addr.s_addr)
5391541Srgrimes				hostIsNew = 0;
5401541Srgrimes		}
5411541Srgrimes		if (ifra->ifra_mask.sin_len) {
542197210Sqingli			/*
543197210Sqingli			 * QL: XXX
544197210Sqingli			 * Need to scrub the prefix here in case
545197210Sqingli			 * the issued command is SIOCAIFADDR with
546197210Sqingli			 * the same address, but with a different
547197210Sqingli			 * prefix length. And if the prefix length
548197210Sqingli			 * is the same as before, then the call is
549197210Sqingli			 * un-necessarily executed here.
550197210Sqingli			 */
551222438Sqingli			in_ifscrub(ifp, ia, LLE_STATIC);
5521541Srgrimes			ia->ia_sockmask = ifra->ifra_mask;
55385740Sdes			ia->ia_sockmask.sin_family = AF_INET;
5541541Srgrimes			ia->ia_subnetmask =
5551541Srgrimes			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
5561541Srgrimes			maskIsNew = 1;
5571541Srgrimes		}
5581541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) &&
5591541Srgrimes		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
560222438Sqingli			in_ifscrub(ifp, ia, LLE_STATIC);
5611541Srgrimes			ia->ia_dstaddr = ifra->ifra_dstaddr;
5621541Srgrimes			maskIsNew  = 1; /* We lie; but the effect's the same */
5631541Srgrimes		}
5641541Srgrimes		if (ifra->ifra_addr.sin_family == AF_INET &&
5651541Srgrimes		    (hostIsNew || maskIsNew))
5661541Srgrimes			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
56787124Sbrian		if (error != 0 && iaIsNew)
568201811Sqingli			break;
56987124Sbrian
5701541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) &&
5711541Srgrimes		    (ifra->ifra_broadaddr.sin_family == AF_INET))
5721541Srgrimes			ia->ia_broadaddr = ifra->ifra_broadaddr;
573168032Sbms		if (error == 0) {
574189603Sbms			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
575189592Sbms			if (iaIsFirst &&
576189592Sbms			    (ifp->if_flags & IFF_MULTICAST) != 0) {
577189592Sbms				error = in_joingroup(ifp, &allhosts_addr,
578189592Sbms				    NULL, &ii->ii_allhosts);
579189592Sbms			}
580126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
581168032Sbms		}
582194760Srwatson		goto out;
5831541Srgrimes
5841541Srgrimes	case SIOCDIFADDR:
58574299Sru		/*
58674299Sru		 * in_ifscrub kills the interface route.
58774299Sru		 */
588222143Sqingli		in_ifscrub(ifp, ia, LLE_STATIC);
589191500Srwatson
59015092Sdg		/*
59174299Sru		 * in_ifadown gets rid of all the rest of
59274299Sru		 * the routes.  This is not quite the right
59374299Sru		 * thing to do, but at least if we are running
59474299Sru		 * a routing process they will come back.
59574299Sru		 */
59676469Sru		in_ifadown(&ia->ia_ifa, 1);
597126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
59887124Sbrian		error = 0;
5991541Srgrimes		break;
6001541Srgrimes
6011541Srgrimes	default:
602191443Srwatson		panic("in_control: unsupported ioctl");
6031541Srgrimes	}
60487124Sbrian
605191285Srwatson	IF_ADDR_LOCK(ifp);
606213932Sbz	/* Re-check that ia is still part of the list. */
607213932Sbz	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
608213932Sbz		if (ifa == &ia->ia_ifa)
609213932Sbz			break;
610213932Sbz	}
611213932Sbz	if (ifa == NULL) {
612213932Sbz		/*
613213932Sbz		 * If we lost the race with another thread, there is no need to
614213932Sbz		 * try it again for the next loop as there is no other exit
615213932Sbz		 * path between here and out.
616213932Sbz		 */
617213932Sbz		IF_ADDR_UNLOCK(ifp);
618213932Sbz		error = EADDRNOTAVAIL;
619213932Sbz		goto out;
620213932Sbz	}
621191285Srwatson	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
622191285Srwatson	IF_ADDR_UNLOCK(ifp);
623194760Srwatson	ifa_free(&ia->ia_ifa);				/* if_addrhead */
624194951Srwatson
625194951Srwatson	IN_IFADDR_WLOCK();
626181803Sbz	TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
627168032Sbms	if (ia->ia_addr.sin_family == AF_INET) {
628194760Srwatson		struct in_ifaddr *if_ia;
629194760Srwatson
630154777Sandre		LIST_REMOVE(ia, ia_hash);
631194951Srwatson		IN_IFADDR_WUNLOCK();
632168032Sbms		/*
633168032Sbms		 * If this is the last IPv4 address configured on this
634168032Sbms		 * interface, leave the all-hosts group.
635189592Sbms		 * No state-change report need be transmitted.
636168032Sbms		 */
637194760Srwatson		if_ia = NULL;
638194760Srwatson		IFP_TO_IA(ifp, if_ia);
639194760Srwatson		if (if_ia == NULL) {
640189603Sbms			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
641168032Sbms			IN_MULTI_LOCK();
642189592Sbms			if (ii->ii_allhosts) {
643189592Sbms				(void)in_leavegroup_locked(ii->ii_allhosts,
644189592Sbms				    NULL);
645189592Sbms				ii->ii_allhosts = NULL;
646189592Sbms			}
647168032Sbms			IN_MULTI_UNLOCK();
648194760Srwatson		} else
649194760Srwatson			ifa_free(&if_ia->ia_ifa);
650194951Srwatson	} else
651194951Srwatson		IN_IFADDR_WUNLOCK();
652194951Srwatson	ifa_free(&ia->ia_ifa);				/* in_ifaddrhead */
653194760Srwatsonout:
654194760Srwatson	if (ia != NULL)
655194760Srwatson		ifa_free(&ia->ia_ifa);
65687124Sbrian	return (error);
6571541Srgrimes}
6581541Srgrimes
6591541Srgrimes/*
66055009Sshin * SIOC[GAD]LIFADDR.
66155009Sshin *	SIOCGLIFADDR: get first address. (?!?)
66255009Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
66355009Sshin *		get first address that matches the specified prefix.
66455009Sshin *	SIOCALIFADDR: add the specified address.
66555009Sshin *	SIOCALIFADDR with IFLR_PREFIX:
66655009Sshin *		EINVAL since we can't deduce hostid part of the address.
66755009Sshin *	SIOCDLIFADDR: delete the specified address.
66855009Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
66955009Sshin *		delete the first address that matches the specified prefix.
67055009Sshin * return values:
67155009Sshin *	EINVAL on invalid parameters
67255009Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
67355009Sshin *	other values may be returned from in_ioctl()
67455009Sshin */
67555009Sshinstatic int
676169454Srwatsonin_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
677169454Srwatson    struct ifnet *ifp, struct thread *td)
67855009Sshin{
67955009Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
68055009Sshin	struct ifaddr *ifa;
68155009Sshin
68255009Sshin	/* sanity checks */
683184295Sbz	if (data == NULL || ifp == NULL) {
68455009Sshin		panic("invalid argument to in_lifaddr_ioctl");
68555009Sshin		/*NOTRECHED*/
68655009Sshin	}
68755009Sshin
68855009Sshin	switch (cmd) {
68955009Sshin	case SIOCGLIFADDR:
69055009Sshin		/* address must be specified on GET with IFLR_PREFIX */
69155009Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
69255009Sshin			break;
69355009Sshin		/*FALLTHROUGH*/
69455009Sshin	case SIOCALIFADDR:
69555009Sshin	case SIOCDLIFADDR:
69655009Sshin		/* address must be specified on ADD and DELETE */
69755917Sshin		if (iflr->addr.ss_family != AF_INET)
698184295Sbz			return (EINVAL);
69955917Sshin		if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
700184295Sbz			return (EINVAL);
70155009Sshin		/* XXX need improvement */
70255917Sshin		if (iflr->dstaddr.ss_family
70355917Sshin		 && iflr->dstaddr.ss_family != AF_INET)
704184295Sbz			return (EINVAL);
70555917Sshin		if (iflr->dstaddr.ss_family
70655917Sshin		 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
707184295Sbz			return (EINVAL);
70855009Sshin		break;
70955009Sshin	default: /*shouldn't happen*/
710184295Sbz		return (EOPNOTSUPP);
71155009Sshin	}
71255009Sshin	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
713184295Sbz		return (EINVAL);
71455009Sshin
71555009Sshin	switch (cmd) {
71655009Sshin	case SIOCALIFADDR:
71755009Sshin	    {
71855009Sshin		struct in_aliasreq ifra;
71955009Sshin
72055009Sshin		if (iflr->flags & IFLR_PREFIX)
721184295Sbz			return (EINVAL);
72255009Sshin
72355009Sshin		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
72455009Sshin		bzero(&ifra, sizeof(ifra));
72555009Sshin		bcopy(iflr->iflr_name, ifra.ifra_name,
72655009Sshin			sizeof(ifra.ifra_name));
72755009Sshin
72855917Sshin		bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
72955009Sshin
73055917Sshin		if (iflr->dstaddr.ss_family) {	/*XXX*/
73155009Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
73255917Sshin				iflr->dstaddr.ss_len);
73355009Sshin		}
73455009Sshin
73555009Sshin		ifra.ifra_mask.sin_family = AF_INET;
73655009Sshin		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
73755009Sshin		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
73855009Sshin
739184295Sbz		return (in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td));
74055009Sshin	    }
74155009Sshin	case SIOCGLIFADDR:
74255009Sshin	case SIOCDLIFADDR:
74355009Sshin	    {
74455009Sshin		struct in_ifaddr *ia;
74555009Sshin		struct in_addr mask, candidate, match;
74655009Sshin		struct sockaddr_in *sin;
74755009Sshin
74855009Sshin		bzero(&mask, sizeof(mask));
749170855Smjacob		bzero(&match, sizeof(match));
75055009Sshin		if (iflr->flags & IFLR_PREFIX) {
75155009Sshin			/* lookup a prefix rather than address. */
75255009Sshin			in_len2mask(&mask, iflr->prefixlen);
75355009Sshin
75455009Sshin			sin = (struct sockaddr_in *)&iflr->addr;
75555009Sshin			match.s_addr = sin->sin_addr.s_addr;
75655009Sshin			match.s_addr &= mask.s_addr;
75755009Sshin
75855009Sshin			/* if you set extra bits, that's wrong */
75955009Sshin			if (match.s_addr != sin->sin_addr.s_addr)
760184295Sbz				return (EINVAL);
76155009Sshin
76255009Sshin		} else {
763170855Smjacob			/* on getting an address, take the 1st match */
764170855Smjacob			/* on deleting an address, do exact match */
765170855Smjacob			if (cmd != SIOCGLIFADDR) {
76655009Sshin				in_len2mask(&mask, 32);
76755009Sshin				sin = (struct sockaddr_in *)&iflr->addr;
76855009Sshin				match.s_addr = sin->sin_addr.s_addr;
76955009Sshin			}
77055009Sshin		}
77155009Sshin
77255009Sshin		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)	{
77355009Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
77455009Sshin				continue;
775170855Smjacob			if (match.s_addr == 0)
77655009Sshin				break;
77755009Sshin			candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
77855009Sshin			candidate.s_addr &= mask.s_addr;
77955009Sshin			if (candidate.s_addr == match.s_addr)
78055009Sshin				break;
78155009Sshin		}
782184295Sbz		if (ifa == NULL)
783184295Sbz			return (EADDRNOTAVAIL);
78455009Sshin		ia = (struct in_ifaddr *)ifa;
78555009Sshin
78655009Sshin		if (cmd == SIOCGLIFADDR) {
78755009Sshin			/* fill in the if_laddrreq structure */
78855009Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
78955009Sshin
79055009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
79155009Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
79255009Sshin					ia->ia_dstaddr.sin_len);
79355009Sshin			} else
79455009Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
79555009Sshin
79655009Sshin			iflr->prefixlen =
79755009Sshin				in_mask2len(&ia->ia_sockmask.sin_addr);
79855009Sshin
79955009Sshin			iflr->flags = 0;	/*XXX*/
80055009Sshin
801184295Sbz			return (0);
80255009Sshin		} else {
80355009Sshin			struct in_aliasreq ifra;
80455009Sshin
80555009Sshin			/* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
80655009Sshin			bzero(&ifra, sizeof(ifra));
80755009Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
80855009Sshin				sizeof(ifra.ifra_name));
80955009Sshin
81055009Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
81155009Sshin				ia->ia_addr.sin_len);
81255009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
81355009Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
81455009Sshin					ia->ia_dstaddr.sin_len);
81555009Sshin			}
81655009Sshin			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
81755009Sshin				ia->ia_sockmask.sin_len);
81855009Sshin
819184295Sbz			return (in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
820184295Sbz			    ifp, td));
82155009Sshin		}
82255009Sshin	    }
82355009Sshin	}
82455009Sshin
825184295Sbz	return (EOPNOTSUPP);	/*just for safety*/
82655009Sshin}
82755009Sshin
82855009Sshin/*
8291541Srgrimes * Delete any existing route for an interface.
8301541Srgrimes */
83122672Swollmanvoid
832222143Sqingliin_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, u_int flags)
8331541Srgrimes{
834169454Srwatson
835222143Sqingli	in_scrubprefix(ia, flags);
8361541Srgrimes}
8371541Srgrimes
8381541Srgrimes/*
8391541Srgrimes * Initialize an interface's internet address
8401541Srgrimes * and routing table entry.
8411541Srgrimes */
84212296Sphkstatic int
843169454Srwatsonin_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
844169454Srwatson    int scrub)
8451541Srgrimes{
8461541Srgrimes	register u_long i = ntohl(sin->sin_addr.s_addr);
8471541Srgrimes	struct sockaddr_in oldaddr;
84894326Sbrian	int s = splimp(), flags = RTF_UP, error = 0;
8491541Srgrimes
8501541Srgrimes	oldaddr = ia->ia_addr;
851105748Ssuz	if (oldaddr.sin_family == AF_INET)
852105748Ssuz		LIST_REMOVE(ia, ia_hash);
8531541Srgrimes	ia->ia_addr = *sin;
854194951Srwatson	if (ia->ia_addr.sin_family == AF_INET) {
855194951Srwatson		IN_IFADDR_WLOCK();
856105748Ssuz		LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
857105748Ssuz		    ia, ia_hash);
858194951Srwatson		IN_IFADDR_WUNLOCK();
859194951Srwatson	}
8601541Srgrimes	/*
8611541Srgrimes	 * Give the interface a chance to initialize
8621541Srgrimes	 * if this is its first address,
8631541Srgrimes	 * and to validate the address if necessary.
8641541Srgrimes	 */
865184295Sbz	if (ifp->if_ioctl != NULL) {
866146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
867146883Siedowse		if (error) {
868146883Siedowse			splx(s);
869146883Siedowse			/* LIST_REMOVE(ia, ia_hash) is done in in_control */
870146883Siedowse			ia->ia_addr = oldaddr;
871194951Srwatson			IN_IFADDR_WLOCK();
872146883Siedowse			if (ia->ia_addr.sin_family == AF_INET)
873146883Siedowse				LIST_INSERT_HEAD(INADDR_HASH(
874146883Siedowse				    ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
875179971Sgonzo			else
876179971Sgonzo				/*
877179971Sgonzo				 * If oldaddr family is not AF_INET (e.g.
878179971Sgonzo				 * interface has been just created) in_control
879179971Sgonzo				 * does not call LIST_REMOVE, and we end up
880179971Sgonzo				 * with bogus ia entries in hash
881179971Sgonzo				 */
882179971Sgonzo				LIST_REMOVE(ia, ia_hash);
883194951Srwatson			IN_IFADDR_WUNLOCK();
884146883Siedowse			return (error);
885146883Siedowse		}
8861541Srgrimes	}
8871541Srgrimes	splx(s);
8881541Srgrimes	if (scrub) {
8891541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
890222143Sqingli		in_ifscrub(ifp, ia, LLE_STATIC);
8911541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
8921541Srgrimes	}
8931541Srgrimes	if (IN_CLASSA(i))
8941541Srgrimes		ia->ia_netmask = IN_CLASSA_NET;
8951541Srgrimes	else if (IN_CLASSB(i))
8961541Srgrimes		ia->ia_netmask = IN_CLASSB_NET;
8971541Srgrimes	else
8981541Srgrimes		ia->ia_netmask = IN_CLASSC_NET;
8991541Srgrimes	/*
9001541Srgrimes	 * The subnet mask usually includes at least the standard network part,
9011541Srgrimes	 * but may may be smaller in the case of supernetting.
9021541Srgrimes	 * If it is set, we believe it.
9031541Srgrimes	 */
9041541Srgrimes	if (ia->ia_subnetmask == 0) {
9051541Srgrimes		ia->ia_subnetmask = ia->ia_netmask;
9061541Srgrimes		ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
9071541Srgrimes	} else
9081541Srgrimes		ia->ia_netmask &= ia->ia_subnetmask;
9091541Srgrimes	ia->ia_net = i & ia->ia_netmask;
9101541Srgrimes	ia->ia_subnet = i & ia->ia_subnetmask;
9111541Srgrimes	in_socktrim(&ia->ia_sockmask);
9121541Srgrimes	/*
913143868Sglebius	 * XXX: carp(4) does not have interface route
914143868Sglebius	 */
915143868Sglebius	if (ifp->if_type == IFT_CARP)
916143868Sglebius		return (0);
917143868Sglebius	/*
9181541Srgrimes	 * Add route for the network.
9191541Srgrimes	 */
9201541Srgrimes	ia->ia_ifa.ifa_metric = ifp->if_metric;
9211541Srgrimes	if (ifp->if_flags & IFF_BROADCAST) {
9221541Srgrimes		ia->ia_broadaddr.sin_addr.s_addr =
9231541Srgrimes			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
9241541Srgrimes		ia->ia_netbroadcast.s_addr =
9251541Srgrimes			htonl(ia->ia_net | ~ ia->ia_netmask);
9261541Srgrimes	} else if (ifp->if_flags & IFF_LOOPBACK) {
927137833Smlaier		ia->ia_dstaddr = ia->ia_addr;
9281541Srgrimes		flags |= RTF_HOST;
9291541Srgrimes	} else if (ifp->if_flags & IFF_POINTOPOINT) {
9301541Srgrimes		if (ia->ia_dstaddr.sin_family != AF_INET)
9311541Srgrimes			return (0);
9321541Srgrimes		flags |= RTF_HOST;
9331541Srgrimes	}
934137628Smlaier	if ((error = in_addprefix(ia, flags)) != 0)
935137628Smlaier		return (error);
93694326Sbrian
937192085Sqingli	if (ia->ia_addr.sin_addr.s_addr == INADDR_ANY)
938192085Sqingli		return (0);
939192085Sqingli
940203401Sqingli	if (ifp->if_flags & IFF_POINTOPOINT) {
941203401Sqingli		if (ia->ia_dstaddr.sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
942203401Sqingli			return (0);
943203401Sqingli	}
944203401Sqingli
945203401Sqingli
946192011Sqingli	/*
947192011Sqingli	 * add a loopback route to self
948192011Sqingli	 */
949201282Sqingli	if (V_useloopback && !(ifp->if_flags & IFF_LOOPBACK)) {
950201282Sqingli		struct route ia_ro;
951201282Sqingli
952201282Sqingli		bzero(&ia_ro, sizeof(ia_ro));
953201282Sqingli		*((struct sockaddr_in *)(&ia_ro.ro_dst)) = ia->ia_addr;
954201282Sqingli		rtalloc_ign_fib(&ia_ro, 0, 0);
955201282Sqingli		if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
956201282Sqingli		    (ia_ro.ro_rt->rt_ifp == V_loif)) {
957201282Sqingli			RT_LOCK(ia_ro.ro_rt);
958201282Sqingli			RT_ADDREF(ia_ro.ro_rt);
959201282Sqingli			RTFREE_LOCKED(ia_ro.ro_rt);
960201282Sqingli		} else
961201282Sqingli			error = ifa_add_loopback_route((struct ifaddr *)ia,
962197227Sqingli				       (struct sockaddr *)&ia->ia_addr);
963201282Sqingli		if (error == 0)
964201282Sqingli			ia->ia_flags |= IFA_RTSELF;
965201282Sqingli		if (ia_ro.ro_rt != NULL)
966201282Sqingli			RTFREE(ia_ro.ro_rt);
967201282Sqingli	}
968192011Sqingli
9691541Srgrimes	return (error);
9701541Srgrimes}
9711541Srgrimes
972137628Smlaier#define rtinitflags(x) \
973137628Smlaier	((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
974137628Smlaier	    ? RTF_HOST : 0)
975201285Sqingli
976137628Smlaier/*
977201285Sqingli * Generate a routing message when inserting or deleting
978201285Sqingli * an interface address alias.
979201285Sqingli */
980201285Sqinglistatic void in_addralias_rtmsg(int cmd, struct in_addr *prefix,
981201285Sqingli    struct in_ifaddr *target)
982201285Sqingli{
983201285Sqingli	struct route pfx_ro;
984201285Sqingli	struct sockaddr_in *pfx_addr;
985201285Sqingli	struct rtentry msg_rt;
986201285Sqingli
987201285Sqingli	/* QL: XXX
988201285Sqingli	 * This is a bit questionable because there is no
989201285Sqingli	 * additional route entry added/deleted for an address
990201285Sqingli	 * alias. Therefore this route report is inaccurate.
991201285Sqingli	 */
992201285Sqingli	bzero(&pfx_ro, sizeof(pfx_ro));
993201285Sqingli	pfx_addr = (struct sockaddr_in *)(&pfx_ro.ro_dst);
994201285Sqingli	pfx_addr->sin_len = sizeof(*pfx_addr);
995201285Sqingli	pfx_addr->sin_family = AF_INET;
996201285Sqingli	pfx_addr->sin_addr = *prefix;
997201285Sqingli	rtalloc_ign_fib(&pfx_ro, 0, 0);
998201285Sqingli	if (pfx_ro.ro_rt != NULL) {
999201285Sqingli		msg_rt = *pfx_ro.ro_rt;
1000201285Sqingli
1001201285Sqingli		/* QL: XXX
1002201285Sqingli		 * Point the gateway to the new interface
1003201285Sqingli		 * address as if a new prefix route entry has
1004201285Sqingli		 * been added through the new address alias.
1005201285Sqingli		 * All other parts of the rtentry is accurate,
1006201285Sqingli		 * e.g., rt_key, rt_mask, rt_ifp etc.
1007201285Sqingli		 */
1008201285Sqingli		msg_rt.rt_gateway =
1009201285Sqingli			(struct sockaddr *)&target->ia_addr;
1010201285Sqingli		rt_newaddrmsg(cmd,
1011201285Sqingli			      (struct ifaddr *)target,
1012201285Sqingli			      0, &msg_rt);
1013201285Sqingli		RTFREE(pfx_ro.ro_rt);
1014201285Sqingli	}
1015201285Sqingli	return;
1016201285Sqingli}
1017201285Sqingli
1018201285Sqingli/*
1019170855Smjacob * Check if we have a route for the given prefix already or add one accordingly.
1020137628Smlaier */
1021137628Smlaierstatic int
1022169454Srwatsonin_addprefix(struct in_ifaddr *target, int flags)
1023137628Smlaier{
1024137628Smlaier	struct in_ifaddr *ia;
1025151555Sglebius	struct in_addr prefix, mask, p, m;
1026137628Smlaier	int error;
10271541Srgrimes
1028170855Smjacob	if ((flags & RTF_HOST) != 0) {
1029137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
1030170855Smjacob		mask.s_addr = 0;
1031170855Smjacob	} else {
1032137628Smlaier		prefix = target->ia_addr.sin_addr;
1033137628Smlaier		mask = target->ia_sockmask.sin_addr;
1034137628Smlaier		prefix.s_addr &= mask.s_addr;
1035137628Smlaier	}
1036137628Smlaier
1037194951Srwatson	IN_IFADDR_RLOCK();
1038181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
1039151555Sglebius		if (rtinitflags(ia)) {
1040137628Smlaier			p = ia->ia_addr.sin_addr;
1041151555Sglebius
1042151555Sglebius			if (prefix.s_addr != p.s_addr)
1043151555Sglebius				continue;
1044151555Sglebius		} else {
1045151555Sglebius			p = ia->ia_addr.sin_addr;
1046151555Sglebius			m = ia->ia_sockmask.sin_addr;
1047151555Sglebius			p.s_addr &= m.s_addr;
1048151555Sglebius
1049151555Sglebius			if (prefix.s_addr != p.s_addr ||
1050151555Sglebius			    mask.s_addr != m.s_addr)
1051151555Sglebius				continue;
1052137628Smlaier		}
1053137628Smlaier
1054137628Smlaier		/*
1055137628Smlaier		 * If we got a matching prefix route inserted by other
1056137628Smlaier		 * interface address, we are done here.
1057137628Smlaier		 */
1058149221Sglebius		if (ia->ia_flags & IFA_ROUTE) {
1059204902Sqingli#ifdef RADIX_MPATH
1060204902Sqingli			if (ia->ia_addr.sin_addr.s_addr ==
1061212209Sbz			    target->ia_addr.sin_addr.s_addr) {
1062212209Sbz				IN_IFADDR_RUNLOCK();
1063204902Sqingli				return (EEXIST);
1064212209Sbz			} else
1065204902Sqingli				break;
1066204902Sqingli#endif
1067181803Sbz			if (V_sameprefixcarponly &&
1068149221Sglebius			    target->ia_ifp->if_type != IFT_CARP &&
1069194951Srwatson			    ia->ia_ifp->if_type != IFT_CARP) {
1070194951Srwatson				IN_IFADDR_RUNLOCK();
1071149221Sglebius				return (EEXIST);
1072194951Srwatson			} else {
1073201285Sqingli				in_addralias_rtmsg(RTM_ADD, &prefix, target);
1074194951Srwatson				IN_IFADDR_RUNLOCK();
1075149221Sglebius				return (0);
1076194951Srwatson			}
1077149221Sglebius		}
1078137628Smlaier	}
1079194951Srwatson	IN_IFADDR_RUNLOCK();
1080137628Smlaier
1081137628Smlaier	/*
1082137628Smlaier	 * No-one seem to have this prefix route, so we try to insert it.
1083137628Smlaier	 */
1084137628Smlaier	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
1085137628Smlaier	if (!error)
1086137628Smlaier		target->ia_flags |= IFA_ROUTE;
1087184295Sbz	return (error);
1088137628Smlaier}
1089137628Smlaier
1090186119Sqingliextern void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
1091186119Sqingli
10921541Srgrimes/*
1093137628Smlaier * If there is no other address in the system that can serve a route to the
1094137628Smlaier * same prefix, remove the route.  Hand over the route to the new address
1095137628Smlaier * otherwise.
1096137628Smlaier */
1097137628Smlaierstatic int
1098222143Sqingliin_scrubprefix(struct in_ifaddr *target, u_int flags)
1099137628Smlaier{
1100137628Smlaier	struct in_ifaddr *ia;
1101137628Smlaier	struct in_addr prefix, mask, p;
1102201282Sqingli	int error = 0;
1103192476Sqingli	struct sockaddr_in prefix0, mask0;
1104137628Smlaier
1105195914Sqingli	/*
1106195914Sqingli	 * Remove the loopback route to the interface address.
1107195914Sqingli	 * The "useloopback" setting is not consulted because if the
1108195914Sqingli	 * user configures an interface address, turns off this
1109195914Sqingli	 * setting, and then tries to delete that interface address,
1110195914Sqingli	 * checking the current setting of "useloopback" would leave
1111195914Sqingli	 * that interface address loopback route untouched, which
1112195914Sqingli	 * would be wrong. Therefore the interface address loopback route
1113195914Sqingli	 * deletion is unconditional.
1114195914Sqingli	 */
1115192085Sqingli	if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) &&
1116201282Sqingli	    !(target->ia_ifp->if_flags & IFF_LOOPBACK) &&
1117201282Sqingli	    (target->ia_flags & IFA_RTSELF)) {
1118201282Sqingli		struct route ia_ro;
1119201282Sqingli		int freeit = 0;
1120201282Sqingli
1121201282Sqingli		bzero(&ia_ro, sizeof(ia_ro));
1122201282Sqingli		*((struct sockaddr_in *)(&ia_ro.ro_dst)) = target->ia_addr;
1123201282Sqingli		rtalloc_ign_fib(&ia_ro, 0, 0);
1124201282Sqingli		if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
1125201282Sqingli		    (ia_ro.ro_rt->rt_ifp == V_loif)) {
1126201282Sqingli			RT_LOCK(ia_ro.ro_rt);
1127201282Sqingli			if (ia_ro.ro_rt->rt_refcnt <= 1)
1128201282Sqingli				freeit = 1;
1129201282Sqingli			else
1130201282Sqingli				RT_REMREF(ia_ro.ro_rt);
1131201282Sqingli			RTFREE_LOCKED(ia_ro.ro_rt);
1132201282Sqingli		}
1133222143Sqingli		if (freeit && (flags & LLE_STATIC)) {
1134201282Sqingli			error = ifa_del_loopback_route((struct ifaddr *)target,
1135197227Sqingli				       (struct sockaddr *)&target->ia_addr);
1136222143Sqingli			if (error == 0)
1137222143Sqingli				target->ia_flags &= ~IFA_RTSELF;
1138222143Sqingli		}
1139222143Sqingli		if (flags & LLE_STATIC)
1140222143Sqingli			/* remove arp cache */
1141222143Sqingli			arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
1142192011Sqingli	}
1143192011Sqingli
1144137628Smlaier	if (rtinitflags(target))
1145137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
1146137628Smlaier	else {
1147137628Smlaier		prefix = target->ia_addr.sin_addr;
1148137628Smlaier		mask = target->ia_sockmask.sin_addr;
1149137628Smlaier		prefix.s_addr &= mask.s_addr;
1150137628Smlaier	}
1151137628Smlaier
1152201285Sqingli	if ((target->ia_flags & IFA_ROUTE) == 0) {
1153201285Sqingli		in_addralias_rtmsg(RTM_DELETE, &prefix, target);
1154201285Sqingli		return (0);
1155201285Sqingli	}
1156201285Sqingli
1157194951Srwatson	IN_IFADDR_RLOCK();
1158181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
1159137628Smlaier		if (rtinitflags(ia))
1160137628Smlaier			p = ia->ia_dstaddr.sin_addr;
1161137628Smlaier		else {
1162137628Smlaier			p = ia->ia_addr.sin_addr;
1163137628Smlaier			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
1164137628Smlaier		}
1165137628Smlaier
1166137628Smlaier		if (prefix.s_addr != p.s_addr)
1167137628Smlaier			continue;
1168137628Smlaier
1169137628Smlaier		/*
1170137628Smlaier		 * If we got a matching prefix address, move IFA_ROUTE and
1171137628Smlaier		 * the route itself to it.  Make sure that routing daemons
1172137628Smlaier		 * get a heads-up.
1173143868Sglebius		 *
1174211157Swill		 * XXX: a special case for carp(4) interface - this should
1175211157Swill		 *      be more generally specified as an interface that
1176211157Swill		 *      doesn't support such action.
1177137628Smlaier		 */
1178143868Sglebius		if ((ia->ia_flags & IFA_ROUTE) == 0
1179219828Spluknet		    && (ia->ia_ifp->if_type != IFT_CARP)) {
1180219828Spluknet			ifa_ref(&ia->ia_ifa);
1181194951Srwatson			IN_IFADDR_RUNLOCK();
1182222438Sqingli			error = rtinit(&(target->ia_ifa), (int)RTM_DELETE,
1183137628Smlaier			    rtinitflags(target));
1184222438Sqingli			if (error == 0)
1185222438Sqingli				target->ia_flags &= ~IFA_ROUTE;
1186222438Sqingli			else
1187222438Sqingli				log(LOG_INFO, "in_scrubprefix: err=%d, old prefix delete failed\n",
1188222438Sqingli					error);
1189137628Smlaier			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
1190137628Smlaier			    rtinitflags(ia) | RTF_UP);
1191137628Smlaier			if (error == 0)
1192137628Smlaier				ia->ia_flags |= IFA_ROUTE;
1193222438Sqingli			else
1194222438Sqingli				log(LOG_INFO, "in_scrubprefix: err=%d, new prefix add failed\n",
1195222438Sqingli					error);
1196219828Spluknet			ifa_free(&ia->ia_ifa);
1197184295Sbz			return (error);
1198137628Smlaier		}
1199137628Smlaier	}
1200194951Srwatson	IN_IFADDR_RUNLOCK();
1201137628Smlaier
1202137628Smlaier	/*
1203192476Sqingli	 * remove all L2 entries on the given prefix
1204192476Sqingli	 */
1205192476Sqingli	bzero(&prefix0, sizeof(prefix0));
1206192476Sqingli	prefix0.sin_len = sizeof(prefix0);
1207192476Sqingli	prefix0.sin_family = AF_INET;
1208192476Sqingli	prefix0.sin_addr.s_addr = target->ia_subnet;
1209192476Sqingli	bzero(&mask0, sizeof(mask0));
1210192476Sqingli	mask0.sin_len = sizeof(mask0);
1211192476Sqingli	mask0.sin_family = AF_INET;
1212192476Sqingli	mask0.sin_addr.s_addr = target->ia_subnetmask;
1213192476Sqingli	lltable_prefix_free(AF_INET, (struct sockaddr *)&prefix0,
1214222143Sqingli			    (struct sockaddr *)&mask0, flags);
1215192476Sqingli
1216192476Sqingli	/*
1217137628Smlaier	 * As no-one seem to have this prefix, we can remove the route.
1218137628Smlaier	 */
1219222438Sqingli	error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
1220222438Sqingli	if (error == 0)
1221222438Sqingli		target->ia_flags &= ~IFA_ROUTE;
1222222438Sqingli	else
1223222438Sqingli		log(LOG_INFO, "in_scrubprefix: err=%d, prefix delete failed\n", error);
1224222438Sqingli	return (error);
1225137628Smlaier}
1226137628Smlaier
1227137628Smlaier#undef rtinitflags
1228137628Smlaier
1229137628Smlaier/*
12301541Srgrimes * Return 1 if the address might be a local broadcast address.
12311541Srgrimes */
12321549Srgrimesint
1233169454Srwatsonin_broadcast(struct in_addr in, struct ifnet *ifp)
12341541Srgrimes{
12351541Srgrimes	register struct ifaddr *ifa;
12361541Srgrimes	u_long t;
12371541Srgrimes
12381541Srgrimes	if (in.s_addr == INADDR_BROADCAST ||
12391541Srgrimes	    in.s_addr == INADDR_ANY)
1240184295Sbz		return (1);
12411541Srgrimes	if ((ifp->if_flags & IFF_BROADCAST) == 0)
1242184295Sbz		return (0);
12431541Srgrimes	t = ntohl(in.s_addr);
12441541Srgrimes	/*
12451541Srgrimes	 * Look through the list of addresses for a match
12461541Srgrimes	 * with a broadcast address.
12471541Srgrimes	 */
12481541Srgrimes#define ia ((struct in_ifaddr *)ifa)
124974362Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
12501541Srgrimes		if (ifa->ifa_addr->sa_family == AF_INET &&
12511541Srgrimes		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
12521541Srgrimes		     in.s_addr == ia->ia_netbroadcast.s_addr ||
12531541Srgrimes		     /*
12541541Srgrimes		      * Check for old-style (host 0) broadcast.
12551541Srgrimes		      */
125613351Sguido		     t == ia->ia_subnet || t == ia->ia_net) &&
125713351Sguido		     /*
125813351Sguido		      * Check for an all one subnetmask. These
125913351Sguido		      * only exist when an interface gets a secondary
126013351Sguido		      * address.
126113351Sguido		      */
126213351Sguido		     ia->ia_subnetmask != (u_long)0xffffffff)
1263184295Sbz			    return (1);
12641541Srgrimes	return (0);
12651541Srgrimes#undef ia
12661541Srgrimes}
1267167729Sbms
12681541Srgrimes/*
1269189592Sbms * On interface removal, clean up IPv4 data structures hung off of the ifnet.
1270189592Sbms */
1271189592Sbmsvoid
1272189592Sbmsin_ifdetach(struct ifnet *ifp)
1273189592Sbms{
1274189592Sbms
1275189592Sbms	in_pcbpurgeif0(&V_ripcbinfo, ifp);
1276189592Sbms	in_pcbpurgeif0(&V_udbinfo, ifp);
1277189592Sbms	in_purgemaddrs(ifp);
1278189592Sbms}
1279189592Sbms
1280189592Sbms/*
1281167729Sbms * Delete all IPv4 multicast address records, and associated link-layer
1282167729Sbms * multicast address records, associated with ifp.
1283189592Sbms * XXX It looks like domifdetach runs AFTER the link layer cleanup.
1284189931Sbms * XXX This should not race with ifma_protospec being set during
1285189931Sbms * a new allocation, if it does, we have bigger problems.
1286162718Sbms */
1287167729Sbmsstatic void
1288167729Sbmsin_purgemaddrs(struct ifnet *ifp)
1289162718Sbms{
1290189592Sbms	LIST_HEAD(,in_multi) purgeinms;
1291189592Sbms	struct in_multi		*inm, *tinm;
1292189592Sbms	struct ifmultiaddr	*ifma;
1293162718Sbms
1294189592Sbms	LIST_INIT(&purgeinms);
1295162718Sbms	IN_MULTI_LOCK();
1296189592Sbms
1297189592Sbms	/*
1298189592Sbms	 * Extract list of in_multi associated with the detaching ifp
1299189592Sbms	 * which the PF_INET layer is about to release.
1300189592Sbms	 * We need to do this as IF_ADDR_LOCK() may be re-acquired
1301189592Sbms	 * by code further down.
1302189592Sbms	 */
1303189592Sbms	IF_ADDR_LOCK(ifp);
1304189592Sbms	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1305189931Sbms		if (ifma->ifma_addr->sa_family != AF_INET ||
1306189931Sbms		    ifma->ifma_protospec == NULL)
1307189592Sbms			continue;
1308189931Sbms#if 0
1309189931Sbms		KASSERT(ifma->ifma_protospec != NULL,
1310189931Sbms		    ("%s: ifma_protospec is NULL", __func__));
1311189931Sbms#endif
1312189592Sbms		inm = (struct in_multi *)ifma->ifma_protospec;
1313189592Sbms		LIST_INSERT_HEAD(&purgeinms, inm, inm_link);
1314162718Sbms	}
1315189592Sbms	IF_ADDR_UNLOCK(ifp);
1316150296Srwatson
1317189592Sbms	LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) {
1318191476Srwatson		LIST_REMOVE(inm, inm_link);
1319189592Sbms		inm_release_locked(inm);
1320189592Sbms	}
1321189592Sbms	igmp_ifdetach(ifp);
1322150296Srwatson
1323189592Sbms	IN_MULTI_UNLOCK();
1324150296Srwatson}
1325186119Sqingli
1326186119Sqingli#include <net/if_dl.h>
1327186119Sqingli#include <netinet/if_ether.h>
1328186119Sqingli
1329186119Sqinglistruct in_llentry {
1330186119Sqingli	struct llentry		base;
1331186119Sqingli	struct sockaddr_in	l3_addr4;
1332186119Sqingli};
1333186119Sqingli
1334186119Sqinglistatic struct llentry *
1335186119Sqingliin_lltable_new(const struct sockaddr *l3addr, u_int flags)
1336186119Sqingli{
1337186119Sqingli	struct in_llentry *lle;
1338186119Sqingli
1339186119Sqingli	lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_DONTWAIT | M_ZERO);
1340186119Sqingli	if (lle == NULL)		/* NB: caller generates msg */
1341186119Sqingli		return NULL;
1342186119Sqingli
1343186119Sqingli	callout_init(&lle->base.la_timer, CALLOUT_MPSAFE);
1344186119Sqingli	/*
1345186119Sqingli	 * For IPv4 this will trigger "arpresolve" to generate
1346186119Sqingli	 * an ARP request.
1347186119Sqingli	 */
1348216075Sglebius	lle->base.la_expire = time_uptime; /* mark expired */
1349186119Sqingli	lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
1350186119Sqingli	lle->base.lle_refcnt = 1;
1351186119Sqingli	LLE_LOCK_INIT(&lle->base);
1352186119Sqingli	return &lle->base;
1353186119Sqingli}
1354186119Sqingli
1355186119Sqingli/*
1356186119Sqingli * Deletes an address from the address table.
1357186119Sqingli * This function is called by the timer functions
1358186119Sqingli * such as arptimer() and nd6_llinfo_timer(), and
1359186119Sqingli * the caller does the locking.
1360186119Sqingli */
1361186119Sqinglistatic void
1362186119Sqingliin_lltable_free(struct lltable *llt, struct llentry *lle)
1363186119Sqingli{
1364186150Skmacy	LLE_WUNLOCK(lle);
1365186150Skmacy	LLE_LOCK_DESTROY(lle);
1366186119Sqingli	free(lle, M_LLTABLE);
1367186119Sqingli}
1368186119Sqingli
1369192476Sqingli
1370192476Sqingli#define IN_ARE_MASKED_ADDR_EQUAL(d, a, m)	(			\
1371192476Sqingli	    (((ntohl((d)->sin_addr.s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 )
1372192476Sqingli
1373192476Sqinglistatic void
1374192476Sqingliin_lltable_prefix_free(struct lltable *llt,
1375192476Sqingli		       const struct sockaddr *prefix,
1376222143Sqingli		       const struct sockaddr *mask,
1377222143Sqingli		       u_int flags)
1378192476Sqingli{
1379192476Sqingli	const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix;
1380192476Sqingli	const struct sockaddr_in *msk = (const struct sockaddr_in *)mask;
1381192476Sqingli	struct llentry *lle, *next;
1382192476Sqingli	register int i;
1383215207Sgnn	size_t pkts_dropped;
1384192476Sqingli
1385192476Sqingli	for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
1386192476Sqingli		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
1387192476Sqingli
1388222143Sqingli		        /*
1389222143Sqingli			 * (flags & LLE_STATIC) means deleting all entries
1390222143Sqingli			 * including static ARP entries
1391222143Sqingli			 */
1392192476Sqingli			if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle),
1393222143Sqingli						     pfx, msk) &&
1394222143Sqingli			    ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC))) {
1395206481Sbz				int canceled;
1396206481Sbz
1397206481Sbz				canceled = callout_drain(&lle->la_timer);
1398192476Sqingli				LLE_WLOCK(lle);
1399206481Sbz				if (canceled)
1400206481Sbz					LLE_REMREF(lle);
1401215207Sgnn				pkts_dropped = llentry_free(lle);
1402215207Sgnn				ARPSTAT_ADD(dropped, pkts_dropped);
1403192476Sqingli			}
1404192476Sqingli		}
1405192476Sqingli	}
1406192476Sqingli}
1407192476Sqingli
1408192476Sqingli
1409186119Sqinglistatic int
1410201282Sqingliin_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
1411186119Sqingli{
1412186119Sqingli	struct rtentry *rt;
1413186119Sqingli
1414186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1415186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1416186119Sqingli
1417186119Sqingli	/* XXX rtalloc1 should take a const param */
1418186119Sqingli	rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
1419223862Szec
1420223862Szec	/*
1421223862Szec	 * If the gateway for an existing host route matches the target L3
1422223862Szec	 * address, allow for ARP to proceed.
1423223862Szec	 */
1424223862Szec	if (rt != NULL && (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) &&
1425223862Szec	    rt->rt_gateway->sa_family == AF_INET &&
1426223862Szec	    memcmp(rt->rt_gateway->sa_data, l3addr->sa_data, 4) == 0) {
1427223862Szec		RTFREE_LOCKED(rt);
1428223862Szec		return (0);
1429223862Szec	}
1430223862Szec
1431208553Sqingli	if (rt == NULL || (!(flags & LLE_PUB) &&
1432208553Sqingli			   ((rt->rt_flags & RTF_GATEWAY) ||
1433208553Sqingli			    (rt->rt_ifp != ifp)))) {
1434198418Sqingli#ifdef DIAGNOSTIC
1435186119Sqingli		log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
1436186119Sqingli		    inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
1437197696Sqingli#endif
1438186119Sqingli		if (rt != NULL)
1439186119Sqingli			RTFREE_LOCKED(rt);
1440186119Sqingli		return (EINVAL);
1441186119Sqingli	}
1442186119Sqingli	RTFREE_LOCKED(rt);
1443186119Sqingli	return 0;
1444186119Sqingli}
1445186119Sqingli
1446186119Sqingli/*
1447186119Sqingli * Return NULL if not found or marked for deletion.
1448186119Sqingli * If found return lle read locked.
1449186119Sqingli */
1450186119Sqinglistatic struct llentry *
1451186119Sqingliin_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
1452186119Sqingli{
1453186119Sqingli	const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
1454186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1455186119Sqingli	struct llentry *lle;
1456186119Sqingli	struct llentries *lleh;
1457186119Sqingli	u_int hashkey;
1458186119Sqingli
1459186119Sqingli	IF_AFDATA_LOCK_ASSERT(ifp);
1460186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1461186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1462186119Sqingli
1463186119Sqingli	hashkey = sin->sin_addr.s_addr;
1464186119Sqingli	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
1465186119Sqingli	LIST_FOREACH(lle, lleh, lle_next) {
1466186708Sqingli		struct sockaddr_in *sa2 = (struct sockaddr_in *)L3_ADDR(lle);
1467186119Sqingli		if (lle->la_flags & LLE_DELETED)
1468186119Sqingli			continue;
1469186708Sqingli		if (sa2->sin_addr.s_addr == sin->sin_addr.s_addr)
1470186119Sqingli			break;
1471186119Sqingli	}
1472186119Sqingli	if (lle == NULL) {
1473198418Sqingli#ifdef DIAGNOSTIC
1474186119Sqingli		if (flags & LLE_DELETE)
1475186119Sqingli			log(LOG_INFO, "interface address is missing from cache = %p  in delete\n", lle);
1476186119Sqingli#endif
1477186119Sqingli		if (!(flags & LLE_CREATE))
1478186119Sqingli			return (NULL);
1479186119Sqingli		/*
1480186119Sqingli		 * A route that covers the given address must have
1481186119Sqingli		 * been installed 1st because we are doing a resolution,
1482186119Sqingli		 * verify this.
1483186119Sqingli		 */
1484186119Sqingli		if (!(flags & LLE_IFADDR) &&
1485201282Sqingli		    in_lltable_rtcheck(ifp, flags, l3addr) != 0)
1486186119Sqingli			goto done;
1487186119Sqingli
1488186119Sqingli		lle = in_lltable_new(l3addr, flags);
1489186119Sqingli		if (lle == NULL) {
1490186119Sqingli			log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
1491186119Sqingli			goto done;
1492186119Sqingli		}
1493186119Sqingli		lle->la_flags = flags & ~LLE_CREATE;
1494186119Sqingli		if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
1495186119Sqingli			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
1496186119Sqingli			lle->la_flags |= (LLE_VALID | LLE_STATIC);
1497186119Sqingli		}
1498186119Sqingli
1499186119Sqingli		lle->lle_tbl  = llt;
1500186119Sqingli		lle->lle_head = lleh;
1501186119Sqingli		LIST_INSERT_HEAD(lleh, lle, lle_next);
1502186119Sqingli	} else if (flags & LLE_DELETE) {
1503186119Sqingli		if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
1504186119Sqingli			LLE_WLOCK(lle);
1505186119Sqingli			lle->la_flags = LLE_DELETED;
1506196995Snp			EVENTHANDLER_INVOKE(arp_update_event, lle);
1507186119Sqingli			LLE_WUNLOCK(lle);
1508198418Sqingli#ifdef DIAGNOSTIC
1509186119Sqingli			log(LOG_INFO, "ifaddr cache = %p  is deleted\n", lle);
1510186119Sqingli#endif
1511186119Sqingli		}
1512186119Sqingli		lle = (void *)-1;
1513186119Sqingli
1514186119Sqingli	}
1515186544Sbz	if (LLE_IS_VALID(lle)) {
1516186119Sqingli		if (flags & LLE_EXCLUSIVE)
1517186119Sqingli			LLE_WLOCK(lle);
1518186119Sqingli		else
1519186119Sqingli			LLE_RLOCK(lle);
1520186119Sqingli	}
1521186119Sqinglidone:
1522186119Sqingli	return (lle);
1523186119Sqingli}
1524186119Sqingli
1525186119Sqinglistatic int
1526186119Sqingliin_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
1527186119Sqingli{
1528186119Sqingli#define	SIN(lle)	((struct sockaddr_in *) L3_ADDR(lle))
1529186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1530186119Sqingli	struct llentry *lle;
1531186119Sqingli	/* XXX stack use */
1532186119Sqingli	struct {
1533186119Sqingli		struct rt_msghdr	rtm;
1534186119Sqingli		struct sockaddr_inarp	sin;
1535186119Sqingli		struct sockaddr_dl	sdl;
1536186119Sqingli	} arpc;
1537186119Sqingli	int error, i;
1538186119Sqingli
1539196535Srwatson	LLTABLE_LOCK_ASSERT();
1540186119Sqingli
1541186119Sqingli	error = 0;
1542186119Sqingli	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
1543186119Sqingli		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
1544186119Sqingli			struct sockaddr_dl *sdl;
1545186119Sqingli
1546186119Sqingli			/* skip deleted entries */
1547198111Sqingli			if ((lle->la_flags & LLE_DELETED) == LLE_DELETED)
1548186119Sqingli				continue;
1549186980Sbz			/* Skip if jailed and not a valid IP of the prison. */
1550188144Sjamie			if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
1551186980Sbz				continue;
1552186119Sqingli			/*
1553186119Sqingli			 * produce a msg made of:
1554186119Sqingli			 *  struct rt_msghdr;
1555186119Sqingli			 *  struct sockaddr_inarp; (IPv4)
1556186119Sqingli			 *  struct sockaddr_dl;
1557186119Sqingli			 */
1558186119Sqingli			bzero(&arpc, sizeof(arpc));
1559186119Sqingli			arpc.rtm.rtm_msglen = sizeof(arpc);
1560186935Sharti			arpc.rtm.rtm_version = RTM_VERSION;
1561186935Sharti			arpc.rtm.rtm_type = RTM_GET;
1562186935Sharti			arpc.rtm.rtm_flags = RTF_UP;
1563186935Sharti			arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
1564186119Sqingli			arpc.sin.sin_family = AF_INET;
1565186119Sqingli			arpc.sin.sin_len = sizeof(arpc.sin);
1566186119Sqingli			arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
1567186119Sqingli
1568186119Sqingli			/* publish */
1569186119Sqingli			if (lle->la_flags & LLE_PUB) {
1570186119Sqingli				arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
1571186119Sqingli				/* proxy only */
1572186119Sqingli				if (lle->la_flags & LLE_PROXY)
1573186119Sqingli					arpc.sin.sin_other = SIN_PROXY;
1574186119Sqingli			}
1575186119Sqingli
1576186119Sqingli			sdl = &arpc.sdl;
1577186119Sqingli			sdl->sdl_family = AF_LINK;
1578186119Sqingli			sdl->sdl_len = sizeof(*sdl);
1579186119Sqingli			sdl->sdl_index = ifp->if_index;
1580186119Sqingli			sdl->sdl_type = ifp->if_type;
1581198111Sqingli			if ((lle->la_flags & LLE_VALID) == LLE_VALID) {
1582198111Sqingli				sdl->sdl_alen = ifp->if_addrlen;
1583198111Sqingli				bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
1584198111Sqingli			} else {
1585198111Sqingli				sdl->sdl_alen = 0;
1586198111Sqingli				bzero(LLADDR(sdl), ifp->if_addrlen);
1587198111Sqingli			}
1588186119Sqingli
1589186119Sqingli			arpc.rtm.rtm_rmx.rmx_expire =
1590186119Sqingli			    lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
1591186500Sqingli			arpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
1592186119Sqingli			if (lle->la_flags & LLE_STATIC)
1593186119Sqingli				arpc.rtm.rtm_flags |= RTF_STATIC;
1594186119Sqingli			arpc.rtm.rtm_index = ifp->if_index;
1595186119Sqingli			error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
1596186119Sqingli			if (error)
1597186119Sqingli				break;
1598186119Sqingli		}
1599186119Sqingli	}
1600186119Sqingli	return error;
1601186119Sqingli#undef SIN
1602186119Sqingli}
1603186119Sqingli
1604186119Sqinglivoid *
1605186119Sqingliin_domifattach(struct ifnet *ifp)
1606189592Sbms{
1607189592Sbms	struct in_ifinfo *ii;
1608189592Sbms	struct lltable *llt;
1609189592Sbms
1610189592Sbms	ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO);
1611189592Sbms
1612189592Sbms	llt = lltable_init(ifp, AF_INET);
1613186119Sqingli	if (llt != NULL) {
1614186119Sqingli		llt->llt_free = in_lltable_free;
1615192476Sqingli		llt->llt_prefix_free = in_lltable_prefix_free;
1616186119Sqingli		llt->llt_lookup = in_lltable_lookup;
1617186119Sqingli		llt->llt_dump = in_lltable_dump;
1618186119Sqingli	}
1619189592Sbms	ii->ii_llt = llt;
1620189592Sbms
1621189592Sbms	ii->ii_igmp = igmp_domifattach(ifp);
1622189592Sbms
1623189592Sbms	return ii;
1624186119Sqingli}
1625186119Sqingli
1626186119Sqinglivoid
1627189592Sbmsin_domifdetach(struct ifnet *ifp, void *aux)
1628186119Sqingli{
1629189592Sbms	struct in_ifinfo *ii = (struct in_ifinfo *)aux;
1630186119Sqingli
1631189592Sbms	igmp_domifdetach(ifp);
1632189592Sbms	lltable_free(ii->ii_llt);
1633189592Sbms	free(ii, M_IFADDR);
1634186119Sqingli}
1635