in.c revision 168032
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
3150477Speter * $FreeBSD: head/sys/netinet/in.c 168032 2007-03-29 21:39:22Z bms $
321541Srgrimes */
331541Srgrimes
34143868Sglebius#include "opt_carp.h"
35143868Sglebius
361541Srgrimes#include <sys/param.h>
371549Srgrimes#include <sys/systm.h>
3824204Sbde#include <sys/sockio.h>
391541Srgrimes#include <sys/malloc.h>
40164033Srwatson#include <sys/priv.h>
411541Srgrimes#include <sys/socket.h>
4212704Sphk#include <sys/kernel.h>
4312704Sphk#include <sys/sysctl.h>
441541Srgrimes
451541Srgrimes#include <net/if.h>
4655009Sshin#include <net/if_types.h>
471541Srgrimes#include <net/route.h>
481541Srgrimes
491541Srgrimes#include <netinet/in.h>
501541Srgrimes#include <netinet/in_var.h>
5181127Sume#include <netinet/in_pcb.h>
521541Srgrimes
536363Sphk#include <netinet/igmp_var.h>
546363Sphk
5530354Sphkstatic MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address");
5630309Sphk
5792723Salfredstatic int in_mask2len(struct in_addr *);
5892723Salfredstatic void in_len2mask(struct in_addr *, int);
5992723Salfredstatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
6092723Salfred	struct ifnet *, struct thread *);
6155009Sshin
62137628Smlaierstatic int	in_addprefix(struct in_ifaddr *, int);
63137628Smlaierstatic int	in_scrubprefix(struct in_ifaddr *);
6492723Salfredstatic void	in_socktrim(struct sockaddr_in *);
6592723Salfredstatic int	in_ifinit(struct ifnet *,
6692723Salfred	    struct in_ifaddr *, struct sockaddr_in *, int);
67167729Sbmsstatic void	in_purgemaddrs(struct ifnet *);
681541Srgrimes
6918193Swollmanstatic int subnetsarelocal = 0;
70133874SrwatsonSYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
71123998Sru	&subnetsarelocal, 0, "Treat all subnets as directly connected");
72149221Sglebiusstatic int sameprefixcarponly = 0;
73149221SglebiusSYSCTL_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW,
74149221Sglebius	&sameprefixcarponly, 0,
75149221Sglebius	"Refuse to create same prefixes on different interfaces");
7621666Swollman
77148682Srwatson/*
78148682Srwatson * The IPv4 multicast list (in_multihead and associated structures) are
79148682Srwatson * protected by the global in_multi_mtx.  See in_var.h for more details.  For
80148682Srwatson * now, in_multi_mtx is marked as recursible due to IGMP's calling back into
81148682Srwatson * ip_output() to send IGMP packets while holding the lock; this probably is
82148682Srwatson * not quite desirable.
83148682Srwatson */
8421666Swollmanstruct in_multihead in_multihead; /* XXX BSS initialization */
85148682Srwatsonstruct mtx in_multi_mtx;
86148682SrwatsonMTX_SYSINIT(in_multi_mtx, &in_multi_mtx, "in_multi_mtx", MTX_DEF | MTX_RECURSE);
8721666Swollman
8881127Sumeextern struct inpcbinfo ripcbinfo;
8981127Sumeextern struct inpcbinfo udbinfo;
9081127Sume
911541Srgrimes/*
921541Srgrimes * Return 1 if an internet address is for a ``local'' host
931541Srgrimes * (one to which we have a connection).  If subnetsarelocal
941541Srgrimes * is true, this includes other subnets of the local net.
951541Srgrimes * Otherwise, it includes only the directly-connected (sub)nets.
961541Srgrimes */
971549Srgrimesint
981541Srgrimesin_localaddr(in)
991541Srgrimes	struct in_addr in;
1001541Srgrimes{
1011541Srgrimes	register u_long i = ntohl(in.s_addr);
1021541Srgrimes	register struct in_ifaddr *ia;
1031541Srgrimes
1041541Srgrimes	if (subnetsarelocal) {
10574362Sphk		TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
1061541Srgrimes			if ((i & ia->ia_netmask) == ia->ia_net)
1071541Srgrimes				return (1);
1081541Srgrimes	} else {
10972012Sphk		TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
1101541Srgrimes			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
1111541Srgrimes				return (1);
1121541Srgrimes	}
1131541Srgrimes	return (0);
1141541Srgrimes}
1151541Srgrimes
1161541Srgrimes/*
117133486Sandre * Return 1 if an internet address is for the local host and configured
118133486Sandre * on one of its interfaces.
119133486Sandre */
120133486Sandreint
121133486Sandrein_localip(in)
122133486Sandre	struct in_addr in;
123133486Sandre{
124133486Sandre	struct in_ifaddr *ia;
125133486Sandre
126133486Sandre	LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
127133486Sandre		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr)
128133486Sandre			return 1;
129133486Sandre	}
130133486Sandre	return 0;
131133486Sandre}
132133486Sandre
133133486Sandre/*
1341541Srgrimes * Determine whether an IP address is in a reserved set of addresses
1351541Srgrimes * that may not be forwarded, or whether datagrams to that destination
1361541Srgrimes * may be forwarded.
1371541Srgrimes */
1381549Srgrimesint
1391541Srgrimesin_canforward(in)
1401541Srgrimes	struct in_addr in;
1411541Srgrimes{
1421541Srgrimes	register u_long i = ntohl(in.s_addr);
1431541Srgrimes	register u_long net;
1441541Srgrimes
145166450Sbms	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i))
1461541Srgrimes		return (0);
1471541Srgrimes	if (IN_CLASSA(i)) {
1481541Srgrimes		net = i & IN_CLASSA_NET;
1491541Srgrimes		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
1501541Srgrimes			return (0);
1511541Srgrimes	}
1521541Srgrimes	return (1);
1531541Srgrimes}
1541541Srgrimes
1551541Srgrimes/*
1561541Srgrimes * Trim a mask in a sockaddr
1571541Srgrimes */
15812296Sphkstatic void
1591541Srgrimesin_socktrim(ap)
1601541Srgrimesstruct sockaddr_in *ap;
1611541Srgrimes{
1621541Srgrimes    register char *cplim = (char *) &ap->sin_addr;
1631541Srgrimes    register char *cp = (char *) (&ap->sin_addr + 1);
1641541Srgrimes
1651541Srgrimes    ap->sin_len = 0;
1664127Swollman    while (--cp >= cplim)
167133874Srwatson	if (*cp) {
1681541Srgrimes	    (ap)->sin_len = cp - (char *) (ap) + 1;
1691541Srgrimes	    break;
1701541Srgrimes	}
1711541Srgrimes}
1721541Srgrimes
17355009Sshinstatic int
17455009Sshinin_mask2len(mask)
17555009Sshin	struct in_addr *mask;
17655009Sshin{
17755009Sshin	int x, y;
17855009Sshin	u_char *p;
17955009Sshin
18055009Sshin	p = (u_char *)mask;
18155009Sshin	for (x = 0; x < sizeof(*mask); x++) {
18255009Sshin		if (p[x] != 0xff)
18355009Sshin			break;
18455009Sshin	}
18555009Sshin	y = 0;
18655009Sshin	if (x < sizeof(*mask)) {
18755009Sshin		for (y = 0; y < 8; y++) {
18855009Sshin			if ((p[x] & (0x80 >> y)) == 0)
18955009Sshin				break;
19055009Sshin		}
19155009Sshin	}
19255009Sshin	return x * 8 + y;
19355009Sshin}
19455009Sshin
19555009Sshinstatic void
19655009Sshinin_len2mask(mask, len)
19755009Sshin	struct in_addr *mask;
19855009Sshin	int len;
19955009Sshin{
20055009Sshin	int i;
20155009Sshin	u_char *p;
20255009Sshin
20355009Sshin	p = (u_char *)mask;
20455009Sshin	bzero(mask, sizeof(*mask));
20555009Sshin	for (i = 0; i < len / 8; i++)
20655009Sshin		p[i] = 0xff;
20755009Sshin	if (len % 8)
20855009Sshin		p[i] = (0xff00 >> (len % 8)) & 0xff;
20955009Sshin}
21055009Sshin
2111541Srgrimes/*
2121541Srgrimes * Generic internet control operations (ioctl's).
2131541Srgrimes * Ifp is 0 if not an interface-specific ioctl.
2141541Srgrimes */
2151541Srgrimes/* ARGSUSED */
2161549Srgrimesint
21783366Sjulianin_control(so, cmd, data, ifp, td)
2181541Srgrimes	struct socket *so;
21936735Sdfr	u_long cmd;
2201541Srgrimes	caddr_t data;
2211541Srgrimes	register struct ifnet *ifp;
22283366Sjulian	struct thread *td;
2231541Srgrimes{
2241541Srgrimes	register struct ifreq *ifr = (struct ifreq *)data;
22514632Sfenner	register struct in_ifaddr *ia = 0, *iap;
2261541Srgrimes	register struct ifaddr *ifa;
227168032Sbms	struct in_addr allhosts_addr;
22884102Sjlemon	struct in_addr dst;
2291541Srgrimes	struct in_ifaddr *oia;
2301541Srgrimes	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
2311541Srgrimes	struct sockaddr_in oldaddr;
23287124Sbrian	int error, hostIsNew, iaIsNew, maskIsNew, s;
233168032Sbms	int iaIsFirst;
2341541Srgrimes
235168032Sbms	iaIsFirst = 0;
23687124Sbrian	iaIsNew = 0;
237168032Sbms	allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
23887124Sbrian
23955009Sshin	switch (cmd) {
24055009Sshin	case SIOCALIFADDR:
241164033Srwatson		if (td != NULL) {
242164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
243164033Srwatson			if (error)
244164033Srwatson				return (error);
245164033Srwatson		}
246164033Srwatson		if (!ifp)
247164033Srwatson			return EINVAL;
248164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
249164033Srwatson
25055009Sshin	case SIOCDLIFADDR:
251164033Srwatson		if (td != NULL) {
252164033Srwatson			error = priv_check(td, PRIV_NET_DELIFADDR);
253164033Srwatson			if (error)
254164033Srwatson				return (error);
255164033Srwatson		}
256164033Srwatson		if (!ifp)
257164033Srwatson			return EINVAL;
258164033Srwatson		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
259164033Srwatson
26055009Sshin	case SIOCGLIFADDR:
26155009Sshin		if (!ifp)
26255009Sshin			return EINVAL;
26383366Sjulian		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
26455009Sshin	}
26555009Sshin
2661541Srgrimes	/*
2671541Srgrimes	 * Find address for this interface, if it exists.
26814632Sfenner	 *
26914632Sfenner	 * If an alias address was specified, find that one instead of
27084102Sjlemon	 * the first one on the interface, if possible.
2711541Srgrimes	 */
27284102Sjlemon	if (ifp) {
27384102Sjlemon		dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
27484102Sjlemon		LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash)
27584102Sjlemon			if (iap->ia_ifp == ifp &&
27684102Sjlemon			    iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
27784102Sjlemon				ia = iap;
27884102Sjlemon				break;
27984102Sjlemon			}
28084102Sjlemon		if (ia == NULL)
28184102Sjlemon			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
28284102Sjlemon				iap = ifatoia(ifa);
28384102Sjlemon				if (iap->ia_addr.sin_family == AF_INET) {
28414632Sfenner					ia = iap;
28514632Sfenner					break;
28614632Sfenner				}
28714632Sfenner			}
288168032Sbms		if (ia == NULL)
289168032Sbms			iaIsFirst = 1;
29084102Sjlemon	}
2911541Srgrimes
2921541Srgrimes	switch (cmd) {
2931541Srgrimes
2941541Srgrimes	case SIOCAIFADDR:
2951541Srgrimes	case SIOCDIFADDR:
29641575Seivind		if (ifp == 0)
29741575Seivind			return (EADDRNOTAVAIL);
2988071Swollman		if (ifra->ifra_addr.sin_family == AF_INET) {
29971999Sphk			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
3008071Swollman				if (ia->ia_ifp == ifp  &&
3018071Swollman				    ia->ia_addr.sin_addr.s_addr ==
3028071Swollman				    ifra->ifra_addr.sin_addr.s_addr)
3038071Swollman					break;
3048071Swollman			}
3058876Srgrimes			if ((ifp->if_flags & IFF_POINTOPOINT)
3068071Swollman			    && (cmd == SIOCAIFADDR)
3078071Swollman			    && (ifra->ifra_dstaddr.sin_addr.s_addr
3088071Swollman				== INADDR_ANY)) {
3099563Swollman				return EDESTADDRREQ;
3108071Swollman			}
3111541Srgrimes		}
3121541Srgrimes		if (cmd == SIOCDIFADDR && ia == 0)
3131541Srgrimes			return (EADDRNOTAVAIL);
3141541Srgrimes		/* FALLTHROUGH */
3151541Srgrimes	case SIOCSIFADDR:
3161541Srgrimes	case SIOCSIFNETMASK:
3171541Srgrimes	case SIOCSIFDSTADDR:
318164033Srwatson		if (td != NULL) {
319164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
320164033Srwatson			if (error)
321164033Srwatson				return (error);
322164033Srwatson		}
3231541Srgrimes
3241541Srgrimes		if (ifp == 0)
32541575Seivind			return (EADDRNOTAVAIL);
3261541Srgrimes		if (ia == (struct in_ifaddr *)0) {
32720407Swollman			ia = (struct in_ifaddr *)
328111119Simp				malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
32920407Swollman			if (ia == (struct in_ifaddr *)NULL)
3301541Srgrimes				return (ENOBUFS);
33115092Sdg			/*
33215092Sdg			 * Protect from ipintr() traversing address list
33315092Sdg			 * while we're modifying it.
33415092Sdg			 */
33515092Sdg			s = splnet();
33620407Swollman			ifa = &ia->ia_ifa;
337108033Shsu			IFA_LOCK_INIT(ifa);
33820407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
33920407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
34020407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
341108033Shsu			ifa->ifa_refcnt = 1;
342108033Shsu			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
343108033Shsu
3441541Srgrimes			ia->ia_sockmask.sin_len = 8;
34585740Sdes			ia->ia_sockmask.sin_family = AF_INET;
3461541Srgrimes			if (ifp->if_flags & IFF_BROADCAST) {
3471541Srgrimes				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
3481541Srgrimes				ia->ia_broadaddr.sin_family = AF_INET;
3491541Srgrimes			}
3501541Srgrimes			ia->ia_ifp = ifp;
351151824Sglebius
352151824Sglebius			TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
35315092Sdg			splx(s);
35487124Sbrian			iaIsNew = 1;
3551541Srgrimes		}
3561541Srgrimes		break;
3571541Srgrimes
3581541Srgrimes	case SIOCSIFBRDADDR:
359164033Srwatson		if (td != NULL) {
360164033Srwatson			error = priv_check(td, PRIV_NET_ADDIFADDR);
361164033Srwatson			if (error)
362164033Srwatson				return (error);
363164033Srwatson		}
3641541Srgrimes		/* FALLTHROUGH */
3651541Srgrimes
3661541Srgrimes	case SIOCGIFADDR:
3671541Srgrimes	case SIOCGIFNETMASK:
3681541Srgrimes	case SIOCGIFDSTADDR:
3691541Srgrimes	case SIOCGIFBRDADDR:
3701541Srgrimes		if (ia == (struct in_ifaddr *)0)
3711541Srgrimes			return (EADDRNOTAVAIL);
3721541Srgrimes		break;
3731541Srgrimes	}
3741541Srgrimes	switch (cmd) {
3751541Srgrimes
3761541Srgrimes	case SIOCGIFADDR:
3771541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
37887124Sbrian		return (0);
3791541Srgrimes
3801541Srgrimes	case SIOCGIFBRDADDR:
3811541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
3821541Srgrimes			return (EINVAL);
3831541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
38487124Sbrian		return (0);
3851541Srgrimes
3861541Srgrimes	case SIOCGIFDSTADDR:
3871541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
3881541Srgrimes			return (EINVAL);
3891541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
39087124Sbrian		return (0);
3911541Srgrimes
3921541Srgrimes	case SIOCGIFNETMASK:
3931541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
39487124Sbrian		return (0);
3951541Srgrimes
3961541Srgrimes	case SIOCSIFDSTADDR:
3971541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
3981541Srgrimes			return (EINVAL);
3991541Srgrimes		oldaddr = ia->ia_dstaddr;
4001541Srgrimes		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
401146883Siedowse		if (ifp->if_ioctl) {
402146883Siedowse			IFF_LOCKGIANT(ifp);
403146883Siedowse			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
404146883Siedowse			    (caddr_t)ia);
405146883Siedowse			IFF_UNLOCKGIANT(ifp);
406146883Siedowse			if (error) {
407146883Siedowse				ia->ia_dstaddr = oldaddr;
408146883Siedowse				return (error);
409146883Siedowse			}
4101541Srgrimes		}
4111541Srgrimes		if (ia->ia_flags & IFA_ROUTE) {
4121541Srgrimes			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
4131541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
4141541Srgrimes			ia->ia_ifa.ifa_dstaddr =
4151541Srgrimes					(struct sockaddr *)&ia->ia_dstaddr;
4161541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
4171541Srgrimes		}
41887124Sbrian		return (0);
4191541Srgrimes
4201541Srgrimes	case SIOCSIFBRDADDR:
4211541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
4221541Srgrimes			return (EINVAL);
4231541Srgrimes		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
42487124Sbrian		return (0);
4251541Srgrimes
4261541Srgrimes	case SIOCSIFADDR:
42787124Sbrian		error = in_ifinit(ifp, ia,
42887124Sbrian		    (struct sockaddr_in *) &ifr->ifr_addr, 1);
42987124Sbrian		if (error != 0 && iaIsNew)
43087124Sbrian			break;
431168032Sbms		if (error == 0) {
432168032Sbms			if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
433168032Sbms				in_addmulti(&allhosts_addr, ifp);
434126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
435168032Sbms		}
43687124Sbrian		return (0);
4371541Srgrimes
4381541Srgrimes	case SIOCSIFNETMASK:
43985740Sdes		ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
44085740Sdes		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
44187124Sbrian		return (0);
4421541Srgrimes
4431541Srgrimes	case SIOCAIFADDR:
4441541Srgrimes		maskIsNew = 0;
4451541Srgrimes		hostIsNew = 1;
4461541Srgrimes		error = 0;
4471541Srgrimes		if (ia->ia_addr.sin_family == AF_INET) {
4481541Srgrimes			if (ifra->ifra_addr.sin_len == 0) {
4491541Srgrimes				ifra->ifra_addr = ia->ia_addr;
4501541Srgrimes				hostIsNew = 0;
4511541Srgrimes			} else if (ifra->ifra_addr.sin_addr.s_addr ==
4521541Srgrimes					       ia->ia_addr.sin_addr.s_addr)
4531541Srgrimes				hostIsNew = 0;
4541541Srgrimes		}
4551541Srgrimes		if (ifra->ifra_mask.sin_len) {
4561541Srgrimes			in_ifscrub(ifp, ia);
4571541Srgrimes			ia->ia_sockmask = ifra->ifra_mask;
45885740Sdes			ia->ia_sockmask.sin_family = AF_INET;
4591541Srgrimes			ia->ia_subnetmask =
4601541Srgrimes			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
4611541Srgrimes			maskIsNew = 1;
4621541Srgrimes		}
4631541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) &&
4641541Srgrimes		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
4651541Srgrimes			in_ifscrub(ifp, ia);
4661541Srgrimes			ia->ia_dstaddr = ifra->ifra_dstaddr;
4671541Srgrimes			maskIsNew  = 1; /* We lie; but the effect's the same */
4681541Srgrimes		}
4691541Srgrimes		if (ifra->ifra_addr.sin_family == AF_INET &&
4701541Srgrimes		    (hostIsNew || maskIsNew))
4711541Srgrimes			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
47287124Sbrian		if (error != 0 && iaIsNew)
47387124Sbrian			break;
47487124Sbrian
4751541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) &&
4761541Srgrimes		    (ifra->ifra_broadaddr.sin_family == AF_INET))
4771541Srgrimes			ia->ia_broadaddr = ifra->ifra_broadaddr;
478168032Sbms		if (error == 0) {
479168032Sbms			if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
480168032Sbms				in_addmulti(&allhosts_addr, ifp);
481126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
482168032Sbms		}
4831541Srgrimes		return (error);
4841541Srgrimes
4851541Srgrimes	case SIOCDIFADDR:
48674299Sru		/*
48774299Sru		 * in_ifscrub kills the interface route.
48874299Sru		 */
4891541Srgrimes		in_ifscrub(ifp, ia);
49015092Sdg		/*
49174299Sru		 * in_ifadown gets rid of all the rest of
49274299Sru		 * the routes.  This is not quite the right
49374299Sru		 * thing to do, but at least if we are running
49474299Sru		 * a routing process they will come back.
49574299Sru		 */
49676469Sru		in_ifadown(&ia->ia_ifa, 1);
497126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
49887124Sbrian		error = 0;
4991541Srgrimes		break;
5001541Srgrimes
5011541Srgrimes	default:
5021541Srgrimes		if (ifp == 0 || ifp->if_ioctl == 0)
5031541Srgrimes			return (EOPNOTSUPP);
504146883Siedowse		IFF_LOCKGIANT(ifp);
505146883Siedowse		error = (*ifp->if_ioctl)(ifp, cmd, data);
506146883Siedowse		IFF_UNLOCKGIANT(ifp);
507146883Siedowse		return (error);
5081541Srgrimes	}
50987124Sbrian
51087124Sbrian	/*
51187124Sbrian	 * Protect from ipintr() traversing address list while we're modifying
51287124Sbrian	 * it.
51387124Sbrian	 */
51487124Sbrian	s = splnet();
51587124Sbrian	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
51687124Sbrian	TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
517168032Sbms	if (ia->ia_addr.sin_family == AF_INET) {
518154777Sandre		LIST_REMOVE(ia, ia_hash);
519168032Sbms		/*
520168032Sbms		 * If this is the last IPv4 address configured on this
521168032Sbms		 * interface, leave the all-hosts group.
522168032Sbms		 * XXX: This is quite ugly because of locking and structure.
523168032Sbms		 */
524168032Sbms		oia = NULL;
525168032Sbms		IFP_TO_IA(ifp, oia);
526168032Sbms		if (oia == NULL) {
527168032Sbms			struct in_multi *inm;
528168032Sbms
529168032Sbms			IFF_LOCKGIANT(ifp);
530168032Sbms			IN_MULTI_LOCK();
531168032Sbms			IN_LOOKUP_MULTI(allhosts_addr, ifp, inm);
532168032Sbms			if (inm != NULL)
533168032Sbms				in_delmulti_locked(inm);
534168032Sbms			IN_MULTI_UNLOCK();
535168032Sbms			IFF_UNLOCKGIANT(ifp);
536168032Sbms		}
537168032Sbms	}
53887124Sbrian	IFAFREE(&ia->ia_ifa);
53987124Sbrian	splx(s);
54087124Sbrian
54187124Sbrian	return (error);
5421541Srgrimes}
5431541Srgrimes
5441541Srgrimes/*
54555009Sshin * SIOC[GAD]LIFADDR.
54655009Sshin *	SIOCGLIFADDR: get first address. (?!?)
54755009Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
54855009Sshin *		get first address that matches the specified prefix.
54955009Sshin *	SIOCALIFADDR: add the specified address.
55055009Sshin *	SIOCALIFADDR with IFLR_PREFIX:
55155009Sshin *		EINVAL since we can't deduce hostid part of the address.
55255009Sshin *	SIOCDLIFADDR: delete the specified address.
55355009Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
55455009Sshin *		delete the first address that matches the specified prefix.
55555009Sshin * return values:
55655009Sshin *	EINVAL on invalid parameters
55755009Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
55855009Sshin *	other values may be returned from in_ioctl()
55955009Sshin */
56055009Sshinstatic int
56183366Sjulianin_lifaddr_ioctl(so, cmd, data, ifp, td)
56255009Sshin	struct socket *so;
56355009Sshin	u_long cmd;
56455009Sshin	caddr_t	data;
56555009Sshin	struct ifnet *ifp;
56683366Sjulian	struct thread *td;
56755009Sshin{
56855009Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
56955009Sshin	struct ifaddr *ifa;
57055009Sshin
57155009Sshin	/* sanity checks */
57255009Sshin	if (!data || !ifp) {
57355009Sshin		panic("invalid argument to in_lifaddr_ioctl");
57455009Sshin		/*NOTRECHED*/
57555009Sshin	}
57655009Sshin
57755009Sshin	switch (cmd) {
57855009Sshin	case SIOCGLIFADDR:
57955009Sshin		/* address must be specified on GET with IFLR_PREFIX */
58055009Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
58155009Sshin			break;
58255009Sshin		/*FALLTHROUGH*/
58355009Sshin	case SIOCALIFADDR:
58455009Sshin	case SIOCDLIFADDR:
58555009Sshin		/* address must be specified on ADD and DELETE */
58655917Sshin		if (iflr->addr.ss_family != AF_INET)
58755009Sshin			return EINVAL;
58855917Sshin		if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
58955009Sshin			return EINVAL;
59055009Sshin		/* XXX need improvement */
59155917Sshin		if (iflr->dstaddr.ss_family
59255917Sshin		 && iflr->dstaddr.ss_family != AF_INET)
59355009Sshin			return EINVAL;
59455917Sshin		if (iflr->dstaddr.ss_family
59555917Sshin		 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
59655009Sshin			return EINVAL;
59755009Sshin		break;
59855009Sshin	default: /*shouldn't happen*/
59955009Sshin		return EOPNOTSUPP;
60055009Sshin	}
60155009Sshin	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
60255009Sshin		return EINVAL;
60355009Sshin
60455009Sshin	switch (cmd) {
60555009Sshin	case SIOCALIFADDR:
60655009Sshin	    {
60755009Sshin		struct in_aliasreq ifra;
60855009Sshin
60955009Sshin		if (iflr->flags & IFLR_PREFIX)
61055009Sshin			return EINVAL;
61155009Sshin
61255009Sshin		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
61355009Sshin		bzero(&ifra, sizeof(ifra));
61455009Sshin		bcopy(iflr->iflr_name, ifra.ifra_name,
61555009Sshin			sizeof(ifra.ifra_name));
61655009Sshin
61755917Sshin		bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
61855009Sshin
61955917Sshin		if (iflr->dstaddr.ss_family) {	/*XXX*/
62055009Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
62155917Sshin				iflr->dstaddr.ss_len);
62255009Sshin		}
62355009Sshin
62455009Sshin		ifra.ifra_mask.sin_family = AF_INET;
62555009Sshin		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
62655009Sshin		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
62755009Sshin
62883366Sjulian		return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td);
62955009Sshin	    }
63055009Sshin	case SIOCGLIFADDR:
63155009Sshin	case SIOCDLIFADDR:
63255009Sshin	    {
63355009Sshin		struct in_ifaddr *ia;
63455009Sshin		struct in_addr mask, candidate, match;
63555009Sshin		struct sockaddr_in *sin;
63655009Sshin		int cmp;
63755009Sshin
63855009Sshin		bzero(&mask, sizeof(mask));
63955009Sshin		if (iflr->flags & IFLR_PREFIX) {
64055009Sshin			/* lookup a prefix rather than address. */
64155009Sshin			in_len2mask(&mask, iflr->prefixlen);
64255009Sshin
64355009Sshin			sin = (struct sockaddr_in *)&iflr->addr;
64455009Sshin			match.s_addr = sin->sin_addr.s_addr;
64555009Sshin			match.s_addr &= mask.s_addr;
64655009Sshin
64755009Sshin			/* if you set extra bits, that's wrong */
64855009Sshin			if (match.s_addr != sin->sin_addr.s_addr)
64955009Sshin				return EINVAL;
65055009Sshin
65155009Sshin			cmp = 1;
65255009Sshin		} else {
65355009Sshin			if (cmd == SIOCGLIFADDR) {
65455009Sshin				/* on getting an address, take the 1st match */
65555009Sshin				cmp = 0;	/*XXX*/
65655009Sshin			} else {
65755009Sshin				/* on deleting an address, do exact match */
65855009Sshin				in_len2mask(&mask, 32);
65955009Sshin				sin = (struct sockaddr_in *)&iflr->addr;
66055009Sshin				match.s_addr = sin->sin_addr.s_addr;
66155009Sshin
66255009Sshin				cmp = 1;
66355009Sshin			}
66455009Sshin		}
66555009Sshin
66655009Sshin		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)	{
66755009Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
66855009Sshin				continue;
66955009Sshin			if (!cmp)
67055009Sshin				break;
67155009Sshin			candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
67255009Sshin			candidate.s_addr &= mask.s_addr;
67355009Sshin			if (candidate.s_addr == match.s_addr)
67455009Sshin				break;
67555009Sshin		}
67655009Sshin		if (!ifa)
67755009Sshin			return EADDRNOTAVAIL;
67855009Sshin		ia = (struct in_ifaddr *)ifa;
67955009Sshin
68055009Sshin		if (cmd == SIOCGLIFADDR) {
68155009Sshin			/* fill in the if_laddrreq structure */
68255009Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
68355009Sshin
68455009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
68555009Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
68655009Sshin					ia->ia_dstaddr.sin_len);
68755009Sshin			} else
68855009Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
68955009Sshin
69055009Sshin			iflr->prefixlen =
69155009Sshin				in_mask2len(&ia->ia_sockmask.sin_addr);
69255009Sshin
69355009Sshin			iflr->flags = 0;	/*XXX*/
69455009Sshin
69555009Sshin			return 0;
69655009Sshin		} else {
69755009Sshin			struct in_aliasreq ifra;
69855009Sshin
69955009Sshin			/* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
70055009Sshin			bzero(&ifra, sizeof(ifra));
70155009Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
70255009Sshin				sizeof(ifra.ifra_name));
70355009Sshin
70455009Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
70555009Sshin				ia->ia_addr.sin_len);
70655009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
70755009Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
70855009Sshin					ia->ia_dstaddr.sin_len);
70955009Sshin			}
71055009Sshin			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
71155009Sshin				ia->ia_sockmask.sin_len);
71255009Sshin
71355009Sshin			return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
71483366Sjulian					  ifp, td);
71555009Sshin		}
71655009Sshin	    }
71755009Sshin	}
71855009Sshin
71955009Sshin	return EOPNOTSUPP;	/*just for safety*/
72055009Sshin}
72155009Sshin
72255009Sshin/*
7231541Srgrimes * Delete any existing route for an interface.
7241541Srgrimes */
72522672Swollmanvoid
7261541Srgrimesin_ifscrub(ifp, ia)
7271541Srgrimes	register struct ifnet *ifp;
7281541Srgrimes	register struct in_ifaddr *ia;
7291541Srgrimes{
730137628Smlaier	in_scrubprefix(ia);
7311541Srgrimes}
7321541Srgrimes
7331541Srgrimes/*
7341541Srgrimes * Initialize an interface's internet address
7351541Srgrimes * and routing table entry.
7361541Srgrimes */
73712296Sphkstatic int
7381541Srgrimesin_ifinit(ifp, ia, sin, scrub)
7391541Srgrimes	register struct ifnet *ifp;
7401541Srgrimes	register struct in_ifaddr *ia;
7411541Srgrimes	struct sockaddr_in *sin;
7421541Srgrimes	int scrub;
7431541Srgrimes{
7441541Srgrimes	register u_long i = ntohl(sin->sin_addr.s_addr);
7451541Srgrimes	struct sockaddr_in oldaddr;
74694326Sbrian	int s = splimp(), flags = RTF_UP, error = 0;
7471541Srgrimes
7481541Srgrimes	oldaddr = ia->ia_addr;
749105748Ssuz	if (oldaddr.sin_family == AF_INET)
750105748Ssuz		LIST_REMOVE(ia, ia_hash);
7511541Srgrimes	ia->ia_addr = *sin;
752105748Ssuz	if (ia->ia_addr.sin_family == AF_INET)
753105748Ssuz		LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
754105748Ssuz		    ia, ia_hash);
7551541Srgrimes	/*
7561541Srgrimes	 * Give the interface a chance to initialize
7571541Srgrimes	 * if this is its first address,
7581541Srgrimes	 * and to validate the address if necessary.
7591541Srgrimes	 */
760146883Siedowse	if (ifp->if_ioctl) {
761146883Siedowse		IFF_LOCKGIANT(ifp);
762146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
763146883Siedowse		IFF_UNLOCKGIANT(ifp);
764146883Siedowse		if (error) {
765146883Siedowse			splx(s);
766146883Siedowse			/* LIST_REMOVE(ia, ia_hash) is done in in_control */
767146883Siedowse			ia->ia_addr = oldaddr;
768146883Siedowse			if (ia->ia_addr.sin_family == AF_INET)
769146883Siedowse				LIST_INSERT_HEAD(INADDR_HASH(
770146883Siedowse				    ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
771146883Siedowse			return (error);
772146883Siedowse		}
7731541Srgrimes	}
7741541Srgrimes	splx(s);
7751541Srgrimes	if (scrub) {
7761541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
7771541Srgrimes		in_ifscrub(ifp, ia);
7781541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
7791541Srgrimes	}
7801541Srgrimes	if (IN_CLASSA(i))
7811541Srgrimes		ia->ia_netmask = IN_CLASSA_NET;
7821541Srgrimes	else if (IN_CLASSB(i))
7831541Srgrimes		ia->ia_netmask = IN_CLASSB_NET;
7841541Srgrimes	else
7851541Srgrimes		ia->ia_netmask = IN_CLASSC_NET;
7861541Srgrimes	/*
7871541Srgrimes	 * The subnet mask usually includes at least the standard network part,
7881541Srgrimes	 * but may may be smaller in the case of supernetting.
7891541Srgrimes	 * If it is set, we believe it.
7901541Srgrimes	 */
7911541Srgrimes	if (ia->ia_subnetmask == 0) {
7921541Srgrimes		ia->ia_subnetmask = ia->ia_netmask;
7931541Srgrimes		ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
7941541Srgrimes	} else
7951541Srgrimes		ia->ia_netmask &= ia->ia_subnetmask;
7961541Srgrimes	ia->ia_net = i & ia->ia_netmask;
7971541Srgrimes	ia->ia_subnet = i & ia->ia_subnetmask;
7981541Srgrimes	in_socktrim(&ia->ia_sockmask);
799143868Sglebius#ifdef DEV_CARP
8001541Srgrimes	/*
801143868Sglebius	 * XXX: carp(4) does not have interface route
802143868Sglebius	 */
803143868Sglebius	if (ifp->if_type == IFT_CARP)
804143868Sglebius		return (0);
805143868Sglebius#endif
806143868Sglebius	/*
8071541Srgrimes	 * Add route for the network.
8081541Srgrimes	 */
8091541Srgrimes	ia->ia_ifa.ifa_metric = ifp->if_metric;
8101541Srgrimes	if (ifp->if_flags & IFF_BROADCAST) {
8111541Srgrimes		ia->ia_broadaddr.sin_addr.s_addr =
8121541Srgrimes			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
8131541Srgrimes		ia->ia_netbroadcast.s_addr =
8141541Srgrimes			htonl(ia->ia_net | ~ ia->ia_netmask);
8151541Srgrimes	} else if (ifp->if_flags & IFF_LOOPBACK) {
816137833Smlaier		ia->ia_dstaddr = ia->ia_addr;
8171541Srgrimes		flags |= RTF_HOST;
8181541Srgrimes	} else if (ifp->if_flags & IFF_POINTOPOINT) {
8191541Srgrimes		if (ia->ia_dstaddr.sin_family != AF_INET)
8201541Srgrimes			return (0);
8211541Srgrimes		flags |= RTF_HOST;
8221541Srgrimes	}
823137628Smlaier	if ((error = in_addprefix(ia, flags)) != 0)
824137628Smlaier		return (error);
82594326Sbrian
8261541Srgrimes	return (error);
8271541Srgrimes}
8281541Srgrimes
829137628Smlaier#define rtinitflags(x) \
830137628Smlaier	((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
831137628Smlaier	    ? RTF_HOST : 0)
832137628Smlaier/*
833137628Smlaier * Check if we have a route for the given prefix already or add a one
834137628Smlaier * accordingly.
835137628Smlaier */
836137628Smlaierstatic int
837137628Smlaierin_addprefix(target, flags)
838137628Smlaier	struct in_ifaddr *target;
839137628Smlaier	int flags;
840137628Smlaier{
841137628Smlaier	struct in_ifaddr *ia;
842151555Sglebius	struct in_addr prefix, mask, p, m;
843137628Smlaier	int error;
8441541Srgrimes
845137628Smlaier	if ((flags & RTF_HOST) != 0)
846137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
847137628Smlaier	else {
848137628Smlaier		prefix = target->ia_addr.sin_addr;
849137628Smlaier		mask = target->ia_sockmask.sin_addr;
850137628Smlaier		prefix.s_addr &= mask.s_addr;
851137628Smlaier	}
852137628Smlaier
853137628Smlaier	TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
854151555Sglebius		if (rtinitflags(ia)) {
855137628Smlaier			p = ia->ia_addr.sin_addr;
856151555Sglebius
857151555Sglebius			if (prefix.s_addr != p.s_addr)
858151555Sglebius				continue;
859151555Sglebius		} else {
860151555Sglebius			p = ia->ia_addr.sin_addr;
861151555Sglebius			m = ia->ia_sockmask.sin_addr;
862151555Sglebius			p.s_addr &= m.s_addr;
863151555Sglebius
864151555Sglebius			if (prefix.s_addr != p.s_addr ||
865151555Sglebius			    mask.s_addr != m.s_addr)
866151555Sglebius				continue;
867137628Smlaier		}
868137628Smlaier
869137628Smlaier		/*
870137628Smlaier		 * If we got a matching prefix route inserted by other
871137628Smlaier		 * interface address, we are done here.
872137628Smlaier		 */
873149221Sglebius		if (ia->ia_flags & IFA_ROUTE) {
874149221Sglebius			if (sameprefixcarponly &&
875149221Sglebius			    target->ia_ifp->if_type != IFT_CARP &&
876149221Sglebius			    ia->ia_ifp->if_type != IFT_CARP)
877149221Sglebius				return (EEXIST);
878149221Sglebius			else
879149221Sglebius				return (0);
880149221Sglebius		}
881137628Smlaier	}
882137628Smlaier
883137628Smlaier	/*
884137628Smlaier	 * No-one seem to have this prefix route, so we try to insert it.
885137628Smlaier	 */
886137628Smlaier	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
887137628Smlaier	if (!error)
888137628Smlaier		target->ia_flags |= IFA_ROUTE;
889137628Smlaier	return error;
890137628Smlaier}
891137628Smlaier
8921541Srgrimes/*
893137628Smlaier * If there is no other address in the system that can serve a route to the
894137628Smlaier * same prefix, remove the route.  Hand over the route to the new address
895137628Smlaier * otherwise.
896137628Smlaier */
897137628Smlaierstatic int
898137628Smlaierin_scrubprefix(target)
899137628Smlaier	struct in_ifaddr *target;
900137628Smlaier{
901137628Smlaier	struct in_ifaddr *ia;
902137628Smlaier	struct in_addr prefix, mask, p;
903137628Smlaier	int error;
904137628Smlaier
905137628Smlaier	if ((target->ia_flags & IFA_ROUTE) == 0)
906137628Smlaier		return 0;
907137628Smlaier
908137628Smlaier	if (rtinitflags(target))
909137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
910137628Smlaier	else {
911137628Smlaier		prefix = target->ia_addr.sin_addr;
912137628Smlaier		mask = target->ia_sockmask.sin_addr;
913137628Smlaier		prefix.s_addr &= mask.s_addr;
914137628Smlaier	}
915137628Smlaier
916137628Smlaier	TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
917137628Smlaier		if (rtinitflags(ia))
918137628Smlaier			p = ia->ia_dstaddr.sin_addr;
919137628Smlaier		else {
920137628Smlaier			p = ia->ia_addr.sin_addr;
921137628Smlaier			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
922137628Smlaier		}
923137628Smlaier
924137628Smlaier		if (prefix.s_addr != p.s_addr)
925137628Smlaier			continue;
926137628Smlaier
927137628Smlaier		/*
928137628Smlaier		 * If we got a matching prefix address, move IFA_ROUTE and
929137628Smlaier		 * the route itself to it.  Make sure that routing daemons
930137628Smlaier		 * get a heads-up.
931143868Sglebius		 *
932143868Sglebius		 * XXX: a special case for carp(4) interface
933137628Smlaier		 */
934143868Sglebius		if ((ia->ia_flags & IFA_ROUTE) == 0
935143868Sglebius#ifdef DEV_CARP
936143868Sglebius		    && (ia->ia_ifp->if_type != IFT_CARP)
937143868Sglebius#endif
938143868Sglebius							) {
939137628Smlaier			rtinit(&(target->ia_ifa), (int)RTM_DELETE,
940137628Smlaier			    rtinitflags(target));
941137628Smlaier			target->ia_flags &= ~IFA_ROUTE;
942137628Smlaier
943137628Smlaier			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
944137628Smlaier			    rtinitflags(ia) | RTF_UP);
945137628Smlaier			if (error == 0)
946137628Smlaier				ia->ia_flags |= IFA_ROUTE;
947137628Smlaier			return error;
948137628Smlaier		}
949137628Smlaier	}
950137628Smlaier
951137628Smlaier	/*
952137628Smlaier	 * As no-one seem to have this prefix, we can remove the route.
953137628Smlaier	 */
954137628Smlaier	rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
955137628Smlaier	target->ia_flags &= ~IFA_ROUTE;
956137628Smlaier	return 0;
957137628Smlaier}
958137628Smlaier
959137628Smlaier#undef rtinitflags
960137628Smlaier
961137628Smlaier/*
9621541Srgrimes * Return 1 if the address might be a local broadcast address.
9631541Srgrimes */
9641549Srgrimesint
9651541Srgrimesin_broadcast(in, ifp)
9661541Srgrimes	struct in_addr in;
967133874Srwatson	struct ifnet *ifp;
9681541Srgrimes{
9691541Srgrimes	register struct ifaddr *ifa;
9701541Srgrimes	u_long t;
9711541Srgrimes
9721541Srgrimes	if (in.s_addr == INADDR_BROADCAST ||
9731541Srgrimes	    in.s_addr == INADDR_ANY)
9741541Srgrimes		return 1;
9751541Srgrimes	if ((ifp->if_flags & IFF_BROADCAST) == 0)
9761541Srgrimes		return 0;
9771541Srgrimes	t = ntohl(in.s_addr);
9781541Srgrimes	/*
9791541Srgrimes	 * Look through the list of addresses for a match
9801541Srgrimes	 * with a broadcast address.
9811541Srgrimes	 */
9821541Srgrimes#define ia ((struct in_ifaddr *)ifa)
98374362Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
9841541Srgrimes		if (ifa->ifa_addr->sa_family == AF_INET &&
9851541Srgrimes		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
9861541Srgrimes		     in.s_addr == ia->ia_netbroadcast.s_addr ||
9871541Srgrimes		     /*
9881541Srgrimes		      * Check for old-style (host 0) broadcast.
9891541Srgrimes		      */
99013351Sguido		     t == ia->ia_subnet || t == ia->ia_net) &&
99113351Sguido		     /*
99213351Sguido		      * Check for an all one subnetmask. These
99313351Sguido		      * only exist when an interface gets a secondary
99413351Sguido		      * address.
99513351Sguido		      */
99613351Sguido		     ia->ia_subnetmask != (u_long)0xffffffff)
9971541Srgrimes			    return 1;
9981541Srgrimes	return (0);
9991541Srgrimes#undef ia
10001541Srgrimes}
1001167729Sbms
10021541Srgrimes/*
10031541Srgrimes * Add an address to the list of IP multicast addresses for a given interface.
10041541Srgrimes */
10051541Srgrimesstruct in_multi *
1006167729Sbmsin_addmulti(struct in_addr *ap, struct ifnet *ifp)
10071541Srgrimes{
1008167729Sbms	struct in_multi *inm;
10091541Srgrimes
1010167729Sbms	inm = NULL;
1011167729Sbms
1012150852Srwatson	IFF_LOCKGIANT(ifp);
1013148682Srwatson	IN_MULTI_LOCK();
10147280Swollman
1015167729Sbms	IN_LOOKUP_MULTI(*ap, ifp, inm);
1016167729Sbms	if (inm != NULL) {
1017167729Sbms		/*
1018167729Sbms		 * If we already joined this group, just bump the
1019167729Sbms		 * refcount and return it.
1020167729Sbms		 */
1021167729Sbms		KASSERT(inm->inm_refcount >= 1,
1022167729Sbms		    ("%s: bad refcount %d", __func__, inm->inm_refcount));
1023167729Sbms		++inm->inm_refcount;
1024167729Sbms	} else do {
1025167729Sbms		struct sockaddr_in sin;
1026167729Sbms		struct ifmultiaddr *ifma;
1027167729Sbms		struct in_multi *ninm;
1028167729Sbms		int error;
102921666Swollman
1030167729Sbms		bzero(&sin, sizeof sin);
1031167729Sbms		sin.sin_family = AF_INET;
1032167729Sbms		sin.sin_len = sizeof(struct sockaddr_in);
1033167729Sbms		sin.sin_addr = *ap;
103421666Swollman
1035167729Sbms		/*
1036167729Sbms		 * Check if a link-layer group is already associated
1037167729Sbms		 * with this network-layer group on the given ifnet.
1038167729Sbms		 * If so, bump the refcount on the existing network-layer
1039167729Sbms		 * group association and return it.
1040167729Sbms		 */
1041167729Sbms		error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
1042167729Sbms		if (error)
1043167729Sbms			break;
1044167729Sbms		if (ifma->ifma_protospec != NULL) {
1045167729Sbms			inm = (struct in_multi *)ifma->ifma_protospec;
1046167729Sbms#ifdef INVARIANTS
1047167729Sbms			if (inm->inm_ifma != ifma || inm->inm_ifp != ifp ||
1048167729Sbms			    inm->inm_addr.s_addr != ap->s_addr)
1049167729Sbms				panic("%s: ifma is inconsistent", __func__);
1050167729Sbms#endif
1051167729Sbms			++inm->inm_refcount;
1052167729Sbms			break;
1053167729Sbms		}
105421666Swollman
1055167729Sbms		/*
1056167729Sbms		 * A new membership is needed; construct it and
1057167729Sbms		 * perform the IGMP join.
1058167729Sbms		 */
1059167729Sbms		ninm = malloc(sizeof(*ninm), M_IPMADDR, M_NOWAIT | M_ZERO);
1060167729Sbms		if (ninm == NULL) {
1061167729Sbms			if_delmulti_ifma(ifma);
1062167729Sbms			break;
1063167729Sbms		}
1064167729Sbms		ninm->inm_addr = *ap;
1065167729Sbms		ninm->inm_ifp = ifp;
1066167729Sbms		ninm->inm_ifma = ifma;
1067167729Sbms		ninm->inm_refcount = 1;
1068167729Sbms		ifma->ifma_protospec = ninm;
1069167729Sbms		LIST_INSERT_HEAD(&in_multihead, ninm, inm_link);
1070167729Sbms
1071167729Sbms		igmp_joingroup(ninm);
1072167729Sbms
1073167729Sbms		inm = ninm;
1074167729Sbms	} while (0);
1075167729Sbms
1076148682Srwatson	IN_MULTI_UNLOCK();
1077150852Srwatson	IFF_UNLOCKGIANT(ifp);
1078167729Sbms
10791541Srgrimes	return (inm);
10801541Srgrimes}
10811541Srgrimes
10821541Srgrimes/*
10831541Srgrimes * Delete a multicast address record.
1084167729Sbms * It is OK to call this routine if the underlying ifnet went away.
1085167729Sbms *
1086167729Sbms * XXX: To deal with the ifp going away, we cheat; the link-layer code in net
1087167729Sbms * will set ifma_ifp to NULL when the associated ifnet instance is detached
1088167729Sbms * from the system.
1089167729Sbms * The only reason we need to violate layers and check ifma_ifp here at all
1090167729Sbms * is because certain hardware drivers still require Giant to be held,
1091167729Sbms * and it must always be taken before other locks.
10921541Srgrimes */
10931549Srgrimesvoid
1094167729Sbmsin_delmulti(struct in_multi *inm)
10951541Srgrimes{
1096150852Srwatson	struct ifnet *ifp;
10971541Srgrimes
1098167729Sbms	KASSERT(inm->inm_ifma != NULL, ("%s: no ifma", __func__));
1099167729Sbms	ifp = inm->inm_ifma->ifma_ifp;
1100167729Sbms
1101167729Sbms	if (ifp != NULL) {
1102167729Sbms		/*
1103167729Sbms		 * Sanity check that netinet's notion of ifp is the
1104167729Sbms		 * same as net's.
1105167729Sbms		 */
1106167729Sbms		KASSERT(inm->inm_ifp == ifp, ("%s: bad ifp", __func__));
1107167729Sbms		IFF_LOCKGIANT(ifp);
1108167729Sbms	}
1109167729Sbms
1110148682Srwatson	IN_MULTI_LOCK();
1111162718Sbms	in_delmulti_locked(inm);
1112162718Sbms	IN_MULTI_UNLOCK();
1113167729Sbms
1114167729Sbms	if (ifp != NULL)
1115167729Sbms		IFF_UNLOCKGIANT(ifp);
1116162718Sbms}
1117162718Sbms
1118167729Sbms/*
1119167729Sbms * Delete a multicast address record, with locks held.
1120167729Sbms *
1121167729Sbms * It is OK to call this routine if the ifp went away.
1122167729Sbms * Assumes that caller holds the IN_MULTI lock, and that
1123167729Sbms * Giant was taken before other locks if required by the hardware.
1124167729Sbms */
1125162718Sbmsvoid
1126167729Sbmsin_delmulti_locked(struct in_multi *inm)
1127162718Sbms{
1128162718Sbms	struct ifmultiaddr *ifma;
1129162718Sbms
1130167729Sbms	IN_MULTI_LOCK_ASSERT();
1131167729Sbms	KASSERT(inm->inm_refcount >= 1, ("%s: freeing freed inm", __func__));
1132167729Sbms
1133167729Sbms	if (--inm->inm_refcount == 0) {
1134167729Sbms		igmp_leavegroup(inm);
1135167729Sbms
1136167729Sbms		ifma = inm->inm_ifma;
1137168032Sbms#ifdef DIAGNOSTIC
1138168032Sbms		printf("%s: purging ifma %p\n", __func__, ifma);
1139168032Sbms#endif
1140167729Sbms		KASSERT(ifma->ifma_protospec == inm,
1141167729Sbms		    ("%s: ifma_protospec != inm", __func__));
1142143881Sglebius		ifma->ifma_protospec = NULL;
1143167729Sbms
114421666Swollman		LIST_REMOVE(inm, inm_link);
11451541Srgrimes		free(inm, M_IPMADDR);
1146167729Sbms
1147167729Sbms		if_delmulti_ifma(ifma);
11481541Srgrimes	}
1149162718Sbms}
1150162718Sbms
1151162718Sbms/*
1152167729Sbms * Delete all IPv4 multicast address records, and associated link-layer
1153167729Sbms * multicast address records, associated with ifp.
1154162718Sbms */
1155167729Sbmsstatic void
1156167729Sbmsin_purgemaddrs(struct ifnet *ifp)
1157162718Sbms{
1158162718Sbms	struct in_multi *inm;
1159162718Sbms	struct in_multi *oinm;
1160162718Sbms
1161168032Sbms#ifdef DIAGNOSTIC
1162168032Sbms	printf("%s: purging ifp %p\n", __func__, ifp);
1163168032Sbms#endif
1164162718Sbms	IFF_LOCKGIANT(ifp);
1165162718Sbms	IN_MULTI_LOCK();
1166162718Sbms	LIST_FOREACH_SAFE(inm, &in_multihead, inm_link, oinm) {
1167162718Sbms		if (inm->inm_ifp == ifp)
1168162718Sbms			in_delmulti_locked(inm);
1169162718Sbms	}
1170150853Srwatson	IN_MULTI_UNLOCK();
1171150852Srwatson	IFF_UNLOCKGIANT(ifp);
11721541Srgrimes}
1173150296Srwatson
1174150296Srwatson/*
1175150296Srwatson * On interface removal, clean up IPv4 data structures hung off of the ifnet.
1176150296Srwatson */
1177150296Srwatsonvoid
1178150296Srwatsonin_ifdetach(ifp)
1179150296Srwatson	struct ifnet *ifp;
1180150296Srwatson{
1181150296Srwatson
1182150296Srwatson	in_pcbpurgeif0(&ripcbinfo, ifp);
1183150296Srwatson	in_pcbpurgeif0(&udbinfo, ifp);
1184167729Sbms	in_purgemaddrs(ifp);
1185150296Srwatson}
1186