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