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