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