xref: /csrg-svn/sys/netinet/in.c (revision 17058)
1 /*	in.c	6.4	84/08/29	*/
2 
3 #include "param.h"
4 #include "mbuf.h"
5 #include "protosw.h"
6 #include "socket.h"
7 #include "socketvar.h"
8 #include "in.h"
9 #include "in_systm.h"
10 #include "../net/if.h"
11 #include "../net/route.h"
12 #include "../net/af.h"
13 
14 #ifdef INET
15 inet_hash(sin, hp)
16 	register struct sockaddr_in *sin;
17 	struct afhash *hp;
18 {
19 
20 	hp->afh_nethash = in_netof(sin->sin_addr);
21 	hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
22 }
23 
24 inet_netmatch(sin1, sin2)
25 	struct sockaddr_in *sin1, *sin2;
26 {
27 
28 	return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
29 }
30 
31 /*
32  * Formulate an Internet address from network + host.  Used in
33  * building addresses stored in the ifnet structure.
34  */
35 struct in_addr
36 if_makeaddr(net, host)
37 	int net, host;
38 {
39 	u_long addr;
40 
41 	if (net < IN_CLASSA_MAX)
42 		addr = (net << IN_CLASSA_NSHIFT) | host;
43 	else if (net < IN_CLASSB_MAX)
44 		addr = (net << IN_CLASSB_NSHIFT) | host;
45 	else
46 		addr = (net << IN_CLASSC_NSHIFT) | host;
47 	addr = htonl(addr);
48 	return (*(struct in_addr *)&addr);
49 }
50 
51 /*
52  * Return the network number from an internet address.
53  */
54 in_netof(in)
55 	struct in_addr in;
56 {
57 	register u_long i = ntohl(in.s_addr);
58 	register u_long net, subnet;
59 	register struct ifnet *ifp;
60 
61 	if (IN_CLASSA(i)) {
62 		net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
63 		if (IN_SUBNETA(i)) {
64 			subnet = (i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT;
65 			/* Fall through and check whether a subnet */
66 		} else
67 			return (net);
68 	} else if (IN_CLASSB(i)) {
69 		net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
70 		if (IN_SUBNETB(i)) {
71 			subnet = (i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT;
72 			/* Fall through and check whether a subnet */
73 		} else
74 			return (net);
75 	} else {
76 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
77 	}
78 
79 	/*
80 	 * Check whether network is a subnet of a `local' network;
81 	 * if so, return subnet number.
82 	 */
83 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
84 		if (ifp->if_addr.sa_family != AF_INET)
85 			continue;
86 		if (ifp->if_flags & IFF_LOCAL) {
87 			if (ifp->if_net == net)
88 				return (subnet);
89 			if ((ifp->if_net >> SUBNETSHIFT) == net)
90 				return (subnet);
91 			/*
92 			 * Hack for use in setting if_net initially.
93 			 */
94 			if (ifp->if_net == 0) {
95 				register struct sockaddr_in *sin;
96 				sin = (struct sockaddr_in *) &ifp->if_addr;
97 				if (sin->sin_addr.s_addr == in.s_addr)
98 					return (subnet);
99 			}
100 		}
101 	}
102 	return (net);
103 }
104 
105 /*
106  * Return the host portion of an internet address.
107  */
108 in_lnaof(in)
109 	struct in_addr in;
110 {
111 	register u_long i = ntohl(in.s_addr);
112 	register u_long net, host, subhost;
113 	register struct ifnet *ifp;
114 
115 	if (IN_CLASSA(i)) {
116 		if (IN_SUBNETA(i)) {
117 			net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
118 			host = i & IN_CLASSA_HOST;
119 			subhost = i & IN_CLASSA_SUBHOST;
120 			/* Fall through and check whether a subnet */
121 		} else
122 			return (i & IN_CLASSA_HOST);
123 	} else if (IN_CLASSB(i)) {
124 		if (IN_SUBNETB(i)) {
125 			net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
126 			host = i & IN_CLASSB_HOST;
127 			subhost = i & IN_CLASSB_SUBHOST;
128 			/* Fall through and check whether a subnet */
129 		} else
130 			return (i & IN_CLASSB_HOST);
131 	} else {
132 		return (i & IN_CLASSC_HOST);
133 	}
134 
135 	/*
136 	 * Check whether network is a subnet of a `local' network;
137 	 * if so, use the modified interpretation of `host'.
138 	 */
139 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
140 		if (ifp->if_addr.sa_family != AF_INET)
141 			continue;
142 		if (ifp->if_flags & IFF_LOCAL) {
143 			if (ifp->if_net == net)
144 			    return (subhost);
145 			if ((ifp->if_net >> SUBNETSHIFT) == net)
146 			    return (subhost);
147 		}
148 	}
149 	return (host);
150 }
151 
152 /*
153  * Initialize an interface's routing
154  * table entry according to the network.
155  * INTERNET SPECIFIC.
156  */
157 if_rtinit(ifp, flags)
158 	register struct ifnet *ifp;
159 	int flags;
160 {
161 	struct sockaddr_in sin;
162 
163 	if (ifp->if_flags & IFF_ROUTE)
164 		return;
165 	bzero((caddr_t)&sin, sizeof (sin));
166 	sin.sin_family = AF_INET;
167 	sin.sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
168 	rtinit((struct sockaddr *)&sin, &ifp->if_addr, flags);
169 }
170 #endif
171