in.c revision 149221
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 149221 2005-08-18 10:34:30Z glebius $
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>
401541Srgrimes#include <sys/socket.h>
4112704Sphk#include <sys/kernel.h>
4212704Sphk#include <sys/sysctl.h>
431541Srgrimes
441541Srgrimes#include <net/if.h>
4555009Sshin#include <net/if_types.h>
461541Srgrimes#include <net/route.h>
471541Srgrimes
481541Srgrimes#include <netinet/in.h>
491541Srgrimes#include <netinet/in_var.h>
5081127Sume#include <netinet/in_pcb.h>
511541Srgrimes
526363Sphk#include <netinet/igmp_var.h>
536363Sphk
5430354Sphkstatic MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address");
5530309Sphk
5692723Salfredstatic int in_mask2len(struct in_addr *);
5792723Salfredstatic void in_len2mask(struct in_addr *, int);
5892723Salfredstatic int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
5992723Salfred	struct ifnet *, struct thread *);
6055009Sshin
61137628Smlaierstatic int	in_addprefix(struct in_ifaddr *, int);
62137628Smlaierstatic int	in_scrubprefix(struct in_ifaddr *);
6392723Salfredstatic void	in_socktrim(struct sockaddr_in *);
6492723Salfredstatic int	in_ifinit(struct ifnet *,
6592723Salfred	    struct in_ifaddr *, struct sockaddr_in *, int);
661541Srgrimes
6718193Swollmanstatic int subnetsarelocal = 0;
68133874SrwatsonSYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
69123998Sru	&subnetsarelocal, 0, "Treat all subnets as directly connected");
70149221Sglebiusstatic int sameprefixcarponly = 0;
71149221SglebiusSYSCTL_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW,
72149221Sglebius	&sameprefixcarponly, 0,
73149221Sglebius	"Refuse to create same prefixes on different interfaces");
7421666Swollman
75148682Srwatson/*
76148682Srwatson * The IPv4 multicast list (in_multihead and associated structures) are
77148682Srwatson * protected by the global in_multi_mtx.  See in_var.h for more details.  For
78148682Srwatson * now, in_multi_mtx is marked as recursible due to IGMP's calling back into
79148682Srwatson * ip_output() to send IGMP packets while holding the lock; this probably is
80148682Srwatson * not quite desirable.
81148682Srwatson */
8221666Swollmanstruct in_multihead in_multihead; /* XXX BSS initialization */
83148682Srwatsonstruct mtx in_multi_mtx;
84148682SrwatsonMTX_SYSINIT(in_multi_mtx, &in_multi_mtx, "in_multi_mtx", MTX_DEF | MTX_RECURSE);
8521666Swollman
8681127Sumeextern struct inpcbinfo ripcbinfo;
8781127Sumeextern struct inpcbinfo udbinfo;
8881127Sume
891541Srgrimes/*
901541Srgrimes * Return 1 if an internet address is for a ``local'' host
911541Srgrimes * (one to which we have a connection).  If subnetsarelocal
921541Srgrimes * is true, this includes other subnets of the local net.
931541Srgrimes * Otherwise, it includes only the directly-connected (sub)nets.
941541Srgrimes */
951549Srgrimesint
961541Srgrimesin_localaddr(in)
971541Srgrimes	struct in_addr in;
981541Srgrimes{
991541Srgrimes	register u_long i = ntohl(in.s_addr);
1001541Srgrimes	register struct in_ifaddr *ia;
1011541Srgrimes
1021541Srgrimes	if (subnetsarelocal) {
10374362Sphk		TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
1041541Srgrimes			if ((i & ia->ia_netmask) == ia->ia_net)
1051541Srgrimes				return (1);
1061541Srgrimes	} else {
10772012Sphk		TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
1081541Srgrimes			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
1091541Srgrimes				return (1);
1101541Srgrimes	}
1111541Srgrimes	return (0);
1121541Srgrimes}
1131541Srgrimes
1141541Srgrimes/*
115133486Sandre * Return 1 if an internet address is for the local host and configured
116133486Sandre * on one of its interfaces.
117133486Sandre */
118133486Sandreint
119133486Sandrein_localip(in)
120133486Sandre	struct in_addr in;
121133486Sandre{
122133486Sandre	struct in_ifaddr *ia;
123133486Sandre
124133486Sandre	LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
125133486Sandre		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr)
126133486Sandre			return 1;
127133486Sandre	}
128133486Sandre	return 0;
129133486Sandre}
130133486Sandre
131133486Sandre/*
1321541Srgrimes * Determine whether an IP address is in a reserved set of addresses
1331541Srgrimes * that may not be forwarded, or whether datagrams to that destination
1341541Srgrimes * may be forwarded.
1351541Srgrimes */
1361549Srgrimesint
1371541Srgrimesin_canforward(in)
1381541Srgrimes	struct in_addr in;
1391541Srgrimes{
1401541Srgrimes	register u_long i = ntohl(in.s_addr);
1411541Srgrimes	register u_long net;
1421541Srgrimes
1431541Srgrimes	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
1441541Srgrimes		return (0);
1451541Srgrimes	if (IN_CLASSA(i)) {
1461541Srgrimes		net = i & IN_CLASSA_NET;
1471541Srgrimes		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
1481541Srgrimes			return (0);
1491541Srgrimes	}
1501541Srgrimes	return (1);
1511541Srgrimes}
1521541Srgrimes
1531541Srgrimes/*
1541541Srgrimes * Trim a mask in a sockaddr
1551541Srgrimes */
15612296Sphkstatic void
1571541Srgrimesin_socktrim(ap)
1581541Srgrimesstruct sockaddr_in *ap;
1591541Srgrimes{
1601541Srgrimes    register char *cplim = (char *) &ap->sin_addr;
1611541Srgrimes    register char *cp = (char *) (&ap->sin_addr + 1);
1621541Srgrimes
1631541Srgrimes    ap->sin_len = 0;
1644127Swollman    while (--cp >= cplim)
165133874Srwatson	if (*cp) {
1661541Srgrimes	    (ap)->sin_len = cp - (char *) (ap) + 1;
1671541Srgrimes	    break;
1681541Srgrimes	}
1691541Srgrimes}
1701541Srgrimes
17155009Sshinstatic int
17255009Sshinin_mask2len(mask)
17355009Sshin	struct in_addr *mask;
17455009Sshin{
17555009Sshin	int x, y;
17655009Sshin	u_char *p;
17755009Sshin
17855009Sshin	p = (u_char *)mask;
17955009Sshin	for (x = 0; x < sizeof(*mask); x++) {
18055009Sshin		if (p[x] != 0xff)
18155009Sshin			break;
18255009Sshin	}
18355009Sshin	y = 0;
18455009Sshin	if (x < sizeof(*mask)) {
18555009Sshin		for (y = 0; y < 8; y++) {
18655009Sshin			if ((p[x] & (0x80 >> y)) == 0)
18755009Sshin				break;
18855009Sshin		}
18955009Sshin	}
19055009Sshin	return x * 8 + y;
19155009Sshin}
19255009Sshin
19355009Sshinstatic void
19455009Sshinin_len2mask(mask, len)
19555009Sshin	struct in_addr *mask;
19655009Sshin	int len;
19755009Sshin{
19855009Sshin	int i;
19955009Sshin	u_char *p;
20055009Sshin
20155009Sshin	p = (u_char *)mask;
20255009Sshin	bzero(mask, sizeof(*mask));
20355009Sshin	for (i = 0; i < len / 8; i++)
20455009Sshin		p[i] = 0xff;
20555009Sshin	if (len % 8)
20655009Sshin		p[i] = (0xff00 >> (len % 8)) & 0xff;
20755009Sshin}
20855009Sshin
2091541Srgrimes/*
2101541Srgrimes * Generic internet control operations (ioctl's).
2111541Srgrimes * Ifp is 0 if not an interface-specific ioctl.
2121541Srgrimes */
2131541Srgrimes/* ARGSUSED */
2141549Srgrimesint
21583366Sjulianin_control(so, cmd, data, ifp, td)
2161541Srgrimes	struct socket *so;
21736735Sdfr	u_long cmd;
2181541Srgrimes	caddr_t data;
2191541Srgrimes	register struct ifnet *ifp;
22083366Sjulian	struct thread *td;
2211541Srgrimes{
2221541Srgrimes	register struct ifreq *ifr = (struct ifreq *)data;
22314632Sfenner	register struct in_ifaddr *ia = 0, *iap;
2241541Srgrimes	register struct ifaddr *ifa;
22584102Sjlemon	struct in_addr dst;
2261541Srgrimes	struct in_ifaddr *oia;
2271541Srgrimes	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
2281541Srgrimes	struct sockaddr_in oldaddr;
22987124Sbrian	int error, hostIsNew, iaIsNew, maskIsNew, s;
2301541Srgrimes
23187124Sbrian	iaIsNew = 0;
23287124Sbrian
23355009Sshin	switch (cmd) {
23455009Sshin	case SIOCALIFADDR:
23555009Sshin	case SIOCDLIFADDR:
23693593Sjhb		if (td && (error = suser(td)) != 0)
23755009Sshin			return error;
23855009Sshin		/*fall through*/
23955009Sshin	case SIOCGLIFADDR:
24055009Sshin		if (!ifp)
24155009Sshin			return EINVAL;
24283366Sjulian		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
24355009Sshin	}
24455009Sshin
2451541Srgrimes	/*
2461541Srgrimes	 * Find address for this interface, if it exists.
24714632Sfenner	 *
24814632Sfenner	 * If an alias address was specified, find that one instead of
24984102Sjlemon	 * the first one on the interface, if possible.
2501541Srgrimes	 */
25184102Sjlemon	if (ifp) {
25284102Sjlemon		dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
25384102Sjlemon		LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash)
25484102Sjlemon			if (iap->ia_ifp == ifp &&
25584102Sjlemon			    iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
25684102Sjlemon				ia = iap;
25784102Sjlemon				break;
25884102Sjlemon			}
25984102Sjlemon		if (ia == NULL)
26084102Sjlemon			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
26184102Sjlemon				iap = ifatoia(ifa);
26284102Sjlemon				if (iap->ia_addr.sin_family == AF_INET) {
26314632Sfenner					ia = iap;
26414632Sfenner					break;
26514632Sfenner				}
26614632Sfenner			}
26784102Sjlemon	}
2681541Srgrimes
2691541Srgrimes	switch (cmd) {
2701541Srgrimes
2711541Srgrimes	case SIOCAIFADDR:
2721541Srgrimes	case SIOCDIFADDR:
27341575Seivind		if (ifp == 0)
27441575Seivind			return (EADDRNOTAVAIL);
2758071Swollman		if (ifra->ifra_addr.sin_family == AF_INET) {
27671999Sphk			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
2778071Swollman				if (ia->ia_ifp == ifp  &&
2788071Swollman				    ia->ia_addr.sin_addr.s_addr ==
2798071Swollman				    ifra->ifra_addr.sin_addr.s_addr)
2808071Swollman					break;
2818071Swollman			}
2828876Srgrimes			if ((ifp->if_flags & IFF_POINTOPOINT)
2838071Swollman			    && (cmd == SIOCAIFADDR)
2848071Swollman			    && (ifra->ifra_dstaddr.sin_addr.s_addr
2858071Swollman				== INADDR_ANY)) {
2869563Swollman				return EDESTADDRREQ;
2878071Swollman			}
2881541Srgrimes		}
2891541Srgrimes		if (cmd == SIOCDIFADDR && ia == 0)
2901541Srgrimes			return (EADDRNOTAVAIL);
2911541Srgrimes		/* FALLTHROUGH */
2921541Srgrimes	case SIOCSIFADDR:
2931541Srgrimes	case SIOCSIFNETMASK:
2941541Srgrimes	case SIOCSIFDSTADDR:
29593593Sjhb		if (td && (error = suser(td)) != 0)
29625201Swollman			return error;
2971541Srgrimes
2981541Srgrimes		if (ifp == 0)
29941575Seivind			return (EADDRNOTAVAIL);
3001541Srgrimes		if (ia == (struct in_ifaddr *)0) {
30120407Swollman			ia = (struct in_ifaddr *)
302111119Simp				malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
30320407Swollman			if (ia == (struct in_ifaddr *)NULL)
3041541Srgrimes				return (ENOBUFS);
30515092Sdg			/*
30615092Sdg			 * Protect from ipintr() traversing address list
30715092Sdg			 * while we're modifying it.
30815092Sdg			 */
30915092Sdg			s = splnet();
31020407Swollman			TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
311108033Shsu
31220407Swollman			ifa = &ia->ia_ifa;
313108033Shsu			IFA_LOCK_INIT(ifa);
31420407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
31520407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
31620407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
317108033Shsu			ifa->ifa_refcnt = 1;
318108033Shsu			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
319108033Shsu
3201541Srgrimes			ia->ia_sockmask.sin_len = 8;
32185740Sdes			ia->ia_sockmask.sin_family = AF_INET;
3221541Srgrimes			if (ifp->if_flags & IFF_BROADCAST) {
3231541Srgrimes				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
3241541Srgrimes				ia->ia_broadaddr.sin_family = AF_INET;
3251541Srgrimes			}
3261541Srgrimes			ia->ia_ifp = ifp;
32715092Sdg			splx(s);
32887124Sbrian			iaIsNew = 1;
3291541Srgrimes		}
3301541Srgrimes		break;
3311541Srgrimes
3321541Srgrimes	case SIOCSIFBRDADDR:
33393593Sjhb		if (td && (error = suser(td)) != 0)
33425201Swollman			return error;
3351541Srgrimes		/* FALLTHROUGH */
3361541Srgrimes
3371541Srgrimes	case SIOCGIFADDR:
3381541Srgrimes	case SIOCGIFNETMASK:
3391541Srgrimes	case SIOCGIFDSTADDR:
3401541Srgrimes	case SIOCGIFBRDADDR:
3411541Srgrimes		if (ia == (struct in_ifaddr *)0)
3421541Srgrimes			return (EADDRNOTAVAIL);
3431541Srgrimes		break;
3441541Srgrimes	}
3451541Srgrimes	switch (cmd) {
3461541Srgrimes
3471541Srgrimes	case SIOCGIFADDR:
3481541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
34987124Sbrian		return (0);
3501541Srgrimes
3511541Srgrimes	case SIOCGIFBRDADDR:
3521541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
3531541Srgrimes			return (EINVAL);
3541541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
35587124Sbrian		return (0);
3561541Srgrimes
3571541Srgrimes	case SIOCGIFDSTADDR:
3581541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
3591541Srgrimes			return (EINVAL);
3601541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
36187124Sbrian		return (0);
3621541Srgrimes
3631541Srgrimes	case SIOCGIFNETMASK:
3641541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
36587124Sbrian		return (0);
3661541Srgrimes
3671541Srgrimes	case SIOCSIFDSTADDR:
3681541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
3691541Srgrimes			return (EINVAL);
3701541Srgrimes		oldaddr = ia->ia_dstaddr;
3711541Srgrimes		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
372146883Siedowse		if (ifp->if_ioctl) {
373146883Siedowse			IFF_LOCKGIANT(ifp);
374146883Siedowse			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
375146883Siedowse			    (caddr_t)ia);
376146883Siedowse			IFF_UNLOCKGIANT(ifp);
377146883Siedowse			if (error) {
378146883Siedowse				ia->ia_dstaddr = oldaddr;
379146883Siedowse				return (error);
380146883Siedowse			}
3811541Srgrimes		}
3821541Srgrimes		if (ia->ia_flags & IFA_ROUTE) {
3831541Srgrimes			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
3841541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
3851541Srgrimes			ia->ia_ifa.ifa_dstaddr =
3861541Srgrimes					(struct sockaddr *)&ia->ia_dstaddr;
3871541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
3881541Srgrimes		}
38987124Sbrian		return (0);
3901541Srgrimes
3911541Srgrimes	case SIOCSIFBRDADDR:
3921541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
3931541Srgrimes			return (EINVAL);
3941541Srgrimes		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
39587124Sbrian		return (0);
3961541Srgrimes
3971541Srgrimes	case SIOCSIFADDR:
39887124Sbrian		error = in_ifinit(ifp, ia,
39987124Sbrian		    (struct sockaddr_in *) &ifr->ifr_addr, 1);
40087124Sbrian		if (error != 0 && iaIsNew)
40187124Sbrian			break;
402126264Smlaier		if (error == 0)
403126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
40487124Sbrian		return (0);
4051541Srgrimes
4061541Srgrimes	case SIOCSIFNETMASK:
40785740Sdes		ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
40885740Sdes		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
40987124Sbrian		return (0);
4101541Srgrimes
4111541Srgrimes	case SIOCAIFADDR:
4121541Srgrimes		maskIsNew = 0;
4131541Srgrimes		hostIsNew = 1;
4141541Srgrimes		error = 0;
4151541Srgrimes		if (ia->ia_addr.sin_family == AF_INET) {
4161541Srgrimes			if (ifra->ifra_addr.sin_len == 0) {
4171541Srgrimes				ifra->ifra_addr = ia->ia_addr;
4181541Srgrimes				hostIsNew = 0;
4191541Srgrimes			} else if (ifra->ifra_addr.sin_addr.s_addr ==
4201541Srgrimes					       ia->ia_addr.sin_addr.s_addr)
4211541Srgrimes				hostIsNew = 0;
4221541Srgrimes		}
4231541Srgrimes		if (ifra->ifra_mask.sin_len) {
4241541Srgrimes			in_ifscrub(ifp, ia);
4251541Srgrimes			ia->ia_sockmask = ifra->ifra_mask;
42685740Sdes			ia->ia_sockmask.sin_family = AF_INET;
4271541Srgrimes			ia->ia_subnetmask =
4281541Srgrimes			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
4291541Srgrimes			maskIsNew = 1;
4301541Srgrimes		}
4311541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) &&
4321541Srgrimes		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
4331541Srgrimes			in_ifscrub(ifp, ia);
4341541Srgrimes			ia->ia_dstaddr = ifra->ifra_dstaddr;
4351541Srgrimes			maskIsNew  = 1; /* We lie; but the effect's the same */
4361541Srgrimes		}
4371541Srgrimes		if (ifra->ifra_addr.sin_family == AF_INET &&
4381541Srgrimes		    (hostIsNew || maskIsNew))
4391541Srgrimes			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
44087124Sbrian		if (error != 0 && iaIsNew)
44187124Sbrian			break;
44287124Sbrian
4431541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) &&
4441541Srgrimes		    (ifra->ifra_broadaddr.sin_family == AF_INET))
4451541Srgrimes			ia->ia_broadaddr = ifra->ifra_broadaddr;
446126264Smlaier		if (error == 0)
447126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
4481541Srgrimes		return (error);
4491541Srgrimes
4501541Srgrimes	case SIOCDIFADDR:
45174299Sru		/*
45274299Sru		 * in_ifscrub kills the interface route.
45374299Sru		 */
4541541Srgrimes		in_ifscrub(ifp, ia);
45515092Sdg		/*
45674299Sru		 * in_ifadown gets rid of all the rest of
45774299Sru		 * the routes.  This is not quite the right
45874299Sru		 * thing to do, but at least if we are running
45974299Sru		 * a routing process they will come back.
46074299Sru		 */
46176469Sru		in_ifadown(&ia->ia_ifa, 1);
46281127Sume		/*
46381127Sume		 * XXX horrible hack to detect that we are being called
46481127Sume		 * from if_detach()
46581127Sume		 */
466121922Ssam		if (ifaddr_byindex(ifp->if_index) == NULL) {
46798102Shsu			in_pcbpurgeif0(&ripcbinfo, ifp);
46898102Shsu			in_pcbpurgeif0(&udbinfo, ifp);
46981127Sume		}
470126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
47187124Sbrian		error = 0;
4721541Srgrimes		break;
4731541Srgrimes
4741541Srgrimes	default:
4751541Srgrimes		if (ifp == 0 || ifp->if_ioctl == 0)
4761541Srgrimes			return (EOPNOTSUPP);
477146883Siedowse		IFF_LOCKGIANT(ifp);
478146883Siedowse		error = (*ifp->if_ioctl)(ifp, cmd, data);
479146883Siedowse		IFF_UNLOCKGIANT(ifp);
480146883Siedowse		return (error);
4811541Srgrimes	}
48287124Sbrian
48387124Sbrian	/*
48487124Sbrian	 * Protect from ipintr() traversing address list while we're modifying
48587124Sbrian	 * it.
48687124Sbrian	 */
48787124Sbrian	s = splnet();
48887124Sbrian	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
48987124Sbrian	TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
49087124Sbrian	LIST_REMOVE(ia, ia_hash);
49187124Sbrian	IFAFREE(&ia->ia_ifa);
49287124Sbrian	splx(s);
49387124Sbrian
49487124Sbrian	return (error);
4951541Srgrimes}
4961541Srgrimes
4971541Srgrimes/*
49855009Sshin * SIOC[GAD]LIFADDR.
49955009Sshin *	SIOCGLIFADDR: get first address. (?!?)
50055009Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
50155009Sshin *		get first address that matches the specified prefix.
50255009Sshin *	SIOCALIFADDR: add the specified address.
50355009Sshin *	SIOCALIFADDR with IFLR_PREFIX:
50455009Sshin *		EINVAL since we can't deduce hostid part of the address.
50555009Sshin *	SIOCDLIFADDR: delete the specified address.
50655009Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
50755009Sshin *		delete the first address that matches the specified prefix.
50855009Sshin * return values:
50955009Sshin *	EINVAL on invalid parameters
51055009Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
51155009Sshin *	other values may be returned from in_ioctl()
51255009Sshin */
51355009Sshinstatic int
51483366Sjulianin_lifaddr_ioctl(so, cmd, data, ifp, td)
51555009Sshin	struct socket *so;
51655009Sshin	u_long cmd;
51755009Sshin	caddr_t	data;
51855009Sshin	struct ifnet *ifp;
51983366Sjulian	struct thread *td;
52055009Sshin{
52155009Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
52255009Sshin	struct ifaddr *ifa;
52355009Sshin
52455009Sshin	/* sanity checks */
52555009Sshin	if (!data || !ifp) {
52655009Sshin		panic("invalid argument to in_lifaddr_ioctl");
52755009Sshin		/*NOTRECHED*/
52855009Sshin	}
52955009Sshin
53055009Sshin	switch (cmd) {
53155009Sshin	case SIOCGLIFADDR:
53255009Sshin		/* address must be specified on GET with IFLR_PREFIX */
53355009Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
53455009Sshin			break;
53555009Sshin		/*FALLTHROUGH*/
53655009Sshin	case SIOCALIFADDR:
53755009Sshin	case SIOCDLIFADDR:
53855009Sshin		/* address must be specified on ADD and DELETE */
53955917Sshin		if (iflr->addr.ss_family != AF_INET)
54055009Sshin			return EINVAL;
54155917Sshin		if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
54255009Sshin			return EINVAL;
54355009Sshin		/* XXX need improvement */
54455917Sshin		if (iflr->dstaddr.ss_family
54555917Sshin		 && iflr->dstaddr.ss_family != AF_INET)
54655009Sshin			return EINVAL;
54755917Sshin		if (iflr->dstaddr.ss_family
54855917Sshin		 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
54955009Sshin			return EINVAL;
55055009Sshin		break;
55155009Sshin	default: /*shouldn't happen*/
55255009Sshin		return EOPNOTSUPP;
55355009Sshin	}
55455009Sshin	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
55555009Sshin		return EINVAL;
55655009Sshin
55755009Sshin	switch (cmd) {
55855009Sshin	case SIOCALIFADDR:
55955009Sshin	    {
56055009Sshin		struct in_aliasreq ifra;
56155009Sshin
56255009Sshin		if (iflr->flags & IFLR_PREFIX)
56355009Sshin			return EINVAL;
56455009Sshin
56555009Sshin		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
56655009Sshin		bzero(&ifra, sizeof(ifra));
56755009Sshin		bcopy(iflr->iflr_name, ifra.ifra_name,
56855009Sshin			sizeof(ifra.ifra_name));
56955009Sshin
57055917Sshin		bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
57155009Sshin
57255917Sshin		if (iflr->dstaddr.ss_family) {	/*XXX*/
57355009Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
57455917Sshin				iflr->dstaddr.ss_len);
57555009Sshin		}
57655009Sshin
57755009Sshin		ifra.ifra_mask.sin_family = AF_INET;
57855009Sshin		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
57955009Sshin		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
58055009Sshin
58183366Sjulian		return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td);
58255009Sshin	    }
58355009Sshin	case SIOCGLIFADDR:
58455009Sshin	case SIOCDLIFADDR:
58555009Sshin	    {
58655009Sshin		struct in_ifaddr *ia;
58755009Sshin		struct in_addr mask, candidate, match;
58855009Sshin		struct sockaddr_in *sin;
58955009Sshin		int cmp;
59055009Sshin
59155009Sshin		bzero(&mask, sizeof(mask));
59255009Sshin		if (iflr->flags & IFLR_PREFIX) {
59355009Sshin			/* lookup a prefix rather than address. */
59455009Sshin			in_len2mask(&mask, iflr->prefixlen);
59555009Sshin
59655009Sshin			sin = (struct sockaddr_in *)&iflr->addr;
59755009Sshin			match.s_addr = sin->sin_addr.s_addr;
59855009Sshin			match.s_addr &= mask.s_addr;
59955009Sshin
60055009Sshin			/* if you set extra bits, that's wrong */
60155009Sshin			if (match.s_addr != sin->sin_addr.s_addr)
60255009Sshin				return EINVAL;
60355009Sshin
60455009Sshin			cmp = 1;
60555009Sshin		} else {
60655009Sshin			if (cmd == SIOCGLIFADDR) {
60755009Sshin				/* on getting an address, take the 1st match */
60855009Sshin				cmp = 0;	/*XXX*/
60955009Sshin			} else {
61055009Sshin				/* on deleting an address, do exact match */
61155009Sshin				in_len2mask(&mask, 32);
61255009Sshin				sin = (struct sockaddr_in *)&iflr->addr;
61355009Sshin				match.s_addr = sin->sin_addr.s_addr;
61455009Sshin
61555009Sshin				cmp = 1;
61655009Sshin			}
61755009Sshin		}
61855009Sshin
61955009Sshin		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)	{
62055009Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
62155009Sshin				continue;
62255009Sshin			if (!cmp)
62355009Sshin				break;
62455009Sshin			candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
62555009Sshin			candidate.s_addr &= mask.s_addr;
62655009Sshin			if (candidate.s_addr == match.s_addr)
62755009Sshin				break;
62855009Sshin		}
62955009Sshin		if (!ifa)
63055009Sshin			return EADDRNOTAVAIL;
63155009Sshin		ia = (struct in_ifaddr *)ifa;
63255009Sshin
63355009Sshin		if (cmd == SIOCGLIFADDR) {
63455009Sshin			/* fill in the if_laddrreq structure */
63555009Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
63655009Sshin
63755009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
63855009Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
63955009Sshin					ia->ia_dstaddr.sin_len);
64055009Sshin			} else
64155009Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
64255009Sshin
64355009Sshin			iflr->prefixlen =
64455009Sshin				in_mask2len(&ia->ia_sockmask.sin_addr);
64555009Sshin
64655009Sshin			iflr->flags = 0;	/*XXX*/
64755009Sshin
64855009Sshin			return 0;
64955009Sshin		} else {
65055009Sshin			struct in_aliasreq ifra;
65155009Sshin
65255009Sshin			/* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
65355009Sshin			bzero(&ifra, sizeof(ifra));
65455009Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
65555009Sshin				sizeof(ifra.ifra_name));
65655009Sshin
65755009Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
65855009Sshin				ia->ia_addr.sin_len);
65955009Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
66055009Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
66155009Sshin					ia->ia_dstaddr.sin_len);
66255009Sshin			}
66355009Sshin			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
66455009Sshin				ia->ia_sockmask.sin_len);
66555009Sshin
66655009Sshin			return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
66783366Sjulian					  ifp, td);
66855009Sshin		}
66955009Sshin	    }
67055009Sshin	}
67155009Sshin
67255009Sshin	return EOPNOTSUPP;	/*just for safety*/
67355009Sshin}
67455009Sshin
67555009Sshin/*
6761541Srgrimes * Delete any existing route for an interface.
6771541Srgrimes */
67822672Swollmanvoid
6791541Srgrimesin_ifscrub(ifp, ia)
6801541Srgrimes	register struct ifnet *ifp;
6811541Srgrimes	register struct in_ifaddr *ia;
6821541Srgrimes{
683137628Smlaier	in_scrubprefix(ia);
6841541Srgrimes}
6851541Srgrimes
6861541Srgrimes/*
6871541Srgrimes * Initialize an interface's internet address
6881541Srgrimes * and routing table entry.
6891541Srgrimes */
69012296Sphkstatic int
6911541Srgrimesin_ifinit(ifp, ia, sin, scrub)
6921541Srgrimes	register struct ifnet *ifp;
6931541Srgrimes	register struct in_ifaddr *ia;
6941541Srgrimes	struct sockaddr_in *sin;
6951541Srgrimes	int scrub;
6961541Srgrimes{
6971541Srgrimes	register u_long i = ntohl(sin->sin_addr.s_addr);
6981541Srgrimes	struct sockaddr_in oldaddr;
69994326Sbrian	int s = splimp(), flags = RTF_UP, error = 0;
7001541Srgrimes
7011541Srgrimes	oldaddr = ia->ia_addr;
702105748Ssuz	if (oldaddr.sin_family == AF_INET)
703105748Ssuz		LIST_REMOVE(ia, ia_hash);
7041541Srgrimes	ia->ia_addr = *sin;
705105748Ssuz	if (ia->ia_addr.sin_family == AF_INET)
706105748Ssuz		LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
707105748Ssuz		    ia, ia_hash);
7081541Srgrimes	/*
7091541Srgrimes	 * Give the interface a chance to initialize
7101541Srgrimes	 * if this is its first address,
7111541Srgrimes	 * and to validate the address if necessary.
7121541Srgrimes	 */
713146883Siedowse	if (ifp->if_ioctl) {
714146883Siedowse		IFF_LOCKGIANT(ifp);
715146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
716146883Siedowse		IFF_UNLOCKGIANT(ifp);
717146883Siedowse		if (error) {
718146883Siedowse			splx(s);
719146883Siedowse			/* LIST_REMOVE(ia, ia_hash) is done in in_control */
720146883Siedowse			ia->ia_addr = oldaddr;
721146883Siedowse			if (ia->ia_addr.sin_family == AF_INET)
722146883Siedowse				LIST_INSERT_HEAD(INADDR_HASH(
723146883Siedowse				    ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
724146883Siedowse			return (error);
725146883Siedowse		}
7261541Srgrimes	}
7271541Srgrimes	splx(s);
7281541Srgrimes	if (scrub) {
7291541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
7301541Srgrimes		in_ifscrub(ifp, ia);
7311541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
7321541Srgrimes	}
7331541Srgrimes	if (IN_CLASSA(i))
7341541Srgrimes		ia->ia_netmask = IN_CLASSA_NET;
7351541Srgrimes	else if (IN_CLASSB(i))
7361541Srgrimes		ia->ia_netmask = IN_CLASSB_NET;
7371541Srgrimes	else
7381541Srgrimes		ia->ia_netmask = IN_CLASSC_NET;
7391541Srgrimes	/*
7401541Srgrimes	 * The subnet mask usually includes at least the standard network part,
7411541Srgrimes	 * but may may be smaller in the case of supernetting.
7421541Srgrimes	 * If it is set, we believe it.
7431541Srgrimes	 */
7441541Srgrimes	if (ia->ia_subnetmask == 0) {
7451541Srgrimes		ia->ia_subnetmask = ia->ia_netmask;
7461541Srgrimes		ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
7471541Srgrimes	} else
7481541Srgrimes		ia->ia_netmask &= ia->ia_subnetmask;
7491541Srgrimes	ia->ia_net = i & ia->ia_netmask;
7501541Srgrimes	ia->ia_subnet = i & ia->ia_subnetmask;
7511541Srgrimes	in_socktrim(&ia->ia_sockmask);
752143868Sglebius#ifdef DEV_CARP
7531541Srgrimes	/*
754143868Sglebius	 * XXX: carp(4) does not have interface route
755143868Sglebius	 */
756143868Sglebius	if (ifp->if_type == IFT_CARP)
757143868Sglebius		return (0);
758143868Sglebius#endif
759143868Sglebius	/*
7601541Srgrimes	 * Add route for the network.
7611541Srgrimes	 */
7621541Srgrimes	ia->ia_ifa.ifa_metric = ifp->if_metric;
7631541Srgrimes	if (ifp->if_flags & IFF_BROADCAST) {
7641541Srgrimes		ia->ia_broadaddr.sin_addr.s_addr =
7651541Srgrimes			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
7661541Srgrimes		ia->ia_netbroadcast.s_addr =
7671541Srgrimes			htonl(ia->ia_net | ~ ia->ia_netmask);
7681541Srgrimes	} else if (ifp->if_flags & IFF_LOOPBACK) {
769137833Smlaier		ia->ia_dstaddr = ia->ia_addr;
7701541Srgrimes		flags |= RTF_HOST;
7711541Srgrimes	} else if (ifp->if_flags & IFF_POINTOPOINT) {
7721541Srgrimes		if (ia->ia_dstaddr.sin_family != AF_INET)
7731541Srgrimes			return (0);
7741541Srgrimes		flags |= RTF_HOST;
7751541Srgrimes	}
776137628Smlaier	if ((error = in_addprefix(ia, flags)) != 0)
777137628Smlaier		return (error);
77894326Sbrian
7791541Srgrimes	/*
7801541Srgrimes	 * If the interface supports multicast, join the "all hosts"
7811541Srgrimes	 * multicast group on that interface.
7821541Srgrimes	 */
7831541Srgrimes	if (ifp->if_flags & IFF_MULTICAST) {
7841541Srgrimes		struct in_addr addr;
7851541Srgrimes
7861541Srgrimes		addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
7871541Srgrimes		in_addmulti(&addr, ifp);
7881541Srgrimes	}
7891541Srgrimes	return (error);
7901541Srgrimes}
7911541Srgrimes
792137628Smlaier#define rtinitflags(x) \
793137628Smlaier	((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
794137628Smlaier	    ? RTF_HOST : 0)
795137628Smlaier/*
796137628Smlaier * Check if we have a route for the given prefix already or add a one
797137628Smlaier * accordingly.
798137628Smlaier */
799137628Smlaierstatic int
800137628Smlaierin_addprefix(target, flags)
801137628Smlaier	struct in_ifaddr *target;
802137628Smlaier	int flags;
803137628Smlaier{
804137628Smlaier	struct in_ifaddr *ia;
805137628Smlaier	struct in_addr prefix, mask, p;
806137628Smlaier	int error;
8071541Srgrimes
808137628Smlaier	if ((flags & RTF_HOST) != 0)
809137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
810137628Smlaier	else {
811137628Smlaier		prefix = target->ia_addr.sin_addr;
812137628Smlaier		mask = target->ia_sockmask.sin_addr;
813137628Smlaier		prefix.s_addr &= mask.s_addr;
814137628Smlaier	}
815137628Smlaier
816137628Smlaier	TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
817137628Smlaier		if (rtinitflags(ia))
818137628Smlaier			p = ia->ia_dstaddr.sin_addr;
819137628Smlaier		else {
820137628Smlaier			p = ia->ia_addr.sin_addr;
821137628Smlaier			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
822137628Smlaier		}
823137628Smlaier
824137628Smlaier		if (prefix.s_addr != p.s_addr)
825137628Smlaier			continue;
826137628Smlaier
827137628Smlaier		/*
828137628Smlaier		 * If we got a matching prefix route inserted by other
829137628Smlaier		 * interface address, we are done here.
830137628Smlaier		 */
831149221Sglebius		if (ia->ia_flags & IFA_ROUTE) {
832149221Sglebius			if (sameprefixcarponly &&
833149221Sglebius			    target->ia_ifp->if_type != IFT_CARP &&
834149221Sglebius			    ia->ia_ifp->if_type != IFT_CARP)
835149221Sglebius				return (EEXIST);
836149221Sglebius			else
837149221Sglebius				return (0);
838149221Sglebius		}
839137628Smlaier	}
840137628Smlaier
841137628Smlaier	/*
842137628Smlaier	 * No-one seem to have this prefix route, so we try to insert it.
843137628Smlaier	 */
844137628Smlaier	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
845137628Smlaier	if (!error)
846137628Smlaier		target->ia_flags |= IFA_ROUTE;
847137628Smlaier	return error;
848137628Smlaier}
849137628Smlaier
8501541Srgrimes/*
851137628Smlaier * If there is no other address in the system that can serve a route to the
852137628Smlaier * same prefix, remove the route.  Hand over the route to the new address
853137628Smlaier * otherwise.
854137628Smlaier */
855137628Smlaierstatic int
856137628Smlaierin_scrubprefix(target)
857137628Smlaier	struct in_ifaddr *target;
858137628Smlaier{
859137628Smlaier	struct in_ifaddr *ia;
860137628Smlaier	struct in_addr prefix, mask, p;
861137628Smlaier	int error;
862137628Smlaier
863137628Smlaier	if ((target->ia_flags & IFA_ROUTE) == 0)
864137628Smlaier		return 0;
865137628Smlaier
866137628Smlaier	if (rtinitflags(target))
867137628Smlaier		prefix = target->ia_dstaddr.sin_addr;
868137628Smlaier	else {
869137628Smlaier		prefix = target->ia_addr.sin_addr;
870137628Smlaier		mask = target->ia_sockmask.sin_addr;
871137628Smlaier		prefix.s_addr &= mask.s_addr;
872137628Smlaier	}
873137628Smlaier
874137628Smlaier	TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
875137628Smlaier		if (rtinitflags(ia))
876137628Smlaier			p = ia->ia_dstaddr.sin_addr;
877137628Smlaier		else {
878137628Smlaier			p = ia->ia_addr.sin_addr;
879137628Smlaier			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
880137628Smlaier		}
881137628Smlaier
882137628Smlaier		if (prefix.s_addr != p.s_addr)
883137628Smlaier			continue;
884137628Smlaier
885137628Smlaier		/*
886137628Smlaier		 * If we got a matching prefix address, move IFA_ROUTE and
887137628Smlaier		 * the route itself to it.  Make sure that routing daemons
888137628Smlaier		 * get a heads-up.
889143868Sglebius		 *
890143868Sglebius		 * XXX: a special case for carp(4) interface
891137628Smlaier		 */
892143868Sglebius		if ((ia->ia_flags & IFA_ROUTE) == 0
893143868Sglebius#ifdef DEV_CARP
894143868Sglebius		    && (ia->ia_ifp->if_type != IFT_CARP)
895143868Sglebius#endif
896143868Sglebius							) {
897137628Smlaier			rtinit(&(target->ia_ifa), (int)RTM_DELETE,
898137628Smlaier			    rtinitflags(target));
899137628Smlaier			target->ia_flags &= ~IFA_ROUTE;
900137628Smlaier
901137628Smlaier			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
902137628Smlaier			    rtinitflags(ia) | RTF_UP);
903137628Smlaier			if (error == 0)
904137628Smlaier				ia->ia_flags |= IFA_ROUTE;
905137628Smlaier			return error;
906137628Smlaier		}
907137628Smlaier	}
908137628Smlaier
909137628Smlaier	/*
910137628Smlaier	 * As no-one seem to have this prefix, we can remove the route.
911137628Smlaier	 */
912137628Smlaier	rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
913137628Smlaier	target->ia_flags &= ~IFA_ROUTE;
914137628Smlaier	return 0;
915137628Smlaier}
916137628Smlaier
917137628Smlaier#undef rtinitflags
918137628Smlaier
919137628Smlaier/*
9201541Srgrimes * Return 1 if the address might be a local broadcast address.
9211541Srgrimes */
9221549Srgrimesint
9231541Srgrimesin_broadcast(in, ifp)
9241541Srgrimes	struct in_addr in;
925133874Srwatson	struct ifnet *ifp;
9261541Srgrimes{
9271541Srgrimes	register struct ifaddr *ifa;
9281541Srgrimes	u_long t;
9291541Srgrimes
9301541Srgrimes	if (in.s_addr == INADDR_BROADCAST ||
9311541Srgrimes	    in.s_addr == INADDR_ANY)
9321541Srgrimes		return 1;
9331541Srgrimes	if ((ifp->if_flags & IFF_BROADCAST) == 0)
9341541Srgrimes		return 0;
9351541Srgrimes	t = ntohl(in.s_addr);
9361541Srgrimes	/*
9371541Srgrimes	 * Look through the list of addresses for a match
9381541Srgrimes	 * with a broadcast address.
9391541Srgrimes	 */
9401541Srgrimes#define ia ((struct in_ifaddr *)ifa)
94174362Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
9421541Srgrimes		if (ifa->ifa_addr->sa_family == AF_INET &&
9431541Srgrimes		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
9441541Srgrimes		     in.s_addr == ia->ia_netbroadcast.s_addr ||
9451541Srgrimes		     /*
9461541Srgrimes		      * Check for old-style (host 0) broadcast.
9471541Srgrimes		      */
94813351Sguido		     t == ia->ia_subnet || t == ia->ia_net) &&
94913351Sguido		     /*
95013351Sguido		      * Check for an all one subnetmask. These
95113351Sguido		      * only exist when an interface gets a secondary
95213351Sguido		      * address.
95313351Sguido		      */
95413351Sguido		     ia->ia_subnetmask != (u_long)0xffffffff)
9551541Srgrimes			    return 1;
9561541Srgrimes	return (0);
9571541Srgrimes#undef ia
9581541Srgrimes}
9591541Srgrimes/*
9601541Srgrimes * Add an address to the list of IP multicast addresses for a given interface.
9611541Srgrimes */
9621541Srgrimesstruct in_multi *
9631541Srgrimesin_addmulti(ap, ifp)
9641541Srgrimes	register struct in_addr *ap;
9651541Srgrimes	register struct ifnet *ifp;
9661541Srgrimes{
9671541Srgrimes	register struct in_multi *inm;
96821666Swollman	int error;
96921666Swollman	struct sockaddr_in sin;
97021666Swollman	struct ifmultiaddr *ifma;
9711541Srgrimes
972148682Srwatson	IN_MULTI_LOCK();
9731541Srgrimes	/*
97421666Swollman	 * Call generic routine to add membership or increment
97521666Swollman	 * refcount.  It wants addresses in the form of a sockaddr,
97621666Swollman	 * so we build one here (being careful to zero the unused bytes).
9771541Srgrimes	 */
97821666Swollman	bzero(&sin, sizeof sin);
97921666Swollman	sin.sin_family = AF_INET;
98021666Swollman	sin.sin_len = sizeof sin;
98121666Swollman	sin.sin_addr = *ap;
98221666Swollman	error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
98321666Swollman	if (error) {
984148682Srwatson		IN_MULTI_UNLOCK();
98521666Swollman		return 0;
9861541Srgrimes	}
9877280Swollman
98821666Swollman	/*
98921666Swollman	 * If ifma->ifma_protospec is null, then if_addmulti() created
99021666Swollman	 * a new record.  Otherwise, we are done.
99121666Swollman	 */
992143881Sglebius	if (ifma->ifma_protospec != NULL) {
993148682Srwatson		IN_MULTI_UNLOCK();
99421666Swollman		return ifma->ifma_protospec;
99564853Sbde	}
99621666Swollman
99769781Sdwmalone	inm = (struct in_multi *)malloc(sizeof(*inm), M_IPMADDR,
99869781Sdwmalone	    M_NOWAIT | M_ZERO);
99921666Swollman	if (inm == NULL) {
1000148682Srwatson		IN_MULTI_UNLOCK();
100121666Swollman		return (NULL);
10021541Srgrimes	}
100321666Swollman
100421666Swollman	inm->inm_addr = *ap;
100521666Swollman	inm->inm_ifp = ifp;
100621666Swollman	inm->inm_ifma = ifma;
100721666Swollman	ifma->ifma_protospec = inm;
100821666Swollman	LIST_INSERT_HEAD(&in_multihead, inm, inm_link);
100921666Swollman
101021666Swollman	/*
101121666Swollman	 * Let IGMP know that we have joined a new IP multicast group.
101221666Swollman	 */
101321666Swollman	igmp_joingroup(inm);
1014148682Srwatson	IN_MULTI_UNLOCK();
10151541Srgrimes	return (inm);
10161541Srgrimes}
10171541Srgrimes
10181541Srgrimes/*
10191541Srgrimes * Delete a multicast address record.
10201541Srgrimes */
10211549Srgrimesvoid
10221541Srgrimesin_delmulti(inm)
10231541Srgrimes	register struct in_multi *inm;
10241541Srgrimes{
1025148682Srwatson	struct ifmultiaddr *ifma;
102645997Sluigi	struct in_multi my_inm;
10271541Srgrimes
1028148682Srwatson	IN_MULTI_LOCK();
1029148682Srwatson	ifma = inm->inm_ifma;
103045997Sluigi	my_inm.inm_ifp = NULL ; /* don't send the leave msg */
103121666Swollman	if (ifma->ifma_refcount == 1) {
10321541Srgrimes		/*
10331541Srgrimes		 * No remaining claims to this record; let IGMP know that
10341541Srgrimes		 * we are leaving the multicast group.
103545997Sluigi		 * But do it after the if_delmulti() which might reset
103645997Sluigi		 * the interface and nuke the packet.
10371541Srgrimes		 */
103845997Sluigi		my_inm = *inm ;
1039143881Sglebius		ifma->ifma_protospec = NULL;
104021666Swollman		LIST_REMOVE(inm, inm_link);
10411541Srgrimes		free(inm, M_IPMADDR);
10421541Srgrimes	}
104321666Swollman	/* XXX - should be separate API for when we have an ifma? */
104421666Swollman	if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
104545997Sluigi	if (my_inm.inm_ifp != NULL)
104645997Sluigi		igmp_leavegroup(&my_inm);
1047148682Srwatson	IN_MULTI_UNLOCK();
10481541Srgrimes}
1049