xref: /csrg-svn/sys/netinet/in.c (revision 17271)
1*17271Skarels /*	in.c	6.5	84/10/19	*/
27159Ssam 
317058Sbloom #include "param.h"
417058Sbloom #include "mbuf.h"
517058Sbloom #include "protosw.h"
617058Sbloom #include "socket.h"
717058Sbloom #include "socketvar.h"
817058Sbloom #include "in.h"
917058Sbloom #include "in_systm.h"
107166Ssam #include "../net/if.h"
117166Ssam #include "../net/route.h"
127159Ssam #include "../net/af.h"
137159Ssam 
147159Ssam #ifdef INET
157159Ssam inet_hash(sin, hp)
167159Ssam 	register struct sockaddr_in *sin;
177159Ssam 	struct afhash *hp;
187159Ssam {
198595Sroot 
207159Ssam 	hp->afh_nethash = in_netof(sin->sin_addr);
218937Sroot 	hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
227159Ssam }
237159Ssam 
247159Ssam inet_netmatch(sin1, sin2)
257159Ssam 	struct sockaddr_in *sin1, *sin2;
267159Ssam {
278595Sroot 
2811566Ssam 	return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
297159Ssam }
307159Ssam 
317159Ssam /*
327159Ssam  * Formulate an Internet address from network + host.  Used in
337159Ssam  * building addresses stored in the ifnet structure.
347159Ssam  */
357159Ssam struct in_addr
367159Ssam if_makeaddr(net, host)
377159Ssam 	int net, host;
387159Ssam {
397159Ssam 	u_long addr;
407159Ssam 
4116377Skarels 	if (net < IN_CLASSA_MAX)
428694Sroot 		addr = (net << IN_CLASSA_NSHIFT) | host;
4316377Skarels 	else if (net < IN_CLASSB_MAX)
448694Sroot 		addr = (net << IN_CLASSB_NSHIFT) | host;
457159Ssam 	else
468694Sroot 		addr = (net << IN_CLASSC_NSHIFT) | host;
477159Ssam 	addr = htonl(addr);
487159Ssam 	return (*(struct in_addr *)&addr);
497159Ssam }
507159Ssam 
517159Ssam /*
528595Sroot  * Return the network number from an internet address.
537159Ssam  */
547159Ssam in_netof(in)
557159Ssam 	struct in_addr in;
567159Ssam {
578937Sroot 	register u_long i = ntohl(in.s_addr);
5816413Skarels 	register u_long net, subnet;
5916413Skarels 	register struct ifnet *ifp;
607159Ssam 
6116377Skarels 	if (IN_CLASSA(i)) {
6216413Skarels 		net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
6316413Skarels 		if (IN_SUBNETA(i)) {
6416413Skarels 			subnet = (i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT;
6516413Skarels 			/* Fall through and check whether a subnet */
6616413Skarels 		} else
6716377Skarels 			return (net);
6816377Skarels 	} else if (IN_CLASSB(i)) {
6916413Skarels 		net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
7016413Skarels 		if (IN_SUBNETB(i)) {
7116413Skarels 			subnet = (i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT;
7216413Skarels 			/* Fall through and check whether a subnet */
7316413Skarels 		} else
7416377Skarels 			return (net);
7516377Skarels 	} else {
7616413Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
7716377Skarels 	}
7816413Skarels 
7916413Skarels 	/*
8016413Skarels 	 * Check whether network is a subnet of a `local' network;
8116413Skarels 	 * if so, return subnet number.
8216413Skarels 	 */
8316413Skarels 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
8416413Skarels 		if (ifp->if_addr.sa_family != AF_INET)
8516413Skarels 			continue;
8616413Skarels 		if (ifp->if_flags & IFF_LOCAL) {
8716413Skarels 			if (ifp->if_net == net)
8816413Skarels 				return (subnet);
8916413Skarels 			if ((ifp->if_net >> SUBNETSHIFT) == net)
9016413Skarels 				return (subnet);
9116413Skarels 			/*
9216413Skarels 			 * Hack for use in setting if_net initially.
9316413Skarels 			 */
9416413Skarels 			if (ifp->if_net == 0) {
9516413Skarels 				register struct sockaddr_in *sin;
9616413Skarels 				sin = (struct sockaddr_in *) &ifp->if_addr;
9716413Skarels 				if (sin->sin_addr.s_addr == in.s_addr)
9816413Skarels 					return (subnet);
9916413Skarels 			}
10016413Skarels 		}
10116413Skarels 	}
10216413Skarels 	return (net);
1037159Ssam }
1047159Ssam 
1057159Ssam /*
1068595Sroot  * Return the host portion of an internet address.
1077159Ssam  */
1087159Ssam in_lnaof(in)
1097159Ssam 	struct in_addr in;
1107159Ssam {
1118937Sroot 	register u_long i = ntohl(in.s_addr);
11216413Skarels 	register u_long net, host, subhost;
11316413Skarels 	register struct ifnet *ifp;
1147159Ssam 
11516377Skarels 	if (IN_CLASSA(i)) {
11616413Skarels 		if (IN_SUBNETA(i)) {
11716413Skarels 			net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
11816413Skarels 			host = i & IN_CLASSA_HOST;
11916413Skarels 			subhost = i & IN_CLASSA_SUBHOST;
12016413Skarels 			/* Fall through and check whether a subnet */
12116413Skarels 		} else
12216413Skarels 			return (i & IN_CLASSA_HOST);
12316377Skarels 	} else if (IN_CLASSB(i)) {
12416413Skarels 		if (IN_SUBNETB(i)) {
12516413Skarels 			net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
12616413Skarels 			host = i & IN_CLASSB_HOST;
12716413Skarels 			subhost = i & IN_CLASSB_SUBHOST;
12816413Skarels 			/* Fall through and check whether a subnet */
12916413Skarels 		} else
13016413Skarels 			return (i & IN_CLASSB_HOST);
13116377Skarels 	} else {
13216413Skarels 		return (i & IN_CLASSC_HOST);
13316377Skarels 	}
1347159Ssam 
13516413Skarels 	/*
13616413Skarels 	 * Check whether network is a subnet of a `local' network;
13716413Skarels 	 * if so, use the modified interpretation of `host'.
13816413Skarels 	 */
13916377Skarels 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
14016377Skarels 		if (ifp->if_addr.sa_family != AF_INET)
14116377Skarels 			continue;
14216377Skarels 		if (ifp->if_flags & IFF_LOCAL) {
14316377Skarels 			if (ifp->if_net == net)
14416413Skarels 			    return (subhost);
14516377Skarels 			if ((ifp->if_net >> SUBNETSHIFT) == net)
14616413Skarels 			    return (subhost);
14716377Skarels 		}
14816377Skarels 	}
14916413Skarels 	return (host);
15016377Skarels }
15116377Skarels 
15216377Skarels /*
153*17271Skarels  * Return 1 if an internet address is for a ``local'' host.
154*17271Skarels  */
155*17271Skarels in_localaddr(in)
156*17271Skarels 	struct in_addr in;
157*17271Skarels {
158*17271Skarels 	register u_long i = ntohl(in.s_addr);
159*17271Skarels 	register u_long net;
160*17271Skarels 	register struct ifnet *ifp;
161*17271Skarels 
162*17271Skarels 	if (IN_CLASSA(i))
163*17271Skarels 		net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
164*17271Skarels 	else if (IN_CLASSB(i))
165*17271Skarels 		net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
166*17271Skarels 	else
167*17271Skarels 		net = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
168*17271Skarels 
169*17271Skarels 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
170*17271Skarels 		if (ifp->if_addr.sa_family != AF_INET)
171*17271Skarels 			continue;
172*17271Skarels 		if (ifp->if_flags & IFF_LOCAL) {
173*17271Skarels 			if (ifp->if_net == net)
174*17271Skarels 				return (1);
175*17271Skarels 			if ((ifp->if_net >> SUBNETSHIFT) == net)
176*17271Skarels 				return (1);
177*17271Skarels 		}
178*17271Skarels 	}
179*17271Skarels 	return (0);
180*17271Skarels }
181*17271Skarels 
182*17271Skarels /*
1837159Ssam  * Initialize an interface's routing
1847159Ssam  * table entry according to the network.
1857159Ssam  * INTERNET SPECIFIC.
1867159Ssam  */
1877159Ssam if_rtinit(ifp, flags)
1887159Ssam 	register struct ifnet *ifp;
1897159Ssam 	int flags;
1907159Ssam {
1917159Ssam 	struct sockaddr_in sin;
1927159Ssam 
1937159Ssam 	if (ifp->if_flags & IFF_ROUTE)
1947159Ssam 		return;
1957159Ssam 	bzero((caddr_t)&sin, sizeof (sin));
1967159Ssam 	sin.sin_family = AF_INET;
19711566Ssam 	sin.sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
1988637Sroot 	rtinit((struct sockaddr *)&sin, &ifp->if_addr, flags);
1997159Ssam }
2007159Ssam #endif
201