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$");
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
59228571Sglebius#include <netinet/if_ether.h>
601541Srgrimes#include <netinet/in.h>
611541Srgrimes#include <netinet/in_var.h>
6281127Sume#include <netinet/in_pcb.h>
63170613Sbms#include <netinet/ip_var.h>
64228571Sglebius#include <netinet/ip_carp.h>
65189592Sbms#include <netinet/igmp_var.h>
66195699Srwatson#include <netinet/udp.h>
67195699Srwatson#include <netinet/udp_var.h>
681541Srgrimes
6992723Salfredstatic int in_mask2len(struct in_addr *);
7092723Salfredstatic void in_len2mask(struct in_addr *, int);
7192723Salfredstatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
7292723Salfred	struct ifnet *, struct thread *);
7355009Sshin
7492723Salfredstatic void	in_socktrim(struct sockaddr_in *);
75228571Sglebiusstatic int	in_ifinit(struct ifnet *, struct in_ifaddr *,
76230207Sglebius		    struct sockaddr_in *, int, int);
77167729Sbmsstatic void	in_purgemaddrs(struct ifnet *);
781541Srgrimes
79228571Sglebiusstatic VNET_DEFINE(int, nosameprefix);
80228571Sglebius#define	V_nosameprefix			VNET(nosameprefix)
81228571SglebiusSYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_RW,
82228571Sglebius	&VNET_NAME(nosameprefix), 0,
83149221Sglebius	"Refuse to create same prefixes on different interfaces");
8421666Swollman
85207369SbzVNET_DECLARE(struct inpcbinfo, ripcbinfo);
86207369Sbz#define	V_ripcbinfo			VNET(ripcbinfo)
87207369Sbz
881541Srgrimes/*
891541Srgrimes * Return 1 if an internet address is for a ``local'' host
90226401Sglebius * (one to which we have a connection).
911541Srgrimes */
921549Srgrimesint
93169454Srwatsonin_localaddr(struct in_addr in)
941541Srgrimes{
951541Srgrimes	register u_long i = ntohl(in.s_addr);
961541Srgrimes	register struct in_ifaddr *ia;
971541Srgrimes
98194951Srwatson	IN_IFADDR_RLOCK();
99226401Sglebius	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
100226401Sglebius		if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
101226401Sglebius			IN_IFADDR_RUNLOCK();
102226401Sglebius			return (1);
103194951Srwatson		}
1041541Srgrimes	}
105194951Srwatson	IN_IFADDR_RUNLOCK();
1061541Srgrimes	return (0);
1071541Srgrimes}
1081541Srgrimes
1091541Srgrimes/*
110133486Sandre * Return 1 if an internet address is for the local host and configured
111133486Sandre * on one of its interfaces.
112133486Sandre */
113133486Sandreint
114169454Srwatsonin_localip(struct in_addr in)
115133486Sandre{
116133486Sandre	struct in_ifaddr *ia;
117133486Sandre
118194951Srwatson	IN_IFADDR_RLOCK();
119133486Sandre	LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
120194951Srwatson		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) {
121194951Srwatson			IN_IFADDR_RUNLOCK();
122184295Sbz			return (1);
123194951Srwatson		}
124133486Sandre	}
125194951Srwatson	IN_IFADDR_RUNLOCK();
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{
2131541Srgrimes	register struct ifreq *ifr = (struct ifreq *)data;
214184295Sbz	register struct in_ifaddr *ia, *iap;
2151541Srgrimes	register struct ifaddr *ifa;
216168032Sbms	struct in_addr allhosts_addr;
21784102Sjlemon	struct in_addr dst;
218189592Sbms	struct in_ifinfo *ii;
2191541Srgrimes	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
220194951Srwatson	int error, hostIsNew, iaIsNew, maskIsNew;
221168032Sbms	int iaIsFirst;
222228768Sglebius	u_long ocmd = cmd;
2231541Srgrimes
224228768Sglebius	/*
225228768Sglebius	 * Pre-10.x compat: OSIOCAIFADDR passes a shorter
226228768Sglebius	 * struct in_aliasreq, without ifra_vhid.
227228768Sglebius	 */
228228768Sglebius	if (cmd == OSIOCAIFADDR)
229228768Sglebius		cmd = SIOCAIFADDR;
230228768Sglebius
231184295Sbz	ia = NULL;
232168032Sbms	iaIsFirst = 0;
23387124Sbrian	iaIsNew = 0;
234168032Sbms	allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
23587124Sbrian
236191443Srwatson	/*
237191443Srwatson	 * Filter out ioctls we implement directly; forward the rest on to
238191443Srwatson	 * in_lifaddr_ioctl() and ifp->if_ioctl().
239191443Srwatson	 */
24055009Sshin	switch (cmd) {
241191443Srwatson	case SIOCGIFADDR:
242191443Srwatson	case SIOCGIFBRDADDR:
243191443Srwatson	case SIOCGIFDSTADDR:
244191443Srwatson	case SIOCGIFNETMASK:
245227791Sglebius	case SIOCDIFADDR:
246227791Sglebius		break;
247227791Sglebius	case SIOCAIFADDR:
248227791Sglebius		/*
249227791Sglebius		 * ifra_addr must be present and be of INET family.
250227791Sglebius		 * ifra_broadaddr and ifra_mask are optional.
251227791Sglebius		 */
252227791Sglebius		if (ifra->ifra_addr.sin_len != sizeof(struct sockaddr_in) ||
253227791Sglebius		    ifra->ifra_addr.sin_family != AF_INET)
254227791Sglebius			return (EINVAL);
255227791Sglebius		if (ifra->ifra_broadaddr.sin_len != 0 &&
256227831Sglebius		    (ifra->ifra_broadaddr.sin_len !=
257227831Sglebius		    sizeof(struct sockaddr_in) ||
258227791Sglebius		    ifra->ifra_broadaddr.sin_family != AF_INET))
259227791Sglebius			return (EINVAL);
260228768Sglebius#if 0
261228768Sglebius		/*
262228768Sglebius		 * ifconfig(8) in pre-10.x doesn't set sin_family for the
263228768Sglebius		 * mask. The code is disabled for the 10.x timeline, to
264228768Sglebius		 * make SIOCAIFADDR compatible with 9.x ifconfig(8).
265228768Sglebius		 * The code should be enabled in 11.x
266228768Sglebius		 */
267227791Sglebius		if (ifra->ifra_mask.sin_len != 0 &&
268227791Sglebius		    (ifra->ifra_mask.sin_len != sizeof(struct sockaddr_in) ||
269227791Sglebius		    ifra->ifra_mask.sin_family != AF_INET))
270227791Sglebius			return (EINVAL);
271228768Sglebius#endif
272227791Sglebius		break;
273191443Srwatson	case SIOCSIFADDR:
274191443Srwatson	case SIOCSIFBRDADDR:
275191443Srwatson	case SIOCSIFDSTADDR:
276191443Srwatson	case SIOCSIFNETMASK:
277230207Sglebius		/* We no longer support that old commands. */
278230207Sglebius		return (EINVAL);
279191443Srwatson
28055009Sshin	case SIOCALIFADDR:
281164033Srwatson		if (td != NULL) {
282164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
283164033Srwatson			if (error)
284164033Srwatson				return (error);
285164033Srwatson		}
286184295Sbz		if (ifp == NULL)
287184295Sbz			return (EINVAL);
288164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
289164033Srwatson
29055009Sshin	case SIOCDLIFADDR:
291164033Srwatson		if (td != NULL) {
292164033Srwatson			error = priv_check(td, PRIV_NET_DELIFADDR);
293164033Srwatson			if (error)
294164033Srwatson				return (error);
295164033Srwatson		}
296184295Sbz		if (ifp == NULL)
297184295Sbz			return (EINVAL);
298164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
299164033Srwatson
30055009Sshin	case SIOCGLIFADDR:
301184295Sbz		if (ifp == NULL)
302184295Sbz			return (EINVAL);
30383366Sjulian		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
304191443Srwatson
305191443Srwatson	default:
306191443Srwatson		if (ifp == NULL || ifp->if_ioctl == NULL)
307191443Srwatson			return (EOPNOTSUPP);
308191443Srwatson		return ((*ifp->if_ioctl)(ifp, cmd, data));
30955009Sshin	}
31055009Sshin
311191443Srwatson	if (ifp == NULL)
312191443Srwatson		return (EADDRNOTAVAIL);
313191443Srwatson
3141541Srgrimes	/*
315191456Srwatson	 * Security checks before we get involved in any work.
316191456Srwatson	 */
317191456Srwatson	switch (cmd) {
318191456Srwatson	case SIOCAIFADDR:
319191456Srwatson		if (td != NULL) {
320191456Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
321191456Srwatson			if (error)
322191456Srwatson				return (error);
323191456Srwatson		}
324191456Srwatson		break;
325191456Srwatson
326191456Srwatson	case SIOCDIFADDR:
327191456Srwatson		if (td != NULL) {
328191456Srwatson			error = priv_check(td, PRIV_NET_DELIFADDR);
329191456Srwatson			if (error)
330191456Srwatson				return (error);
331191456Srwatson		}
332191456Srwatson		break;
333191456Srwatson	}
334191456Srwatson
335191456Srwatson	/*
3361541Srgrimes	 * Find address for this interface, if it exists.
33714632Sfenner	 *
338191443Srwatson	 * If an alias address was specified, find that one instead of the
339191443Srwatson	 * first one on the interface, if possible.
3401541Srgrimes	 */
341191443Srwatson	dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
342194951Srwatson	IN_IFADDR_RLOCK();
343191443Srwatson	LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) {
344191443Srwatson		if (iap->ia_ifp == ifp &&
345191443Srwatson		    iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
346191443Srwatson			if (td == NULL || prison_check_ip4(td->td_ucred,
347191443Srwatson			    &dst) == 0)
348191443Srwatson				ia = iap;
349191443Srwatson			break;
350191443Srwatson		}
351191443Srwatson	}
352194760Srwatson	if (ia != NULL)
353194760Srwatson		ifa_ref(&ia->ia_ifa);
354194951Srwatson	IN_IFADDR_RUNLOCK();
355191443Srwatson	if (ia == NULL) {
356229621Sjhb		IF_ADDR_RLOCK(ifp);
357191443Srwatson		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
358191443Srwatson			iap = ifatoia(ifa);
359191443Srwatson			if (iap->ia_addr.sin_family == AF_INET) {
360191443Srwatson				if (td != NULL &&
361191443Srwatson				    prison_check_ip4(td->td_ucred,
362191443Srwatson				    &iap->ia_addr.sin_addr) != 0)
363191443Srwatson					continue;
364191443Srwatson				ia = iap;
36584102Sjlemon				break;
36684102Sjlemon			}
367191443Srwatson		}
368194760Srwatson		if (ia != NULL)
369194760Srwatson			ifa_ref(&ia->ia_ifa);
370229621Sjhb		IF_ADDR_RUNLOCK(ifp);
37184102Sjlemon	}
372191443Srwatson	if (ia == NULL)
373191443Srwatson		iaIsFirst = 1;
3741541Srgrimes
375191500Srwatson	error = 0;
3761541Srgrimes	switch (cmd) {
3771541Srgrimes	case SIOCAIFADDR:
3781541Srgrimes	case SIOCDIFADDR:
379227958Sglebius		if (ifra->ifra_addr.sin_family == AF_INET) {
380194760Srwatson			struct in_ifaddr *oia;
381194760Srwatson
382194951Srwatson			IN_IFADDR_RLOCK();
38371999Sphk			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
3848071Swollman				if (ia->ia_ifp == ifp  &&
3858071Swollman				    ia->ia_addr.sin_addr.s_addr ==
3868071Swollman				    ifra->ifra_addr.sin_addr.s_addr)
3878071Swollman					break;
3888071Swollman			}
389194760Srwatson			if (ia != NULL && ia != oia)
390194760Srwatson				ifa_ref(&ia->ia_ifa);
391194760Srwatson			if (oia != NULL && ia != oia)
392194760Srwatson				ifa_free(&oia->ia_ifa);
393194951Srwatson			IN_IFADDR_RUNLOCK();
3948876Srgrimes			if ((ifp->if_flags & IFF_POINTOPOINT)
3958071Swollman			    && (cmd == SIOCAIFADDR)
3968071Swollman			    && (ifra->ifra_dstaddr.sin_addr.s_addr
3978071Swollman				== INADDR_ANY)) {
398191500Srwatson				error = EDESTADDRREQ;
399194760Srwatson				goto out;
4008071Swollman			}
4011541Srgrimes		}
402191500Srwatson		if (cmd == SIOCDIFADDR && ia == NULL) {
403191500Srwatson			error = EADDRNOTAVAIL;
404194760Srwatson			goto out;
405191500Srwatson		}
406184295Sbz		if (ia == NULL) {
40720407Swollman			ia = (struct in_ifaddr *)
408191500Srwatson				malloc(sizeof *ia, M_IFADDR, M_NOWAIT |
409191500Srwatson				    M_ZERO);
410191500Srwatson			if (ia == NULL) {
411191500Srwatson				error = ENOBUFS;
412194760Srwatson				goto out;
413191500Srwatson			}
414191500Srwatson
41520407Swollman			ifa = &ia->ia_ifa;
416194602Srwatson			ifa_init(ifa);
41720407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
41820407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
41920407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
420108033Shsu
4211541Srgrimes			ia->ia_sockmask.sin_len = 8;
42285740Sdes			ia->ia_sockmask.sin_family = AF_INET;
4231541Srgrimes			if (ifp->if_flags & IFF_BROADCAST) {
4241541Srgrimes				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
4251541Srgrimes				ia->ia_broadaddr.sin_family = AF_INET;
4261541Srgrimes			}
4271541Srgrimes			ia->ia_ifp = ifp;
428151824Sglebius
429194760Srwatson			ifa_ref(ifa);			/* if_addrhead */
430229621Sjhb			IF_ADDR_WLOCK(ifp);
431191285Srwatson			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
432229621Sjhb			IF_ADDR_WUNLOCK(ifp);
433194760Srwatson			ifa_ref(ifa);			/* in_ifaddrhead */
434194951Srwatson			IN_IFADDR_WLOCK();
435181803Sbz			TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
436194951Srwatson			IN_IFADDR_WUNLOCK();
43787124Sbrian			iaIsNew = 1;
4381541Srgrimes		}
4391541Srgrimes		break;
4401541Srgrimes
4411541Srgrimes	case SIOCGIFADDR:
4421541Srgrimes	case SIOCGIFNETMASK:
4431541Srgrimes	case SIOCGIFDSTADDR:
4441541Srgrimes	case SIOCGIFBRDADDR:
445191500Srwatson		if (ia == NULL) {
446191500Srwatson			error = EADDRNOTAVAIL;
447194760Srwatson			goto out;
448191500Srwatson		}
4491541Srgrimes		break;
4501541Srgrimes	}
451191500Srwatson
452191500Srwatson	/*
453194760Srwatson	 * Most paths in this switch return directly or via out.  Only paths
454194760Srwatson	 * that remove the address break in order to hit common removal code.
455191500Srwatson	 */
4561541Srgrimes	switch (cmd) {
4571541Srgrimes	case SIOCGIFADDR:
4581541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
459194760Srwatson		goto out;
4601541Srgrimes
4611541Srgrimes	case SIOCGIFBRDADDR:
462191500Srwatson		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
463191500Srwatson			error = EINVAL;
464194760Srwatson			goto out;
465191500Srwatson		}
4661541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
467194760Srwatson		goto out;
4681541Srgrimes
4691541Srgrimes	case SIOCGIFDSTADDR:
470191500Srwatson		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
471191500Srwatson			error = EINVAL;
472194760Srwatson			goto out;
473191500Srwatson		}
4741541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
475194760Srwatson		goto out;
4761541Srgrimes
4771541Srgrimes	case SIOCGIFNETMASK:
4781541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
479194760Srwatson		goto out;
4801541Srgrimes
4811541Srgrimes	case SIOCAIFADDR:
4821541Srgrimes		maskIsNew = 0;
4831541Srgrimes		hostIsNew = 1;
4841541Srgrimes		error = 0;
485227959Sglebius		if (ifra->ifra_addr.sin_addr.s_addr ==
486227791Sglebius			    ia->ia_addr.sin_addr.s_addr)
487227791Sglebius			hostIsNew = 0;
4881541Srgrimes		if (ifra->ifra_mask.sin_len) {
489238945Sglebius			/*
490197210Sqingli			 * QL: XXX
491197210Sqingli			 * Need to scrub the prefix here in case
492197210Sqingli			 * the issued command is SIOCAIFADDR with
493197210Sqingli			 * the same address, but with a different
494197210Sqingli			 * prefix length. And if the prefix length
495238945Sglebius			 * is the same as before, then the call is
496197210Sqingli			 * un-necessarily executed here.
497197210Sqingli			 */
498222438Sqingli			in_ifscrub(ifp, ia, LLE_STATIC);
4991541Srgrimes			ia->ia_sockmask = ifra->ifra_mask;
50085740Sdes			ia->ia_sockmask.sin_family = AF_INET;
5011541Srgrimes			ia->ia_subnetmask =
502238945Sglebius			    ntohl(ia->ia_sockmask.sin_addr.s_addr);
5031541Srgrimes			maskIsNew = 1;
5041541Srgrimes		}
5051541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) &&
5061541Srgrimes		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
507222438Sqingli			in_ifscrub(ifp, ia, LLE_STATIC);
5081541Srgrimes			ia->ia_dstaddr = ifra->ifra_dstaddr;
5091541Srgrimes			maskIsNew  = 1; /* We lie; but the effect's the same */
5101541Srgrimes		}
511227801Sglebius		if (hostIsNew || maskIsNew)
512230207Sglebius			error = in_ifinit(ifp, ia, &ifra->ifra_addr, maskIsNew,
513230207Sglebius			    (ocmd == cmd ? ifra->ifra_vhid : 0));
51487124Sbrian		if (error != 0 && iaIsNew)
515201811Sqingli			break;
51687124Sbrian
5171541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) &&
518227791Sglebius		    ifra->ifra_broadaddr.sin_len)
5191541Srgrimes			ia->ia_broadaddr = ifra->ifra_broadaddr;
520168032Sbms		if (error == 0) {
521189603Sbms			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
522189592Sbms			if (iaIsFirst &&
523189592Sbms			    (ifp->if_flags & IFF_MULTICAST) != 0) {
524189592Sbms				error = in_joingroup(ifp, &allhosts_addr,
525189592Sbms				    NULL, &ii->ii_allhosts);
526189592Sbms			}
527126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
528168032Sbms		}
529194760Srwatson		goto out;
5301541Srgrimes
5311541Srgrimes	case SIOCDIFADDR:
53274299Sru		/*
53374299Sru		 * in_ifscrub kills the interface route.
53474299Sru		 */
535222143Sqingli		in_ifscrub(ifp, ia, LLE_STATIC);
536191500Srwatson
53715092Sdg		/*
53874299Sru		 * in_ifadown gets rid of all the rest of
53974299Sru		 * the routes.  This is not quite the right
54074299Sru		 * thing to do, but at least if we are running
54174299Sru		 * a routing process they will come back.
54274299Sru		 */
54376469Sru		in_ifadown(&ia->ia_ifa, 1);
544126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
54587124Sbrian		error = 0;
5461541Srgrimes		break;
5471541Srgrimes
5481541Srgrimes	default:
549191443Srwatson		panic("in_control: unsupported ioctl");
5501541Srgrimes	}
55187124Sbrian
552228571Sglebius	if (ia->ia_ifa.ifa_carp)
553228571Sglebius		(*carp_detach_p)(&ia->ia_ifa);
554228571Sglebius
555229621Sjhb	IF_ADDR_WLOCK(ifp);
556213932Sbz	/* Re-check that ia is still part of the list. */
557213932Sbz	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
558213932Sbz		if (ifa == &ia->ia_ifa)
559213932Sbz			break;
560213932Sbz	}
561213932Sbz	if (ifa == NULL) {
562213932Sbz		/*
563213932Sbz		 * If we lost the race with another thread, there is no need to
564213932Sbz		 * try it again for the next loop as there is no other exit
565213932Sbz		 * path between here and out.
566213932Sbz		 */
567229621Sjhb		IF_ADDR_WUNLOCK(ifp);
568213932Sbz		error = EADDRNOTAVAIL;
569213932Sbz		goto out;
570213932Sbz	}
571191285Srwatson	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
572229621Sjhb	IF_ADDR_WUNLOCK(ifp);
573239395Srrs	ifa_free(&ia->ia_ifa);		      /* if_addrhead */
574194951Srwatson
575194951Srwatson	IN_IFADDR_WLOCK();
576181803Sbz	TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
577194760Srwatson
578227791Sglebius	LIST_REMOVE(ia, ia_hash);
579227791Sglebius	IN_IFADDR_WUNLOCK();
580227791Sglebius	/*
581227791Sglebius	 * If this is the last IPv4 address configured on this
582227791Sglebius	 * interface, leave the all-hosts group.
583227791Sglebius	 * No state-change report need be transmitted.
584227791Sglebius	 */
585227791Sglebius	IFP_TO_IA(ifp, iap);
586227791Sglebius	if (iap == NULL) {
587227791Sglebius		ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
588227791Sglebius		IN_MULTI_LOCK();
589227791Sglebius		if (ii->ii_allhosts) {
590227791Sglebius			(void)in_leavegroup_locked(ii->ii_allhosts, NULL);
591227791Sglebius			ii->ii_allhosts = NULL;
592227791Sglebius		}
593227791Sglebius		IN_MULTI_UNLOCK();
594194951Srwatson	} else
595227791Sglebius		ifa_free(&iap->ia_ifa);
596227791Sglebius
597194951Srwatson	ifa_free(&ia->ia_ifa);				/* in_ifaddrhead */
598194760Srwatsonout:
599194760Srwatson	if (ia != NULL)
600194760Srwatson		ifa_free(&ia->ia_ifa);
60187124Sbrian	return (error);
6021541Srgrimes}
6031541Srgrimes
6041541Srgrimes/*
60555009Sshin * SIOC[GAD]LIFADDR.
60655009Sshin *	SIOCGLIFADDR: get first address. (?!?)
60755009Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
60855009Sshin *		get first address that matches the specified prefix.
60955009Sshin *	SIOCALIFADDR: add the specified address.
61055009Sshin *	SIOCALIFADDR with IFLR_PREFIX:
61155009Sshin *		EINVAL since we can't deduce hostid part of the address.
61255009Sshin *	SIOCDLIFADDR: delete the specified address.
61355009Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
61455009Sshin *		delete the first address that matches the specified prefix.
61555009Sshin * return values:
61655009Sshin *	EINVAL on invalid parameters
61755009Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
61855009Sshin *	other values may be returned from in_ioctl()
61955009Sshin */
62055009Sshinstatic int
621169454Srwatsonin_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
622169454Srwatson    struct ifnet *ifp, struct thread *td)
62355009Sshin{
62455009Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
62555009Sshin	struct ifaddr *ifa;
62655009Sshin
62755009Sshin	/* sanity checks */
628184295Sbz	if (data == NULL || ifp == NULL) {
62955009Sshin		panic("invalid argument to in_lifaddr_ioctl");
63055009Sshin		/*NOTRECHED*/
63155009Sshin	}
63255009Sshin
63355009Sshin	switch (cmd) {
63455009Sshin	case SIOCGLIFADDR:
63555009Sshin		/* address must be specified on GET with IFLR_PREFIX */
63655009Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
63755009Sshin			break;
63855009Sshin		/*FALLTHROUGH*/
63955009Sshin	case SIOCALIFADDR:
64055009Sshin	case SIOCDLIFADDR:
64155009Sshin		/* address must be specified on ADD and DELETE */
64255917Sshin		if (iflr->addr.ss_family != AF_INET)
643184295Sbz			return (EINVAL);
64455917Sshin		if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
645184295Sbz			return (EINVAL);
64655009Sshin		/* XXX need improvement */
64755917Sshin		if (iflr->dstaddr.ss_family
64855917Sshin		 && iflr->dstaddr.ss_family != AF_INET)
649184295Sbz			return (EINVAL);
65055917Sshin		if (iflr->dstaddr.ss_family
65155917Sshin		 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
652184295Sbz			return (EINVAL);
65355009Sshin		break;
65455009Sshin	default: /*shouldn't happen*/
655184295Sbz		return (EOPNOTSUPP);
65655009Sshin	}
65755009Sshin	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
658184295Sbz		return (EINVAL);
65955009Sshin
66055009Sshin	switch (cmd) {
66155009Sshin	case SIOCALIFADDR:
66255009Sshin	    {
66355009Sshin		struct in_aliasreq ifra;
66455009Sshin
66555009Sshin		if (iflr->flags & IFLR_PREFIX)
666184295Sbz			return (EINVAL);
66755009Sshin
668229476Sjhb		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
66955009Sshin		bzero(&ifra, sizeof(ifra));
67055009Sshin		bcopy(iflr->iflr_name, ifra.ifra_name,
67155009Sshin			sizeof(ifra.ifra_name));
67255009Sshin
67355917Sshin		bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
67455009Sshin
67555917Sshin		if (iflr->dstaddr.ss_family) {	/*XXX*/
67655009Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
67755917Sshin				iflr->dstaddr.ss_len);
67855009Sshin		}
67955009Sshin
68055009Sshin		ifra.ifra_mask.sin_family = AF_INET;
68155009Sshin		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
68255009Sshin		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
68355009Sshin
684184295Sbz		return (in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td));
68555009Sshin	    }
68655009Sshin	case SIOCGLIFADDR:
68755009Sshin	case SIOCDLIFADDR:
68855009Sshin	    {
68955009Sshin		struct in_ifaddr *ia;
69055009Sshin		struct in_addr mask, candidate, match;
69155009Sshin		struct sockaddr_in *sin;
69255009Sshin
69355009Sshin		bzero(&mask, sizeof(mask));
694170855Smjacob		bzero(&match, sizeof(match));
69555009Sshin		if (iflr->flags & IFLR_PREFIX) {
69655009Sshin			/* lookup a prefix rather than address. */
69755009Sshin			in_len2mask(&mask, iflr->prefixlen);
69855009Sshin
69955009Sshin			sin = (struct sockaddr_in *)&iflr->addr;
70055009Sshin			match.s_addr = sin->sin_addr.s_addr;
70155009Sshin			match.s_addr &= mask.s_addr;
70255009Sshin
70355009Sshin			/* if you set extra bits, that's wrong */
70455009Sshin			if (match.s_addr != sin->sin_addr.s_addr)
705184295Sbz				return (EINVAL);
70655009Sshin
70755009Sshin		} else {
708170855Smjacob			/* on getting an address, take the 1st match */
709170855Smjacob			/* on deleting an address, do exact match */
710170855Smjacob			if (cmd != SIOCGLIFADDR) {
71155009Sshin				in_len2mask(&mask, 32);
71255009Sshin				sin = (struct sockaddr_in *)&iflr->addr;
71355009Sshin				match.s_addr = sin->sin_addr.s_addr;
71455009Sshin			}
71555009Sshin		}
71655009Sshin
717229621Sjhb		IF_ADDR_RLOCK(ifp);
71855009Sshin		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)	{
719229476Sjhb			if (ifa->ifa_addr->sa_family != AF_INET)
72055009Sshin				continue;
721170855Smjacob			if (match.s_addr == 0)
72255009Sshin				break;
723229478Sjhb			sin = (struct sockaddr_in *)&ifa->ifa_addr;
724229478Sjhb			candidate.s_addr = sin->sin_addr.s_addr;
72555009Sshin			candidate.s_addr &= mask.s_addr;
72655009Sshin			if (candidate.s_addr == match.s_addr)
72755009Sshin				break;
72855009Sshin		}
729229477Sjhb		if (ifa != NULL)
730229477Sjhb			ifa_ref(ifa);
731229621Sjhb		IF_ADDR_RUNLOCK(ifp);
732184295Sbz		if (ifa == NULL)
733184295Sbz			return (EADDRNOTAVAIL);
73455009Sshin		ia = (struct in_ifaddr *)ifa;
73555009Sshin
73655009Sshin		if (cmd == SIOCGLIFADDR) {
73755009Sshin			/* fill in the if_laddrreq structure */
73855009Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
73955009Sshin
74055009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
74155009Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
74255009Sshin					ia->ia_dstaddr.sin_len);
74355009Sshin			} else
74455009Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
74555009Sshin
74655009Sshin			iflr->prefixlen =
74755009Sshin				in_mask2len(&ia->ia_sockmask.sin_addr);
74855009Sshin
74955009Sshin			iflr->flags = 0;	/*XXX*/
750229477Sjhb			ifa_free(ifa);
75155009Sshin
752184295Sbz			return (0);
75355009Sshin		} else {
75455009Sshin			struct in_aliasreq ifra;
75555009Sshin
756229476Sjhb			/* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
75755009Sshin			bzero(&ifra, sizeof(ifra));
75855009Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
75955009Sshin				sizeof(ifra.ifra_name));
76055009Sshin
76155009Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
76255009Sshin				ia->ia_addr.sin_len);
76355009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
76455009Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
76555009Sshin					ia->ia_dstaddr.sin_len);
76655009Sshin			}
76755009Sshin			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
76855009Sshin				ia->ia_sockmask.sin_len);
769229477Sjhb			ifa_free(ifa);
77055009Sshin
771184295Sbz			return (in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
772184295Sbz			    ifp, td));
77355009Sshin		}
77455009Sshin	    }
77555009Sshin	}
77655009Sshin
777184295Sbz	return (EOPNOTSUPP);	/*just for safety*/
77855009Sshin}
77955009Sshin
78055009Sshin/*
7811541Srgrimes * Delete any existing route for an interface.
7821541Srgrimes */
78322672Swollmanvoid
784222143Sqingliin_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, u_int flags)
7851541Srgrimes{
786169454Srwatson
787222143Sqingli	in_scrubprefix(ia, flags);
7881541Srgrimes}
7891541Srgrimes
7901541Srgrimes/*
7911541Srgrimes * Initialize an interface's internet address
7921541Srgrimes * and routing table entry.
7931541Srgrimes */
79412296Sphkstatic int
795169454Srwatsonin_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
796230207Sglebius    int masksupplied, int vhid)
7971541Srgrimes{
7981541Srgrimes	register u_long i = ntohl(sin->sin_addr.s_addr);
799244665Sglebius	int flags, error = 0;
8001541Srgrimes
801227791Sglebius	IN_IFADDR_WLOCK();
802227791Sglebius	if (ia->ia_addr.sin_family == AF_INET)
803105748Ssuz		LIST_REMOVE(ia, ia_hash);
8041541Srgrimes	ia->ia_addr = *sin;
805227791Sglebius	LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
806227791Sglebius	    ia, ia_hash);
807227791Sglebius	IN_IFADDR_WUNLOCK();
808227791Sglebius
809228571Sglebius	if (vhid > 0) {
810228571Sglebius		if (carp_attach_p != NULL)
811228571Sglebius			error = (*carp_attach_p)(&ia->ia_ifa, vhid);
812228571Sglebius		else
813228571Sglebius			error = EPROTONOSUPPORT;
814228571Sglebius	}
815228571Sglebius	if (error)
816228571Sglebius		return (error);
817228571Sglebius
8181541Srgrimes	/*
819244989Speter	 * Give the interface a chance to initialize
820244989Speter	 * if this is its first address,
821244989Speter	 * and to validate the address if necessary.
8221541Srgrimes	 */
823227791Sglebius	if (ifp->if_ioctl != NULL &&
824227791Sglebius	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) != 0)
825146883Siedowse			/* LIST_REMOVE(ia, ia_hash) is done in in_control */
826146883Siedowse			return (error);
827227791Sglebius
8281541Srgrimes	/*
829226401Sglebius	 * Be compatible with network classes, if netmask isn't supplied,
830226401Sglebius	 * guess it based on classes.
8311541Srgrimes	 */
832228313Sglebius	if (!masksupplied) {
833226401Sglebius		if (IN_CLASSA(i))
834226401Sglebius			ia->ia_subnetmask = IN_CLASSA_NET;
835226401Sglebius		else if (IN_CLASSB(i))
836226401Sglebius			ia->ia_subnetmask = IN_CLASSB_NET;
837226401Sglebius		else
838226401Sglebius			ia->ia_subnetmask = IN_CLASSC_NET;
8391541Srgrimes		ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
840226401Sglebius	}
8411541Srgrimes	ia->ia_subnet = i & ia->ia_subnetmask;
8421541Srgrimes	in_socktrim(&ia->ia_sockmask);
843244665Sglebius
8441541Srgrimes	/*
8451541Srgrimes	 * Add route for the network.
8461541Srgrimes	 */
847244665Sglebius	flags = RTF_UP;
8481541Srgrimes	ia->ia_ifa.ifa_metric = ifp->if_metric;
8491541Srgrimes	if (ifp->if_flags & IFF_BROADCAST) {
850226402Sglebius		if (ia->ia_subnetmask == IN_RFC3021_MASK)
851226402Sglebius			ia->ia_broadaddr.sin_addr.s_addr = INADDR_BROADCAST;
852226402Sglebius		else
853226402Sglebius			ia->ia_broadaddr.sin_addr.s_addr =
854226402Sglebius			    htonl(ia->ia_subnet | ~ia->ia_subnetmask);
8551541Srgrimes	} else if (ifp->if_flags & IFF_LOOPBACK) {
856137833Smlaier		ia->ia_dstaddr = ia->ia_addr;
8571541Srgrimes		flags |= RTF_HOST;
8581541Srgrimes	} else if (ifp->if_flags & IFF_POINTOPOINT) {
8591541Srgrimes		if (ia->ia_dstaddr.sin_family != AF_INET)
8601541Srgrimes			return (0);
8611541Srgrimes		flags |= RTF_HOST;
8621541Srgrimes	}
863228571Sglebius	if (!vhid && (error = in_addprefix(ia, flags)) != 0)
864137628Smlaier		return (error);
86594326Sbrian
866192085Sqingli	if (ia->ia_addr.sin_addr.s_addr == INADDR_ANY)
867192085Sqingli		return (0);
868192085Sqingli
869227791Sglebius	if (ifp->if_flags & IFF_POINTOPOINT &&
870227791Sglebius	    ia->ia_dstaddr.sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
871203401Sqingli			return (0);
872203401Sqingli
873192011Sqingli	/*
874192011Sqingli	 * add a loopback route to self
875192011Sqingli	 */
876228571Sglebius	if (V_useloopback && !vhid && !(ifp->if_flags & IFF_LOOPBACK)) {
877201282Sqingli		struct route ia_ro;
878201282Sqingli
879201282Sqingli		bzero(&ia_ro, sizeof(ia_ro));
880201282Sqingli		*((struct sockaddr_in *)(&ia_ro.ro_dst)) = ia->ia_addr;
881231852Sbz		rtalloc_ign_fib(&ia_ro, 0, RT_DEFAULT_FIB);
882201282Sqingli		if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
883201282Sqingli		    (ia_ro.ro_rt->rt_ifp == V_loif)) {
884201282Sqingli			RT_LOCK(ia_ro.ro_rt);
885201282Sqingli			RT_ADDREF(ia_ro.ro_rt);
886201282Sqingli			RTFREE_LOCKED(ia_ro.ro_rt);
887201282Sqingli		} else
888238945Sglebius			error = ifa_add_loopback_route((struct ifaddr *)ia,
889238945Sglebius			    (struct sockaddr *)&ia->ia_addr);
890201282Sqingli		if (error == 0)
891201282Sqingli			ia->ia_flags |= IFA_RTSELF;
892201282Sqingli		if (ia_ro.ro_rt != NULL)
893201282Sqingli			RTFREE(ia_ro.ro_rt);
894201282Sqingli	}
895192011Sqingli
8961541Srgrimes	return (error);
8971541Srgrimes}
8981541Srgrimes
899137628Smlaier#define rtinitflags(x) \
900137628Smlaier	((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
901137628Smlaier	    ? RTF_HOST : 0)
902201285Sqingli
903137628Smlaier/*
904238945Sglebius * Generate a routing message when inserting or deleting
905201285Sqingli * an interface address alias.
906201285Sqingli */
907238945Sglebiusstatic void in_addralias_rtmsg(int cmd, struct in_addr *prefix,
908201285Sqingli    struct in_ifaddr *target)
909201285Sqingli{
910201285Sqingli	struct route pfx_ro;
911201285Sqingli	struct sockaddr_in *pfx_addr;
912201285Sqingli	struct rtentry msg_rt;
913201285Sqingli
914201285Sqingli	/* QL: XXX
915201285Sqingli	 * This is a bit questionable because there is no
916201285Sqingli	 * additional route entry added/deleted for an address
917201285Sqingli	 * alias. Therefore this route report is inaccurate.
918201285Sqingli	 */
919201285Sqingli	bzero(&pfx_ro, sizeof(pfx_ro));
920201285Sqingli	pfx_addr = (struct sockaddr_in *)(&pfx_ro.ro_dst);
921201285Sqingli	pfx_addr->sin_len = sizeof(*pfx_addr);
922201285Sqingli	pfx_addr->sin_family = AF_INET;
923201285Sqingli	pfx_addr->sin_addr = *prefix;
924201285Sqingli	rtalloc_ign_fib(&pfx_ro, 0, 0);
925201285Sqingli	if (pfx_ro.ro_rt != NULL) {
926201285Sqingli		msg_rt = *pfx_ro.ro_rt;
927201285Sqingli
928201285Sqingli		/* QL: XXX
929201285Sqingli		 * Point the gateway to the new interface
930238945Sglebius		 * address as if a new prefix route entry has
931238945Sglebius		 * been added through the new address alias.
932238945Sglebius		 * All other parts of the rtentry is accurate,
933201285Sqingli		 * e.g., rt_key, rt_mask, rt_ifp etc.
934201285Sqingli		 */
935238945Sglebius		msg_rt.rt_gateway = (struct sockaddr *)&target->ia_addr;
936238945Sglebius		rt_newaddrmsg(cmd, (struct ifaddr *)target, 0, &msg_rt);
937201285Sqingli		RTFREE(pfx_ro.ro_rt);
938201285Sqingli	}
939201285Sqingli	return;
940201285Sqingli}
941201285Sqingli
942201285Sqingli/*
943170855Smjacob * Check if we have a route for the given prefix already or add one accordingly.
944137628Smlaier */
945228571Sglebiusint
946169454Srwatsonin_addprefix(struct in_ifaddr *target, int flags)
947137628Smlaier{
948137628Smlaier	struct in_ifaddr *ia;
949151555Sglebius	struct in_addr prefix, mask, p, m;
950137628Smlaier	int error;
9511541Srgrimes
952170855Smjacob	if ((flags & RTF_HOST) != 0) {
953137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
954170855Smjacob		mask.s_addr = 0;
955170855Smjacob	} else {
956137628Smlaier		prefix = target->ia_addr.sin_addr;
957137628Smlaier		mask = target->ia_sockmask.sin_addr;
958137628Smlaier		prefix.s_addr &= mask.s_addr;
959137628Smlaier	}
960137628Smlaier
961194951Srwatson	IN_IFADDR_RLOCK();
962181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
963151555Sglebius		if (rtinitflags(ia)) {
964224747Skevlo			p = ia->ia_dstaddr.sin_addr;
965151555Sglebius
966151555Sglebius			if (prefix.s_addr != p.s_addr)
967151555Sglebius				continue;
968151555Sglebius		} else {
969151555Sglebius			p = ia->ia_addr.sin_addr;
970151555Sglebius			m = ia->ia_sockmask.sin_addr;
971151555Sglebius			p.s_addr &= m.s_addr;
972151555Sglebius
973151555Sglebius			if (prefix.s_addr != p.s_addr ||
974151555Sglebius			    mask.s_addr != m.s_addr)
975151555Sglebius				continue;
976137628Smlaier		}
977137628Smlaier
978137628Smlaier		/*
979137628Smlaier		 * If we got a matching prefix route inserted by other
980137628Smlaier		 * interface address, we are done here.
981137628Smlaier		 */
982149221Sglebius		if (ia->ia_flags & IFA_ROUTE) {
983204902Sqingli#ifdef RADIX_MPATH
984238945Sglebius			if (ia->ia_addr.sin_addr.s_addr ==
985212209Sbz			    target->ia_addr.sin_addr.s_addr) {
986212209Sbz				IN_IFADDR_RUNLOCK();
987204902Sqingli				return (EEXIST);
988212209Sbz			} else
989204902Sqingli				break;
990204902Sqingli#endif
991228571Sglebius			if (V_nosameprefix) {
992194951Srwatson				IN_IFADDR_RUNLOCK();
993149221Sglebius				return (EEXIST);
994194951Srwatson			} else {
995201285Sqingli				in_addralias_rtmsg(RTM_ADD, &prefix, target);
996194951Srwatson				IN_IFADDR_RUNLOCK();
997149221Sglebius				return (0);
998194951Srwatson			}
999149221Sglebius		}
1000137628Smlaier	}
1001194951Srwatson	IN_IFADDR_RUNLOCK();
1002137628Smlaier
1003137628Smlaier	/*
1004137628Smlaier	 * No-one seem to have this prefix route, so we try to insert it.
1005137628Smlaier	 */
1006137628Smlaier	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
1007137628Smlaier	if (!error)
1008137628Smlaier		target->ia_flags |= IFA_ROUTE;
1009184295Sbz	return (error);
1010137628Smlaier}
1011137628Smlaier
10121541Srgrimes/*
1013137628Smlaier * If there is no other address in the system that can serve a route to the
1014137628Smlaier * same prefix, remove the route.  Hand over the route to the new address
1015137628Smlaier * otherwise.
1016137628Smlaier */
1017228571Sglebiusint
1018222143Sqingliin_scrubprefix(struct in_ifaddr *target, u_int flags)
1019137628Smlaier{
1020137628Smlaier	struct in_ifaddr *ia;
1021228454Sglebius	struct in_addr prefix, mask, p, m;
1022201282Sqingli	int error = 0;
1023192476Sqingli	struct sockaddr_in prefix0, mask0;
1024137628Smlaier
1025195914Sqingli	/*
1026195914Sqingli	 * Remove the loopback route to the interface address.
1027195914Sqingli	 * The "useloopback" setting is not consulted because if the
1028195914Sqingli	 * user configures an interface address, turns off this
1029195914Sqingli	 * setting, and then tries to delete that interface address,
1030195914Sqingli	 * checking the current setting of "useloopback" would leave
1031195914Sqingli	 * that interface address loopback route untouched, which
1032195914Sqingli	 * would be wrong. Therefore the interface address loopback route
1033195914Sqingli	 * deletion is unconditional.
1034195914Sqingli	 */
1035192085Sqingli	if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) &&
1036201282Sqingli	    !(target->ia_ifp->if_flags & IFF_LOOPBACK) &&
1037201282Sqingli	    (target->ia_flags & IFA_RTSELF)) {
1038201282Sqingli		struct route ia_ro;
1039201282Sqingli		int freeit = 0;
1040201282Sqingli
1041201282Sqingli		bzero(&ia_ro, sizeof(ia_ro));
1042201282Sqingli		*((struct sockaddr_in *)(&ia_ro.ro_dst)) = target->ia_addr;
1043201282Sqingli		rtalloc_ign_fib(&ia_ro, 0, 0);
1044201282Sqingli		if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
1045201282Sqingli		    (ia_ro.ro_rt->rt_ifp == V_loif)) {
1046201282Sqingli			RT_LOCK(ia_ro.ro_rt);
1047201282Sqingli			if (ia_ro.ro_rt->rt_refcnt <= 1)
1048201282Sqingli				freeit = 1;
1049226114Sqingli			else if (flags & LLE_STATIC) {
1050201282Sqingli				RT_REMREF(ia_ro.ro_rt);
1051226114Sqingli				target->ia_flags &= ~IFA_RTSELF;
1052226114Sqingli			}
1053201282Sqingli			RTFREE_LOCKED(ia_ro.ro_rt);
1054201282Sqingli		}
1055222143Sqingli		if (freeit && (flags & LLE_STATIC)) {
1056201282Sqingli			error = ifa_del_loopback_route((struct ifaddr *)target,
1057238945Sglebius			    (struct sockaddr *)&target->ia_addr);
1058222143Sqingli			if (error == 0)
1059222143Sqingli				target->ia_flags &= ~IFA_RTSELF;
1060222143Sqingli		}
1061226120Sqingli		if ((flags & LLE_STATIC) &&
1062226120Sqingli			!(target->ia_ifp->if_flags & IFF_NOARP))
1063222143Sqingli			/* remove arp cache */
1064222143Sqingli			arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
1065192011Sqingli	}
1066192011Sqingli
1067228454Sglebius	if (rtinitflags(target)) {
1068137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
1069228454Sglebius		mask.s_addr = 0;
1070228454Sglebius	} else {
1071137628Smlaier		prefix = target->ia_addr.sin_addr;
1072137628Smlaier		mask = target->ia_sockmask.sin_addr;
1073137628Smlaier		prefix.s_addr &= mask.s_addr;
1074137628Smlaier	}
1075137628Smlaier
1076201285Sqingli	if ((target->ia_flags & IFA_ROUTE) == 0) {
1077201285Sqingli		in_addralias_rtmsg(RTM_DELETE, &prefix, target);
1078201285Sqingli		return (0);
1079201285Sqingli	}
1080201285Sqingli
1081194951Srwatson	IN_IFADDR_RLOCK();
1082181803Sbz	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
1083228454Sglebius		if (rtinitflags(ia)) {
1084137628Smlaier			p = ia->ia_dstaddr.sin_addr;
1085228454Sglebius
1086228454Sglebius			if (prefix.s_addr != p.s_addr)
1087228454Sglebius				continue;
1088228454Sglebius		} else {
1089137628Smlaier			p = ia->ia_addr.sin_addr;
1090228454Sglebius			m = ia->ia_sockmask.sin_addr;
1091228454Sglebius			p.s_addr &= m.s_addr;
1092228454Sglebius
1093228454Sglebius			if (prefix.s_addr != p.s_addr ||
1094228454Sglebius			    mask.s_addr != m.s_addr)
1095228454Sglebius				continue;
1096137628Smlaier		}
1097137628Smlaier
1098228454Sglebius		if ((ia->ia_ifp->if_flags & IFF_UP) == 0)
1099137628Smlaier			continue;
1100137628Smlaier
1101137628Smlaier		/*
1102137628Smlaier		 * If we got a matching prefix address, move IFA_ROUTE and
1103137628Smlaier		 * the route itself to it.  Make sure that routing daemons
1104137628Smlaier		 * get a heads-up.
1105137628Smlaier		 */
1106228571Sglebius		if ((ia->ia_flags & IFA_ROUTE) == 0) {
1107219828Spluknet			ifa_ref(&ia->ia_ifa);
1108194951Srwatson			IN_IFADDR_RUNLOCK();
1109222438Sqingli			error = rtinit(&(target->ia_ifa), (int)RTM_DELETE,
1110137628Smlaier			    rtinitflags(target));
1111222438Sqingli			if (error == 0)
1112222438Sqingli				target->ia_flags &= ~IFA_ROUTE;
1113222438Sqingli			else
1114222438Sqingli				log(LOG_INFO, "in_scrubprefix: err=%d, old prefix delete failed\n",
1115222438Sqingli					error);
1116137628Smlaier			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
1117137628Smlaier			    rtinitflags(ia) | RTF_UP);
1118137628Smlaier			if (error == 0)
1119137628Smlaier				ia->ia_flags |= IFA_ROUTE;
1120222438Sqingli			else
1121222438Sqingli				log(LOG_INFO, "in_scrubprefix: err=%d, new prefix add failed\n",
1122222438Sqingli					error);
1123219828Spluknet			ifa_free(&ia->ia_ifa);
1124184295Sbz			return (error);
1125137628Smlaier		}
1126137628Smlaier	}
1127194951Srwatson	IN_IFADDR_RUNLOCK();
1128137628Smlaier
1129137628Smlaier	/*
1130192476Sqingli	 * remove all L2 entries on the given prefix
1131192476Sqingli	 */
1132192476Sqingli	bzero(&prefix0, sizeof(prefix0));
1133192476Sqingli	prefix0.sin_len = sizeof(prefix0);
1134192476Sqingli	prefix0.sin_family = AF_INET;
1135192476Sqingli	prefix0.sin_addr.s_addr = target->ia_subnet;
1136192476Sqingli	bzero(&mask0, sizeof(mask0));
1137192476Sqingli	mask0.sin_len = sizeof(mask0);
1138192476Sqingli	mask0.sin_family = AF_INET;
1139192476Sqingli	mask0.sin_addr.s_addr = target->ia_subnetmask;
1140238945Sglebius	lltable_prefix_free(AF_INET, (struct sockaddr *)&prefix0,
1141238945Sglebius	    (struct sockaddr *)&mask0, flags);
1142192476Sqingli
1143192476Sqingli	/*
1144137628Smlaier	 * As no-one seem to have this prefix, we can remove the route.
1145137628Smlaier	 */
1146222438Sqingli	error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
1147222438Sqingli	if (error == 0)
1148222438Sqingli		target->ia_flags &= ~IFA_ROUTE;
1149222438Sqingli	else
1150222438Sqingli		log(LOG_INFO, "in_scrubprefix: err=%d, prefix delete failed\n", error);
1151222438Sqingli	return (error);
1152137628Smlaier}
1153137628Smlaier
1154137628Smlaier#undef rtinitflags
1155137628Smlaier
1156137628Smlaier/*
11571541Srgrimes * Return 1 if the address might be a local broadcast address.
11581541Srgrimes */
11591549Srgrimesint
1160169454Srwatsonin_broadcast(struct in_addr in, struct ifnet *ifp)
11611541Srgrimes{
11621541Srgrimes	register struct ifaddr *ifa;
11631541Srgrimes	u_long t;
11641541Srgrimes
11651541Srgrimes	if (in.s_addr == INADDR_BROADCAST ||
11661541Srgrimes	    in.s_addr == INADDR_ANY)
1167184295Sbz		return (1);
11681541Srgrimes	if ((ifp->if_flags & IFF_BROADCAST) == 0)
1169184295Sbz		return (0);
11701541Srgrimes	t = ntohl(in.s_addr);
11711541Srgrimes	/*
11721541Srgrimes	 * Look through the list of addresses for a match
11731541Srgrimes	 * with a broadcast address.
11741541Srgrimes	 */
11751541Srgrimes#define ia ((struct in_ifaddr *)ifa)
117674362Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
11771541Srgrimes		if (ifa->ifa_addr->sa_family == AF_INET &&
11781541Srgrimes		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
11791541Srgrimes		     /*
1180226402Sglebius		      * Check for old-style (host 0) broadcast, but
1181226402Sglebius		      * taking into account that RFC 3021 obsoletes it.
11821541Srgrimes		      */
1183238945Sglebius		    (ia->ia_subnetmask != IN_RFC3021_MASK &&
1184238945Sglebius		    t == ia->ia_subnet)) &&
118513351Sguido		     /*
118613351Sguido		      * Check for an all one subnetmask. These
118713351Sguido		      * only exist when an interface gets a secondary
118813351Sguido		      * address.
118913351Sguido		      */
1190238945Sglebius		    ia->ia_subnetmask != (u_long)0xffffffff)
1191184295Sbz			    return (1);
11921541Srgrimes	return (0);
11931541Srgrimes#undef ia
11941541Srgrimes}
1195167729Sbms
11961541Srgrimes/*
1197189592Sbms * On interface removal, clean up IPv4 data structures hung off of the ifnet.
1198189592Sbms */
1199189592Sbmsvoid
1200189592Sbmsin_ifdetach(struct ifnet *ifp)
1201189592Sbms{
1202189592Sbms
1203189592Sbms	in_pcbpurgeif0(&V_ripcbinfo, ifp);
1204189592Sbms	in_pcbpurgeif0(&V_udbinfo, ifp);
1205189592Sbms	in_purgemaddrs(ifp);
1206189592Sbms}
1207189592Sbms
1208189592Sbms/*
1209167729Sbms * Delete all IPv4 multicast address records, and associated link-layer
1210167729Sbms * multicast address records, associated with ifp.
1211189592Sbms * XXX It looks like domifdetach runs AFTER the link layer cleanup.
1212189931Sbms * XXX This should not race with ifma_protospec being set during
1213189931Sbms * a new allocation, if it does, we have bigger problems.
1214162718Sbms */
1215167729Sbmsstatic void
1216167729Sbmsin_purgemaddrs(struct ifnet *ifp)
1217162718Sbms{
1218189592Sbms	LIST_HEAD(,in_multi) purgeinms;
1219189592Sbms	struct in_multi		*inm, *tinm;
1220189592Sbms	struct ifmultiaddr	*ifma;
1221162718Sbms
1222189592Sbms	LIST_INIT(&purgeinms);
1223162718Sbms	IN_MULTI_LOCK();
1224189592Sbms
1225189592Sbms	/*
1226189592Sbms	 * Extract list of in_multi associated with the detaching ifp
1227189592Sbms	 * which the PF_INET layer is about to release.
1228189592Sbms	 * We need to do this as IF_ADDR_LOCK() may be re-acquired
1229189592Sbms	 * by code further down.
1230189592Sbms	 */
1231229621Sjhb	IF_ADDR_RLOCK(ifp);
1232189592Sbms	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1233189931Sbms		if (ifma->ifma_addr->sa_family != AF_INET ||
1234189931Sbms		    ifma->ifma_protospec == NULL)
1235189592Sbms			continue;
1236189931Sbms#if 0
1237189931Sbms		KASSERT(ifma->ifma_protospec != NULL,
1238189931Sbms		    ("%s: ifma_protospec is NULL", __func__));
1239189931Sbms#endif
1240189592Sbms		inm = (struct in_multi *)ifma->ifma_protospec;
1241189592Sbms		LIST_INSERT_HEAD(&purgeinms, inm, inm_link);
1242162718Sbms	}
1243229621Sjhb	IF_ADDR_RUNLOCK(ifp);
1244150296Srwatson
1245189592Sbms	LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) {
1246191476Srwatson		LIST_REMOVE(inm, inm_link);
1247189592Sbms		inm_release_locked(inm);
1248189592Sbms	}
1249189592Sbms	igmp_ifdetach(ifp);
1250150296Srwatson
1251189592Sbms	IN_MULTI_UNLOCK();
1252150296Srwatson}
1253186119Sqingli
1254186119Sqinglistruct in_llentry {
1255186119Sqingli	struct llentry		base;
1256186119Sqingli	struct sockaddr_in	l3_addr4;
1257186119Sqingli};
1258186119Sqingli
1259232054Skmacy/*
1260232054Skmacy * Deletes an address from the address table.
1261232054Skmacy * This function is called by the timer functions
1262232054Skmacy * such as arptimer() and nd6_llinfo_timer(), and
1263232054Skmacy * the caller does the locking.
1264232054Skmacy */
1265232054Skmacystatic void
1266232054Skmacyin_lltable_free(struct lltable *llt, struct llentry *lle)
1267232054Skmacy{
1268232054Skmacy	LLE_WUNLOCK(lle);
1269232054Skmacy	LLE_LOCK_DESTROY(lle);
1270232054Skmacy	free(lle, M_LLTABLE);
1271232054Skmacy}
1272232054Skmacy
1273186119Sqinglistatic struct llentry *
1274186119Sqingliin_lltable_new(const struct sockaddr *l3addr, u_int flags)
1275186119Sqingli{
1276186119Sqingli	struct in_llentry *lle;
1277186119Sqingli
1278234087Sglebius	lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
1279186119Sqingli	if (lle == NULL)		/* NB: caller generates msg */
1280186119Sqingli		return NULL;
1281186119Sqingli
1282186119Sqingli	/*
1283186119Sqingli	 * For IPv4 this will trigger "arpresolve" to generate
1284186119Sqingli	 * an ARP request.
1285186119Sqingli	 */
1286216075Sglebius	lle->base.la_expire = time_uptime; /* mark expired */
1287186119Sqingli	lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
1288186119Sqingli	lle->base.lle_refcnt = 1;
1289232054Skmacy	lle->base.lle_free = in_lltable_free;
1290186119Sqingli	LLE_LOCK_INIT(&lle->base);
1291238990Sglebius	callout_init_rw(&lle->base.la_timer, &lle->base.lle_lock,
1292238990Sglebius	    CALLOUT_RETURNUNLOCKED);
1293238990Sglebius
1294238990Sglebius	return (&lle->base);
1295186119Sqingli}
1296186119Sqingli
1297192476Sqingli#define IN_ARE_MASKED_ADDR_EQUAL(d, a, m)	(			\
1298192476Sqingli	    (((ntohl((d)->sin_addr.s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 )
1299192476Sqingli
1300192476Sqinglistatic void
1301238945Sglebiusin_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
1302238945Sglebius    const struct sockaddr *mask, u_int flags)
1303192476Sqingli{
1304192476Sqingli	const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix;
1305192476Sqingli	const struct sockaddr_in *msk = (const struct sockaddr_in *)mask;
1306192476Sqingli	struct llentry *lle, *next;
1307238945Sglebius	int i;
1308215207Sgnn	size_t pkts_dropped;
1309192476Sqingli
1310238990Sglebius	IF_AFDATA_WLOCK(llt->llt_ifp);
1311238945Sglebius	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
1312192476Sqingli		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
1313238945Sglebius			/*
1314222143Sqingli			 * (flags & LLE_STATIC) means deleting all entries
1315238945Sglebius			 * including static ARP entries.
1316222143Sqingli			 */
1317238945Sglebius			if (IN_ARE_MASKED_ADDR_EQUAL(satosin(L3_ADDR(lle)),
1318238945Sglebius			    pfx, msk) && ((flags & LLE_STATIC) ||
1319238945Sglebius			    !(lle->la_flags & LLE_STATIC))) {
1320192476Sqingli				LLE_WLOCK(lle);
1321238990Sglebius				if (callout_stop(&lle->la_timer))
1322206481Sbz					LLE_REMREF(lle);
1323215207Sgnn				pkts_dropped = llentry_free(lle);
1324215207Sgnn				ARPSTAT_ADD(dropped, pkts_dropped);
1325192476Sqingli			}
1326192476Sqingli		}
1327192476Sqingli	}
1328238990Sglebius	IF_AFDATA_WUNLOCK(llt->llt_ifp);
1329192476Sqingli}
1330192476Sqingli
1331192476Sqingli
1332186119Sqinglistatic int
1333201282Sqingliin_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
1334186119Sqingli{
1335186119Sqingli	struct rtentry *rt;
1336186119Sqingli
1337186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1338186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1339186119Sqingli
1340186119Sqingli	/* XXX rtalloc1 should take a const param */
1341186119Sqingli	rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
1342223862Szec
1343225946Sqingli	if (rt == NULL)
1344225946Sqingli		return (EINVAL);
1345225946Sqingli
1346223862Szec	/*
1347223862Szec	 * If the gateway for an existing host route matches the target L3
1348225946Sqingli	 * address, which is a special route inserted by some implementation
1349225946Sqingli	 * such as MANET, and the interface is of the correct type, then
1350225946Sqingli	 * allow for ARP to proceed.
1351223862Szec	 */
1352225947Sqingli	if (rt->rt_flags & RTF_GATEWAY) {
1353226224Sqingli		if (!(rt->rt_flags & RTF_HOST) || !rt->rt_ifp ||
1354238945Sglebius		    rt->rt_ifp->if_type != IFT_ETHER ||
1355238945Sglebius		    (rt->rt_ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) != 0 ||
1356238945Sglebius		    memcmp(rt->rt_gateway->sa_data, l3addr->sa_data,
1357238945Sglebius		    sizeof(in_addr_t)) != 0) {
1358226224Sqingli			RTFREE_LOCKED(rt);
1359226224Sqingli			return (EINVAL);
1360226224Sqingli		}
1361225947Sqingli	}
1362225947Sqingli
1363225947Sqingli	/*
1364238945Sglebius	 * Make sure that at least the destination address is covered
1365238945Sglebius	 * by the route. This is for handling the case where 2 or more
1366225947Sqingli	 * interfaces have the same prefix. An incoming packet arrives
1367225947Sqingli	 * on one interface and the corresponding outgoing packet leaves
1368225947Sqingli	 * another interface.
1369225947Sqingli	 */
1370226713Sqingli	if (!(rt->rt_flags & RTF_HOST) && rt->rt_ifp != ifp) {
1371226224Sqingli		const char *sa, *mask, *addr, *lim;
1372225947Sqingli		int len;
1373225947Sqingli
1374226713Sqingli		mask = (const char *)rt_mask(rt);
1375226713Sqingli		/*
1376226713Sqingli		 * Just being extra cautious to avoid some custom
1377226713Sqingli		 * code getting into trouble.
1378226713Sqingli		 */
1379226713Sqingli		if (mask == NULL) {
1380226713Sqingli			RTFREE_LOCKED(rt);
1381226713Sqingli			return (EINVAL);
1382226713Sqingli		}
1383226713Sqingli
1384226224Sqingli		sa = (const char *)rt_key(rt);
1385226224Sqingli		addr = (const char *)l3addr;
1386226224Sqingli		len = ((const struct sockaddr_in *)l3addr)->sin_len;
1387225947Sqingli		lim = addr + len;
1388225947Sqingli
1389225947Sqingli		for ( ; addr < lim; sa++, mask++, addr++) {
1390225947Sqingli			if ((*sa ^ *addr) & *mask) {
1391198418Sqingli#ifdef DIAGNOSTIC
1392225947Sqingli				log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
1393225947Sqingli				    inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
1394197696Sqingli#endif
1395226224Sqingli				RTFREE_LOCKED(rt);
1396226224Sqingli				return (EINVAL);
1397225947Sqingli			}
1398225947Sqingli		}
1399186119Sqingli	}
1400225947Sqingli
1401186119Sqingli	RTFREE_LOCKED(rt);
1402226224Sqingli	return (0);
1403186119Sqingli}
1404186119Sqingli
1405186119Sqingli/*
1406186119Sqingli * Return NULL if not found or marked for deletion.
1407186119Sqingli * If found return lle read locked.
1408186119Sqingli */
1409186119Sqinglistatic struct llentry *
1410186119Sqingliin_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
1411186119Sqingli{
1412186119Sqingli	const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
1413186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1414186119Sqingli	struct llentry *lle;
1415186119Sqingli	struct llentries *lleh;
1416186119Sqingli	u_int hashkey;
1417186119Sqingli
1418186119Sqingli	IF_AFDATA_LOCK_ASSERT(ifp);
1419186119Sqingli	KASSERT(l3addr->sa_family == AF_INET,
1420186119Sqingli	    ("sin_family %d", l3addr->sa_family));
1421186119Sqingli
1422186119Sqingli	hashkey = sin->sin_addr.s_addr;
1423186119Sqingli	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
1424186119Sqingli	LIST_FOREACH(lle, lleh, lle_next) {
1425238945Sglebius		struct sockaddr_in *sa2 = satosin(L3_ADDR(lle));
1426186119Sqingli		if (lle->la_flags & LLE_DELETED)
1427186119Sqingli			continue;
1428186708Sqingli		if (sa2->sin_addr.s_addr == sin->sin_addr.s_addr)
1429186119Sqingli			break;
1430186119Sqingli	}
1431186119Sqingli	if (lle == NULL) {
1432198418Sqingli#ifdef DIAGNOSTIC
1433186119Sqingli		if (flags & LLE_DELETE)
1434238967Sglebius			log(LOG_INFO, "interface address is missing from cache = %p  in delete\n", lle);
1435186119Sqingli#endif
1436186119Sqingli		if (!(flags & LLE_CREATE))
1437186119Sqingli			return (NULL);
1438186119Sqingli		/*
1439186119Sqingli		 * A route that covers the given address must have
1440186119Sqingli		 * been installed 1st because we are doing a resolution,
1441186119Sqingli		 * verify this.
1442186119Sqingli		 */
1443186119Sqingli		if (!(flags & LLE_IFADDR) &&
1444201282Sqingli		    in_lltable_rtcheck(ifp, flags, l3addr) != 0)
1445186119Sqingli			goto done;
1446186119Sqingli
1447186119Sqingli		lle = in_lltable_new(l3addr, flags);
1448186119Sqingli		if (lle == NULL) {
1449186119Sqingli			log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
1450186119Sqingli			goto done;
1451186119Sqingli		}
1452186119Sqingli		lle->la_flags = flags & ~LLE_CREATE;
1453186119Sqingli		if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
1454186119Sqingli			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
1455186119Sqingli			lle->la_flags |= (LLE_VALID | LLE_STATIC);
1456186119Sqingli		}
1457186119Sqingli
1458186119Sqingli		lle->lle_tbl  = llt;
1459186119Sqingli		lle->lle_head = lleh;
1460238990Sglebius		lle->la_flags |= LLE_LINKED;
1461186119Sqingli		LIST_INSERT_HEAD(lleh, lle, lle_next);
1462186119Sqingli	} else if (flags & LLE_DELETE) {
1463186119Sqingli		if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
1464186119Sqingli			LLE_WLOCK(lle);
1465238990Sglebius			lle->la_flags |= LLE_DELETED;
1466237263Snp			EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED);
1467198418Sqingli#ifdef DIAGNOSTIC
1468249742Soleg			log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
1469186119Sqingli#endif
1470249742Soleg			if ((lle->la_flags &
1471249742Soleg			    (LLE_STATIC | LLE_IFADDR)) == LLE_STATIC)
1472249742Soleg				llentry_free(lle);
1473249742Soleg			else
1474249742Soleg				LLE_WUNLOCK(lle);
1475186119Sqingli		}
1476186119Sqingli		lle = (void *)-1;
1477238967Sglebius
1478186119Sqingli	}
1479186544Sbz	if (LLE_IS_VALID(lle)) {
1480186119Sqingli		if (flags & LLE_EXCLUSIVE)
1481186119Sqingli			LLE_WLOCK(lle);
1482186119Sqingli		else
1483186119Sqingli			LLE_RLOCK(lle);
1484186119Sqingli	}
1485186119Sqinglidone:
1486186119Sqingli	return (lle);
1487186119Sqingli}
1488186119Sqingli
1489186119Sqinglistatic int
1490186119Sqingliin_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
1491186119Sqingli{
1492186119Sqingli#define	SIN(lle)	((struct sockaddr_in *) L3_ADDR(lle))
1493186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
1494186119Sqingli	struct llentry *lle;
1495186119Sqingli	/* XXX stack use */
1496186119Sqingli	struct {
1497186119Sqingli		struct rt_msghdr	rtm;
1498246143Sglebius		struct sockaddr_in	sin;
1499186119Sqingli		struct sockaddr_dl	sdl;
1500186119Sqingli	} arpc;
1501186119Sqingli	int error, i;
1502186119Sqingli
1503196535Srwatson	LLTABLE_LOCK_ASSERT();
1504186119Sqingli
1505186119Sqingli	error = 0;
1506186119Sqingli	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
1507186119Sqingli		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
1508186119Sqingli			struct sockaddr_dl *sdl;
1509238967Sglebius
1510186119Sqingli			/* skip deleted entries */
1511198111Sqingli			if ((lle->la_flags & LLE_DELETED) == LLE_DELETED)
1512186119Sqingli				continue;
1513186980Sbz			/* Skip if jailed and not a valid IP of the prison. */
1514188144Sjamie			if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
1515186980Sbz				continue;
1516186119Sqingli			/*
1517186119Sqingli			 * produce a msg made of:
1518186119Sqingli			 *  struct rt_msghdr;
1519246143Sglebius			 *  struct sockaddr_in; (IPv4)
1520186119Sqingli			 *  struct sockaddr_dl;
1521186119Sqingli			 */
1522186119Sqingli			bzero(&arpc, sizeof(arpc));
1523186119Sqingli			arpc.rtm.rtm_msglen = sizeof(arpc);
1524186935Sharti			arpc.rtm.rtm_version = RTM_VERSION;
1525186935Sharti			arpc.rtm.rtm_type = RTM_GET;
1526186935Sharti			arpc.rtm.rtm_flags = RTF_UP;
1527186935Sharti			arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
1528186119Sqingli			arpc.sin.sin_family = AF_INET;
1529186119Sqingli			arpc.sin.sin_len = sizeof(arpc.sin);
1530186119Sqingli			arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
1531186119Sqingli
1532186119Sqingli			/* publish */
1533246143Sglebius			if (lle->la_flags & LLE_PUB)
1534186119Sqingli				arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
1535186119Sqingli
1536186119Sqingli			sdl = &arpc.sdl;
1537186119Sqingli			sdl->sdl_family = AF_LINK;
1538186119Sqingli			sdl->sdl_len = sizeof(*sdl);
1539186119Sqingli			sdl->sdl_index = ifp->if_index;
1540186119Sqingli			sdl->sdl_type = ifp->if_type;
1541198111Sqingli			if ((lle->la_flags & LLE_VALID) == LLE_VALID) {
1542198111Sqingli				sdl->sdl_alen = ifp->if_addrlen;
1543198111Sqingli				bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
1544198111Sqingli			} else {
1545198111Sqingli				sdl->sdl_alen = 0;
1546198111Sqingli				bzero(LLADDR(sdl), ifp->if_addrlen);
1547198111Sqingli			}
1548186119Sqingli
1549186119Sqingli			arpc.rtm.rtm_rmx.rmx_expire =
1550186119Sqingli			    lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
1551186500Sqingli			arpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
1552186119Sqingli			if (lle->la_flags & LLE_STATIC)
1553186119Sqingli				arpc.rtm.rtm_flags |= RTF_STATIC;
1554186119Sqingli			arpc.rtm.rtm_index = ifp->if_index;
1555186119Sqingli			error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
1556186119Sqingli			if (error)
1557186119Sqingli				break;
1558186119Sqingli		}
1559186119Sqingli	}
1560186119Sqingli	return error;
1561186119Sqingli#undef SIN
1562186119Sqingli}
1563186119Sqingli
1564186119Sqinglivoid *
1565186119Sqingliin_domifattach(struct ifnet *ifp)
1566189592Sbms{
1567189592Sbms	struct in_ifinfo *ii;
1568189592Sbms	struct lltable *llt;
1569189592Sbms
1570189592Sbms	ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO);
1571189592Sbms
1572189592Sbms	llt = lltable_init(ifp, AF_INET);
1573186119Sqingli	if (llt != NULL) {
1574192476Sqingli		llt->llt_prefix_free = in_lltable_prefix_free;
1575186119Sqingli		llt->llt_lookup = in_lltable_lookup;
1576186119Sqingli		llt->llt_dump = in_lltable_dump;
1577186119Sqingli	}
1578189592Sbms	ii->ii_llt = llt;
1579189592Sbms
1580189592Sbms	ii->ii_igmp = igmp_domifattach(ifp);
1581189592Sbms
1582189592Sbms	return ii;
1583186119Sqingli}
1584186119Sqingli
1585186119Sqinglivoid
1586189592Sbmsin_domifdetach(struct ifnet *ifp, void *aux)
1587186119Sqingli{
1588189592Sbms	struct in_ifinfo *ii = (struct in_ifinfo *)aux;
1589186119Sqingli
1590189592Sbms	igmp_domifdetach(ifp);
1591189592Sbms	lltable_free(ii->ii_llt);
1592189592Sbms	free(ii, M_IFADDR);
1593186119Sqingli}
1594