xref: /csrg-svn/sys/netinet/in.c (revision 37471)
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*37471Ssklower  *	@(#)in.c	7.10 (Berkeley) 04/22/89
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 "uio.h"
2718377Skarels #include "dir.h"
2818377Skarels #include "user.h"
2917058Sbloom #include "in_systm.h"
307166Ssam #include "../net/if.h"
317166Ssam #include "../net/route.h"
327159Ssam #include "../net/af.h"
3318377Skarels #include "in.h"
3418377Skarels #include "in_var.h"
357159Ssam 
367159Ssam #ifdef INET
377159Ssam /*
3818377Skarels  * Formulate an Internet address from network + host.
397159Ssam  */
407159Ssam struct in_addr
4118377Skarels in_makeaddr(net, host)
4218377Skarels 	u_long net, host;
437159Ssam {
4418377Skarels 	register struct in_ifaddr *ia;
4518377Skarels 	register u_long mask;
467159Ssam 	u_long addr;
477159Ssam 
4818377Skarels 	if (IN_CLASSA(net))
4918377Skarels 		mask = IN_CLASSA_HOST;
5018377Skarels 	else if (IN_CLASSB(net))
5118377Skarels 		mask = IN_CLASSB_HOST;
527159Ssam 	else
5318377Skarels 		mask = IN_CLASSC_HOST;
5418377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
5518377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net) {
5618377Skarels 			mask = ~ia->ia_subnetmask;
5718377Skarels 			break;
5818377Skarels 		}
5918377Skarels 	addr = htonl(net | (host & mask));
607159Ssam 	return (*(struct in_addr *)&addr);
617159Ssam }
627159Ssam 
637159Ssam /*
648595Sroot  * Return the network number from an internet address.
657159Ssam  */
6624805Skarels u_long
677159Ssam in_netof(in)
687159Ssam 	struct in_addr in;
697159Ssam {
708937Sroot 	register u_long i = ntohl(in.s_addr);
7118377Skarels 	register u_long net;
7218377Skarels 	register struct in_ifaddr *ia;
737159Ssam 
7418377Skarels 	if (IN_CLASSA(i))
7518377Skarels 		net = i & IN_CLASSA_NET;
7618377Skarels 	else if (IN_CLASSB(i))
7718377Skarels 		net = i & IN_CLASSB_NET;
7831392Skarels 	else if (IN_CLASSC(i))
7931392Skarels 		net = i & IN_CLASSC_NET;
8018377Skarels 	else
8131392Skarels 		return (0);
8216413Skarels 
8316413Skarels 	/*
8418377Skarels 	 * Check whether network is a subnet;
8516413Skarels 	 * if so, return subnet number.
8616413Skarels 	 */
8718377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
8824805Skarels 		if (net == ia->ia_net)
8918377Skarels 			return (i & ia->ia_subnetmask);
9016413Skarels 	return (net);
917159Ssam }
927159Ssam 
937159Ssam /*
94*37471Ssklower  * Compute and save network mask as sockaddr from an internet address.
95*37471Ssklower  */
96*37471Ssklower in_sockmaskof(in, sockmask)
97*37471Ssklower 	struct in_addr in;
98*37471Ssklower 	register struct sockaddr_in *sockmask;
99*37471Ssklower {
100*37471Ssklower 	register u_long net;
101*37471Ssklower 	register u_long mask;
102*37471Ssklower     {
103*37471Ssklower 	register u_long i = ntohl(in.s_addr);
104*37471Ssklower 
105*37471Ssklower 	if (i == 0)
106*37471Ssklower 		net = 0, mask = 0;
107*37471Ssklower 	else if (IN_CLASSA(i))
108*37471Ssklower 		net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
109*37471Ssklower 	else if (IN_CLASSB(i))
110*37471Ssklower 		net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
111*37471Ssklower 	else if (IN_CLASSC(i))
112*37471Ssklower 		net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
113*37471Ssklower 	else
114*37471Ssklower 		net = i, mask = -1;
115*37471Ssklower     }
116*37471Ssklower     {
117*37471Ssklower 	register struct in_ifaddr *ia;
118*37471Ssklower 	/*
119*37471Ssklower 	 * Check whether network is a subnet;
120*37471Ssklower 	 * if so, return subnet number.
121*37471Ssklower 	 */
122*37471Ssklower 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
123*37471Ssklower 		if (net == ia->ia_net)
124*37471Ssklower 			mask =  ia->ia_subnetmask;
125*37471Ssklower     }
126*37471Ssklower     {
127*37471Ssklower 	register char *cp = (char *)&(sockmask->sin_port);
128*37471Ssklower 	register char *cpbase = (char *)&(sockmask->sin_addr);
129*37471Ssklower 
130*37471Ssklower 	sockmask->sin_addr.s_addr = htonl(mask);
131*37471Ssklower 	sockmask->sin_len = 0;
132*37471Ssklower 	while (--cp >= cpbase)
133*37471Ssklower 		if (*cp) {
134*37471Ssklower 			sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
135*37471Ssklower 			break;
136*37471Ssklower 		}
137*37471Ssklower     }
138*37471Ssklower }
139*37471Ssklower 
140*37471Ssklower /*
1418595Sroot  * Return the host portion of an internet address.
1427159Ssam  */
14326381Skarels u_long
1447159Ssam in_lnaof(in)
1457159Ssam 	struct in_addr in;
1467159Ssam {
1478937Sroot 	register u_long i = ntohl(in.s_addr);
14818377Skarels 	register u_long net, host;
14918377Skarels 	register struct in_ifaddr *ia;
1507159Ssam 
15116377Skarels 	if (IN_CLASSA(i)) {
15218377Skarels 		net = i & IN_CLASSA_NET;
15318377Skarels 		host = i & IN_CLASSA_HOST;
15416377Skarels 	} else if (IN_CLASSB(i)) {
15518377Skarels 		net = i & IN_CLASSB_NET;
15618377Skarels 		host = i & IN_CLASSB_HOST;
15731392Skarels 	} else if (IN_CLASSC(i)) {
15818377Skarels 		net = i & IN_CLASSC_NET;
15918377Skarels 		host = i & IN_CLASSC_HOST;
16031392Skarels 	} else
16131392Skarels 		return (i);
1627159Ssam 
16316413Skarels 	/*
16418377Skarels 	 * Check whether network is a subnet;
16516413Skarels 	 * if so, use the modified interpretation of `host'.
16616413Skarels 	 */
16718377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
16824805Skarels 		if (net == ia->ia_net)
16918377Skarels 			return (host &~ ia->ia_subnetmask);
17016413Skarels 	return (host);
17116377Skarels }
17216377Skarels 
17326381Skarels #ifndef SUBNETSARELOCAL
17426381Skarels #define	SUBNETSARELOCAL	1
17526381Skarels #endif
17626381Skarels int subnetsarelocal = SUBNETSARELOCAL;
17716377Skarels /*
17818377Skarels  * Return 1 if an internet address is for a ``local'' host
17926381Skarels  * (one to which we have a connection).  If subnetsarelocal
18026381Skarels  * is true, this includes other subnets of the local net.
18126381Skarels  * Otherwise, it includes only the directly-connected (sub)nets.
18217271Skarels  */
18317271Skarels in_localaddr(in)
18417271Skarels 	struct in_addr in;
18517271Skarels {
18617271Skarels 	register u_long i = ntohl(in.s_addr);
18718377Skarels 	register struct in_ifaddr *ia;
18817271Skarels 
18930697Skarels 	if (subnetsarelocal) {
19030697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
19130697Skarels 			if ((i & ia->ia_netmask) == ia->ia_net)
19230697Skarels 				return (1);
19330697Skarels 	} else {
19430697Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
19530697Skarels 			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
19630697Skarels 				return (1);
19730697Skarels 	}
19818377Skarels 	return (0);
19918377Skarels }
20018377Skarels 
20131392Skarels /*
20231392Skarels  * Determine whether an IP address is in a reserved set of addresses
20331392Skarels  * that may not be forwarded, or whether datagrams to that destination
20431392Skarels  * may be forwarded.
20531392Skarels  */
20631392Skarels in_canforward(in)
20731392Skarels 	struct in_addr in;
20831392Skarels {
20931392Skarels 	register u_long i = ntohl(in.s_addr);
21031392Skarels 	register u_long net;
21131392Skarels 
21231392Skarels 	if (IN_EXPERIMENTAL(i))
21331392Skarels 		return (0);
21431392Skarels 	if (IN_CLASSA(i)) {
21531392Skarels 		net = i & IN_CLASSA_NET;
21631392Skarels 		if (net == 0 || net == IN_LOOPBACKNET)
21731392Skarels 			return (0);
21831392Skarels 	}
21931392Skarels 	return (1);
22031392Skarels }
22131392Skarels 
22224805Skarels int	in_interfaces;		/* number of external internet interfaces */
22324805Skarels extern	struct ifnet loif;
22424805Skarels 
22518377Skarels /*
22618377Skarels  * Generic internet control operations (ioctl's).
22718377Skarels  * Ifp is 0 if not an interface-specific ioctl.
22818377Skarels  */
22924805Skarels /* ARGSUSED */
23018377Skarels in_control(so, cmd, data, ifp)
23118377Skarels 	struct socket *so;
23218377Skarels 	int cmd;
23318377Skarels 	caddr_t data;
23418377Skarels 	register struct ifnet *ifp;
23518377Skarels {
23618377Skarels 	register struct ifreq *ifr = (struct ifreq *)data;
23718377Skarels 	register struct in_ifaddr *ia = 0;
238*37471Ssklower 	register struct ifaddr *ifa;
239*37471Ssklower 	struct in_ifaddr *oia;
240*37471Ssklower 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
24118377Skarels 	struct mbuf *m;
242*37471Ssklower 	struct sockaddr_in oldaddr;
243*37471Ssklower 	int error, hostIsNew, maskIsNew;
244*37471Ssklower 	u_long i;
24518377Skarels 
24618377Skarels 	/*
24718377Skarels 	 * Find address for this interface, if it exists.
24818377Skarels 	 */
24918377Skarels 	if (ifp)
25018377Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
25118377Skarels 			if (ia->ia_ifp == ifp)
25218377Skarels 				break;
25318377Skarels 
25418377Skarels 	switch (cmd) {
25518377Skarels 
256*37471Ssklower 	case SIOCAIFADDR:
257*37471Ssklower 	case SIOCDIFADDR:
258*37471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET)
259*37471Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
260*37471Ssklower 			if (ia->ia_ifp == ifp  &&
261*37471Ssklower 			    ia->ia_addr.sin_addr.s_addr ==
262*37471Ssklower 				ifra->ifra_addr.sin_addr.s_addr)
263*37471Ssklower 			    break;
264*37471Ssklower 		}
265*37471Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
266*37471Ssklower 			return (EADDRNOTAVAIL);
267*37471Ssklower 		/* FALLTHROUGH */
26818377Skarels 	case SIOCSIFADDR:
26918377Skarels 	case SIOCSIFNETMASK:
27026456Skarels 	case SIOCSIFDSTADDR:
27118377Skarels 		if (!suser())
27218377Skarels 			return (u.u_error);
27318377Skarels 
27418377Skarels 		if (ifp == 0)
27518377Skarels 			panic("in_control");
27618377Skarels 		if (ia == (struct in_ifaddr *)0) {
27718377Skarels 			m = m_getclr(M_WAIT, MT_IFADDR);
27818377Skarels 			if (m == (struct mbuf *)NULL)
27918377Skarels 				return (ENOBUFS);
28018377Skarels 			if (ia = in_ifaddr) {
28118377Skarels 				for ( ; ia->ia_next; ia = ia->ia_next)
28218377Skarels 					;
28318377Skarels 				ia->ia_next = mtod(m, struct in_ifaddr *);
28418377Skarels 			} else
28518377Skarels 				in_ifaddr = mtod(m, struct in_ifaddr *);
28618377Skarels 			ia = mtod(m, struct in_ifaddr *);
28718377Skarels 			if (ifa = ifp->if_addrlist) {
28818377Skarels 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
28918377Skarels 					;
29018377Skarels 				ifa->ifa_next = (struct ifaddr *) ia;
29118377Skarels 			} else
29218377Skarels 				ifp->if_addrlist = (struct ifaddr *) ia;
293*37471Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
294*37471Ssklower 			ia->ia_ifa.ifa_dstaddr
295*37471Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
296*37471Ssklower 			ia->ia_ifa.ifa_netmask
297*37471Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
298*37471Ssklower 			ia->ia_sockmask.sin_len = 8;
299*37471Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
300*37471Ssklower 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
301*37471Ssklower 				ia->ia_broadaddr.sin_family = AF_INET;
302*37471Ssklower 			}
30318377Skarels 			ia->ia_ifp = ifp;
30424805Skarels 			if (ifp != &loif)
30524805Skarels 				in_interfaces++;
30617271Skarels 		}
30718377Skarels 		break;
30826317Skarels 
30926317Skarels 	case SIOCSIFBRDADDR:
31026317Skarels 		if (!suser())
31126317Skarels 			return (u.u_error);
31226317Skarels 		/* FALLTHROUGH */
31326317Skarels 
31426317Skarels 	default:
31526317Skarels 		if (ia == (struct in_ifaddr *)0)
31626317Skarels 			return (EADDRNOTAVAIL);
31726317Skarels 		break;
31817271Skarels 	}
31918377Skarels 	switch (cmd) {
32018377Skarels 
32118377Skarels 	case SIOCGIFADDR:
322*37471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
32318377Skarels 		break;
32418377Skarels 
32518377Skarels 	case SIOCGIFBRDADDR:
32618377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
32718377Skarels 			return (EINVAL);
328*37471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
32918377Skarels 		break;
33018377Skarels 
33118377Skarels 	case SIOCGIFDSTADDR:
33218377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
33318377Skarels 			return (EINVAL);
334*37471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
33518377Skarels 		break;
33618377Skarels 
33718377Skarels 	case SIOCGIFNETMASK:
338*37471Ssklower 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
33918377Skarels 		break;
34018377Skarels 
34118377Skarels 	case SIOCSIFDSTADDR:
34218377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
34318377Skarels 			return (EINVAL);
34427066Skarels 		oldaddr = ia->ia_dstaddr;
345*37471Ssklower 		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
34618377Skarels 		if (ifp->if_ioctl &&
34727066Skarels 		    (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
34827066Skarels 			ia->ia_dstaddr = oldaddr;
34918377Skarels 			return (error);
35027066Skarels 		}
35127066Skarels 		if (ia->ia_flags & IFA_ROUTE) {
352*37471Ssklower 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
353*37471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
354*37471Ssklower 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_addr;
355*37471Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
35627066Skarels 		}
35718377Skarels 		break;
35818377Skarels 
35918377Skarels 	case SIOCSIFBRDADDR:
36018377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
36118377Skarels 			return (EINVAL);
362*37471Ssklower 		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
36318377Skarels 		break;
36418377Skarels 
36518377Skarels 	case SIOCSIFADDR:
36634500Skarels 		return (in_ifinit(ifp, ia,
367*37471Ssklower 		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
36818377Skarels 
36918377Skarels 	case SIOCSIFNETMASK:
370*37471Ssklower 		i = ifra->ifra_addr.sin_addr.s_addr;
371*37471Ssklower 		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
37218377Skarels 		break;
37318377Skarels 
374*37471Ssklower 	case SIOCAIFADDR:
375*37471Ssklower 		maskIsNew = 0; hostIsNew = 1; error = u.u_error;
376*37471Ssklower 		if (ia->ia_addr.sin_family == AF_INET) {
377*37471Ssklower 			if (ifra->ifra_addr.sin_len == 0) {
378*37471Ssklower 				ifra->ifra_addr = ia->ia_addr;
379*37471Ssklower 				hostIsNew = 0;
380*37471Ssklower 			} else if (ifra->ifra_addr.sin_addr.s_addr ==
381*37471Ssklower 					       ia->ia_addr.sin_addr.s_addr)
382*37471Ssklower 				hostIsNew = 0;
383*37471Ssklower 		}
384*37471Ssklower 		if (ifra->ifra_mask.sin_len) {
385*37471Ssklower 			in_ifscrub(ifp, ia);
386*37471Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
387*37471Ssklower 			ia->ia_subnetmask =
388*37471Ssklower 					ntohl(ia->ia_sockmask.sin_addr.s_addr);
389*37471Ssklower 			maskIsNew = 1;
390*37471Ssklower 		}
391*37471Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
392*37471Ssklower 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
393*37471Ssklower 			in_ifscrub(ifp, ia);
394*37471Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
395*37471Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
396*37471Ssklower 		}
397*37471Ssklower 		if (ifra->ifra_addr.sin_family == AF_INET &&
398*37471Ssklower 					    (hostIsNew || maskIsNew))
399*37471Ssklower 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
400*37471Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) &&
401*37471Ssklower 		    (ifra->ifra_broadaddr.sin_family == AF_INET))
402*37471Ssklower 			ia->ia_broadaddr = ifra->ifra_broadaddr;
403*37471Ssklower 		return (error);
404*37471Ssklower 
405*37471Ssklower 	case SIOCDIFADDR:
406*37471Ssklower 		in_ifscrub(ifp, ia);
407*37471Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
408*37471Ssklower 			ifp->if_addrlist = ifa->ifa_next;
409*37471Ssklower 		else {
410*37471Ssklower 			while (ifa->ifa_next &&
411*37471Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
412*37471Ssklower 				    ifa = ifa->ifa_next;
413*37471Ssklower 			if (ifa->ifa_next)
414*37471Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
415*37471Ssklower 			else
416*37471Ssklower 				printf("Couldn't unlink inifaddr from ifp\n");
417*37471Ssklower 		}
418*37471Ssklower 		oia = ia;
419*37471Ssklower 		if (oia == (ia = in_ifaddr)) {
420*37471Ssklower 			in_ifaddr = ia->ia_next;
421*37471Ssklower 		} else {
422*37471Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
423*37471Ssklower 				ia = ia->ia_next;
424*37471Ssklower 			}
425*37471Ssklower 			if (ia->ia_next)
426*37471Ssklower 			    ia->ia_next = oia->ia_next;
427*37471Ssklower 			else
428*37471Ssklower 				printf("Didn't unlink inifadr from list\n");
429*37471Ssklower 		}
430*37471Ssklower 		(void) m_free(dtom(oia));
431*37471Ssklower 		break;
432*37471Ssklower 
43318377Skarels 	default:
43418377Skarels 		if (ifp == 0 || ifp->if_ioctl == 0)
43518377Skarels 			return (EOPNOTSUPP);
43618377Skarels 		return ((*ifp->if_ioctl)(ifp, cmd, data));
43718377Skarels 	}
43817271Skarels 	return (0);
43917271Skarels }
44017271Skarels 
44117271Skarels /*
442*37471Ssklower  * Delete any existing route for an interface.
443*37471Ssklower  */
444*37471Ssklower in_ifscrub(ifp, ia)
445*37471Ssklower 	register struct ifnet *ifp;
446*37471Ssklower 	register struct in_ifaddr *ia;
447*37471Ssklower {
448*37471Ssklower 
449*37471Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
450*37471Ssklower 		return;
451*37471Ssklower 	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
452*37471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
453*37471Ssklower 	else
454*37471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
455*37471Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
456*37471Ssklower }
457*37471Ssklower 
458*37471Ssklower /*
45918377Skarels  * Initialize an interface's internet address
46018377Skarels  * and routing table entry.
4617159Ssam  */
462*37471Ssklower in_ifinit(ifp, ia, sin, scrub)
4637159Ssam 	register struct ifnet *ifp;
46418377Skarels 	register struct in_ifaddr *ia;
46518377Skarels 	struct sockaddr_in *sin;
4667159Ssam {
46718377Skarels 	register u_long i = ntohl(sin->sin_addr.s_addr);
468*37471Ssklower 	struct sockaddr_in oldaddr;
46918377Skarels 	int s = splimp(), error;
4707159Ssam 
47127066Skarels 	oldaddr = ia->ia_addr;
472*37471Ssklower 	ia->ia_addr = *sin;
47318377Skarels 	/*
47426317Skarels 	 * Give the interface a chance to initialize
47526317Skarels 	 * if this is its first address,
47626317Skarels 	 * and to validate the address if necessary.
47726317Skarels 	 */
47826317Skarels 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
47926317Skarels 		splx(s);
48027066Skarels 		ia->ia_addr = oldaddr;
48126317Skarels 		return (error);
48226317Skarels 	}
483*37471Ssklower 	if (scrub) {
484*37471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
485*37471Ssklower 		in_ifscrub(ifp, ia);
486*37471Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
48718377Skarels 	}
48818377Skarels 	if (IN_CLASSA(i))
48918377Skarels 		ia->ia_netmask = IN_CLASSA_NET;
49018377Skarels 	else if (IN_CLASSB(i))
49118377Skarels 		ia->ia_netmask = IN_CLASSB_NET;
49218377Skarels 	else
49318377Skarels 		ia->ia_netmask = IN_CLASSC_NET;
49418377Skarels 	ia->ia_net = i & ia->ia_netmask;
49518377Skarels 	/*
49618377Skarels 	 * The subnet mask includes at least the standard network part,
49718377Skarels 	 * but may already have been set to a larger value.
49818377Skarels 	 */
49918377Skarels 	ia->ia_subnetmask |= ia->ia_netmask;
50018377Skarels 	ia->ia_subnet = i & ia->ia_subnetmask;
501*37471Ssklower 	ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
50218377Skarels 	if (ifp->if_flags & IFF_BROADCAST) {
503*37471Ssklower 		ia->ia_broadaddr.sin_addr =
50418377Skarels 			in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
50525195Skarels 		ia->ia_netbroadcast.s_addr =
50625195Skarels 		    htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
50718377Skarels 	}
50818377Skarels 	/*
50918377Skarels 	 * Add route for the network.
51018377Skarels 	 */
511*37471Ssklower 	if (ifp->if_flags & IFF_LOOPBACK) {
512*37471Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
513*37471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
514*37471Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
515*37471Ssklower 		 ia->ia_dstaddr.sin_family == AF_INET)
516*37471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
51727066Skarels 	else {
518*37471Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
51927066Skarels 	}
52018377Skarels 	ia->ia_flags |= IFA_ROUTE;
52130523Skarels 	splx(s);
52218642Skarels 	return (0);
5237159Ssam }
52418377Skarels 
52518377Skarels /*
52618377Skarels  * Return address info for specified internet network.
52718377Skarels  */
52818377Skarels struct in_ifaddr *
52918377Skarels in_iaonnetof(net)
53018377Skarels 	u_long net;
53118377Skarels {
53218377Skarels 	register struct in_ifaddr *ia;
53318377Skarels 
53418377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
53518377Skarels 		if (ia->ia_subnet == net)
53618377Skarels 			return (ia);
53718377Skarels 	return ((struct in_ifaddr *)0);
53818377Skarels }
53918377Skarels 
54018377Skarels /*
54130523Skarels  * Return 1 if the address might be a local broadcast address.
54218377Skarels  */
54318377Skarels in_broadcast(in)
54418377Skarels 	struct in_addr in;
54518377Skarels {
54618377Skarels 	register struct in_ifaddr *ia;
54730523Skarels 	u_long t;
54818377Skarels 
54918377Skarels 	/*
55018377Skarels 	 * Look through the list of addresses for a match
55118377Skarels 	 * with a broadcast address.
55218377Skarels 	 */
55318377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
55430523Skarels 	    if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
555*37471Ssklower 		if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
55618377Skarels 		     return (1);
55730523Skarels 		/*
55830523Skarels 		 * Check for old-style (host 0) broadcast.
55930523Skarels 		 */
56030523Skarels 		if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
56130523Skarels 		    return (1);
56230523Skarels 	}
56330523Skarels 	if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
56430523Skarels 		return (1);
56518377Skarels 	return (0);
56618377Skarels }
5677159Ssam #endif
568