xref: /csrg-svn/sys/netinet/in.c (revision 18377)
1*18377Skarels /*	in.c	6.6	85/03/18	*/
27159Ssam 
317058Sbloom #include "param.h"
4*18377Skarels #include "ioctl.h"
517058Sbloom #include "mbuf.h"
617058Sbloom #include "protosw.h"
717058Sbloom #include "socket.h"
817058Sbloom #include "socketvar.h"
9*18377Skarels #include "uio.h"
10*18377Skarels #include "dir.h"
11*18377Skarels #include "user.h"
1217058Sbloom #include "in_systm.h"
137166Ssam #include "../net/if.h"
147166Ssam #include "../net/route.h"
157159Ssam #include "../net/af.h"
16*18377Skarels #include "in.h"
17*18377Skarels #include "in_var.h"
187159Ssam 
197159Ssam #ifdef INET
207159Ssam inet_hash(sin, hp)
217159Ssam 	register struct sockaddr_in *sin;
227159Ssam 	struct afhash *hp;
237159Ssam {
24*18377Skarels 	register u_long n;
258595Sroot 
26*18377Skarels 	n = in_netof(sin->sin_addr);
27*18377Skarels 	if (n)
28*18377Skarels 	    while ((n & 0xff) == 0)
29*18377Skarels 		n >>= 8;
30*18377Skarels 	hp->afh_nethash = n;
318937Sroot 	hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
327159Ssam }
337159Ssam 
347159Ssam inet_netmatch(sin1, sin2)
357159Ssam 	struct sockaddr_in *sin1, *sin2;
367159Ssam {
378595Sroot 
3811566Ssam 	return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
397159Ssam }
407159Ssam 
417159Ssam /*
42*18377Skarels  * Formulate an Internet address from network + host.
437159Ssam  */
447159Ssam struct in_addr
45*18377Skarels in_makeaddr(net, host)
46*18377Skarels 	u_long net, host;
477159Ssam {
48*18377Skarels 	register struct in_ifaddr *ia;
49*18377Skarels 	register u_long mask;
507159Ssam 	u_long addr;
517159Ssam 
52*18377Skarels 	if (IN_CLASSA(net))
53*18377Skarels 		mask = IN_CLASSA_HOST;
54*18377Skarels 	else if (IN_CLASSB(net))
55*18377Skarels 		mask = IN_CLASSB_HOST;
567159Ssam 	else
57*18377Skarels 		mask = IN_CLASSC_HOST;
58*18377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
59*18377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net) {
60*18377Skarels 			mask = ~ia->ia_subnetmask;
61*18377Skarels 			break;
62*18377Skarels 		}
63*18377Skarels 	addr = htonl(net | (host & mask));
647159Ssam 	return (*(struct in_addr *)&addr);
657159Ssam }
667159Ssam 
677159Ssam /*
688595Sroot  * Return the network number from an internet address.
697159Ssam  */
707159Ssam in_netof(in)
717159Ssam 	struct in_addr in;
727159Ssam {
738937Sroot 	register u_long i = ntohl(in.s_addr);
74*18377Skarels 	register u_long net;
75*18377Skarels 	register struct in_ifaddr *ia;
767159Ssam 
77*18377Skarels 	if (IN_CLASSA(i))
78*18377Skarels 		net = i & IN_CLASSA_NET;
79*18377Skarels 	else if (IN_CLASSB(i))
80*18377Skarels 		net = i & IN_CLASSB_NET;
81*18377Skarels 	else
82*18377Skarels 		net = i & IN_CLASSC_NET;
8316413Skarels 
8416413Skarels 	/*
85*18377Skarels 	 * Check whether network is a subnet;
8616413Skarels 	 * if so, return subnet number.
8716413Skarels 	 */
88*18377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
89*18377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net)
90*18377Skarels 			return (i & ia->ia_subnetmask);
9116413Skarels 	return (net);
927159Ssam }
937159Ssam 
947159Ssam /*
958595Sroot  * Return the host portion of an internet address.
967159Ssam  */
977159Ssam in_lnaof(in)
987159Ssam 	struct in_addr in;
997159Ssam {
1008937Sroot 	register u_long i = ntohl(in.s_addr);
101*18377Skarels 	register u_long net, host;
102*18377Skarels 	register struct in_ifaddr *ia;
1037159Ssam 
10416377Skarels 	if (IN_CLASSA(i)) {
105*18377Skarels 		net = i & IN_CLASSA_NET;
106*18377Skarels 		host = i & IN_CLASSA_HOST;
10716377Skarels 	} else if (IN_CLASSB(i)) {
108*18377Skarels 		net = i & IN_CLASSB_NET;
109*18377Skarels 		host = i & IN_CLASSB_HOST;
11016377Skarels 	} else {
111*18377Skarels 		net = i & IN_CLASSC_NET;
112*18377Skarels 		host = i & IN_CLASSC_HOST;
11316377Skarels 	}
1147159Ssam 
11516413Skarels 	/*
116*18377Skarels 	 * Check whether network is a subnet;
11716413Skarels 	 * if so, use the modified interpretation of `host'.
11816413Skarels 	 */
119*18377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
120*18377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net)
121*18377Skarels 			return (host &~ ia->ia_subnetmask);
12216413Skarels 	return (host);
12316377Skarels }
12416377Skarels 
12516377Skarels /*
126*18377Skarels  * Return 1 if an internet address is for a ``local'' host
127*18377Skarels  * (one to which we have a connection).
12817271Skarels  */
12917271Skarels in_localaddr(in)
13017271Skarels 	struct in_addr in;
13117271Skarels {
13217271Skarels 	register u_long i = ntohl(in.s_addr);
13317271Skarels 	register u_long net;
134*18377Skarels 	register struct in_ifaddr *ia;
13517271Skarels 
13617271Skarels 	if (IN_CLASSA(i))
137*18377Skarels 		net = i & IN_CLASSA_NET;
13817271Skarels 	else if (IN_CLASSB(i))
139*18377Skarels 		net = i & IN_CLASSB_NET;
14017271Skarels 	else
141*18377Skarels 		net = i & IN_CLASSC_NET;
14217271Skarels 
143*18377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
144*18377Skarels 		if ((ia->ia_netmask & net) == ia->ia_net)
145*18377Skarels 			return (1);
146*18377Skarels 	return (0);
147*18377Skarels }
148*18377Skarels 
149*18377Skarels /*
150*18377Skarels  * Generic internet control operations (ioctl's).
151*18377Skarels  * Ifp is 0 if not an interface-specific ioctl.
152*18377Skarels  */
153*18377Skarels in_control(so, cmd, data, ifp)
154*18377Skarels 	struct socket *so;
155*18377Skarels 	int cmd;
156*18377Skarels 	caddr_t data;
157*18377Skarels 	register struct ifnet *ifp;
158*18377Skarels {
159*18377Skarels 	register struct ifreq *ifr = (struct ifreq *)data;
160*18377Skarels 	register struct in_ifaddr *ia = 0;
161*18377Skarels 	struct ifaddr *ifa;
162*18377Skarels 	struct mbuf *m;
163*18377Skarels 	int error;
164*18377Skarels 
165*18377Skarels 	/*
166*18377Skarels 	 * Find address for this interface, if it exists.
167*18377Skarels 	 */
168*18377Skarels 	if (ifp)
169*18377Skarels 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
170*18377Skarels 			if (ia->ia_ifp == ifp)
171*18377Skarels 				break;
172*18377Skarels 
173*18377Skarels 	switch (cmd) {
174*18377Skarels 
175*18377Skarels 	case SIOCGIFADDR:
176*18377Skarels 	case SIOCGIFBRDADDR:
177*18377Skarels 	case SIOCGIFDSTADDR:
178*18377Skarels 	case SIOCGIFNETMASK:
179*18377Skarels 		if (ia == (struct in_ifaddr *)0)
180*18377Skarels 			return (EADDRNOTAVAIL);
181*18377Skarels 		break;
182*18377Skarels 
183*18377Skarels 	case SIOCSIFADDR:
184*18377Skarels 	case SIOCSIFDSTADDR:
185*18377Skarels 	case SIOCSIFBRDADDR:
186*18377Skarels 	case SIOCSIFNETMASK:
187*18377Skarels 		if (!suser())
188*18377Skarels 			return (u.u_error);
189*18377Skarels 
190*18377Skarels 		if (ifp == 0)
191*18377Skarels 			panic("in_control");
192*18377Skarels 		if (ia == (struct in_ifaddr *)0) {
193*18377Skarels 			m = m_getclr(M_WAIT, MT_IFADDR);
194*18377Skarels 			if (m == (struct mbuf *)NULL)
195*18377Skarels 				return (ENOBUFS);
196*18377Skarels 			if (ia = in_ifaddr) {
197*18377Skarels 				for ( ; ia->ia_next; ia = ia->ia_next)
198*18377Skarels 					;
199*18377Skarels 				ia->ia_next = mtod(m, struct in_ifaddr *);
200*18377Skarels 			} else
201*18377Skarels 				in_ifaddr = mtod(m, struct in_ifaddr *);
202*18377Skarels 			ia = mtod(m, struct in_ifaddr *);
203*18377Skarels 			if (ifa = ifp->if_addrlist) {
204*18377Skarels 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
205*18377Skarels 					;
206*18377Skarels 				ifa->ifa_next = (struct ifaddr *) ia;
207*18377Skarels 			} else
208*18377Skarels 				ifp->if_addrlist = (struct ifaddr *) ia;
209*18377Skarels 			ia->ia_ifp = ifp;
210*18377Skarels 			IA_SIN(ia)->sin_family = AF_INET;
21117271Skarels 		}
212*18377Skarels 		break;
21317271Skarels 	}
214*18377Skarels 
215*18377Skarels 	switch (cmd) {
216*18377Skarels 
217*18377Skarels 	case SIOCGIFADDR:
218*18377Skarels 		ifr->ifr_addr = ia->ia_addr;
219*18377Skarels 		break;
220*18377Skarels 
221*18377Skarels 	case SIOCGIFBRDADDR:
222*18377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
223*18377Skarels 			return (EINVAL);
224*18377Skarels 		ifr->ifr_dstaddr = ia->ia_broadaddr;
225*18377Skarels 		break;
226*18377Skarels 
227*18377Skarels 	case SIOCGIFDSTADDR:
228*18377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
229*18377Skarels 			return (EINVAL);
230*18377Skarels 		ifr->ifr_dstaddr = ia->ia_dstaddr;
231*18377Skarels 		break;
232*18377Skarels 
233*18377Skarels 	case SIOCGIFNETMASK:
234*18377Skarels #define	satosin(sa)	((struct sockaddr_in *)(sa))
235*18377Skarels 		satosin(&ifr->ifr_addr)->sin_family = AF_INET;
236*18377Skarels 		satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
237*18377Skarels 		break;
238*18377Skarels 
239*18377Skarels 	case SIOCSIFDSTADDR:
240*18377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
241*18377Skarels 			return (EINVAL);
242*18377Skarels 		if (ifp->if_ioctl &&
243*18377Skarels 		    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia)))
244*18377Skarels 			return (error);
245*18377Skarels 		ia->ia_dstaddr = ifr->ifr_dstaddr;
246*18377Skarels 		break;
247*18377Skarels 
248*18377Skarels 	case SIOCSIFBRDADDR:
249*18377Skarels 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
250*18377Skarels 			return (EINVAL);
251*18377Skarels 		ia->ia_broadaddr = ifr->ifr_broadaddr;
252*18377Skarels 		break;
253*18377Skarels 
254*18377Skarels 	case SIOCSIFADDR:
255*18377Skarels 		return (in_ifinit(ifp, ia, &ifr->ifr_addr));
256*18377Skarels 		break;
257*18377Skarels 
258*18377Skarels 	case SIOCSIFNETMASK:
259*18377Skarels 		ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
260*18377Skarels 		break;
261*18377Skarels 
262*18377Skarels 	default:
263*18377Skarels 		if (ifp == 0 || ifp->if_ioctl == 0)
264*18377Skarels 			return (EOPNOTSUPP);
265*18377Skarels 		return ((*ifp->if_ioctl)(ifp, cmd, data));
266*18377Skarels 	}
26717271Skarels 	return (0);
26817271Skarels }
26917271Skarels 
27017271Skarels /*
271*18377Skarels  * Initialize an interface's internet address
272*18377Skarels  * and routing table entry.
2737159Ssam  */
274*18377Skarels in_ifinit(ifp, ia, sin)
2757159Ssam 	register struct ifnet *ifp;
276*18377Skarels 	register struct in_ifaddr *ia;
277*18377Skarels 	struct sockaddr_in *sin;
2787159Ssam {
279*18377Skarels 	register u_long i = ntohl(sin->sin_addr.s_addr);
280*18377Skarels 	struct sockaddr_in netaddr;
281*18377Skarels 	int s = splimp(), error;
2827159Ssam 
283*18377Skarels 	bzero((caddr_t)&netaddr, sizeof (netaddr));
284*18377Skarels 	netaddr.sin_family = AF_INET;
285*18377Skarels 	/*
286*18377Skarels 	 * Delete any previous route for an old address.
287*18377Skarels 	 */
288*18377Skarels 	if (ia->ia_flags & IFA_ROUTE) {
289*18377Skarels 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
290*18377Skarels 		    netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
291*18377Skarels 		    rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1);
292*18377Skarels 		} else
293*18377Skarels 		    rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1);
294*18377Skarels 		ia->ia_flags &= ~IFA_ROUTE;
295*18377Skarels 	}
296*18377Skarels 	ia->ia_addr = *(struct sockaddr *)sin;
297*18377Skarels 	if (IN_CLASSA(i))
298*18377Skarels 		ia->ia_netmask = IN_CLASSA_NET;
299*18377Skarels 	else if (IN_CLASSB(i))
300*18377Skarels 		ia->ia_netmask = IN_CLASSB_NET;
301*18377Skarels 	else
302*18377Skarels 		ia->ia_netmask = IN_CLASSC_NET;
303*18377Skarels 	ia->ia_net = i & ia->ia_netmask;
304*18377Skarels 	/*
305*18377Skarels 	 * The subnet mask includes at least the standard network part,
306*18377Skarels 	 * but may already have been set to a larger value.
307*18377Skarels 	 */
308*18377Skarels 	ia->ia_subnetmask |= ia->ia_netmask;
309*18377Skarels 	ia->ia_subnet = i & ia->ia_subnetmask;
310*18377Skarels 	if (ifp->if_flags & IFF_BROADCAST) {
311*18377Skarels 		ia->ia_broadaddr.sa_family = AF_INET;
312*18377Skarels 		((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr =
313*18377Skarels 			in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
314*18377Skarels 	}
315*18377Skarels 
316*18377Skarels 	/*
317*18377Skarels 	 * Give the interface a chance to initialize
318*18377Skarels 	 * if this is its first address,
319*18377Skarels 	 * and to validate the address if necessary.
320*18377Skarels 	 */
321*18377Skarels 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
322*18377Skarels 		splx(s);
323*18377Skarels 		bzero((caddr_t)&ia->ia_addr, sizeof(ia->ia_addr));
324*18377Skarels 		return (error);
325*18377Skarels 	}
326*18377Skarels 	splx(s);
327*18377Skarels 	/*
328*18377Skarels 	 * Add route for the network.
329*18377Skarels 	 */
330*18377Skarels 	if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
331*18377Skarels 		netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
332*18377Skarels 		rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP);
333*18377Skarels 	} else
334*18377Skarels 		rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
335*18377Skarels 			RTF_HOST|RTF_UP);
336*18377Skarels 	ia->ia_flags |= IFA_ROUTE;
3377159Ssam }
338*18377Skarels 
339*18377Skarels /*
340*18377Skarels  * Return address info for specified internet network.
341*18377Skarels  */
342*18377Skarels struct in_ifaddr *
343*18377Skarels in_iaonnetof(net)
344*18377Skarels 	u_long net;
345*18377Skarels {
346*18377Skarels 	register struct in_ifaddr *ia;
347*18377Skarels 
348*18377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
349*18377Skarels 		if (ia->ia_subnet == net)
350*18377Skarels 			return (ia);
351*18377Skarels 	return ((struct in_ifaddr *)0);
352*18377Skarels }
353*18377Skarels 
354*18377Skarels /*
355*18377Skarels  * Return 1 if the address is a local broadcast address.
356*18377Skarels  */
357*18377Skarels in_broadcast(in)
358*18377Skarels 	struct in_addr in;
359*18377Skarels {
360*18377Skarels 	register struct in_ifaddr *ia;
361*18377Skarels 
362*18377Skarels 	/*
363*18377Skarels 	 * Look through the list of addresses for a match
364*18377Skarels 	 * with a broadcast address.
365*18377Skarels 	 */
366*18377Skarels 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
367*18377Skarels 	    if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr ==
368*18377Skarels 		in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST))
369*18377Skarels 		     return (1);
370*18377Skarels 	return (0);
371*18377Skarels }
3727159Ssam #endif
373