in.c revision 24204
11541Srgrimes/*
21541Srgrimes * Copyright (c) 1982, 1986, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 3. All advertising materials mentioning features or use of this software
141541Srgrimes *    must display the following acknowledgement:
151541Srgrimes *	This product includes software developed by the University of
161541Srgrimes *	California, Berkeley and its contributors.
171541Srgrimes * 4. Neither the name of the University nor the names of its contributors
181541Srgrimes *    may be used to endorse or promote products derived from this software
191541Srgrimes *    without specific prior written permission.
201541Srgrimes *
211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311541Srgrimes * SUCH DAMAGE.
321541Srgrimes *
3310939Swollman *	@(#)in.c	8.4 (Berkeley) 1/9/95
3424204Sbde *	$Id: in.c,v 1.32 1997/02/22 09:41:27 peter Exp $
351541Srgrimes */
361541Srgrimes
371541Srgrimes#include <sys/param.h>
3814546Sdg#include <sys/queue.h>
391549Srgrimes#include <sys/systm.h>
4024204Sbde#include <sys/sockio.h>
411541Srgrimes#include <sys/errno.h>
421541Srgrimes#include <sys/malloc.h>
431541Srgrimes#include <sys/socket.h>
441541Srgrimes#include <sys/socketvar.h>
4512704Sphk#include <sys/kernel.h>
4612704Sphk#include <sys/sysctl.h>
471541Srgrimes
481541Srgrimes#include <net/if.h>
491541Srgrimes#include <net/route.h>
501541Srgrimes
511541Srgrimes#include <netinet/in_systm.h>
521541Srgrimes#include <netinet/in.h>
531541Srgrimes#include <netinet/in_var.h>
541541Srgrimes#include <netinet/if_ether.h>
551541Srgrimes
566363Sphk#include <netinet/igmp_var.h>
576363Sphk
5812296Sphkstatic void	in_socktrim __P((struct sockaddr_in *));
5912296Sphkstatic int	in_ifinit __P((struct ifnet *,
6012296Sphk	    struct in_ifaddr *, struct sockaddr_in *, int));
611541Srgrimes
6218193Swollmanstatic int subnetsarelocal = 0;
6312704SphkSYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
6412704Sphk	&subnetsarelocal, 0, "");
6521666Swollman
6621666Swollmanstruct in_multihead in_multihead; /* XXX BSS initialization */
6721666Swollman
681541Srgrimes/*
691541Srgrimes * Return 1 if an internet address is for a ``local'' host
701541Srgrimes * (one to which we have a connection).  If subnetsarelocal
711541Srgrimes * is true, this includes other subnets of the local net.
721541Srgrimes * Otherwise, it includes only the directly-connected (sub)nets.
731541Srgrimes */
741549Srgrimesint
751541Srgrimesin_localaddr(in)
761541Srgrimes	struct in_addr in;
771541Srgrimes{
781541Srgrimes	register u_long i = ntohl(in.s_addr);
791541Srgrimes	register struct in_ifaddr *ia;
801541Srgrimes
811541Srgrimes	if (subnetsarelocal) {
8220407Swollman		for (ia = in_ifaddrhead.tqh_first; ia;
8320407Swollman		     ia = ia->ia_link.tqe_next)
841541Srgrimes			if ((i & ia->ia_netmask) == ia->ia_net)
851541Srgrimes				return (1);
861541Srgrimes	} else {
8720407Swollman		for (ia = in_ifaddrhead.tqh_first; ia;
8820407Swollman		     ia = ia->ia_link.tqe_next)
891541Srgrimes			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
901541Srgrimes				return (1);
911541Srgrimes	}
921541Srgrimes	return (0);
931541Srgrimes}
941541Srgrimes
951541Srgrimes/*
961541Srgrimes * Determine whether an IP address is in a reserved set of addresses
971541Srgrimes * that may not be forwarded, or whether datagrams to that destination
981541Srgrimes * may be forwarded.
991541Srgrimes */
1001549Srgrimesint
1011541Srgrimesin_canforward(in)
1021541Srgrimes	struct in_addr in;
1031541Srgrimes{
1041541Srgrimes	register u_long i = ntohl(in.s_addr);
1051541Srgrimes	register u_long net;
1061541Srgrimes
1071541Srgrimes	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
1081541Srgrimes		return (0);
1091541Srgrimes	if (IN_CLASSA(i)) {
1101541Srgrimes		net = i & IN_CLASSA_NET;
1111541Srgrimes		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
1121541Srgrimes			return (0);
1131541Srgrimes	}
1141541Srgrimes	return (1);
1151541Srgrimes}
1161541Srgrimes
1171541Srgrimes/*
1181541Srgrimes * Trim a mask in a sockaddr
1191541Srgrimes */
12012296Sphkstatic void
1211541Srgrimesin_socktrim(ap)
1221541Srgrimesstruct sockaddr_in *ap;
1231541Srgrimes{
1241541Srgrimes    register char *cplim = (char *) &ap->sin_addr;
1251541Srgrimes    register char *cp = (char *) (&ap->sin_addr + 1);
1261541Srgrimes
1271541Srgrimes    ap->sin_len = 0;
1284127Swollman    while (--cp >= cplim)
1291541Srgrimes        if (*cp) {
1301541Srgrimes	    (ap)->sin_len = cp - (char *) (ap) + 1;
1311541Srgrimes	    break;
1321541Srgrimes	}
1331541Srgrimes}
1341541Srgrimes
13512704Sphkstatic int in_interfaces;	/* number of external internet interfaces */
1361541Srgrimes
1371541Srgrimes/*
1381541Srgrimes * Generic internet control operations (ioctl's).
1391541Srgrimes * Ifp is 0 if not an interface-specific ioctl.
1401541Srgrimes */
1411541Srgrimes/* ARGSUSED */
1421549Srgrimesint
1431541Srgrimesin_control(so, cmd, data, ifp)
1441541Srgrimes	struct socket *so;
14522900Swollman	int cmd;
1461541Srgrimes	caddr_t data;
1471541Srgrimes	register struct ifnet *ifp;
1481541Srgrimes{
1491541Srgrimes	register struct ifreq *ifr = (struct ifreq *)data;
15014632Sfenner	register struct in_ifaddr *ia = 0, *iap;
1511541Srgrimes	register struct ifaddr *ifa;
1521541Srgrimes	struct in_ifaddr *oia;
1531541Srgrimes	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
1541541Srgrimes	struct sockaddr_in oldaddr;
15515092Sdg	int error, hostIsNew, maskIsNew, s;
1561541Srgrimes	u_long i;
1571541Srgrimes
1581541Srgrimes	/*
1591541Srgrimes	 * Find address for this interface, if it exists.
16014632Sfenner	 *
16114632Sfenner	 * If an alias address was specified, find that one instead of
16214632Sfenner	 * the first one on the interface.
1631541Srgrimes	 */
1641541Srgrimes	if (ifp)
16520407Swollman		for (iap = in_ifaddrhead.tqh_first; iap;
16620407Swollman		     iap = iap->ia_link.tqe_next)
16714632Sfenner			if (iap->ia_ifp == ifp) {
16814632Sfenner				if (((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr ==
16914632Sfenner				    iap->ia_addr.sin_addr.s_addr) {
17014632Sfenner					ia = iap;
17114632Sfenner					break;
17214632Sfenner				} else if (ia == NULL) {
17314632Sfenner					ia = iap;
17414632Sfenner					if (ifr->ifr_addr.sa_family != AF_INET)
17514632Sfenner						break;
17614632Sfenner				}
17714632Sfenner			}
1781541Srgrimes
1791541Srgrimes	switch (cmd) {
1801541Srgrimes
1811541Srgrimes	case SIOCAIFADDR:
1821541Srgrimes	case SIOCDIFADDR:
1838071Swollman		if (ifra->ifra_addr.sin_family == AF_INET) {
18420532Swollman			for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
1858071Swollman				if (ia->ia_ifp == ifp  &&
1868071Swollman				    ia->ia_addr.sin_addr.s_addr ==
1878071Swollman				    ifra->ifra_addr.sin_addr.s_addr)
1888071Swollman					break;
1898071Swollman			}
1908876Srgrimes			if ((ifp->if_flags & IFF_POINTOPOINT)
1918071Swollman			    && (cmd == SIOCAIFADDR)
1928071Swollman			    && (ifra->ifra_dstaddr.sin_addr.s_addr
1938071Swollman				== INADDR_ANY)) {
1949563Swollman				return EDESTADDRREQ;
1958071Swollman			}
1961541Srgrimes		}
1971541Srgrimes		if (cmd == SIOCDIFADDR && ia == 0)
1981541Srgrimes			return (EADDRNOTAVAIL);
1991541Srgrimes		/* FALLTHROUGH */
2001541Srgrimes	case SIOCSIFADDR:
2011541Srgrimes	case SIOCSIFNETMASK:
2021541Srgrimes	case SIOCSIFDSTADDR:
2031541Srgrimes		if ((so->so_state & SS_PRIV) == 0)
2041541Srgrimes			return (EPERM);
2051541Srgrimes
2061541Srgrimes		if (ifp == 0)
2071541Srgrimes			panic("in_control");
2081541Srgrimes		if (ia == (struct in_ifaddr *)0) {
20920407Swollman			ia = (struct in_ifaddr *)
21020407Swollman				malloc(sizeof *ia, M_IFADDR, M_WAITOK);
21120407Swollman			if (ia == (struct in_ifaddr *)NULL)
2121541Srgrimes				return (ENOBUFS);
21320407Swollman			bzero((caddr_t)ia, sizeof *ia);
21415092Sdg			/*
21515092Sdg			 * Protect from ipintr() traversing address list
21615092Sdg			 * while we're modifying it.
21715092Sdg			 */
21815092Sdg			s = splnet();
21920407Swollman
22020407Swollman			TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
22120407Swollman			ifa = &ia->ia_ifa;
22220407Swollman			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
22315092Sdg
22420407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
22520407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
22620407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
2271541Srgrimes			ia->ia_sockmask.sin_len = 8;
2281541Srgrimes			if (ifp->if_flags & IFF_BROADCAST) {
2291541Srgrimes				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
2301541Srgrimes				ia->ia_broadaddr.sin_family = AF_INET;
2311541Srgrimes			}
2321541Srgrimes			ia->ia_ifp = ifp;
2338090Spst			if (!(ifp->if_flags & IFF_LOOPBACK))
2341541Srgrimes				in_interfaces++;
23515092Sdg			splx(s);
2361541Srgrimes		}
2371541Srgrimes		break;
2381541Srgrimes
2391541Srgrimes	case SIOCSIFBRDADDR:
2401541Srgrimes		if ((so->so_state & SS_PRIV) == 0)
2411541Srgrimes			return (EPERM);
2421541Srgrimes		/* FALLTHROUGH */
2431541Srgrimes
2441541Srgrimes	case SIOCGIFADDR:
2451541Srgrimes	case SIOCGIFNETMASK:
2461541Srgrimes	case SIOCGIFDSTADDR:
2471541Srgrimes	case SIOCGIFBRDADDR:
2481541Srgrimes		if (ia == (struct in_ifaddr *)0)
2491541Srgrimes			return (EADDRNOTAVAIL);
2501541Srgrimes		break;
2511541Srgrimes	}
2521541Srgrimes	switch (cmd) {
2531541Srgrimes
2541541Srgrimes	case SIOCGIFADDR:
2551541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
2561541Srgrimes		break;
2571541Srgrimes
2581541Srgrimes	case SIOCGIFBRDADDR:
2591541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
2601541Srgrimes			return (EINVAL);
2611541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
2621541Srgrimes		break;
2631541Srgrimes
2641541Srgrimes	case SIOCGIFDSTADDR:
2651541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
2661541Srgrimes			return (EINVAL);
2671541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
2681541Srgrimes		break;
2691541Srgrimes
2701541Srgrimes	case SIOCGIFNETMASK:
2711541Srgrimes		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
2721541Srgrimes		break;
2731541Srgrimes
2741541Srgrimes	case SIOCSIFDSTADDR:
2751541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
2761541Srgrimes			return (EINVAL);
2771541Srgrimes		oldaddr = ia->ia_dstaddr;
2781541Srgrimes		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
2791541Srgrimes		if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
2801541Srgrimes					(ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
2811541Srgrimes			ia->ia_dstaddr = oldaddr;
2821541Srgrimes			return (error);
2831541Srgrimes		}
2841541Srgrimes		if (ia->ia_flags & IFA_ROUTE) {
2851541Srgrimes			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
2861541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
2871541Srgrimes			ia->ia_ifa.ifa_dstaddr =
2881541Srgrimes					(struct sockaddr *)&ia->ia_dstaddr;
2891541Srgrimes			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
2901541Srgrimes		}
2911541Srgrimes		break;
2921541Srgrimes
2931541Srgrimes	case SIOCSIFBRDADDR:
2941541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) == 0)
2951541Srgrimes			return (EINVAL);
2961541Srgrimes		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
2971541Srgrimes		break;
2981541Srgrimes
2991541Srgrimes	case SIOCSIFADDR:
3001541Srgrimes		return (in_ifinit(ifp, ia,
3011541Srgrimes		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
3021541Srgrimes
3031541Srgrimes	case SIOCSIFNETMASK:
3041541Srgrimes		i = ifra->ifra_addr.sin_addr.s_addr;
3051541Srgrimes		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
3061541Srgrimes		break;
3071541Srgrimes
3081541Srgrimes	case SIOCAIFADDR:
3091541Srgrimes		maskIsNew = 0;
3101541Srgrimes		hostIsNew = 1;
3111541Srgrimes		error = 0;
3121541Srgrimes		if (ia->ia_addr.sin_family == AF_INET) {
3131541Srgrimes			if (ifra->ifra_addr.sin_len == 0) {
3141541Srgrimes				ifra->ifra_addr = ia->ia_addr;
3151541Srgrimes				hostIsNew = 0;
3161541Srgrimes			} else if (ifra->ifra_addr.sin_addr.s_addr ==
3171541Srgrimes					       ia->ia_addr.sin_addr.s_addr)
3181541Srgrimes				hostIsNew = 0;
3191541Srgrimes		}
3201541Srgrimes		if (ifra->ifra_mask.sin_len) {
3211541Srgrimes			in_ifscrub(ifp, ia);
3221541Srgrimes			ia->ia_sockmask = ifra->ifra_mask;
3231541Srgrimes			ia->ia_subnetmask =
3241541Srgrimes			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
3251541Srgrimes			maskIsNew = 1;
3261541Srgrimes		}
3271541Srgrimes		if ((ifp->if_flags & IFF_POINTOPOINT) &&
3281541Srgrimes		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
3291541Srgrimes			in_ifscrub(ifp, ia);
3301541Srgrimes			ia->ia_dstaddr = ifra->ifra_dstaddr;
3311541Srgrimes			maskIsNew  = 1; /* We lie; but the effect's the same */
3321541Srgrimes		}
3331541Srgrimes		if (ifra->ifra_addr.sin_family == AF_INET &&
3341541Srgrimes		    (hostIsNew || maskIsNew))
3351541Srgrimes			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
3361541Srgrimes		if ((ifp->if_flags & IFF_BROADCAST) &&
3371541Srgrimes		    (ifra->ifra_broadaddr.sin_family == AF_INET))
3381541Srgrimes			ia->ia_broadaddr = ifra->ifra_broadaddr;
3391541Srgrimes		return (error);
3401541Srgrimes
3411541Srgrimes	case SIOCDIFADDR:
3421541Srgrimes		in_ifscrub(ifp, ia);
34315092Sdg		/*
34415092Sdg		 * Protect from ipintr() traversing address list
34515092Sdg		 * while we're modifying it.
34615092Sdg		 */
34715092Sdg		s = splnet();
34815092Sdg
34920407Swollman		ifa = &ia->ia_ifa;
35020407Swollman		TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
3511541Srgrimes		oia = ia;
35220407Swollman		TAILQ_REMOVE(&in_ifaddrhead, oia, ia_link);
35321666Swollman		IFAFREE(&oia->ia_ifa);
35415092Sdg		splx(s);
3551541Srgrimes		break;
3561541Srgrimes
3571541Srgrimes	default:
3581541Srgrimes		if (ifp == 0 || ifp->if_ioctl == 0)
3591541Srgrimes			return (EOPNOTSUPP);
3601541Srgrimes		return ((*ifp->if_ioctl)(ifp, cmd, data));
3611541Srgrimes	}
3621541Srgrimes	return (0);
3631541Srgrimes}
3641541Srgrimes
3651541Srgrimes/*
3661541Srgrimes * Delete any existing route for an interface.
3671541Srgrimes */
36822672Swollmanvoid
3691541Srgrimesin_ifscrub(ifp, ia)
3701541Srgrimes	register struct ifnet *ifp;
3711541Srgrimes	register struct in_ifaddr *ia;
3721541Srgrimes{
3731541Srgrimes
3741541Srgrimes	if ((ia->ia_flags & IFA_ROUTE) == 0)
3751541Srgrimes		return;
3761541Srgrimes	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
3771541Srgrimes		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
3781541Srgrimes	else
3791541Srgrimes		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
3801541Srgrimes	ia->ia_flags &= ~IFA_ROUTE;
3811541Srgrimes}
3821541Srgrimes
3831541Srgrimes/*
3841541Srgrimes * Initialize an interface's internet address
3851541Srgrimes * and routing table entry.
3861541Srgrimes */
38712296Sphkstatic int
3881541Srgrimesin_ifinit(ifp, ia, sin, scrub)
3891541Srgrimes	register struct ifnet *ifp;
3901541Srgrimes	register struct in_ifaddr *ia;
3911541Srgrimes	struct sockaddr_in *sin;
3921541Srgrimes	int scrub;
3931541Srgrimes{
3941541Srgrimes	register u_long i = ntohl(sin->sin_addr.s_addr);
3951541Srgrimes	struct sockaddr_in oldaddr;
3962112Swollman	int s = splimp(), flags = RTF_UP, error;
3971541Srgrimes
3981541Srgrimes	oldaddr = ia->ia_addr;
3991541Srgrimes	ia->ia_addr = *sin;
4001541Srgrimes	/*
4011541Srgrimes	 * Give the interface a chance to initialize
4021541Srgrimes	 * if this is its first address,
4031541Srgrimes	 * and to validate the address if necessary.
4041541Srgrimes	 */
4051541Srgrimes	if (ifp->if_ioctl &&
4061541Srgrimes	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
4071541Srgrimes		splx(s);
4081541Srgrimes		ia->ia_addr = oldaddr;
4091541Srgrimes		return (error);
4101541Srgrimes	}
4111541Srgrimes	splx(s);
4121541Srgrimes	if (scrub) {
4131541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
4141541Srgrimes		in_ifscrub(ifp, ia);
4151541Srgrimes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
4161541Srgrimes	}
4171541Srgrimes	if (IN_CLASSA(i))
4181541Srgrimes		ia->ia_netmask = IN_CLASSA_NET;
4191541Srgrimes	else if (IN_CLASSB(i))
4201541Srgrimes		ia->ia_netmask = IN_CLASSB_NET;
4211541Srgrimes	else
4221541Srgrimes		ia->ia_netmask = IN_CLASSC_NET;
4231541Srgrimes	/*
4241541Srgrimes	 * The subnet mask usually includes at least the standard network part,
4251541Srgrimes	 * but may may be smaller in the case of supernetting.
4261541Srgrimes	 * If it is set, we believe it.
4271541Srgrimes	 */
4281541Srgrimes	if (ia->ia_subnetmask == 0) {
4291541Srgrimes		ia->ia_subnetmask = ia->ia_netmask;
4301541Srgrimes		ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
4311541Srgrimes	} else
4321541Srgrimes		ia->ia_netmask &= ia->ia_subnetmask;
4331541Srgrimes	ia->ia_net = i & ia->ia_netmask;
4341541Srgrimes	ia->ia_subnet = i & ia->ia_subnetmask;
4351541Srgrimes	in_socktrim(&ia->ia_sockmask);
4361541Srgrimes	/*
4371541Srgrimes	 * Add route for the network.
4381541Srgrimes	 */
4391541Srgrimes	ia->ia_ifa.ifa_metric = ifp->if_metric;
4401541Srgrimes	if (ifp->if_flags & IFF_BROADCAST) {
4411541Srgrimes		ia->ia_broadaddr.sin_addr.s_addr =
4421541Srgrimes			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
4431541Srgrimes		ia->ia_netbroadcast.s_addr =
4441541Srgrimes			htonl(ia->ia_net | ~ ia->ia_netmask);
4451541Srgrimes	} else if (ifp->if_flags & IFF_LOOPBACK) {
4461541Srgrimes		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
4471541Srgrimes		flags |= RTF_HOST;
4481541Srgrimes	} else if (ifp->if_flags & IFF_POINTOPOINT) {
4491541Srgrimes		if (ia->ia_dstaddr.sin_family != AF_INET)
4501541Srgrimes			return (0);
4511541Srgrimes		flags |= RTF_HOST;
4521541Srgrimes	}
4531541Srgrimes	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
4541541Srgrimes		ia->ia_flags |= IFA_ROUTE;
4557280Swollman
4561541Srgrimes	/*
4571541Srgrimes	 * If the interface supports multicast, join the "all hosts"
4581541Srgrimes	 * multicast group on that interface.
4591541Srgrimes	 */
4601541Srgrimes	if (ifp->if_flags & IFF_MULTICAST) {
4611541Srgrimes		struct in_addr addr;
4621541Srgrimes
4631541Srgrimes		addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
4641541Srgrimes		in_addmulti(&addr, ifp);
4651541Srgrimes	}
4661541Srgrimes	return (error);
4671541Srgrimes}
4681541Srgrimes
4691541Srgrimes
4701541Srgrimes/*
4711541Srgrimes * Return 1 if the address might be a local broadcast address.
4721541Srgrimes */
4731549Srgrimesint
4741541Srgrimesin_broadcast(in, ifp)
4751541Srgrimes	struct in_addr in;
4761541Srgrimes        struct ifnet *ifp;
4771541Srgrimes{
4781541Srgrimes	register struct ifaddr *ifa;
4791541Srgrimes	u_long t;
4801541Srgrimes
4811541Srgrimes	if (in.s_addr == INADDR_BROADCAST ||
4821541Srgrimes	    in.s_addr == INADDR_ANY)
4831541Srgrimes		return 1;
4841541Srgrimes	if ((ifp->if_flags & IFF_BROADCAST) == 0)
4851541Srgrimes		return 0;
4861541Srgrimes	t = ntohl(in.s_addr);
4871541Srgrimes	/*
4881541Srgrimes	 * Look through the list of addresses for a match
4891541Srgrimes	 * with a broadcast address.
4901541Srgrimes	 */
4911541Srgrimes#define ia ((struct in_ifaddr *)ifa)
49220407Swollman	for (ifa = ifp->if_addrhead.tqh_first; ifa;
49320407Swollman	     ifa = ifa->ifa_link.tqe_next)
4941541Srgrimes		if (ifa->ifa_addr->sa_family == AF_INET &&
4951541Srgrimes		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
4961541Srgrimes		     in.s_addr == ia->ia_netbroadcast.s_addr ||
4971541Srgrimes		     /*
4981541Srgrimes		      * Check for old-style (host 0) broadcast.
4991541Srgrimes		      */
50013351Sguido		     t == ia->ia_subnet || t == ia->ia_net) &&
50113351Sguido		     /*
50213351Sguido		      * Check for an all one subnetmask. These
50313351Sguido		      * only exist when an interface gets a secondary
50413351Sguido		      * address.
50513351Sguido		      */
50613351Sguido		     ia->ia_subnetmask != (u_long)0xffffffff)
5071541Srgrimes			    return 1;
5081541Srgrimes	return (0);
5091541Srgrimes#undef ia
5101541Srgrimes}
5111541Srgrimes/*
5121541Srgrimes * Add an address to the list of IP multicast addresses for a given interface.
5131541Srgrimes */
5141541Srgrimesstruct in_multi *
5151541Srgrimesin_addmulti(ap, ifp)
5161541Srgrimes	register struct in_addr *ap;
5171541Srgrimes	register struct ifnet *ifp;
5181541Srgrimes{
5191541Srgrimes	register struct in_multi *inm;
52021666Swollman	int error;
52121666Swollman	struct sockaddr_in sin;
52221666Swollman	struct ifmultiaddr *ifma;
5231541Srgrimes	int s = splnet();
5241541Srgrimes
5251541Srgrimes	/*
52621666Swollman	 * Call generic routine to add membership or increment
52721666Swollman	 * refcount.  It wants addresses in the form of a sockaddr,
52821666Swollman	 * so we build one here (being careful to zero the unused bytes).
5291541Srgrimes	 */
53021666Swollman	bzero(&sin, sizeof sin);
53121666Swollman	sin.sin_family = AF_INET;
53221666Swollman	sin.sin_len = sizeof sin;
53321666Swollman	sin.sin_addr = *ap;
53421666Swollman	error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
53521666Swollman	if (error) {
53621666Swollman		splx(s);
53721666Swollman		return 0;
5381541Srgrimes	}
5397280Swollman
54021666Swollman	/*
54121666Swollman	 * If ifma->ifma_protospec is null, then if_addmulti() created
54221666Swollman	 * a new record.  Otherwise, we are done.
54321666Swollman	 */
54421666Swollman	if (ifma->ifma_protospec != 0)
54521666Swollman		return ifma->ifma_protospec;
54621666Swollman
54721666Swollman	/* XXX - if_addmulti uses M_WAITOK.  Can this really be called
54821666Swollman	   at interrupt time?  If so, need to fix if_addmulti. XXX */
54921666Swollman	inm = (struct in_multi *)malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT);
55021666Swollman	if (inm == NULL) {
55121666Swollman		splx(s);
55221666Swollman		return (NULL);
5531541Srgrimes	}
55421666Swollman
55521666Swollman	bzero(inm, sizeof *inm);
55621666Swollman	inm->inm_addr = *ap;
55721666Swollman	inm->inm_ifp = ifp;
55821666Swollman	inm->inm_ifma = ifma;
55921666Swollman	ifma->ifma_protospec = inm;
56021666Swollman	LIST_INSERT_HEAD(&in_multihead, inm, inm_link);
56121666Swollman
56221666Swollman	/*
56321666Swollman	 * Let IGMP know that we have joined a new IP multicast group.
56421666Swollman	 */
56521666Swollman	igmp_joingroup(inm);
5661541Srgrimes	splx(s);
5671541Srgrimes	return (inm);
5681541Srgrimes}
5691541Srgrimes
5701541Srgrimes/*
5711541Srgrimes * Delete a multicast address record.
5721541Srgrimes */
5731549Srgrimesvoid
5741541Srgrimesin_delmulti(inm)
5751541Srgrimes	register struct in_multi *inm;
5761541Srgrimes{
57721666Swollman	struct ifmultiaddr *ifma = inm->inm_ifma;
5781541Srgrimes	int s = splnet();
5791541Srgrimes
58021666Swollman	if (ifma->ifma_refcount == 1) {
5811541Srgrimes		/*
5821541Srgrimes		 * No remaining claims to this record; let IGMP know that
5831541Srgrimes		 * we are leaving the multicast group.
5841541Srgrimes		 */
5851541Srgrimes		igmp_leavegroup(inm);
58621666Swollman		ifma->ifma_protospec = 0;
58721666Swollman		LIST_REMOVE(inm, inm_link);
5881541Srgrimes		free(inm, M_IPMADDR);
5891541Srgrimes	}
59021666Swollman	/* XXX - should be separate API for when we have an ifma? */
59121666Swollman	if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
5921541Srgrimes	splx(s);
5931541Srgrimes}
594