xref: /csrg-svn/sys/netinet/in.c (revision 61335)
123175Smckusick /*
248464Skarels  * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
332787Sbostic  * All rights reserved.
423175Smckusick  *
544472Sbostic  * %sccs.include.redist.c%
632787Sbostic  *
7*61335Sbostic  *	@(#)in.c	7.33 (Berkeley) 06/04/93
823175Smckusick  */
97159Ssam 
1056531Sbostic #include <sys/param.h>
1156531Sbostic #include <sys/ioctl.h>
1256531Sbostic #include <sys/errno.h>
1356531Sbostic #include <sys/malloc.h>
1456531Sbostic #include <sys/socket.h>
1556531Sbostic #include <sys/socketvar.h>
167159Ssam 
1756531Sbostic #include <net/if.h>
1856531Sbostic #include <net/route.h>
1956531Sbostic #include <net/af.h>
2056531Sbostic 
2156531Sbostic #include <netinet/in_systm.h>
2256531Sbostic #include <netinet/in.h>
2356531Sbostic #include <netinet/in_var.h>
24*61335Sbostic #include <netinet/if_ether.h>
2556531Sbostic 
267159Ssam #ifdef INET
277159Ssam /*
288595Sroot  * Return the network number from an internet address.
297159Ssam  */
3024805Skarels u_long
317159Ssam in_netof(in)
327159Ssam 	struct in_addr in;
337159Ssam {
348937Sroot 	register u_long i = ntohl(in.s_addr);
3518377Skarels 	register u_long net;
3618377Skarels 	register struct in_ifaddr *ia;
377159Ssam 
3818377Skarels 	if (IN_CLASSA(i))
3918377Skarels 		net = i & IN_CLASSA_NET;
4018377Skarels 	else if (IN_CLASSB(i))
4118377Skarels 		net = i & IN_CLASSB_NET;
4231392Skarels 	else if (IN_CLASSC(i))
4331392Skarels 		net = i & IN_CLASSC_NET;
4454716Ssklower 	else if (IN_CLASSD(i))
4554716Ssklower 		net = i & IN_CLASSD_NET;
4618377Skarels 	else
4731392Skarels 		return (0);
4816413Skarels 
4916413Skarels 	/*
5018377Skarels 	 * Check whether network is a subnet;
5116413Skarels 	 * if so, return subnet number.
5216413Skarels 	 */
5318377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
5424805Skarels 		if (net == ia->ia_net)
5518377Skarels 			return (i & ia->ia_subnetmask);
5616413Skarels 	return (net);
577159Ssam }
587159Ssam 
5926381Skarels #ifndef SUBNETSARELOCAL
6026381Skarels #define	SUBNETSARELOCAL	1
6126381Skarels #endif
6226381Skarels int subnetsarelocal = SUBNETSARELOCAL;
6316377Skarels /*
6418377Skarels  * Return 1 if an internet address is for a ``local'' host
6526381Skarels  * (one to which we have a connection).  If subnetsarelocal
6626381Skarels  * is true, this includes other subnets of the local net.
6726381Skarels  * Otherwise, it includes only the directly-connected (sub)nets.
6817271Skarels  */
6917271Skarels in_localaddr(in)
7017271Skarels 	struct in_addr in;
7117271Skarels {
7217271Skarels 	register u_long i = ntohl(in.s_addr);
7318377Skarels 	register struct in_ifaddr *ia;
7417271Skarels 
7530697Skarels 	if (subnetsarelocal) {
7630697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
7730697Skarels 			if ((i & ia->ia_netmask) == ia->ia_net)
7830697Skarels 				return (1);
7930697Skarels 	} else {
8030697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
8130697Skarels 			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
8230697Skarels 				return (1);
8330697Skarels 	}
8418377Skarels 	return (0);
8518377Skarels }
8618377Skarels 
8731392Skarels /*
8831392Skarels  * Determine whether an IP address is in a reserved set of addresses
8931392Skarels  * that may not be forwarded, or whether datagrams to that destination
9031392Skarels  * may be forwarded.
9131392Skarels  */
9231392Skarels in_canforward(in)
9331392Skarels 	struct in_addr in;
9431392Skarels {
9531392Skarels 	register u_long i = ntohl(in.s_addr);
9631392Skarels 	register u_long net;
9731392Skarels 
9858998Ssklower 	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
9931392Skarels 		return (0);
10031392Skarels 	if (IN_CLASSA(i)) {
10131392Skarels 		net = i & IN_CLASSA_NET;
10257938Ssklower 		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
10331392Skarels 			return (0);
10431392Skarels 	}
10531392Skarels 	return (1);
10631392Skarels }
10731392Skarels 
10858998Ssklower /*
10958998Ssklower  * Trim a mask in a sockaddr
11058998Ssklower  */
11158998Ssklower void
11258998Ssklower in_socktrim(ap)
11358998Ssklower struct sockaddr_in *ap;
11458998Ssklower {
11558998Ssklower     register char *cplim = (char *) &ap->sin_addr;
11658998Ssklower     register char *cp = (char *) (&ap->sin_addr + 1);
11758998Ssklower 
11858998Ssklower     ap->sin_len = 0;
11958998Ssklower     while (--cp > cplim)
12058998Ssklower         if (*cp) {
12158998Ssklower 	    (ap)->sin_len = cp - (char *) (ap) + 1;
12258998Ssklower 	    break;
12358998Ssklower 	}
12458998Ssklower }
12558998Ssklower 
12624805Skarels int	in_interfaces;		/* number of external internet interfaces */
12724805Skarels extern	struct ifnet loif;
12824805Skarels 
12918377Skarels /*
13018377Skarels  * Generic internet control operations (ioctl's).
13118377Skarels  * Ifp is 0 if not an interface-specific ioctl.
13218377Skarels  */
13324805Skarels /* ARGSUSED */
13418377Skarels in_control(so, cmd, data, ifp)
13518377Skarels 	struct socket *so;
13618377Skarels 	int cmd;
13718377Skarels 	caddr_t data;
13818377Skarels 	register struct ifnet *ifp;
13918377Skarels {
14018377Skarels 	register struct ifreq *ifr = (struct ifreq *)data;
14118377Skarels 	register struct in_ifaddr *ia = 0;
14237471Ssklower 	register struct ifaddr *ifa;
14337471Ssklower 	struct in_ifaddr *oia;
14437471Ssklower 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
14537471Ssklower 	struct sockaddr_in oldaddr;
14637471Ssklower 	int error, hostIsNew, maskIsNew;
14737471Ssklower 	u_long i;
14818377Skarels 
14918377Skarels 	/*
15018377Skarels 	 * Find address for this interface, if it exists.
15118377Skarels 	 */
15218377Skarels 	if (ifp)
15318377Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
15418377Skarels 			if (ia->ia_ifp == ifp)
15518377Skarels 				break;
15618377Skarels 
15718377Skarels 	switch (cmd) {
15818377Skarels 
15937471Ssklower 	case SIOCAIFADDR:
16037471Ssklower 	case SIOCDIFADDR:
16137471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET)
16237471Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
16337471Ssklower 			if (ia->ia_ifp == ifp  &&
16437471Ssklower 			    ia->ia_addr.sin_addr.s_addr ==
16537471Ssklower 				ifra->ifra_addr.sin_addr.s_addr)
16637471Ssklower 			    break;
16737471Ssklower 		}
16837471Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
16937471Ssklower 			return (EADDRNOTAVAIL);
17037471Ssklower 		/* FALLTHROUGH */
17118377Skarels 	case SIOCSIFADDR:
17218377Skarels 	case SIOCSIFNETMASK:
17326456Skarels 	case SIOCSIFDSTADDR:
17448464Skarels 		if ((so->so_state & SS_PRIV) == 0)
17548464Skarels 			return (EPERM);
17618377Skarels 
17718377Skarels 		if (ifp == 0)
17818377Skarels 			panic("in_control");
17918377Skarels 		if (ia == (struct in_ifaddr *)0) {
18052028Ssklower 			oia = (struct in_ifaddr *)
18152028Ssklower 				malloc(sizeof *oia, M_IFADDR, M_WAITOK);
18252028Ssklower 			if (oia == (struct in_ifaddr *)NULL)
18318377Skarels 				return (ENOBUFS);
18452028Ssklower 			bzero((caddr_t)oia, sizeof *oia);
18518377Skarels 			if (ia = in_ifaddr) {
18618377Skarels 				for ( ; ia->ia_next; ia = ia->ia_next)
18752915Storek 					continue;
18852028Ssklower 				ia->ia_next = oia;
18918377Skarels 			} else
19052028Ssklower 				in_ifaddr = oia;
19152028Ssklower 			ia = oia;
19218377Skarels 			if (ifa = ifp->if_addrlist) {
19318377Skarels 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
19452915Storek 					continue;
19518377Skarels 				ifa->ifa_next = (struct ifaddr *) ia;
19618377Skarels 			} else
19718377Skarels 				ifp->if_addrlist = (struct ifaddr *) ia;
19837471Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
19937471Ssklower 			ia->ia_ifa.ifa_dstaddr
20037471Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
20137471Ssklower 			ia->ia_ifa.ifa_netmask
20237471Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
20337471Ssklower 			ia->ia_sockmask.sin_len = 8;
20437471Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
20537471Ssklower 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
20637471Ssklower 				ia->ia_broadaddr.sin_family = AF_INET;
20737471Ssklower 			}
20818377Skarels 			ia->ia_ifp = ifp;
20924805Skarels 			if (ifp != &loif)
21024805Skarels 				in_interfaces++;
21117271Skarels 		}
21218377Skarels 		break;
21326317Skarels 
21426317Skarels 	case SIOCSIFBRDADDR:
21548464Skarels 		if ((so->so_state & SS_PRIV) == 0)
21648464Skarels 			return (EPERM);
21726317Skarels 		/* FALLTHROUGH */
21826317Skarels 
21939183Ssklower 	case SIOCGIFADDR:
22039183Ssklower 	case SIOCGIFNETMASK:
22139183Ssklower 	case SIOCGIFDSTADDR:
22239183Ssklower 	case SIOCGIFBRDADDR:
22326317Skarels 		if (ia == (struct in_ifaddr *)0)
22426317Skarels 			return (EADDRNOTAVAIL);
22526317Skarels 		break;
22617271Skarels 	}
22718377Skarels 	switch (cmd) {
22818377Skarels 
22918377Skarels 	case SIOCGIFADDR:
23037471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
23118377Skarels 		break;
23218377Skarels 
23318377Skarels 	case SIOCGIFBRDADDR:
23418377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
23518377Skarels 			return (EINVAL);
23637471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
23718377Skarels 		break;
23818377Skarels 
23918377Skarels 	case SIOCGIFDSTADDR:
24018377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
24118377Skarels 			return (EINVAL);
24237471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
24318377Skarels 		break;
24418377Skarels 
24518377Skarels 	case SIOCGIFNETMASK:
24637471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
24718377Skarels 		break;
24818377Skarels 
24918377Skarels 	case SIOCSIFDSTADDR:
25018377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
25118377Skarels 			return (EINVAL);
25227066Skarels 		oldaddr = ia->ia_dstaddr;
25337471Ssklower 		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
25452619Ssklower 		if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
25552619Ssklower 					(ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
25627066Skarels 			ia->ia_dstaddr = oldaddr;
25718377Skarels 			return (error);
25827066Skarels 		}
25927066Skarels 		if (ia->ia_flags & IFA_ROUTE) {
26037471Ssklower 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
26137471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
26245454Ssklower 			ia->ia_ifa.ifa_dstaddr =
26345454Ssklower 					(struct sockaddr *)&ia->ia_dstaddr;
26437471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
26527066Skarels 		}
26618377Skarels 		break;
26718377Skarels 
26818377Skarels 	case SIOCSIFBRDADDR:
26918377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
27018377Skarels 			return (EINVAL);
27137471Ssklower 		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
27218377Skarels 		break;
27318377Skarels 
27418377Skarels 	case SIOCSIFADDR:
27534500Skarels 		return (in_ifinit(ifp, ia,
27637471Ssklower 		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
27718377Skarels 
27818377Skarels 	case SIOCSIFNETMASK:
27937471Ssklower 		i = ifra->ifra_addr.sin_addr.s_addr;
28037471Ssklower 		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
28118377Skarels 		break;
28218377Skarels 
28337471Ssklower 	case SIOCAIFADDR:
28444368Skarels 		maskIsNew = 0;
28544368Skarels 		hostIsNew = 1;
28644368Skarels 		error = 0;
28737471Ssklower 		if (ia->ia_addr.sin_family == AF_INET) {
28837471Ssklower 			if (ifra->ifra_addr.sin_len == 0) {
28937471Ssklower 				ifra->ifra_addr = ia->ia_addr;
29037471Ssklower 				hostIsNew = 0;
29137471Ssklower 			} else if (ifra->ifra_addr.sin_addr.s_addr ==
29237471Ssklower 					       ia->ia_addr.sin_addr.s_addr)
29337471Ssklower 				hostIsNew = 0;
29437471Ssklower 		}
29537471Ssklower 		if (ifra->ifra_mask.sin_len) {
29637471Ssklower 			in_ifscrub(ifp, ia);
29737471Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
29837471Ssklower 			ia->ia_subnetmask =
29944368Skarels 			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
30037471Ssklower 			maskIsNew = 1;
30137471Ssklower 		}
30237471Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
30337471Ssklower 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
30437471Ssklower 			in_ifscrub(ifp, ia);
30537471Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
30637471Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
30737471Ssklower 		}
30837471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET &&
30944368Skarels 		    (hostIsNew || maskIsNew))
31037471Ssklower 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
31137471Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) &&
31237471Ssklower 		    (ifra->ifra_broadaddr.sin_family == AF_INET))
31337471Ssklower 			ia->ia_broadaddr = ifra->ifra_broadaddr;
31437471Ssklower 		return (error);
31537471Ssklower 
31637471Ssklower 	case SIOCDIFADDR:
31737471Ssklower 		in_ifscrub(ifp, ia);
31837471Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
31937471Ssklower 			ifp->if_addrlist = ifa->ifa_next;
32037471Ssklower 		else {
32137471Ssklower 			while (ifa->ifa_next &&
32237471Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
32337471Ssklower 				    ifa = ifa->ifa_next;
32437471Ssklower 			if (ifa->ifa_next)
32544368Skarels 				ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
32637471Ssklower 			else
32737471Ssklower 				printf("Couldn't unlink inifaddr from ifp\n");
32837471Ssklower 		}
32937471Ssklower 		oia = ia;
33044368Skarels 		if (oia == (ia = in_ifaddr))
33137471Ssklower 			in_ifaddr = ia->ia_next;
33244368Skarels 		else {
33344368Skarels 			while (ia->ia_next && (ia->ia_next != oia))
33437471Ssklower 				ia = ia->ia_next;
33537471Ssklower 			if (ia->ia_next)
33644368Skarels 				ia->ia_next = oia->ia_next;
33737471Ssklower 			else
33837471Ssklower 				printf("Didn't unlink inifadr from list\n");
33937471Ssklower 		}
34052028Ssklower 		IFAFREE((&oia->ia_ifa));
34137471Ssklower 		break;
34237471Ssklower 
34318377Skarels 	default:
34418377Skarels 		if (ifp == 0 || ifp->if_ioctl == 0)
34518377Skarels 			return (EOPNOTSUPP);
34618377Skarels 		return ((*ifp->if_ioctl)(ifp, cmd, data));
34718377Skarels 	}
34817271Skarels 	return (0);
34917271Skarels }
35017271Skarels 
35117271Skarels /*
35237471Ssklower  * Delete any existing route for an interface.
35337471Ssklower  */
354*61335Sbostic void
35537471Ssklower in_ifscrub(ifp, ia)
35637471Ssklower 	register struct ifnet *ifp;
35737471Ssklower 	register struct in_ifaddr *ia;
35837471Ssklower {
35937471Ssklower 
36037471Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
36137471Ssklower 		return;
36237471Ssklower 	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
36337471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
36437471Ssklower 	else
36537471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
36637471Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
36737471Ssklower }
36837471Ssklower 
36937471Ssklower /*
37018377Skarels  * Initialize an interface's internet address
37118377Skarels  * and routing table entry.
3727159Ssam  */
37337471Ssklower in_ifinit(ifp, ia, sin, scrub)
3747159Ssam 	register struct ifnet *ifp;
37518377Skarels 	register struct in_ifaddr *ia;
37618377Skarels 	struct sockaddr_in *sin;
37752274Storek 	int scrub;
3787159Ssam {
37918377Skarels 	register u_long i = ntohl(sin->sin_addr.s_addr);
38037471Ssklower 	struct sockaddr_in oldaddr;
38154716Ssklower 	int s = splimp(), flags = RTF_UP, error, ether_output();
3827159Ssam 
38327066Skarels 	oldaddr = ia->ia_addr;
38437471Ssklower 	ia->ia_addr = *sin;
38518377Skarels 	/*
38626317Skarels 	 * Give the interface a chance to initialize
38726317Skarels 	 * if this is its first address,
38826317Skarels 	 * and to validate the address if necessary.
38926317Skarels 	 */
39052274Storek 	if (ifp->if_ioctl &&
39152274Storek 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
39226317Skarels 		splx(s);
39327066Skarels 		ia->ia_addr = oldaddr;
39426317Skarels 		return (error);
39526317Skarels 	}
39650134Ssklower 	if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
39750134Ssklower 		ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
39850134Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
39950134Ssklower 	}
40045454Ssklower 	splx(s);
40137471Ssklower 	if (scrub) {
40237471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
40337471Ssklower 		in_ifscrub(ifp, ia);
40437471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
40518377Skarels 	}
40618377Skarels 	if (IN_CLASSA(i))
40718377Skarels 		ia->ia_netmask = IN_CLASSA_NET;
40818377Skarels 	else if (IN_CLASSB(i))
40918377Skarels 		ia->ia_netmask = IN_CLASSB_NET;
41018377Skarels 	else
41118377Skarels 		ia->ia_netmask = IN_CLASSC_NET;
41218377Skarels 	ia->ia_net = i & ia->ia_netmask;
41318377Skarels 	/*
41418377Skarels 	 * The subnet mask includes at least the standard network part,
41518377Skarels 	 * but may already have been set to a larger value.
41618377Skarels 	 */
41718377Skarels 	ia->ia_subnetmask |= ia->ia_netmask;
41818377Skarels 	ia->ia_subnet = i & ia->ia_subnetmask;
41937471Ssklower 	ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
42058998Ssklower 	in_socktrim(&ia->ia_sockmask);
42145454Ssklower 	/*
42245454Ssklower 	 * Add route for the network.
42345454Ssklower 	 */
42452617Ssklower 	ia->ia_ifa.ifa_metric = ifp->if_metric;
42518377Skarels 	if (ifp->if_flags & IFF_BROADCAST) {
42658998Ssklower 		ia->ia_broadaddr.sin_addr.s_addr =
42758998Ssklower 			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
42825195Skarels 		ia->ia_netbroadcast.s_addr =
42958998Ssklower 			htonl(ia->ia_net | ~ ia->ia_netmask);
43045454Ssklower 	} else if (ifp->if_flags & IFF_LOOPBACK) {
43137471Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
43245454Ssklower 		flags |= RTF_HOST;
43345454Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT) {
43445454Ssklower 		if (ia->ia_dstaddr.sin_family != AF_INET)
43545454Ssklower 			return (0);
43645454Ssklower 		flags |= RTF_HOST;
43727066Skarels 	}
43845454Ssklower 	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
43945454Ssklower 		ia->ia_flags |= IFA_ROUTE;
44054716Ssklower 	/*
44154716Ssklower 	 * If the interface supports multicast, join the "all hosts"
44254716Ssklower 	 * multicast group on that interface.
44354716Ssklower 	 */
44454716Ssklower 	if (ifp->if_flags & IFF_MULTICAST) {
44554716Ssklower 		struct in_addr addr;
44654716Ssklower 
44754716Ssklower 		addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
44854716Ssklower 		in_addmulti(&addr, ifp);
44954716Ssklower 	}
45045454Ssklower 	return (error);
4517159Ssam }
45218377Skarels 
45318377Skarels 
45418377Skarels /*
45530523Skarels  * Return 1 if the address might be a local broadcast address.
45618377Skarels  */
45758998Ssklower in_broadcast(in, ifp)
45818377Skarels 	struct in_addr in;
45958998Ssklower         struct ifnet *ifp;
46018377Skarels {
46158998Ssklower 	register struct ifaddr *ifa;
46230523Skarels 	u_long t;
46318377Skarels 
46458998Ssklower 	if (in.s_addr == INADDR_BROADCAST ||
46558998Ssklower 	    in.s_addr == INADDR_ANY)
46658998Ssklower 		return 1;
46758998Ssklower 	if ((ifp->if_flags & IFF_BROADCAST) == 0)
46858998Ssklower 		return 0;
46958998Ssklower 	t = ntohl(in.s_addr);
47018377Skarels 	/*
47118377Skarels 	 * Look through the list of addresses for a match
47218377Skarels 	 * with a broadcast address.
47318377Skarels 	 */
47458998Ssklower #define ia ((struct in_ifaddr *)ifa)
47558998Ssklower 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
47658998Ssklower 		if (ifa->ifa_addr->sa_family == AF_INET &&
47758998Ssklower 		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
47858998Ssklower 		     in.s_addr == ia->ia_netbroadcast.s_addr ||
47958998Ssklower 		     /*
48058998Ssklower 		      * Check for old-style (host 0) broadcast.
48158998Ssklower 		      */
48258998Ssklower 		     t == ia->ia_subnet || t == ia->ia_net))
48358998Ssklower 			    return 1;
484*61335Sbostic 	return (0);
48558998Ssklower #undef ia
48618377Skarels }
48754716Ssklower /*
48854716Ssklower  * Add an address to the list of IP multicast addresses for a given interface.
48954716Ssklower  */
49054716Ssklower struct in_multi *
49154716Ssklower in_addmulti(ap, ifp)
49254716Ssklower 	register struct in_addr *ap;
49354716Ssklower 	register struct ifnet *ifp;
49454716Ssklower {
49554716Ssklower 	register struct in_multi *inm;
49654716Ssklower 	struct ifreq ifr;
49754716Ssklower 	struct in_ifaddr *ia;
49854716Ssklower 	int s = splnet();
49954716Ssklower 
50054716Ssklower 	/*
50154716Ssklower 	 * See if address already in list.
50254716Ssklower 	 */
50354716Ssklower 	IN_LOOKUP_MULTI(*ap, ifp, inm);
50454716Ssklower 	if (inm != NULL) {
50554716Ssklower 		/*
50654716Ssklower 		 * Found it; just increment the reference count.
50754716Ssklower 		 */
50854716Ssklower 		++inm->inm_refcount;
50954716Ssklower 	}
51054716Ssklower 	else {
51154716Ssklower 		/*
51254716Ssklower 		 * New address; allocate a new multicast record
51354716Ssklower 		 * and link it into the interface's multicast list.
51454716Ssklower 		 */
51554716Ssklower 		inm = (struct in_multi *)malloc(sizeof(*inm),
51654716Ssklower 		    M_IPMADDR, M_NOWAIT);
51754716Ssklower 		if (inm == NULL) {
51854716Ssklower 			splx(s);
51954716Ssklower 			return (NULL);
52054716Ssklower 		}
52154716Ssklower 		inm->inm_addr = *ap;
52254716Ssklower 		inm->inm_ifp = ifp;
52354716Ssklower 		inm->inm_refcount = 1;
52454716Ssklower 		IFP_TO_IA(ifp, ia);
52554716Ssklower 		if (ia == NULL) {
52654716Ssklower 			free(inm, M_IPMADDR);
52754716Ssklower 			splx(s);
52854716Ssklower 			return (NULL);
52954716Ssklower 		}
53054716Ssklower 		inm->inm_ia = ia;
53158413Ssklower 		inm->inm_next = ia->ia_multiaddrs;
53258413Ssklower 		ia->ia_multiaddrs = inm;
53354716Ssklower 		/*
53454716Ssklower 		 * Ask the network driver to update its multicast reception
53554716Ssklower 		 * filter appropriately for the new address.
53654716Ssklower 		 */
53754716Ssklower 		((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
53854716Ssklower 		((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
53958413Ssklower 		if ((ifp->if_ioctl == NULL) ||
54058413Ssklower 		    (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
54158413Ssklower 			ia->ia_multiaddrs = inm->inm_next;
54254716Ssklower 			free(inm, M_IPMADDR);
54354716Ssklower 			splx(s);
54454716Ssklower 			return (NULL);
54554716Ssklower 		}
54654716Ssklower 		/*
54754716Ssklower 		 * Let IGMP know that we have joined a new IP multicast group.
54854716Ssklower 		 */
54954716Ssklower 		igmp_joingroup(inm);
55054716Ssklower 	}
55154716Ssklower 	splx(s);
55254716Ssklower 	return (inm);
55354716Ssklower }
55454716Ssklower 
55554716Ssklower /*
55654716Ssklower  * Delete a multicast address record.
55754716Ssklower  */
55854716Ssklower int
55954716Ssklower in_delmulti(inm)
56054716Ssklower 	register struct in_multi *inm;
56154716Ssklower {
56254716Ssklower 	register struct in_multi **p;
56354716Ssklower 	struct ifreq ifr;
56454716Ssklower 	int s = splnet();
56554716Ssklower 
56654716Ssklower 	if (--inm->inm_refcount == 0) {
56754716Ssklower 		/*
56854716Ssklower 		 * No remaining claims to this record; let IGMP know that
56954716Ssklower 		 * we are leaving the multicast group.
57054716Ssklower 		 */
57154716Ssklower 		igmp_leavegroup(inm);
57254716Ssklower 		/*
57354716Ssklower 		 * Unlink from list.
57454716Ssklower 		 */
57554716Ssklower 		for (p = &inm->inm_ia->ia_multiaddrs;
57654716Ssklower 		     *p != inm;
57754716Ssklower 		     p = &(*p)->inm_next)
57854716Ssklower 			 continue;
57954716Ssklower 		*p = (*p)->inm_next;
58054716Ssklower 		/*
58154716Ssklower 		 * Notify the network driver to update its multicast reception
58254716Ssklower 		 * filter.
58354716Ssklower 		 */
58454716Ssklower 		((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
58554716Ssklower 		((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
58654716Ssklower 								inm->inm_addr;
58754716Ssklower 		(*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
58854716Ssklower 							     (caddr_t)&ifr);
58954716Ssklower 		free(inm, M_IPMADDR);
59054716Ssklower 	}
59154716Ssklower 	splx(s);
59254716Ssklower }
5937159Ssam #endif
594