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