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