xref: /csrg-svn/sys/netinet/in.c (revision 58998)
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*58998Ssklower  *	@(#)in.c	7.31 (Berkeley) 04/07/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>
2456531Sbostic 
257159Ssam #ifdef INET
267159Ssam /*
2718377Skarels  * Formulate an Internet address from network + host.
287159Ssam  */
297159Ssam struct in_addr
3018377Skarels in_makeaddr(net, host)
3118377Skarels 	u_long net, host;
327159Ssam {
3318377Skarels 	register struct in_ifaddr *ia;
3418377Skarels 	register u_long mask;
357159Ssam 	u_long addr;
367159Ssam 
3718377Skarels 	if (IN_CLASSA(net))
3818377Skarels 		mask = IN_CLASSA_HOST;
3918377Skarels 	else if (IN_CLASSB(net))
4018377Skarels 		mask = IN_CLASSB_HOST;
417159Ssam 	else
4218377Skarels 		mask = IN_CLASSC_HOST;
4318377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
4418377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net) {
4518377Skarels 			mask = ~ia->ia_subnetmask;
4618377Skarels 			break;
4718377Skarels 		}
4818377Skarels 	addr = htonl(net | (host & mask));
497159Ssam 	return (*(struct in_addr *)&addr);
507159Ssam }
517159Ssam 
527159Ssam /*
538595Sroot  * Return the network number from an internet address.
547159Ssam  */
5524805Skarels u_long
567159Ssam in_netof(in)
577159Ssam 	struct in_addr in;
587159Ssam {
598937Sroot 	register u_long i = ntohl(in.s_addr);
6018377Skarels 	register u_long net;
6118377Skarels 	register struct in_ifaddr *ia;
627159Ssam 
6318377Skarels 	if (IN_CLASSA(i))
6418377Skarels 		net = i & IN_CLASSA_NET;
6518377Skarels 	else if (IN_CLASSB(i))
6618377Skarels 		net = i & IN_CLASSB_NET;
6731392Skarels 	else if (IN_CLASSC(i))
6831392Skarels 		net = i & IN_CLASSC_NET;
6954716Ssklower 	else if (IN_CLASSD(i))
7054716Ssklower 		net = i & IN_CLASSD_NET;
7118377Skarels 	else
7231392Skarels 		return (0);
7316413Skarels 
7416413Skarels 	/*
7518377Skarels 	 * Check whether network is a subnet;
7616413Skarels 	 * if so, return subnet number.
7716413Skarels 	 */
7818377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
7924805Skarels 		if (net == ia->ia_net)
8018377Skarels 			return (i & ia->ia_subnetmask);
8116413Skarels 	return (net);
827159Ssam }
837159Ssam 
847159Ssam /*
8537471Ssklower  * Compute and save network mask as sockaddr from an internet address.
8637471Ssklower  */
8737471Ssklower in_sockmaskof(in, sockmask)
8837471Ssklower 	struct in_addr in;
8937471Ssklower 	register struct sockaddr_in *sockmask;
9037471Ssklower {
9137471Ssklower 	register u_long net;
9237471Ssklower 	register u_long mask;
9337471Ssklower     {
9437471Ssklower 	register u_long i = ntohl(in.s_addr);
9537471Ssklower 
9637471Ssklower 	if (i == 0)
9737471Ssklower 		net = 0, mask = 0;
9837471Ssklower 	else if (IN_CLASSA(i))
9937471Ssklower 		net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
10037471Ssklower 	else if (IN_CLASSB(i))
10137471Ssklower 		net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
10237471Ssklower 	else if (IN_CLASSC(i))
10337471Ssklower 		net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
10437471Ssklower 	else
10537471Ssklower 		net = i, mask = -1;
10637471Ssklower     }
10737471Ssklower     {
10837471Ssklower 	register struct in_ifaddr *ia;
10937471Ssklower 	/*
11037471Ssklower 	 * Check whether network is a subnet;
11137471Ssklower 	 * if so, return subnet number.
11237471Ssklower 	 */
11337471Ssklower 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
11437471Ssklower 		if (net == ia->ia_net)
11537471Ssklower 			mask =  ia->ia_subnetmask;
11637471Ssklower     }
11737471Ssklower     {
11837471Ssklower 	register char *cpbase = (char *)&(sockmask->sin_addr);
11939183Ssklower 	register char *cp = (char *)(1 + &(sockmask->sin_addr));
12037471Ssklower 
12137471Ssklower 	sockmask->sin_addr.s_addr = htonl(mask);
12237471Ssklower 	sockmask->sin_len = 0;
12337471Ssklower 	while (--cp >= cpbase)
12437471Ssklower 		if (*cp) {
12537471Ssklower 			sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
12637471Ssklower 			break;
12737471Ssklower 		}
12837471Ssklower     }
12937471Ssklower }
13037471Ssklower 
13126381Skarels #ifndef SUBNETSARELOCAL
13226381Skarels #define	SUBNETSARELOCAL	1
13326381Skarels #endif
13426381Skarels int subnetsarelocal = SUBNETSARELOCAL;
13516377Skarels /*
13618377Skarels  * Return 1 if an internet address is for a ``local'' host
13726381Skarels  * (one to which we have a connection).  If subnetsarelocal
13826381Skarels  * is true, this includes other subnets of the local net.
13926381Skarels  * Otherwise, it includes only the directly-connected (sub)nets.
14017271Skarels  */
14117271Skarels in_localaddr(in)
14217271Skarels 	struct in_addr in;
14317271Skarels {
14417271Skarels 	register u_long i = ntohl(in.s_addr);
14518377Skarels 	register struct in_ifaddr *ia;
14617271Skarels 
14730697Skarels 	if (subnetsarelocal) {
14830697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
14930697Skarels 			if ((i & ia->ia_netmask) == ia->ia_net)
15030697Skarels 				return (1);
15130697Skarels 	} else {
15230697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
15330697Skarels 			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
15430697Skarels 				return (1);
15530697Skarels 	}
15618377Skarels 	return (0);
15718377Skarels }
15818377Skarels 
15931392Skarels /*
16031392Skarels  * Determine whether an IP address is in a reserved set of addresses
16131392Skarels  * that may not be forwarded, or whether datagrams to that destination
16231392Skarels  * may be forwarded.
16331392Skarels  */
16431392Skarels in_canforward(in)
16531392Skarels 	struct in_addr in;
16631392Skarels {
16731392Skarels 	register u_long i = ntohl(in.s_addr);
16831392Skarels 	register u_long net;
16931392Skarels 
170*58998Ssklower 	if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
17131392Skarels 		return (0);
17231392Skarels 	if (IN_CLASSA(i)) {
17331392Skarels 		net = i & IN_CLASSA_NET;
17457938Ssklower 		if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
17531392Skarels 			return (0);
17631392Skarels 	}
17731392Skarels 	return (1);
17831392Skarels }
17931392Skarels 
180*58998Ssklower /*
181*58998Ssklower  * Trim a mask in a sockaddr
182*58998Ssklower  */
183*58998Ssklower void
184*58998Ssklower in_socktrim(ap)
185*58998Ssklower struct sockaddr_in *ap;
186*58998Ssklower {
187*58998Ssklower     register char *cplim = (char *) &ap->sin_addr;
188*58998Ssklower     register char *cp = (char *) (&ap->sin_addr + 1);
189*58998Ssklower 
190*58998Ssklower     ap->sin_len = 0;
191*58998Ssklower     while (--cp > cplim)
192*58998Ssklower         if (*cp) {
193*58998Ssklower 	    (ap)->sin_len = cp - (char *) (ap) + 1;
194*58998Ssklower 	    break;
195*58998Ssklower 	}
196*58998Ssklower }
197*58998Ssklower 
19824805Skarels int	in_interfaces;		/* number of external internet interfaces */
19924805Skarels extern	struct ifnet loif;
20024805Skarels 
20118377Skarels /*
20218377Skarels  * Generic internet control operations (ioctl's).
20318377Skarels  * Ifp is 0 if not an interface-specific ioctl.
20418377Skarels  */
20524805Skarels /* ARGSUSED */
20618377Skarels in_control(so, cmd, data, ifp)
20718377Skarels 	struct socket *so;
20818377Skarels 	int cmd;
20918377Skarels 	caddr_t data;
21018377Skarels 	register struct ifnet *ifp;
21118377Skarels {
21218377Skarels 	register struct ifreq *ifr = (struct ifreq *)data;
21318377Skarels 	register struct in_ifaddr *ia = 0;
21437471Ssklower 	register struct ifaddr *ifa;
21537471Ssklower 	struct in_ifaddr *oia;
21637471Ssklower 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
21737471Ssklower 	struct sockaddr_in oldaddr;
21837471Ssklower 	int error, hostIsNew, maskIsNew;
21937471Ssklower 	u_long i;
22018377Skarels 
22118377Skarels 	/*
22218377Skarels 	 * Find address for this interface, if it exists.
22318377Skarels 	 */
22418377Skarels 	if (ifp)
22518377Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
22618377Skarels 			if (ia->ia_ifp == ifp)
22718377Skarels 				break;
22818377Skarels 
22918377Skarels 	switch (cmd) {
23018377Skarels 
23137471Ssklower 	case SIOCAIFADDR:
23237471Ssklower 	case SIOCDIFADDR:
23337471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET)
23437471Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
23537471Ssklower 			if (ia->ia_ifp == ifp  &&
23637471Ssklower 			    ia->ia_addr.sin_addr.s_addr ==
23737471Ssklower 				ifra->ifra_addr.sin_addr.s_addr)
23837471Ssklower 			    break;
23937471Ssklower 		}
24037471Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
24137471Ssklower 			return (EADDRNOTAVAIL);
24237471Ssklower 		/* FALLTHROUGH */
24318377Skarels 	case SIOCSIFADDR:
24418377Skarels 	case SIOCSIFNETMASK:
24526456Skarels 	case SIOCSIFDSTADDR:
24648464Skarels 		if ((so->so_state & SS_PRIV) == 0)
24748464Skarels 			return (EPERM);
24818377Skarels 
24918377Skarels 		if (ifp == 0)
25018377Skarels 			panic("in_control");
25118377Skarels 		if (ia == (struct in_ifaddr *)0) {
25252028Ssklower 			oia = (struct in_ifaddr *)
25352028Ssklower 				malloc(sizeof *oia, M_IFADDR, M_WAITOK);
25452028Ssklower 			if (oia == (struct in_ifaddr *)NULL)
25518377Skarels 				return (ENOBUFS);
25652028Ssklower 			bzero((caddr_t)oia, sizeof *oia);
25718377Skarels 			if (ia = in_ifaddr) {
25818377Skarels 				for ( ; ia->ia_next; ia = ia->ia_next)
25952915Storek 					continue;
26052028Ssklower 				ia->ia_next = oia;
26118377Skarels 			} else
26252028Ssklower 				in_ifaddr = oia;
26352028Ssklower 			ia = oia;
26418377Skarels 			if (ifa = ifp->if_addrlist) {
26518377Skarels 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
26652915Storek 					continue;
26718377Skarels 				ifa->ifa_next = (struct ifaddr *) ia;
26818377Skarels 			} else
26918377Skarels 				ifp->if_addrlist = (struct ifaddr *) ia;
27037471Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
27137471Ssklower 			ia->ia_ifa.ifa_dstaddr
27237471Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
27337471Ssklower 			ia->ia_ifa.ifa_netmask
27437471Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
27537471Ssklower 			ia->ia_sockmask.sin_len = 8;
27637471Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
27737471Ssklower 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
27837471Ssklower 				ia->ia_broadaddr.sin_family = AF_INET;
27937471Ssklower 			}
28018377Skarels 			ia->ia_ifp = ifp;
28124805Skarels 			if (ifp != &loif)
28224805Skarels 				in_interfaces++;
28317271Skarels 		}
28418377Skarels 		break;
28526317Skarels 
28626317Skarels 	case SIOCSIFBRDADDR:
28748464Skarels 		if ((so->so_state & SS_PRIV) == 0)
28848464Skarels 			return (EPERM);
28926317Skarels 		/* FALLTHROUGH */
29026317Skarels 
29139183Ssklower 	case SIOCGIFADDR:
29239183Ssklower 	case SIOCGIFNETMASK:
29339183Ssklower 	case SIOCGIFDSTADDR:
29439183Ssklower 	case SIOCGIFBRDADDR:
29526317Skarels 		if (ia == (struct in_ifaddr *)0)
29626317Skarels 			return (EADDRNOTAVAIL);
29726317Skarels 		break;
29817271Skarels 	}
29918377Skarels 	switch (cmd) {
30018377Skarels 
30118377Skarels 	case SIOCGIFADDR:
30237471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
30318377Skarels 		break;
30418377Skarels 
30518377Skarels 	case SIOCGIFBRDADDR:
30618377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
30718377Skarels 			return (EINVAL);
30837471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
30918377Skarels 		break;
31018377Skarels 
31118377Skarels 	case SIOCGIFDSTADDR:
31218377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
31318377Skarels 			return (EINVAL);
31437471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
31518377Skarels 		break;
31618377Skarels 
31718377Skarels 	case SIOCGIFNETMASK:
31837471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
31918377Skarels 		break;
32018377Skarels 
32118377Skarels 	case SIOCSIFDSTADDR:
32218377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
32318377Skarels 			return (EINVAL);
32427066Skarels 		oldaddr = ia->ia_dstaddr;
32537471Ssklower 		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
32652619Ssklower 		if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
32752619Ssklower 					(ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
32827066Skarels 			ia->ia_dstaddr = oldaddr;
32918377Skarels 			return (error);
33027066Skarels 		}
33127066Skarels 		if (ia->ia_flags & IFA_ROUTE) {
33237471Ssklower 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
33337471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
33445454Ssklower 			ia->ia_ifa.ifa_dstaddr =
33545454Ssklower 					(struct sockaddr *)&ia->ia_dstaddr;
33637471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
33727066Skarels 		}
33818377Skarels 		break;
33918377Skarels 
34018377Skarels 	case SIOCSIFBRDADDR:
34118377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
34218377Skarels 			return (EINVAL);
34337471Ssklower 		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
34418377Skarels 		break;
34518377Skarels 
34618377Skarels 	case SIOCSIFADDR:
34734500Skarels 		return (in_ifinit(ifp, ia,
34837471Ssklower 		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
34918377Skarels 
35018377Skarels 	case SIOCSIFNETMASK:
35137471Ssklower 		i = ifra->ifra_addr.sin_addr.s_addr;
35237471Ssklower 		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
35318377Skarels 		break;
35418377Skarels 
35537471Ssklower 	case SIOCAIFADDR:
35644368Skarels 		maskIsNew = 0;
35744368Skarels 		hostIsNew = 1;
35844368Skarels 		error = 0;
35937471Ssklower 		if (ia->ia_addr.sin_family == AF_INET) {
36037471Ssklower 			if (ifra->ifra_addr.sin_len == 0) {
36137471Ssklower 				ifra->ifra_addr = ia->ia_addr;
36237471Ssklower 				hostIsNew = 0;
36337471Ssklower 			} else if (ifra->ifra_addr.sin_addr.s_addr ==
36437471Ssklower 					       ia->ia_addr.sin_addr.s_addr)
36537471Ssklower 				hostIsNew = 0;
36637471Ssklower 		}
36737471Ssklower 		if (ifra->ifra_mask.sin_len) {
36837471Ssklower 			in_ifscrub(ifp, ia);
36937471Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
37037471Ssklower 			ia->ia_subnetmask =
37144368Skarels 			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
37237471Ssklower 			maskIsNew = 1;
37337471Ssklower 		}
37437471Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
37537471Ssklower 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
37637471Ssklower 			in_ifscrub(ifp, ia);
37737471Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
37837471Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
37937471Ssklower 		}
38037471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET &&
38144368Skarels 		    (hostIsNew || maskIsNew))
38237471Ssklower 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
38337471Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) &&
38437471Ssklower 		    (ifra->ifra_broadaddr.sin_family == AF_INET))
38537471Ssklower 			ia->ia_broadaddr = ifra->ifra_broadaddr;
38637471Ssklower 		return (error);
38737471Ssklower 
38837471Ssklower 	case SIOCDIFADDR:
38937471Ssklower 		in_ifscrub(ifp, ia);
39037471Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
39137471Ssklower 			ifp->if_addrlist = ifa->ifa_next;
39237471Ssklower 		else {
39337471Ssklower 			while (ifa->ifa_next &&
39437471Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
39537471Ssklower 				    ifa = ifa->ifa_next;
39637471Ssklower 			if (ifa->ifa_next)
39744368Skarels 				ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
39837471Ssklower 			else
39937471Ssklower 				printf("Couldn't unlink inifaddr from ifp\n");
40037471Ssklower 		}
40137471Ssklower 		oia = ia;
40244368Skarels 		if (oia == (ia = in_ifaddr))
40337471Ssklower 			in_ifaddr = ia->ia_next;
40444368Skarels 		else {
40544368Skarels 			while (ia->ia_next && (ia->ia_next != oia))
40637471Ssklower 				ia = ia->ia_next;
40737471Ssklower 			if (ia->ia_next)
40844368Skarels 				ia->ia_next = oia->ia_next;
40937471Ssklower 			else
41037471Ssklower 				printf("Didn't unlink inifadr from list\n");
41137471Ssklower 		}
41252028Ssklower 		IFAFREE((&oia->ia_ifa));
41337471Ssklower 		break;
41437471Ssklower 
41518377Skarels 	default:
41618377Skarels 		if (ifp == 0 || ifp->if_ioctl == 0)
41718377Skarels 			return (EOPNOTSUPP);
41818377Skarels 		return ((*ifp->if_ioctl)(ifp, cmd, data));
41918377Skarels 	}
42017271Skarels 	return (0);
42117271Skarels }
42217271Skarels 
42317271Skarels /*
42437471Ssklower  * Delete any existing route for an interface.
42537471Ssklower  */
42637471Ssklower in_ifscrub(ifp, ia)
42737471Ssklower 	register struct ifnet *ifp;
42837471Ssklower 	register struct in_ifaddr *ia;
42937471Ssklower {
43037471Ssklower 
43137471Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
43237471Ssklower 		return;
43337471Ssklower 	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
43437471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
43537471Ssklower 	else
43637471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
43737471Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
43837471Ssklower }
43937471Ssklower 
44037471Ssklower /*
44118377Skarels  * Initialize an interface's internet address
44218377Skarels  * and routing table entry.
4437159Ssam  */
44437471Ssklower in_ifinit(ifp, ia, sin, scrub)
4457159Ssam 	register struct ifnet *ifp;
44618377Skarels 	register struct in_ifaddr *ia;
44718377Skarels 	struct sockaddr_in *sin;
44852274Storek 	int scrub;
4497159Ssam {
45018377Skarels 	register u_long i = ntohl(sin->sin_addr.s_addr);
45137471Ssklower 	struct sockaddr_in oldaddr;
45254716Ssklower 	int s = splimp(), flags = RTF_UP, error, ether_output();
45354716Ssklower 	void arp_rtrequest();
4547159Ssam 
45527066Skarels 	oldaddr = ia->ia_addr;
45637471Ssklower 	ia->ia_addr = *sin;
45718377Skarels 	/*
45826317Skarels 	 * Give the interface a chance to initialize
45926317Skarels 	 * if this is its first address,
46026317Skarels 	 * and to validate the address if necessary.
46126317Skarels 	 */
46252274Storek 	if (ifp->if_ioctl &&
46352274Storek 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
46426317Skarels 		splx(s);
46527066Skarels 		ia->ia_addr = oldaddr;
46626317Skarels 		return (error);
46726317Skarels 	}
46850134Ssklower 	if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
46950134Ssklower 		ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
47050134Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
47150134Ssklower 	}
47245454Ssklower 	splx(s);
47337471Ssklower 	if (scrub) {
47437471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
47537471Ssklower 		in_ifscrub(ifp, ia);
47637471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
47718377Skarels 	}
47818377Skarels 	if (IN_CLASSA(i))
47918377Skarels 		ia->ia_netmask = IN_CLASSA_NET;
48018377Skarels 	else if (IN_CLASSB(i))
48118377Skarels 		ia->ia_netmask = IN_CLASSB_NET;
48218377Skarels 	else
48318377Skarels 		ia->ia_netmask = IN_CLASSC_NET;
48418377Skarels 	ia->ia_net = i & ia->ia_netmask;
48518377Skarels 	/*
48618377Skarels 	 * The subnet mask includes at least the standard network part,
48718377Skarels 	 * but may already have been set to a larger value.
48818377Skarels 	 */
48918377Skarels 	ia->ia_subnetmask |= ia->ia_netmask;
49018377Skarels 	ia->ia_subnet = i & ia->ia_subnetmask;
49137471Ssklower 	ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
492*58998Ssklower 	in_socktrim(&ia->ia_sockmask);
49345454Ssklower 	/*
49445454Ssklower 	 * Add route for the network.
49545454Ssklower 	 */
49652617Ssklower 	ia->ia_ifa.ifa_metric = ifp->if_metric;
49718377Skarels 	if (ifp->if_flags & IFF_BROADCAST) {
498*58998Ssklower 		ia->ia_broadaddr.sin_addr.s_addr =
499*58998Ssklower 			htonl(ia->ia_subnet | ~ia->ia_subnetmask);
50025195Skarels 		ia->ia_netbroadcast.s_addr =
501*58998Ssklower 			htonl(ia->ia_net | ~ ia->ia_netmask);
50245454Ssklower 	} else if (ifp->if_flags & IFF_LOOPBACK) {
50337471Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
50445454Ssklower 		flags |= RTF_HOST;
50545454Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT) {
50645454Ssklower 		if (ia->ia_dstaddr.sin_family != AF_INET)
50745454Ssklower 			return (0);
50845454Ssklower 		flags |= RTF_HOST;
50927066Skarels 	}
51045454Ssklower 	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
51145454Ssklower 		ia->ia_flags |= IFA_ROUTE;
51254716Ssklower 	/*
51354716Ssklower 	 * If the interface supports multicast, join the "all hosts"
51454716Ssklower 	 * multicast group on that interface.
51554716Ssklower 	 */
51654716Ssklower 	if (ifp->if_flags & IFF_MULTICAST) {
51754716Ssklower 		struct in_addr addr;
51854716Ssklower 
51954716Ssklower 		addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
52054716Ssklower 		in_addmulti(&addr, ifp);
52154716Ssklower 	}
52245454Ssklower 	return (error);
5237159Ssam }
52418377Skarels 
52518377Skarels 
52618377Skarels /*
52730523Skarels  * Return 1 if the address might be a local broadcast address.
52818377Skarels  */
529*58998Ssklower in_broadcast(in, ifp)
53018377Skarels 	struct in_addr in;
531*58998Ssklower         struct ifnet *ifp;
53218377Skarels {
533*58998Ssklower 	register struct ifaddr *ifa;
53430523Skarels 	u_long t;
53518377Skarels 
536*58998Ssklower 	if (in.s_addr == INADDR_BROADCAST ||
537*58998Ssklower 	    in.s_addr == INADDR_ANY)
538*58998Ssklower 		return 1;
539*58998Ssklower 	if ((ifp->if_flags & IFF_BROADCAST) == 0)
540*58998Ssklower 		return 0;
541*58998Ssklower 	t = ntohl(in.s_addr);
54218377Skarels 	/*
54318377Skarels 	 * Look through the list of addresses for a match
54418377Skarels 	 * with a broadcast address.
54518377Skarels 	 */
546*58998Ssklower #define ia ((struct in_ifaddr *)ifa)
547*58998Ssklower 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
548*58998Ssklower 		if (ifa->ifa_addr->sa_family == AF_INET &&
549*58998Ssklower 		    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
550*58998Ssklower 		     in.s_addr == ia->ia_netbroadcast.s_addr ||
551*58998Ssklower 		     /*
552*58998Ssklower 		      * Check for old-style (host 0) broadcast.
553*58998Ssklower 		      */
554*58998Ssklower 		     t == ia->ia_subnet || t == ia->ia_net))
555*58998Ssklower 			    return 1;
556*58998Ssklower 	return 0;
557*58998Ssklower #undef ia
55818377Skarels }
55954716Ssklower /*
56054716Ssklower  * Add an address to the list of IP multicast addresses for a given interface.
56154716Ssklower  */
56254716Ssklower struct in_multi *
56354716Ssklower in_addmulti(ap, ifp)
56454716Ssklower 	register struct in_addr *ap;
56554716Ssklower 	register struct ifnet *ifp;
56654716Ssklower {
56754716Ssklower 	register struct in_multi *inm;
56854716Ssklower 	struct ifreq ifr;
56954716Ssklower 	struct in_ifaddr *ia;
57054716Ssklower 	int s = splnet();
57154716Ssklower 
57254716Ssklower 	/*
57354716Ssklower 	 * See if address already in list.
57454716Ssklower 	 */
57554716Ssklower 	IN_LOOKUP_MULTI(*ap, ifp, inm);
57654716Ssklower 	if (inm != NULL) {
57754716Ssklower 		/*
57854716Ssklower 		 * Found it; just increment the reference count.
57954716Ssklower 		 */
58054716Ssklower 		++inm->inm_refcount;
58154716Ssklower 	}
58254716Ssklower 	else {
58354716Ssklower 		/*
58454716Ssklower 		 * New address; allocate a new multicast record
58554716Ssklower 		 * and link it into the interface's multicast list.
58654716Ssklower 		 */
58754716Ssklower 		inm = (struct in_multi *)malloc(sizeof(*inm),
58854716Ssklower 		    M_IPMADDR, M_NOWAIT);
58954716Ssklower 		if (inm == NULL) {
59054716Ssklower 			splx(s);
59154716Ssklower 			return (NULL);
59254716Ssklower 		}
59354716Ssklower 		inm->inm_addr = *ap;
59454716Ssklower 		inm->inm_ifp = ifp;
59554716Ssklower 		inm->inm_refcount = 1;
59654716Ssklower 		IFP_TO_IA(ifp, ia);
59754716Ssklower 		if (ia == NULL) {
59854716Ssklower 			free(inm, M_IPMADDR);
59954716Ssklower 			splx(s);
60054716Ssklower 			return (NULL);
60154716Ssklower 		}
60254716Ssklower 		inm->inm_ia = ia;
60358413Ssklower 		inm->inm_next = ia->ia_multiaddrs;
60458413Ssklower 		ia->ia_multiaddrs = inm;
60554716Ssklower 		/*
60654716Ssklower 		 * Ask the network driver to update its multicast reception
60754716Ssklower 		 * filter appropriately for the new address.
60854716Ssklower 		 */
60954716Ssklower 		((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
61054716Ssklower 		((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
61158413Ssklower 		if ((ifp->if_ioctl == NULL) ||
61258413Ssklower 		    (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
61358413Ssklower 			ia->ia_multiaddrs = inm->inm_next;
61454716Ssklower 			free(inm, M_IPMADDR);
61554716Ssklower 			splx(s);
61654716Ssklower 			return (NULL);
61754716Ssklower 		}
61854716Ssklower 		/*
61954716Ssklower 		 * Let IGMP know that we have joined a new IP multicast group.
62054716Ssklower 		 */
62154716Ssklower 		igmp_joingroup(inm);
62254716Ssklower 	}
62354716Ssklower 	splx(s);
62454716Ssklower 	return (inm);
62554716Ssklower }
62654716Ssklower 
62754716Ssklower /*
62854716Ssklower  * Delete a multicast address record.
62954716Ssklower  */
63054716Ssklower int
63154716Ssklower in_delmulti(inm)
63254716Ssklower 	register struct in_multi *inm;
63354716Ssklower {
63454716Ssklower 	register struct in_multi **p;
63554716Ssklower 	struct ifreq ifr;
63654716Ssklower 	int s = splnet();
63754716Ssklower 
63854716Ssklower 	if (--inm->inm_refcount == 0) {
63954716Ssklower 		/*
64054716Ssklower 		 * No remaining claims to this record; let IGMP know that
64154716Ssklower 		 * we are leaving the multicast group.
64254716Ssklower 		 */
64354716Ssklower 		igmp_leavegroup(inm);
64454716Ssklower 		/*
64554716Ssklower 		 * Unlink from list.
64654716Ssklower 		 */
64754716Ssklower 		for (p = &inm->inm_ia->ia_multiaddrs;
64854716Ssklower 		     *p != inm;
64954716Ssklower 		     p = &(*p)->inm_next)
65054716Ssklower 			 continue;
65154716Ssklower 		*p = (*p)->inm_next;
65254716Ssklower 		/*
65354716Ssklower 		 * Notify the network driver to update its multicast reception
65454716Ssklower 		 * filter.
65554716Ssklower 		 */
65654716Ssklower 		((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
65754716Ssklower 		((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
65854716Ssklower 								inm->inm_addr;
65954716Ssklower 		(*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
66054716Ssklower 							     (caddr_t)&ifr);
66154716Ssklower 		free(inm, M_IPMADDR);
66254716Ssklower 	}
66354716Ssklower 	splx(s);
66454716Ssklower }
6657159Ssam #endif
666