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