xref: /csrg-svn/sys/netinet/in.c (revision 44368)
123175Smckusick /*
229136Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
332787Sbostic  * All rights reserved.
423175Smckusick  *
532787Sbostic  * Redistribution and use in source and binary forms are permitted
634854Sbostic  * provided that the above copyright notice and this paragraph are
734854Sbostic  * duplicated in all such forms and that any documentation,
834854Sbostic  * advertising materials, and other materials related to such
934854Sbostic  * distribution and use acknowledge that the software was developed
1034854Sbostic  * by the University of California, Berkeley.  The name of the
1134854Sbostic  * University may not be used to endorse or promote products derived
1234854Sbostic  * from this software without specific prior written permission.
1334854Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434854Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534854Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1632787Sbostic  *
17*44368Skarels  *	@(#)in.c	7.14 (Berkeley) 06/28/90
1823175Smckusick  */
197159Ssam 
2017058Sbloom #include "param.h"
2118377Skarels #include "ioctl.h"
2217058Sbloom #include "mbuf.h"
2317058Sbloom #include "protosw.h"
2417058Sbloom #include "socket.h"
2517058Sbloom #include "socketvar.h"
2618377Skarels #include "user.h"
2717058Sbloom #include "in_systm.h"
287166Ssam #include "../net/if.h"
297166Ssam #include "../net/route.h"
307159Ssam #include "../net/af.h"
3118377Skarels #include "in.h"
3218377Skarels #include "in_var.h"
337159Ssam 
347159Ssam #ifdef INET
357159Ssam /*
3618377Skarels  * Formulate an Internet address from network + host.
377159Ssam  */
387159Ssam struct in_addr
3918377Skarels in_makeaddr(net, host)
4018377Skarels 	u_long net, host;
417159Ssam {
4218377Skarels 	register struct in_ifaddr *ia;
4318377Skarels 	register u_long mask;
447159Ssam 	u_long addr;
457159Ssam 
4618377Skarels 	if (IN_CLASSA(net))
4718377Skarels 		mask = IN_CLASSA_HOST;
4818377Skarels 	else if (IN_CLASSB(net))
4918377Skarels 		mask = IN_CLASSB_HOST;
507159Ssam 	else
5118377Skarels 		mask = IN_CLASSC_HOST;
5218377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
5318377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net) {
5418377Skarels 			mask = ~ia->ia_subnetmask;
5518377Skarels 			break;
5618377Skarels 		}
5718377Skarels 	addr = htonl(net | (host & mask));
587159Ssam 	return (*(struct in_addr *)&addr);
597159Ssam }
607159Ssam 
617159Ssam /*
628595Sroot  * Return the network number from an internet address.
637159Ssam  */
6424805Skarels u_long
657159Ssam in_netof(in)
667159Ssam 	struct in_addr in;
677159Ssam {
688937Sroot 	register u_long i = ntohl(in.s_addr);
6918377Skarels 	register u_long net;
7018377Skarels 	register struct in_ifaddr *ia;
717159Ssam 
7218377Skarels 	if (IN_CLASSA(i))
7318377Skarels 		net = i & IN_CLASSA_NET;
7418377Skarels 	else if (IN_CLASSB(i))
7518377Skarels 		net = i & IN_CLASSB_NET;
7631392Skarels 	else if (IN_CLASSC(i))
7731392Skarels 		net = i & IN_CLASSC_NET;
7818377Skarels 	else
7931392Skarels 		return (0);
8016413Skarels 
8116413Skarels 	/*
8218377Skarels 	 * Check whether network is a subnet;
8316413Skarels 	 * if so, return subnet number.
8416413Skarels 	 */
8518377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
8624805Skarels 		if (net == ia->ia_net)
8718377Skarels 			return (i & ia->ia_subnetmask);
8816413Skarels 	return (net);
897159Ssam }
907159Ssam 
917159Ssam /*
9237471Ssklower  * Compute and save network mask as sockaddr from an internet address.
9337471Ssklower  */
9437471Ssklower in_sockmaskof(in, sockmask)
9537471Ssklower 	struct in_addr in;
9637471Ssklower 	register struct sockaddr_in *sockmask;
9737471Ssklower {
9837471Ssklower 	register u_long net;
9937471Ssklower 	register u_long mask;
10037471Ssklower     {
10137471Ssklower 	register u_long i = ntohl(in.s_addr);
10237471Ssklower 
10337471Ssklower 	if (i == 0)
10437471Ssklower 		net = 0, mask = 0;
10537471Ssklower 	else if (IN_CLASSA(i))
10637471Ssklower 		net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
10737471Ssklower 	else if (IN_CLASSB(i))
10837471Ssklower 		net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
10937471Ssklower 	else if (IN_CLASSC(i))
11037471Ssklower 		net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
11137471Ssklower 	else
11237471Ssklower 		net = i, mask = -1;
11337471Ssklower     }
11437471Ssklower     {
11537471Ssklower 	register struct in_ifaddr *ia;
11637471Ssklower 	/*
11737471Ssklower 	 * Check whether network is a subnet;
11837471Ssklower 	 * if so, return subnet number.
11937471Ssklower 	 */
12037471Ssklower 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
12137471Ssklower 		if (net == ia->ia_net)
12237471Ssklower 			mask =  ia->ia_subnetmask;
12337471Ssklower     }
12437471Ssklower     {
12537471Ssklower 	register char *cpbase = (char *)&(sockmask->sin_addr);
12639183Ssklower 	register char *cp = (char *)(1 + &(sockmask->sin_addr));
12737471Ssklower 
12837471Ssklower 	sockmask->sin_addr.s_addr = htonl(mask);
12937471Ssklower 	sockmask->sin_len = 0;
13037471Ssklower 	while (--cp >= cpbase)
13137471Ssklower 		if (*cp) {
13237471Ssklower 			sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
13337471Ssklower 			break;
13437471Ssklower 		}
13537471Ssklower     }
13637471Ssklower }
13737471Ssklower 
13837471Ssklower /*
1398595Sroot  * Return the host portion of an internet address.
1407159Ssam  */
14126381Skarels u_long
1427159Ssam in_lnaof(in)
1437159Ssam 	struct in_addr in;
1447159Ssam {
1458937Sroot 	register u_long i = ntohl(in.s_addr);
14618377Skarels 	register u_long net, host;
14718377Skarels 	register struct in_ifaddr *ia;
1487159Ssam 
14916377Skarels 	if (IN_CLASSA(i)) {
15018377Skarels 		net = i & IN_CLASSA_NET;
15118377Skarels 		host = i & IN_CLASSA_HOST;
15216377Skarels 	} else if (IN_CLASSB(i)) {
15318377Skarels 		net = i & IN_CLASSB_NET;
15418377Skarels 		host = i & IN_CLASSB_HOST;
15531392Skarels 	} else if (IN_CLASSC(i)) {
15618377Skarels 		net = i & IN_CLASSC_NET;
15718377Skarels 		host = i & IN_CLASSC_HOST;
15831392Skarels 	} else
15931392Skarels 		return (i);
1607159Ssam 
16116413Skarels 	/*
16218377Skarels 	 * Check whether network is a subnet;
16316413Skarels 	 * if so, use the modified interpretation of `host'.
16416413Skarels 	 */
16518377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
16624805Skarels 		if (net == ia->ia_net)
16718377Skarels 			return (host &~ ia->ia_subnetmask);
16816413Skarels 	return (host);
16916377Skarels }
17016377Skarels 
17126381Skarels #ifndef SUBNETSARELOCAL
17226381Skarels #define	SUBNETSARELOCAL	1
17326381Skarels #endif
17426381Skarels int subnetsarelocal = SUBNETSARELOCAL;
17516377Skarels /*
17618377Skarels  * Return 1 if an internet address is for a ``local'' host
17726381Skarels  * (one to which we have a connection).  If subnetsarelocal
17826381Skarels  * is true, this includes other subnets of the local net.
17926381Skarels  * Otherwise, it includes only the directly-connected (sub)nets.
18017271Skarels  */
18117271Skarels in_localaddr(in)
18217271Skarels 	struct in_addr in;
18317271Skarels {
18417271Skarels 	register u_long i = ntohl(in.s_addr);
18518377Skarels 	register struct in_ifaddr *ia;
18617271Skarels 
18730697Skarels 	if (subnetsarelocal) {
18830697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
18930697Skarels 			if ((i & ia->ia_netmask) == ia->ia_net)
19030697Skarels 				return (1);
19130697Skarels 	} else {
19230697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
19330697Skarels 			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
19430697Skarels 				return (1);
19530697Skarels 	}
19618377Skarels 	return (0);
19718377Skarels }
19818377Skarels 
19931392Skarels /*
20031392Skarels  * Determine whether an IP address is in a reserved set of addresses
20131392Skarels  * that may not be forwarded, or whether datagrams to that destination
20231392Skarels  * may be forwarded.
20331392Skarels  */
20431392Skarels in_canforward(in)
20531392Skarels 	struct in_addr in;
20631392Skarels {
20731392Skarels 	register u_long i = ntohl(in.s_addr);
20831392Skarels 	register u_long net;
20931392Skarels 
21031392Skarels 	if (IN_EXPERIMENTAL(i))
21131392Skarels 		return (0);
21231392Skarels 	if (IN_CLASSA(i)) {
21331392Skarels 		net = i & IN_CLASSA_NET;
21431392Skarels 		if (net == 0 || net == IN_LOOPBACKNET)
21531392Skarels 			return (0);
21631392Skarels 	}
21731392Skarels 	return (1);
21831392Skarels }
21931392Skarels 
22024805Skarels int	in_interfaces;		/* number of external internet interfaces */
22124805Skarels extern	struct ifnet loif;
22224805Skarels 
22318377Skarels /*
22418377Skarels  * Generic internet control operations (ioctl's).
22518377Skarels  * Ifp is 0 if not an interface-specific ioctl.
22618377Skarels  */
22724805Skarels /* ARGSUSED */
22818377Skarels in_control(so, cmd, data, ifp)
22918377Skarels 	struct socket *so;
23018377Skarels 	int cmd;
23118377Skarels 	caddr_t data;
23218377Skarels 	register struct ifnet *ifp;
23318377Skarels {
23418377Skarels 	register struct ifreq *ifr = (struct ifreq *)data;
23518377Skarels 	register struct in_ifaddr *ia = 0;
23637471Ssklower 	register struct ifaddr *ifa;
23737471Ssklower 	struct in_ifaddr *oia;
23837471Ssklower 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
23918377Skarels 	struct mbuf *m;
24037471Ssklower 	struct sockaddr_in oldaddr;
24137471Ssklower 	int error, hostIsNew, maskIsNew;
24237471Ssklower 	u_long i;
24318377Skarels 
24418377Skarels 	/*
24518377Skarels 	 * Find address for this interface, if it exists.
24618377Skarels 	 */
24718377Skarels 	if (ifp)
24818377Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
24918377Skarels 			if (ia->ia_ifp == ifp)
25018377Skarels 				break;
25118377Skarels 
25218377Skarels 	switch (cmd) {
25318377Skarels 
25437471Ssklower 	case SIOCAIFADDR:
25537471Ssklower 	case SIOCDIFADDR:
25637471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET)
25737471Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
25837471Ssklower 			if (ia->ia_ifp == ifp  &&
25937471Ssklower 			    ia->ia_addr.sin_addr.s_addr ==
26037471Ssklower 				ifra->ifra_addr.sin_addr.s_addr)
26137471Ssklower 			    break;
26237471Ssklower 		}
26337471Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
26437471Ssklower 			return (EADDRNOTAVAIL);
26537471Ssklower 		/* FALLTHROUGH */
26618377Skarels 	case SIOCSIFADDR:
26718377Skarels 	case SIOCSIFNETMASK:
26826456Skarels 	case SIOCSIFDSTADDR:
26937548Smckusick 		if (error = suser(u.u_cred, &u.u_acflag))
27037548Smckusick 			return (error);
27118377Skarels 
27218377Skarels 		if (ifp == 0)
27318377Skarels 			panic("in_control");
27418377Skarels 		if (ia == (struct in_ifaddr *)0) {
27518377Skarels 			m = m_getclr(M_WAIT, MT_IFADDR);
27618377Skarels 			if (m == (struct mbuf *)NULL)
27718377Skarels 				return (ENOBUFS);
27818377Skarels 			if (ia = in_ifaddr) {
27918377Skarels 				for ( ; ia->ia_next; ia = ia->ia_next)
28018377Skarels 					;
28118377Skarels 				ia->ia_next = mtod(m, struct in_ifaddr *);
28218377Skarels 			} else
28318377Skarels 				in_ifaddr = mtod(m, struct in_ifaddr *);
28418377Skarels 			ia = mtod(m, struct in_ifaddr *);
28518377Skarels 			if (ifa = ifp->if_addrlist) {
28618377Skarels 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
28718377Skarels 					;
28818377Skarels 				ifa->ifa_next = (struct ifaddr *) ia;
28918377Skarels 			} else
29018377Skarels 				ifp->if_addrlist = (struct ifaddr *) ia;
29137471Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
29237471Ssklower 			ia->ia_ifa.ifa_dstaddr
29337471Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
29437471Ssklower 			ia->ia_ifa.ifa_netmask
29537471Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
29637471Ssklower 			ia->ia_sockmask.sin_len = 8;
29737471Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
29837471Ssklower 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
29937471Ssklower 				ia->ia_broadaddr.sin_family = AF_INET;
30037471Ssklower 			}
30118377Skarels 			ia->ia_ifp = ifp;
30224805Skarels 			if (ifp != &loif)
30324805Skarels 				in_interfaces++;
30417271Skarels 		}
30518377Skarels 		break;
30626317Skarels 
30726317Skarels 	case SIOCSIFBRDADDR:
30837548Smckusick 		if (error = suser(u.u_cred, &u.u_acflag))
30937548Smckusick 			return (error);
31026317Skarels 		/* FALLTHROUGH */
31126317Skarels 
31239183Ssklower 	case SIOCGIFADDR:
31339183Ssklower 	case SIOCGIFNETMASK:
31439183Ssklower 	case SIOCGIFDSTADDR:
31539183Ssklower 	case SIOCGIFBRDADDR:
31626317Skarels 		if (ia == (struct in_ifaddr *)0)
31726317Skarels 			return (EADDRNOTAVAIL);
31826317Skarels 		break;
31939183Ssklower 
32039183Ssklower 	default:
32139183Ssklower 		return (EOPNOTSUPP);
32239183Ssklower 		break;
32317271Skarels 	}
32418377Skarels 	switch (cmd) {
32518377Skarels 
32618377Skarels 	case SIOCGIFADDR:
32737471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
32818377Skarels 		break;
32918377Skarels 
33018377Skarels 	case SIOCGIFBRDADDR:
33118377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
33218377Skarels 			return (EINVAL);
33337471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
33418377Skarels 		break;
33518377Skarels 
33618377Skarels 	case SIOCGIFDSTADDR:
33718377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
33818377Skarels 			return (EINVAL);
33937471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
34018377Skarels 		break;
34118377Skarels 
34218377Skarels 	case SIOCGIFNETMASK:
34337471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
34418377Skarels 		break;
34518377Skarels 
34618377Skarels 	case SIOCSIFDSTADDR:
34718377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
34818377Skarels 			return (EINVAL);
34927066Skarels 		oldaddr = ia->ia_dstaddr;
35037471Ssklower 		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
35118377Skarels 		if (ifp->if_ioctl &&
35227066Skarels 		    (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
35327066Skarels 			ia->ia_dstaddr = oldaddr;
35418377Skarels 			return (error);
35527066Skarels 		}
35627066Skarels 		if (ia->ia_flags & IFA_ROUTE) {
35737471Ssklower 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
35837471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
35937471Ssklower 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_addr;
36037471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
36127066Skarels 		}
36218377Skarels 		break;
36318377Skarels 
36418377Skarels 	case SIOCSIFBRDADDR:
36518377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
36618377Skarels 			return (EINVAL);
36737471Ssklower 		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
36818377Skarels 		break;
36918377Skarels 
37018377Skarels 	case SIOCSIFADDR:
37134500Skarels 		return (in_ifinit(ifp, ia,
37237471Ssklower 		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
37318377Skarels 
37418377Skarels 	case SIOCSIFNETMASK:
37537471Ssklower 		i = ifra->ifra_addr.sin_addr.s_addr;
37637471Ssklower 		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
37718377Skarels 		break;
37818377Skarels 
37937471Ssklower 	case SIOCAIFADDR:
380*44368Skarels 		maskIsNew = 0;
381*44368Skarels 		hostIsNew = 1;
382*44368Skarels 		error = 0;
38337471Ssklower 		if (ia->ia_addr.sin_family == AF_INET) {
38437471Ssklower 			if (ifra->ifra_addr.sin_len == 0) {
38537471Ssklower 				ifra->ifra_addr = ia->ia_addr;
38637471Ssklower 				hostIsNew = 0;
38737471Ssklower 			} else if (ifra->ifra_addr.sin_addr.s_addr ==
38837471Ssklower 					       ia->ia_addr.sin_addr.s_addr)
38937471Ssklower 				hostIsNew = 0;
39037471Ssklower 		}
39137471Ssklower 		if (ifra->ifra_mask.sin_len) {
39237471Ssklower 			in_ifscrub(ifp, ia);
39337471Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
39437471Ssklower 			ia->ia_subnetmask =
395*44368Skarels 			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
39637471Ssklower 			maskIsNew = 1;
39737471Ssklower 		}
39837471Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
39937471Ssklower 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
40037471Ssklower 			in_ifscrub(ifp, ia);
40137471Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
40237471Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
40337471Ssklower 		}
40437471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET &&
405*44368Skarels 		    (hostIsNew || maskIsNew))
40637471Ssklower 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
40737471Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) &&
40837471Ssklower 		    (ifra->ifra_broadaddr.sin_family == AF_INET))
40937471Ssklower 			ia->ia_broadaddr = ifra->ifra_broadaddr;
41037471Ssklower 		return (error);
41137471Ssklower 
41237471Ssklower 	case SIOCDIFADDR:
41337471Ssklower 		in_ifscrub(ifp, ia);
41437471Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
41537471Ssklower 			ifp->if_addrlist = ifa->ifa_next;
41637471Ssklower 		else {
41737471Ssklower 			while (ifa->ifa_next &&
41837471Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
41937471Ssklower 				    ifa = ifa->ifa_next;
42037471Ssklower 			if (ifa->ifa_next)
421*44368Skarels 				ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
42237471Ssklower 			else
42337471Ssklower 				printf("Couldn't unlink inifaddr from ifp\n");
42437471Ssklower 		}
42537471Ssklower 		oia = ia;
426*44368Skarels 		if (oia == (ia = in_ifaddr))
42737471Ssklower 			in_ifaddr = ia->ia_next;
428*44368Skarels 		else {
429*44368Skarels 			while (ia->ia_next && (ia->ia_next != oia))
43037471Ssklower 				ia = ia->ia_next;
43137471Ssklower 			if (ia->ia_next)
432*44368Skarels 				ia->ia_next = oia->ia_next;
43337471Ssklower 			else
43437471Ssklower 				printf("Didn't unlink inifadr from list\n");
43537471Ssklower 		}
43637471Ssklower 		(void) m_free(dtom(oia));
43737471Ssklower 		break;
43837471Ssklower 
43918377Skarels 	default:
44018377Skarels 		if (ifp == 0 || ifp->if_ioctl == 0)
44118377Skarels 			return (EOPNOTSUPP);
44218377Skarels 		return ((*ifp->if_ioctl)(ifp, cmd, data));
44318377Skarels 	}
44417271Skarels 	return (0);
44517271Skarels }
44617271Skarels 
44717271Skarels /*
44837471Ssklower  * Delete any existing route for an interface.
44937471Ssklower  */
45037471Ssklower in_ifscrub(ifp, ia)
45137471Ssklower 	register struct ifnet *ifp;
45237471Ssklower 	register struct in_ifaddr *ia;
45337471Ssklower {
45437471Ssklower 
45537471Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
45637471Ssklower 		return;
45737471Ssklower 	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
45837471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
45937471Ssklower 	else
46037471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
46137471Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
46237471Ssklower }
46337471Ssklower 
46437471Ssklower /*
46518377Skarels  * Initialize an interface's internet address
46618377Skarels  * and routing table entry.
4677159Ssam  */
46837471Ssklower in_ifinit(ifp, ia, sin, scrub)
4697159Ssam 	register struct ifnet *ifp;
47018377Skarels 	register struct in_ifaddr *ia;
47118377Skarels 	struct sockaddr_in *sin;
4727159Ssam {
47318377Skarels 	register u_long i = ntohl(sin->sin_addr.s_addr);
47437471Ssklower 	struct sockaddr_in oldaddr;
47518377Skarels 	int s = splimp(), error;
4767159Ssam 
47727066Skarels 	oldaddr = ia->ia_addr;
47837471Ssklower 	ia->ia_addr = *sin;
47918377Skarels 	/*
48026317Skarels 	 * Give the interface a chance to initialize
48126317Skarels 	 * if this is its first address,
48226317Skarels 	 * and to validate the address if necessary.
48326317Skarels 	 */
48426317Skarels 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
48526317Skarels 		splx(s);
48627066Skarels 		ia->ia_addr = oldaddr;
48726317Skarels 		return (error);
48826317Skarels 	}
48937471Ssklower 	if (scrub) {
49037471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
49137471Ssklower 		in_ifscrub(ifp, ia);
49237471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
49318377Skarels 	}
49418377Skarels 	if (IN_CLASSA(i))
49518377Skarels 		ia->ia_netmask = IN_CLASSA_NET;
49618377Skarels 	else if (IN_CLASSB(i))
49718377Skarels 		ia->ia_netmask = IN_CLASSB_NET;
49818377Skarels 	else
49918377Skarels 		ia->ia_netmask = IN_CLASSC_NET;
50018377Skarels 	ia->ia_net = i & ia->ia_netmask;
50118377Skarels 	/*
50218377Skarels 	 * The subnet mask includes at least the standard network part,
50318377Skarels 	 * but may already have been set to a larger value.
50418377Skarels 	 */
50518377Skarels 	ia->ia_subnetmask |= ia->ia_netmask;
50618377Skarels 	ia->ia_subnet = i & ia->ia_subnetmask;
50737471Ssklower 	ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
50839183Ssklower 	{
50939183Ssklower 		register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr));
51039183Ssklower 		register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr);
51139183Ssklower 		while (--cp >= cpbase)
51239183Ssklower 			if (*cp) {
51339183Ssklower 				ia->ia_sockmask.sin_len =
51439183Ssklower 					1 + cp - (char *) &(ia->ia_sockmask);
51539183Ssklower 				break;
51639183Ssklower 			}
51739183Ssklower 	}
51818377Skarels 	if (ifp->if_flags & IFF_BROADCAST) {
51937471Ssklower 		ia->ia_broadaddr.sin_addr =
52018377Skarels 			in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
52125195Skarels 		ia->ia_netbroadcast.s_addr =
52225195Skarels 		    htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
52318377Skarels 	}
52418377Skarels 	/*
52518377Skarels 	 * Add route for the network.
52618377Skarels 	 */
52737471Ssklower 	if (ifp->if_flags & IFF_LOOPBACK) {
52837471Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
52937471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
53037471Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
53137471Ssklower 		 ia->ia_dstaddr.sin_family == AF_INET)
53237471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
53327066Skarels 	else {
53437471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
53527066Skarels 	}
53618377Skarels 	ia->ia_flags |= IFA_ROUTE;
53730523Skarels 	splx(s);
53818642Skarels 	return (0);
5397159Ssam }
54018377Skarels 
54118377Skarels /*
54218377Skarels  * Return address info for specified internet network.
54318377Skarels  */
54418377Skarels struct in_ifaddr *
54518377Skarels in_iaonnetof(net)
54618377Skarels 	u_long net;
54718377Skarels {
54818377Skarels 	register struct in_ifaddr *ia;
54918377Skarels 
55018377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
55118377Skarels 		if (ia->ia_subnet == net)
55218377Skarels 			return (ia);
55318377Skarels 	return ((struct in_ifaddr *)0);
55418377Skarels }
55518377Skarels 
55618377Skarels /*
55730523Skarels  * Return 1 if the address might be a local broadcast address.
55818377Skarels  */
55918377Skarels in_broadcast(in)
56018377Skarels 	struct in_addr in;
56118377Skarels {
56218377Skarels 	register struct in_ifaddr *ia;
56330523Skarels 	u_long t;
56418377Skarels 
56518377Skarels 	/*
56618377Skarels 	 * Look through the list of addresses for a match
56718377Skarels 	 * with a broadcast address.
56818377Skarels 	 */
56918377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
57030523Skarels 	    if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
57137471Ssklower 		if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
57218377Skarels 		     return (1);
57330523Skarels 		/*
57430523Skarels 		 * Check for old-style (host 0) broadcast.
57530523Skarels 		 */
57630523Skarels 		if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
57730523Skarels 		    return (1);
57830523Skarels 	}
57930523Skarels 	if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
58030523Skarels 		return (1);
58118377Skarels 	return (0);
58218377Skarels }
5837159Ssam #endif
584