xref: /csrg-svn/sys/netinet/in.c (revision 37471)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)in.c	7.10 (Berkeley) 04/22/89
18  */
19 
20 #include "param.h"
21 #include "ioctl.h"
22 #include "mbuf.h"
23 #include "protosw.h"
24 #include "socket.h"
25 #include "socketvar.h"
26 #include "uio.h"
27 #include "dir.h"
28 #include "user.h"
29 #include "in_systm.h"
30 #include "../net/if.h"
31 #include "../net/route.h"
32 #include "../net/af.h"
33 #include "in.h"
34 #include "in_var.h"
35 
36 #ifdef INET
37 /*
38  * Formulate an Internet address from network + host.
39  */
40 struct in_addr
41 in_makeaddr(net, host)
42 	u_long net, host;
43 {
44 	register struct in_ifaddr *ia;
45 	register u_long mask;
46 	u_long addr;
47 
48 	if (IN_CLASSA(net))
49 		mask = IN_CLASSA_HOST;
50 	else if (IN_CLASSB(net))
51 		mask = IN_CLASSB_HOST;
52 	else
53 		mask = IN_CLASSC_HOST;
54 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
55 		if ((ia->ia_netmask & net) == ia->ia_net) {
56 			mask = ~ia->ia_subnetmask;
57 			break;
58 		}
59 	addr = htonl(net | (host & mask));
60 	return (*(struct in_addr *)&addr);
61 }
62 
63 /*
64  * Return the network number from an internet address.
65  */
66 u_long
67 in_netof(in)
68 	struct in_addr in;
69 {
70 	register u_long i = ntohl(in.s_addr);
71 	register u_long net;
72 	register struct in_ifaddr *ia;
73 
74 	if (IN_CLASSA(i))
75 		net = i & IN_CLASSA_NET;
76 	else if (IN_CLASSB(i))
77 		net = i & IN_CLASSB_NET;
78 	else if (IN_CLASSC(i))
79 		net = i & IN_CLASSC_NET;
80 	else
81 		return (0);
82 
83 	/*
84 	 * Check whether network is a subnet;
85 	 * if so, return subnet number.
86 	 */
87 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
88 		if (net == ia->ia_net)
89 			return (i & ia->ia_subnetmask);
90 	return (net);
91 }
92 
93 /*
94  * Compute and save network mask as sockaddr from an internet address.
95  */
96 in_sockmaskof(in, sockmask)
97 	struct in_addr in;
98 	register struct sockaddr_in *sockmask;
99 {
100 	register u_long net;
101 	register u_long mask;
102     {
103 	register u_long i = ntohl(in.s_addr);
104 
105 	if (i == 0)
106 		net = 0, mask = 0;
107 	else if (IN_CLASSA(i))
108 		net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
109 	else if (IN_CLASSB(i))
110 		net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
111 	else if (IN_CLASSC(i))
112 		net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
113 	else
114 		net = i, mask = -1;
115     }
116     {
117 	register struct in_ifaddr *ia;
118 	/*
119 	 * Check whether network is a subnet;
120 	 * if so, return subnet number.
121 	 */
122 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
123 		if (net == ia->ia_net)
124 			mask =  ia->ia_subnetmask;
125     }
126     {
127 	register char *cp = (char *)&(sockmask->sin_port);
128 	register char *cpbase = (char *)&(sockmask->sin_addr);
129 
130 	sockmask->sin_addr.s_addr = htonl(mask);
131 	sockmask->sin_len = 0;
132 	while (--cp >= cpbase)
133 		if (*cp) {
134 			sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
135 			break;
136 		}
137     }
138 }
139 
140 /*
141  * Return the host portion of an internet address.
142  */
143 u_long
144 in_lnaof(in)
145 	struct in_addr in;
146 {
147 	register u_long i = ntohl(in.s_addr);
148 	register u_long net, host;
149 	register struct in_ifaddr *ia;
150 
151 	if (IN_CLASSA(i)) {
152 		net = i & IN_CLASSA_NET;
153 		host = i & IN_CLASSA_HOST;
154 	} else if (IN_CLASSB(i)) {
155 		net = i & IN_CLASSB_NET;
156 		host = i & IN_CLASSB_HOST;
157 	} else if (IN_CLASSC(i)) {
158 		net = i & IN_CLASSC_NET;
159 		host = i & IN_CLASSC_HOST;
160 	} else
161 		return (i);
162 
163 	/*
164 	 * Check whether network is a subnet;
165 	 * if so, use the modified interpretation of `host'.
166 	 */
167 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
168 		if (net == ia->ia_net)
169 			return (host &~ ia->ia_subnetmask);
170 	return (host);
171 }
172 
173 #ifndef SUBNETSARELOCAL
174 #define	SUBNETSARELOCAL	1
175 #endif
176 int subnetsarelocal = SUBNETSARELOCAL;
177 /*
178  * Return 1 if an internet address is for a ``local'' host
179  * (one to which we have a connection).  If subnetsarelocal
180  * is true, this includes other subnets of the local net.
181  * Otherwise, it includes only the directly-connected (sub)nets.
182  */
183 in_localaddr(in)
184 	struct in_addr in;
185 {
186 	register u_long i = ntohl(in.s_addr);
187 	register struct in_ifaddr *ia;
188 
189 	if (subnetsarelocal) {
190 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
191 			if ((i & ia->ia_netmask) == ia->ia_net)
192 				return (1);
193 	} else {
194 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
195 			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
196 				return (1);
197 	}
198 	return (0);
199 }
200 
201 /*
202  * Determine whether an IP address is in a reserved set of addresses
203  * that may not be forwarded, or whether datagrams to that destination
204  * may be forwarded.
205  */
206 in_canforward(in)
207 	struct in_addr in;
208 {
209 	register u_long i = ntohl(in.s_addr);
210 	register u_long net;
211 
212 	if (IN_EXPERIMENTAL(i))
213 		return (0);
214 	if (IN_CLASSA(i)) {
215 		net = i & IN_CLASSA_NET;
216 		if (net == 0 || net == IN_LOOPBACKNET)
217 			return (0);
218 	}
219 	return (1);
220 }
221 
222 int	in_interfaces;		/* number of external internet interfaces */
223 extern	struct ifnet loif;
224 
225 /*
226  * Generic internet control operations (ioctl's).
227  * Ifp is 0 if not an interface-specific ioctl.
228  */
229 /* ARGSUSED */
230 in_control(so, cmd, data, ifp)
231 	struct socket *so;
232 	int cmd;
233 	caddr_t data;
234 	register struct ifnet *ifp;
235 {
236 	register struct ifreq *ifr = (struct ifreq *)data;
237 	register struct in_ifaddr *ia = 0;
238 	register struct ifaddr *ifa;
239 	struct in_ifaddr *oia;
240 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
241 	struct mbuf *m;
242 	struct sockaddr_in oldaddr;
243 	int error, hostIsNew, maskIsNew;
244 	u_long i;
245 
246 	/*
247 	 * Find address for this interface, if it exists.
248 	 */
249 	if (ifp)
250 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
251 			if (ia->ia_ifp == ifp)
252 				break;
253 
254 	switch (cmd) {
255 
256 	case SIOCAIFADDR:
257 	case SIOCDIFADDR:
258 		if (ifra->ifra_addr.sin_family == AF_INET)
259 		    for (oia = ia; ia; ia = ia->ia_next) {
260 			if (ia->ia_ifp == ifp  &&
261 			    ia->ia_addr.sin_addr.s_addr ==
262 				ifra->ifra_addr.sin_addr.s_addr)
263 			    break;
264 		}
265 		if (cmd == SIOCDIFADDR && ia == 0)
266 			return (EADDRNOTAVAIL);
267 		/* FALLTHROUGH */
268 	case SIOCSIFADDR:
269 	case SIOCSIFNETMASK:
270 	case SIOCSIFDSTADDR:
271 		if (!suser())
272 			return (u.u_error);
273 
274 		if (ifp == 0)
275 			panic("in_control");
276 		if (ia == (struct in_ifaddr *)0) {
277 			m = m_getclr(M_WAIT, MT_IFADDR);
278 			if (m == (struct mbuf *)NULL)
279 				return (ENOBUFS);
280 			if (ia = in_ifaddr) {
281 				for ( ; ia->ia_next; ia = ia->ia_next)
282 					;
283 				ia->ia_next = mtod(m, struct in_ifaddr *);
284 			} else
285 				in_ifaddr = mtod(m, struct in_ifaddr *);
286 			ia = mtod(m, struct in_ifaddr *);
287 			if (ifa = ifp->if_addrlist) {
288 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
289 					;
290 				ifa->ifa_next = (struct ifaddr *) ia;
291 			} else
292 				ifp->if_addrlist = (struct ifaddr *) ia;
293 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
294 			ia->ia_ifa.ifa_dstaddr
295 					= (struct sockaddr *)&ia->ia_dstaddr;
296 			ia->ia_ifa.ifa_netmask
297 					= (struct sockaddr *)&ia->ia_sockmask;
298 			ia->ia_sockmask.sin_len = 8;
299 			if (ifp->if_flags & IFF_BROADCAST) {
300 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
301 				ia->ia_broadaddr.sin_family = AF_INET;
302 			}
303 			ia->ia_ifp = ifp;
304 			if (ifp != &loif)
305 				in_interfaces++;
306 		}
307 		break;
308 
309 	case SIOCSIFBRDADDR:
310 		if (!suser())
311 			return (u.u_error);
312 		/* FALLTHROUGH */
313 
314 	default:
315 		if (ia == (struct in_ifaddr *)0)
316 			return (EADDRNOTAVAIL);
317 		break;
318 	}
319 	switch (cmd) {
320 
321 	case SIOCGIFADDR:
322 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
323 		break;
324 
325 	case SIOCGIFBRDADDR:
326 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
327 			return (EINVAL);
328 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
329 		break;
330 
331 	case SIOCGIFDSTADDR:
332 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
333 			return (EINVAL);
334 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
335 		break;
336 
337 	case SIOCGIFNETMASK:
338 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
339 		break;
340 
341 	case SIOCSIFDSTADDR:
342 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
343 			return (EINVAL);
344 		oldaddr = ia->ia_dstaddr;
345 		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
346 		if (ifp->if_ioctl &&
347 		    (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
348 			ia->ia_dstaddr = oldaddr;
349 			return (error);
350 		}
351 		if (ia->ia_flags & IFA_ROUTE) {
352 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
353 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
354 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_addr;
355 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
356 		}
357 		break;
358 
359 	case SIOCSIFBRDADDR:
360 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
361 			return (EINVAL);
362 		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
363 		break;
364 
365 	case SIOCSIFADDR:
366 		return (in_ifinit(ifp, ia,
367 		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
368 
369 	case SIOCSIFNETMASK:
370 		i = ifra->ifra_addr.sin_addr.s_addr;
371 		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
372 		break;
373 
374 	case SIOCAIFADDR:
375 		maskIsNew = 0; hostIsNew = 1; error = u.u_error;
376 		if (ia->ia_addr.sin_family == AF_INET) {
377 			if (ifra->ifra_addr.sin_len == 0) {
378 				ifra->ifra_addr = ia->ia_addr;
379 				hostIsNew = 0;
380 			} else if (ifra->ifra_addr.sin_addr.s_addr ==
381 					       ia->ia_addr.sin_addr.s_addr)
382 				hostIsNew = 0;
383 		}
384 		if (ifra->ifra_mask.sin_len) {
385 			in_ifscrub(ifp, ia);
386 			ia->ia_sockmask = ifra->ifra_mask;
387 			ia->ia_subnetmask =
388 					ntohl(ia->ia_sockmask.sin_addr.s_addr);
389 			maskIsNew = 1;
390 		}
391 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
392 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
393 			in_ifscrub(ifp, ia);
394 			ia->ia_dstaddr = ifra->ifra_dstaddr;
395 			maskIsNew  = 1; /* We lie; but the effect's the same */
396 		}
397 		if (ifra->ifra_addr.sin_family == AF_INET &&
398 					    (hostIsNew || maskIsNew))
399 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
400 		if ((ifp->if_flags & IFF_BROADCAST) &&
401 		    (ifra->ifra_broadaddr.sin_family == AF_INET))
402 			ia->ia_broadaddr = ifra->ifra_broadaddr;
403 		return (error);
404 
405 	case SIOCDIFADDR:
406 		in_ifscrub(ifp, ia);
407 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
408 			ifp->if_addrlist = ifa->ifa_next;
409 		else {
410 			while (ifa->ifa_next &&
411 			       (ifa->ifa_next != (struct ifaddr *)ia))
412 				    ifa = ifa->ifa_next;
413 			if (ifa->ifa_next)
414 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
415 			else
416 				printf("Couldn't unlink inifaddr from ifp\n");
417 		}
418 		oia = ia;
419 		if (oia == (ia = in_ifaddr)) {
420 			in_ifaddr = ia->ia_next;
421 		} else {
422 			while (ia->ia_next && (ia->ia_next != oia)) {
423 				ia = ia->ia_next;
424 			}
425 			if (ia->ia_next)
426 			    ia->ia_next = oia->ia_next;
427 			else
428 				printf("Didn't unlink inifadr from list\n");
429 		}
430 		(void) m_free(dtom(oia));
431 		break;
432 
433 	default:
434 		if (ifp == 0 || ifp->if_ioctl == 0)
435 			return (EOPNOTSUPP);
436 		return ((*ifp->if_ioctl)(ifp, cmd, data));
437 	}
438 	return (0);
439 }
440 
441 /*
442  * Delete any existing route for an interface.
443  */
444 in_ifscrub(ifp, ia)
445 	register struct ifnet *ifp;
446 	register struct in_ifaddr *ia;
447 {
448 
449 	if ((ia->ia_flags & IFA_ROUTE) == 0)
450 		return;
451 	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
452 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
453 	else
454 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
455 	ia->ia_flags &= ~IFA_ROUTE;
456 }
457 
458 /*
459  * Initialize an interface's internet address
460  * and routing table entry.
461  */
462 in_ifinit(ifp, ia, sin, scrub)
463 	register struct ifnet *ifp;
464 	register struct in_ifaddr *ia;
465 	struct sockaddr_in *sin;
466 {
467 	register u_long i = ntohl(sin->sin_addr.s_addr);
468 	struct sockaddr_in oldaddr;
469 	int s = splimp(), error;
470 
471 	oldaddr = ia->ia_addr;
472 	ia->ia_addr = *sin;
473 	/*
474 	 * Give the interface a chance to initialize
475 	 * if this is its first address,
476 	 * and to validate the address if necessary.
477 	 */
478 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
479 		splx(s);
480 		ia->ia_addr = oldaddr;
481 		return (error);
482 	}
483 	if (scrub) {
484 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
485 		in_ifscrub(ifp, ia);
486 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
487 	}
488 	if (IN_CLASSA(i))
489 		ia->ia_netmask = IN_CLASSA_NET;
490 	else if (IN_CLASSB(i))
491 		ia->ia_netmask = IN_CLASSB_NET;
492 	else
493 		ia->ia_netmask = IN_CLASSC_NET;
494 	ia->ia_net = i & ia->ia_netmask;
495 	/*
496 	 * The subnet mask includes at least the standard network part,
497 	 * but may already have been set to a larger value.
498 	 */
499 	ia->ia_subnetmask |= ia->ia_netmask;
500 	ia->ia_subnet = i & ia->ia_subnetmask;
501 	ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
502 	if (ifp->if_flags & IFF_BROADCAST) {
503 		ia->ia_broadaddr.sin_addr =
504 			in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
505 		ia->ia_netbroadcast.s_addr =
506 		    htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
507 	}
508 	/*
509 	 * Add route for the network.
510 	 */
511 	if (ifp->if_flags & IFF_LOOPBACK) {
512 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
513 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
514 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
515 		 ia->ia_dstaddr.sin_family == AF_INET)
516 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
517 	else {
518 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
519 	}
520 	ia->ia_flags |= IFA_ROUTE;
521 	splx(s);
522 	return (0);
523 }
524 
525 /*
526  * Return address info for specified internet network.
527  */
528 struct in_ifaddr *
529 in_iaonnetof(net)
530 	u_long net;
531 {
532 	register struct in_ifaddr *ia;
533 
534 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
535 		if (ia->ia_subnet == net)
536 			return (ia);
537 	return ((struct in_ifaddr *)0);
538 }
539 
540 /*
541  * Return 1 if the address might be a local broadcast address.
542  */
543 in_broadcast(in)
544 	struct in_addr in;
545 {
546 	register struct in_ifaddr *ia;
547 	u_long t;
548 
549 	/*
550 	 * Look through the list of addresses for a match
551 	 * with a broadcast address.
552 	 */
553 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
554 	    if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
555 		if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
556 		     return (1);
557 		/*
558 		 * Check for old-style (host 0) broadcast.
559 		 */
560 		if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
561 		    return (1);
562 	}
563 	if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
564 		return (1);
565 	return (0);
566 }
567 #endif
568