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