xref: /csrg-svn/sys/netinet/in.c (revision 52619)
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*52619Ssklower  *	@(#)in.c	7.23 (Berkeley) 02/20/92
823175Smckusick  */
97159Ssam 
1017058Sbloom #include "param.h"
1118377Skarels #include "ioctl.h"
1250134Ssklower #include "errno.h"
1317058Sbloom #include "mbuf.h"
1417058Sbloom #include "socket.h"
1517058Sbloom #include "socketvar.h"
1617058Sbloom #include "in_systm.h"
1748464Skarels #include "net/if.h"
1848464Skarels #include "net/route.h"
1948464Skarels #include "net/af.h"
2018377Skarels #include "in.h"
2118377Skarels #include "in_var.h"
227159Ssam 
237159Ssam #ifdef INET
247159Ssam /*
2518377Skarels  * Formulate an Internet address from network + host.
267159Ssam  */
277159Ssam struct in_addr
2818377Skarels in_makeaddr(net, host)
2918377Skarels 	u_long net, host;
307159Ssam {
3118377Skarels 	register struct in_ifaddr *ia;
3218377Skarels 	register u_long mask;
337159Ssam 	u_long addr;
347159Ssam 
3518377Skarels 	if (IN_CLASSA(net))
3618377Skarels 		mask = IN_CLASSA_HOST;
3718377Skarels 	else if (IN_CLASSB(net))
3818377Skarels 		mask = IN_CLASSB_HOST;
397159Ssam 	else
4018377Skarels 		mask = IN_CLASSC_HOST;
4118377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
4218377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net) {
4318377Skarels 			mask = ~ia->ia_subnetmask;
4418377Skarels 			break;
4518377Skarels 		}
4618377Skarels 	addr = htonl(net | (host & mask));
477159Ssam 	return (*(struct in_addr *)&addr);
487159Ssam }
497159Ssam 
507159Ssam /*
518595Sroot  * Return the network number from an internet address.
527159Ssam  */
5324805Skarels u_long
547159Ssam in_netof(in)
557159Ssam 	struct in_addr in;
567159Ssam {
578937Sroot 	register u_long i = ntohl(in.s_addr);
5818377Skarels 	register u_long net;
5918377Skarels 	register struct in_ifaddr *ia;
607159Ssam 
6118377Skarels 	if (IN_CLASSA(i))
6218377Skarels 		net = i & IN_CLASSA_NET;
6318377Skarels 	else if (IN_CLASSB(i))
6418377Skarels 		net = i & IN_CLASSB_NET;
6531392Skarels 	else if (IN_CLASSC(i))
6631392Skarels 		net = i & IN_CLASSC_NET;
6718377Skarels 	else
6831392Skarels 		return (0);
6916413Skarels 
7016413Skarels 	/*
7118377Skarels 	 * Check whether network is a subnet;
7216413Skarels 	 * if so, return subnet number.
7316413Skarels 	 */
7418377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
7524805Skarels 		if (net == ia->ia_net)
7618377Skarels 			return (i & ia->ia_subnetmask);
7716413Skarels 	return (net);
787159Ssam }
797159Ssam 
807159Ssam /*
8137471Ssklower  * Compute and save network mask as sockaddr from an internet address.
8237471Ssklower  */
8337471Ssklower in_sockmaskof(in, sockmask)
8437471Ssklower 	struct in_addr in;
8537471Ssklower 	register struct sockaddr_in *sockmask;
8637471Ssklower {
8737471Ssklower 	register u_long net;
8837471Ssklower 	register u_long mask;
8937471Ssklower     {
9037471Ssklower 	register u_long i = ntohl(in.s_addr);
9137471Ssklower 
9237471Ssklower 	if (i == 0)
9337471Ssklower 		net = 0, mask = 0;
9437471Ssklower 	else if (IN_CLASSA(i))
9537471Ssklower 		net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
9637471Ssklower 	else if (IN_CLASSB(i))
9737471Ssklower 		net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
9837471Ssklower 	else if (IN_CLASSC(i))
9937471Ssklower 		net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
10037471Ssklower 	else
10137471Ssklower 		net = i, mask = -1;
10237471Ssklower     }
10337471Ssklower     {
10437471Ssklower 	register struct in_ifaddr *ia;
10537471Ssklower 	/*
10637471Ssklower 	 * Check whether network is a subnet;
10737471Ssklower 	 * if so, return subnet number.
10837471Ssklower 	 */
10937471Ssklower 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
11037471Ssklower 		if (net == ia->ia_net)
11137471Ssklower 			mask =  ia->ia_subnetmask;
11237471Ssklower     }
11337471Ssklower     {
11437471Ssklower 	register char *cpbase = (char *)&(sockmask->sin_addr);
11539183Ssklower 	register char *cp = (char *)(1 + &(sockmask->sin_addr));
11637471Ssklower 
11737471Ssklower 	sockmask->sin_addr.s_addr = htonl(mask);
11837471Ssklower 	sockmask->sin_len = 0;
11937471Ssklower 	while (--cp >= cpbase)
12037471Ssklower 		if (*cp) {
12137471Ssklower 			sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
12237471Ssklower 			break;
12337471Ssklower 		}
12437471Ssklower     }
12537471Ssklower }
12637471Ssklower 
12737471Ssklower /*
1288595Sroot  * Return the host portion of an internet address.
1297159Ssam  */
13026381Skarels u_long
1317159Ssam in_lnaof(in)
1327159Ssam 	struct in_addr in;
1337159Ssam {
1348937Sroot 	register u_long i = ntohl(in.s_addr);
13518377Skarels 	register u_long net, host;
13618377Skarels 	register struct in_ifaddr *ia;
1377159Ssam 
13816377Skarels 	if (IN_CLASSA(i)) {
13918377Skarels 		net = i & IN_CLASSA_NET;
14018377Skarels 		host = i & IN_CLASSA_HOST;
14116377Skarels 	} else if (IN_CLASSB(i)) {
14218377Skarels 		net = i & IN_CLASSB_NET;
14318377Skarels 		host = i & IN_CLASSB_HOST;
14431392Skarels 	} else if (IN_CLASSC(i)) {
14518377Skarels 		net = i & IN_CLASSC_NET;
14618377Skarels 		host = i & IN_CLASSC_HOST;
14731392Skarels 	} else
14831392Skarels 		return (i);
1497159Ssam 
15016413Skarels 	/*
15118377Skarels 	 * Check whether network is a subnet;
15216413Skarels 	 * if so, use the modified interpretation of `host'.
15316413Skarels 	 */
15418377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
15524805Skarels 		if (net == ia->ia_net)
15618377Skarels 			return (host &~ ia->ia_subnetmask);
15716413Skarels 	return (host);
15816377Skarels }
15916377Skarels 
16026381Skarels #ifndef SUBNETSARELOCAL
16126381Skarels #define	SUBNETSARELOCAL	1
16226381Skarels #endif
16326381Skarels int subnetsarelocal = SUBNETSARELOCAL;
16416377Skarels /*
16518377Skarels  * Return 1 if an internet address is for a ``local'' host
16626381Skarels  * (one to which we have a connection).  If subnetsarelocal
16726381Skarels  * is true, this includes other subnets of the local net.
16826381Skarels  * Otherwise, it includes only the directly-connected (sub)nets.
16917271Skarels  */
17017271Skarels in_localaddr(in)
17117271Skarels 	struct in_addr in;
17217271Skarels {
17317271Skarels 	register u_long i = ntohl(in.s_addr);
17418377Skarels 	register struct in_ifaddr *ia;
17517271Skarels 
17630697Skarels 	if (subnetsarelocal) {
17730697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
17830697Skarels 			if ((i & ia->ia_netmask) == ia->ia_net)
17930697Skarels 				return (1);
18030697Skarels 	} else {
18130697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
18230697Skarels 			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
18330697Skarels 				return (1);
18430697Skarels 	}
18518377Skarels 	return (0);
18618377Skarels }
18718377Skarels 
18831392Skarels /*
18931392Skarels  * Determine whether an IP address is in a reserved set of addresses
19031392Skarels  * that may not be forwarded, or whether datagrams to that destination
19131392Skarels  * may be forwarded.
19231392Skarels  */
19331392Skarels in_canforward(in)
19431392Skarels 	struct in_addr in;
19531392Skarels {
19631392Skarels 	register u_long i = ntohl(in.s_addr);
19731392Skarels 	register u_long net;
19831392Skarels 
19931392Skarels 	if (IN_EXPERIMENTAL(i))
20031392Skarels 		return (0);
20131392Skarels 	if (IN_CLASSA(i)) {
20231392Skarels 		net = i & IN_CLASSA_NET;
20331392Skarels 		if (net == 0 || net == IN_LOOPBACKNET)
20431392Skarels 			return (0);
20531392Skarels 	}
20631392Skarels 	return (1);
20731392Skarels }
20831392Skarels 
20924805Skarels int	in_interfaces;		/* number of external internet interfaces */
21024805Skarels extern	struct ifnet loif;
21124805Skarels 
21218377Skarels /*
21318377Skarels  * Generic internet control operations (ioctl's).
21418377Skarels  * Ifp is 0 if not an interface-specific ioctl.
21518377Skarels  */
21624805Skarels /* ARGSUSED */
21718377Skarels in_control(so, cmd, data, ifp)
21818377Skarels 	struct socket *so;
21918377Skarels 	int cmd;
22018377Skarels 	caddr_t data;
22118377Skarels 	register struct ifnet *ifp;
22218377Skarels {
22318377Skarels 	register struct ifreq *ifr = (struct ifreq *)data;
22418377Skarels 	register struct in_ifaddr *ia = 0;
22537471Ssklower 	register struct ifaddr *ifa;
22637471Ssklower 	struct in_ifaddr *oia;
22737471Ssklower 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
22837471Ssklower 	struct sockaddr_in oldaddr;
22937471Ssklower 	int error, hostIsNew, maskIsNew;
23037471Ssklower 	u_long i;
23118377Skarels 
23218377Skarels 	/*
23318377Skarels 	 * Find address for this interface, if it exists.
23418377Skarels 	 */
23518377Skarels 	if (ifp)
23618377Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
23718377Skarels 			if (ia->ia_ifp == ifp)
23818377Skarels 				break;
23918377Skarels 
24018377Skarels 	switch (cmd) {
24118377Skarels 
24237471Ssklower 	case SIOCAIFADDR:
24337471Ssklower 	case SIOCDIFADDR:
24437471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET)
24537471Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
24637471Ssklower 			if (ia->ia_ifp == ifp  &&
24737471Ssklower 			    ia->ia_addr.sin_addr.s_addr ==
24837471Ssklower 				ifra->ifra_addr.sin_addr.s_addr)
24937471Ssklower 			    break;
25037471Ssklower 		}
25137471Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
25237471Ssklower 			return (EADDRNOTAVAIL);
25337471Ssklower 		/* FALLTHROUGH */
25418377Skarels 	case SIOCSIFADDR:
25518377Skarels 	case SIOCSIFNETMASK:
25626456Skarels 	case SIOCSIFDSTADDR:
25748464Skarels 		if ((so->so_state & SS_PRIV) == 0)
25848464Skarels 			return (EPERM);
25918377Skarels 
26018377Skarels 		if (ifp == 0)
26118377Skarels 			panic("in_control");
26218377Skarels 		if (ia == (struct in_ifaddr *)0) {
26352028Ssklower 			oia = (struct in_ifaddr *)
26452028Ssklower 				malloc(sizeof *oia, M_IFADDR, M_WAITOK);
26552028Ssklower 			if (oia == (struct in_ifaddr *)NULL)
26618377Skarels 				return (ENOBUFS);
26752028Ssklower 			bzero((caddr_t)oia, sizeof *oia);
26818377Skarels 			if (ia = in_ifaddr) {
26918377Skarels 				for ( ; ia->ia_next; ia = ia->ia_next)
27018377Skarels 					;
27152028Ssklower 				ia->ia_next = oia;
27218377Skarels 			} else
27352028Ssklower 				in_ifaddr = oia;
27452028Ssklower 			ia = oia;
27518377Skarels 			if (ifa = ifp->if_addrlist) {
27618377Skarels 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
27718377Skarels 					;
27818377Skarels 				ifa->ifa_next = (struct ifaddr *) ia;
27918377Skarels 			} else
28018377Skarels 				ifp->if_addrlist = (struct ifaddr *) ia;
28137471Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
28237471Ssklower 			ia->ia_ifa.ifa_dstaddr
28337471Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
28437471Ssklower 			ia->ia_ifa.ifa_netmask
28537471Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
28637471Ssklower 			ia->ia_sockmask.sin_len = 8;
28737471Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
28837471Ssklower 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
28937471Ssklower 				ia->ia_broadaddr.sin_family = AF_INET;
29037471Ssklower 			}
29118377Skarels 			ia->ia_ifp = ifp;
29224805Skarels 			if (ifp != &loif)
29324805Skarels 				in_interfaces++;
29417271Skarels 		}
29518377Skarels 		break;
29626317Skarels 
29726317Skarels 	case SIOCSIFBRDADDR:
29848464Skarels 		if ((so->so_state & SS_PRIV) == 0)
29948464Skarels 			return (EPERM);
30026317Skarels 		/* FALLTHROUGH */
30126317Skarels 
30239183Ssklower 	case SIOCGIFADDR:
30339183Ssklower 	case SIOCGIFNETMASK:
30439183Ssklower 	case SIOCGIFDSTADDR:
30539183Ssklower 	case SIOCGIFBRDADDR:
30626317Skarels 		if (ia == (struct in_ifaddr *)0)
30726317Skarels 			return (EADDRNOTAVAIL);
30826317Skarels 		break;
30917271Skarels 	}
31018377Skarels 	switch (cmd) {
31118377Skarels 
31218377Skarels 	case SIOCGIFADDR:
31337471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
31418377Skarels 		break;
31518377Skarels 
31618377Skarels 	case SIOCGIFBRDADDR:
31718377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
31818377Skarels 			return (EINVAL);
31937471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
32018377Skarels 		break;
32118377Skarels 
32218377Skarels 	case SIOCGIFDSTADDR:
32318377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
32418377Skarels 			return (EINVAL);
32537471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
32618377Skarels 		break;
32718377Skarels 
32818377Skarels 	case SIOCGIFNETMASK:
32937471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
33018377Skarels 		break;
33118377Skarels 
33218377Skarels 	case SIOCSIFDSTADDR:
33318377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
33418377Skarels 			return (EINVAL);
33527066Skarels 		oldaddr = ia->ia_dstaddr;
33637471Ssklower 		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
337*52619Ssklower 		if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
338*52619Ssklower 					(ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
33927066Skarels 			ia->ia_dstaddr = oldaddr;
34018377Skarels 			return (error);
34127066Skarels 		}
34227066Skarels 		if (ia->ia_flags & IFA_ROUTE) {
34337471Ssklower 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
34437471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
34545454Ssklower 			ia->ia_ifa.ifa_dstaddr =
34645454Ssklower 					(struct sockaddr *)&ia->ia_dstaddr;
34737471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
34827066Skarels 		}
34918377Skarels 		break;
35018377Skarels 
35118377Skarels 	case SIOCSIFBRDADDR:
35218377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
35318377Skarels 			return (EINVAL);
35437471Ssklower 		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
35518377Skarels 		break;
35618377Skarels 
35718377Skarels 	case SIOCSIFADDR:
35834500Skarels 		return (in_ifinit(ifp, ia,
35937471Ssklower 		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
36018377Skarels 
36118377Skarels 	case SIOCSIFNETMASK:
36237471Ssklower 		i = ifra->ifra_addr.sin_addr.s_addr;
36337471Ssklower 		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
36418377Skarels 		break;
36518377Skarels 
36637471Ssklower 	case SIOCAIFADDR:
36744368Skarels 		maskIsNew = 0;
36844368Skarels 		hostIsNew = 1;
36944368Skarels 		error = 0;
37037471Ssklower 		if (ia->ia_addr.sin_family == AF_INET) {
37137471Ssklower 			if (ifra->ifra_addr.sin_len == 0) {
37237471Ssklower 				ifra->ifra_addr = ia->ia_addr;
37337471Ssklower 				hostIsNew = 0;
37437471Ssklower 			} else if (ifra->ifra_addr.sin_addr.s_addr ==
37537471Ssklower 					       ia->ia_addr.sin_addr.s_addr)
37637471Ssklower 				hostIsNew = 0;
37737471Ssklower 		}
37837471Ssklower 		if (ifra->ifra_mask.sin_len) {
37937471Ssklower 			in_ifscrub(ifp, ia);
38037471Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
38137471Ssklower 			ia->ia_subnetmask =
38244368Skarels 			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
38337471Ssklower 			maskIsNew = 1;
38437471Ssklower 		}
38537471Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
38637471Ssklower 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
38737471Ssklower 			in_ifscrub(ifp, ia);
38837471Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
38937471Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
39037471Ssklower 		}
39137471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET &&
39244368Skarels 		    (hostIsNew || maskIsNew))
39337471Ssklower 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
39437471Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) &&
39537471Ssklower 		    (ifra->ifra_broadaddr.sin_family == AF_INET))
39637471Ssklower 			ia->ia_broadaddr = ifra->ifra_broadaddr;
39737471Ssklower 		return (error);
39837471Ssklower 
39937471Ssklower 	case SIOCDIFADDR:
40037471Ssklower 		in_ifscrub(ifp, ia);
40137471Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
40237471Ssklower 			ifp->if_addrlist = ifa->ifa_next;
40337471Ssklower 		else {
40437471Ssklower 			while (ifa->ifa_next &&
40537471Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
40637471Ssklower 				    ifa = ifa->ifa_next;
40737471Ssklower 			if (ifa->ifa_next)
40844368Skarels 				ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
40937471Ssklower 			else
41037471Ssklower 				printf("Couldn't unlink inifaddr from ifp\n");
41137471Ssklower 		}
41237471Ssklower 		oia = ia;
41344368Skarels 		if (oia == (ia = in_ifaddr))
41437471Ssklower 			in_ifaddr = ia->ia_next;
41544368Skarels 		else {
41644368Skarels 			while (ia->ia_next && (ia->ia_next != oia))
41737471Ssklower 				ia = ia->ia_next;
41837471Ssklower 			if (ia->ia_next)
41944368Skarels 				ia->ia_next = oia->ia_next;
42037471Ssklower 			else
42137471Ssklower 				printf("Didn't unlink inifadr from list\n");
42237471Ssklower 		}
42352028Ssklower 		IFAFREE((&oia->ia_ifa));
42437471Ssklower 		break;
42537471Ssklower 
42618377Skarels 	default:
42718377Skarels 		if (ifp == 0 || ifp->if_ioctl == 0)
42818377Skarels 			return (EOPNOTSUPP);
42918377Skarels 		return ((*ifp->if_ioctl)(ifp, cmd, data));
43018377Skarels 	}
43117271Skarels 	return (0);
43217271Skarels }
43317271Skarels 
43417271Skarels /*
43537471Ssklower  * Delete any existing route for an interface.
43637471Ssklower  */
43737471Ssklower in_ifscrub(ifp, ia)
43837471Ssklower 	register struct ifnet *ifp;
43937471Ssklower 	register struct in_ifaddr *ia;
44037471Ssklower {
44137471Ssklower 
44237471Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
44337471Ssklower 		return;
44437471Ssklower 	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
44537471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
44637471Ssklower 	else
44737471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
44837471Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
44937471Ssklower }
45037471Ssklower 
45137471Ssklower /*
45218377Skarels  * Initialize an interface's internet address
45318377Skarels  * and routing table entry.
4547159Ssam  */
45537471Ssklower in_ifinit(ifp, ia, sin, scrub)
4567159Ssam 	register struct ifnet *ifp;
45718377Skarels 	register struct in_ifaddr *ia;
45818377Skarels 	struct sockaddr_in *sin;
45952274Storek 	int scrub;
4607159Ssam {
46118377Skarels 	register u_long i = ntohl(sin->sin_addr.s_addr);
46237471Ssklower 	struct sockaddr_in oldaddr;
46345454Ssklower 	int s = splimp(), error, flags = RTF_UP;
46450134Ssklower 	int ether_output(), arp_rtrequest();
4657159Ssam 
46627066Skarels 	oldaddr = ia->ia_addr;
46737471Ssklower 	ia->ia_addr = *sin;
46818377Skarels 	/*
46926317Skarels 	 * Give the interface a chance to initialize
47026317Skarels 	 * if this is its first address,
47126317Skarels 	 * and to validate the address if necessary.
47226317Skarels 	 */
47352274Storek 	if (ifp->if_ioctl &&
47452274Storek 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
47526317Skarels 		splx(s);
47627066Skarels 		ia->ia_addr = oldaddr;
47726317Skarels 		return (error);
47826317Skarels 	}
47950134Ssklower 	if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
48050134Ssklower 		ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
48150134Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
48250134Ssklower 	}
48345454Ssklower 	splx(s);
48437471Ssklower 	if (scrub) {
48537471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
48637471Ssklower 		in_ifscrub(ifp, ia);
48737471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
48818377Skarels 	}
48918377Skarels 	if (IN_CLASSA(i))
49018377Skarels 		ia->ia_netmask = IN_CLASSA_NET;
49118377Skarels 	else if (IN_CLASSB(i))
49218377Skarels 		ia->ia_netmask = IN_CLASSB_NET;
49318377Skarels 	else
49418377Skarels 		ia->ia_netmask = IN_CLASSC_NET;
49518377Skarels 	ia->ia_net = i & ia->ia_netmask;
49618377Skarels 	/*
49718377Skarels 	 * The subnet mask includes at least the standard network part,
49818377Skarels 	 * but may already have been set to a larger value.
49918377Skarels 	 */
50018377Skarels 	ia->ia_subnetmask |= ia->ia_netmask;
50118377Skarels 	ia->ia_subnet = i & ia->ia_subnetmask;
50237471Ssklower 	ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
50339183Ssklower 	{
50439183Ssklower 		register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr));
50539183Ssklower 		register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr);
50639183Ssklower 		while (--cp >= cpbase)
50739183Ssklower 			if (*cp) {
50839183Ssklower 				ia->ia_sockmask.sin_len =
50939183Ssklower 					1 + cp - (char *) &(ia->ia_sockmask);
51039183Ssklower 				break;
51139183Ssklower 			}
51239183Ssklower 	}
51345454Ssklower 	/*
51445454Ssklower 	 * Add route for the network.
51545454Ssklower 	 */
51652617Ssklower 	ia->ia_ifa.ifa_metric = ifp->if_metric;
51718377Skarels 	if (ifp->if_flags & IFF_BROADCAST) {
51837471Ssklower 		ia->ia_broadaddr.sin_addr =
51918377Skarels 			in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
52025195Skarels 		ia->ia_netbroadcast.s_addr =
52125195Skarels 		    htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
52245454Ssklower 	} else if (ifp->if_flags & IFF_LOOPBACK) {
52337471Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
52445454Ssklower 		flags |= RTF_HOST;
52545454Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT) {
52645454Ssklower 		if (ia->ia_dstaddr.sin_family != AF_INET)
52745454Ssklower 			return (0);
52845454Ssklower 		flags |= RTF_HOST;
52927066Skarels 	}
53045454Ssklower 	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
53145454Ssklower 		ia->ia_flags |= IFA_ROUTE;
53245454Ssklower 	return (error);
5337159Ssam }
53418377Skarels 
53518377Skarels /*
53618377Skarels  * Return address info for specified internet network.
53718377Skarels  */
53818377Skarels struct in_ifaddr *
53918377Skarels in_iaonnetof(net)
54018377Skarels 	u_long net;
54118377Skarels {
54218377Skarels 	register struct in_ifaddr *ia;
54318377Skarels 
54418377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
54518377Skarels 		if (ia->ia_subnet == net)
54618377Skarels 			return (ia);
54718377Skarels 	return ((struct in_ifaddr *)0);
54818377Skarels }
54918377Skarels 
55018377Skarels /*
55130523Skarels  * Return 1 if the address might be a local broadcast address.
55218377Skarels  */
55318377Skarels in_broadcast(in)
55418377Skarels 	struct in_addr in;
55518377Skarels {
55618377Skarels 	register struct in_ifaddr *ia;
55730523Skarels 	u_long t;
55818377Skarels 
55918377Skarels 	/*
56018377Skarels 	 * Look through the list of addresses for a match
56118377Skarels 	 * with a broadcast address.
56218377Skarels 	 */
56318377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
56430523Skarels 	    if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
56537471Ssklower 		if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
56618377Skarels 		     return (1);
56730523Skarels 		/*
56830523Skarels 		 * Check for old-style (host 0) broadcast.
56930523Skarels 		 */
57030523Skarels 		if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
57130523Skarels 		    return (1);
57230523Skarels 	}
57330523Skarels 	if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
57430523Skarels 		return (1);
57518377Skarels 	return (0);
57618377Skarels }
5777159Ssam #endif
578