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