in.c revision 1.71 1 /* $NetBSD: in.c,v 1.71 2001/11/13 00:32:35 lukem Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * 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. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 1998 The NetBSD Foundation, Inc.
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Public Access Networks Corporation ("Panix"). It was developed under
38 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the NetBSD
51 * Foundation, Inc. and its contributors.
52 * 4. Neither the name of The NetBSD Foundation nor the names of its
53 * contributors may be used to endorse or promote products derived
54 * from this software without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
57 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
58 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
59 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
60 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
61 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
62 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
64 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
65 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66 * POSSIBILITY OF SUCH DAMAGE.
67 */
68
69 /*
70 * Copyright (c) 1982, 1986, 1991, 1993
71 * The Regents of the University of California. All rights reserved.
72 *
73 * Redistribution and use in source and binary forms, with or without
74 * modification, are permitted provided that the following conditions
75 * are met:
76 * 1. Redistributions of source code must retain the above copyright
77 * notice, this list of conditions and the following disclaimer.
78 * 2. Redistributions in binary form must reproduce the above copyright
79 * notice, this list of conditions and the following disclaimer in the
80 * documentation and/or other materials provided with the distribution.
81 * 3. All advertising materials mentioning features or use of this software
82 * must display the following acknowledgement:
83 * This product includes software developed by the University of
84 * California, Berkeley and its contributors.
85 * 4. Neither the name of the University nor the names of its contributors
86 * may be used to endorse or promote products derived from this software
87 * without specific prior written permission.
88 *
89 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
90 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
91 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
92 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
93 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
94 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
95 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
96 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
97 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
98 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
99 * SUCH DAMAGE.
100 *
101 * @(#)in.c 8.4 (Berkeley) 1/9/95
102 */
103
104 #include <sys/cdefs.h>
105 __KERNEL_RCSID(0, "$NetBSD: in.c,v 1.71 2001/11/13 00:32:35 lukem Exp $");
106
107 #include "opt_inet.h"
108 #include "opt_inet_conf.h"
109 #include "opt_mrouting.h"
110
111 #include <sys/param.h>
112 #include <sys/ioctl.h>
113 #include <sys/errno.h>
114 #include <sys/malloc.h>
115 #include <sys/socket.h>
116 #include <sys/socketvar.h>
117 #include <sys/systm.h>
118 #include <sys/proc.h>
119
120 #include <net/if.h>
121 #include <net/route.h>
122
123 #include <net/if_ether.h>
124
125 #include <netinet/in_systm.h>
126 #include <netinet/in.h>
127 #include <netinet/in_var.h>
128 #include <netinet/if_inarp.h>
129 #include <netinet/ip_mroute.h>
130 #include <netinet/igmp_var.h>
131
132 #ifdef INET
133
134 static int in_mask2len __P((struct in_addr *));
135 static void in_len2mask __P((struct in_addr *, int));
136 static int in_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
137 struct ifnet *, struct proc *));
138
139 static int in_addprefix __P((struct in_ifaddr *, int));
140 static int in_scrubprefix __P((struct in_ifaddr *));
141
142 #ifndef SUBNETSARELOCAL
143 #define SUBNETSARELOCAL 1
144 #endif
145
146 #ifndef HOSTZEROBROADCAST
147 #define HOSTZEROBROADCAST 1
148 #endif
149
150 int subnetsarelocal = SUBNETSARELOCAL;
151 int hostzeroisbroadcast = HOSTZEROBROADCAST;
152
153 /*
154 * This list is used to keep track of in_multi chains which belong to
155 * deleted interface addresses. We use in_ifaddr so that a chain head
156 * won't be deallocated until all multicast address record are deleted.
157 */
158 static TAILQ_HEAD(, in_ifaddr) in_mk = TAILQ_HEAD_INITIALIZER(in_mk);
159
160 /*
161 * Return 1 if an internet address is for a ``local'' host
162 * (one to which we have a connection). If subnetsarelocal
163 * is true, this includes other subnets of the local net.
164 * Otherwise, it includes only the directly-connected (sub)nets.
165 */
166 int
167 in_localaddr(in)
168 struct in_addr in;
169 {
170 struct in_ifaddr *ia;
171
172 if (subnetsarelocal) {
173 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
174 if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
175 return (1);
176 } else {
177 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
178 if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
179 return (1);
180 }
181 return (0);
182 }
183
184 /*
185 * Determine whether an IP address is in a reserved set of addresses
186 * that may not be forwarded, or whether datagrams to that destination
187 * may be forwarded.
188 */
189 int
190 in_canforward(in)
191 struct in_addr in;
192 {
193 u_int32_t net;
194
195 if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
196 return (0);
197 if (IN_CLASSA(in.s_addr)) {
198 net = in.s_addr & IN_CLASSA_NET;
199 if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
200 return (0);
201 }
202 return (1);
203 }
204
205 /*
206 * Trim a mask in a sockaddr
207 */
208 void
209 in_socktrim(ap)
210 struct sockaddr_in *ap;
211 {
212 char *cplim = (char *) &ap->sin_addr;
213 char *cp = (char *) (&ap->sin_addr + 1);
214
215 ap->sin_len = 0;
216 while (--cp >= cplim)
217 if (*cp) {
218 (ap)->sin_len = cp - (char *) (ap) + 1;
219 break;
220 }
221 }
222
223 /*
224 * Routine to take an Internet address and convert into a
225 * "dotted quad" representation for printing.
226 */
227 const char *
228 in_fmtaddr(addr)
229 struct in_addr addr;
230 {
231 static char buf[sizeof("123.456.789.123")];
232
233 addr.s_addr = ntohl(addr.s_addr);
234
235 sprintf(buf, "%d.%d.%d.%d",
236 (addr.s_addr >> 24) & 0xFF,
237 (addr.s_addr >> 16) & 0xFF,
238 (addr.s_addr >> 8) & 0xFF,
239 (addr.s_addr >> 0) & 0xFF);
240 return buf;
241 }
242
243 /*
244 * Maintain the "in_maxmtu" variable, which is the largest
245 * mtu for non-local interfaces with AF_INET addresses assigned
246 * to them that are up.
247 */
248 unsigned long in_maxmtu;
249
250 void
251 in_setmaxmtu()
252 {
253 struct in_ifaddr *ia;
254 struct ifnet *ifp;
255 unsigned long maxmtu = 0;
256
257 TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
258 if ((ifp = ia->ia_ifp) == 0)
259 continue;
260 if ((ifp->if_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
261 continue;
262 if (ifp->if_mtu > maxmtu)
263 maxmtu = ifp->if_mtu;
264 }
265 if (maxmtu)
266 in_maxmtu = maxmtu;
267 }
268
269 static int
270 in_mask2len(mask)
271 struct in_addr *mask;
272 {
273 int x, y;
274 u_char *p;
275
276 p = (u_char *)mask;
277 for (x = 0; x < sizeof(*mask); x++) {
278 if (p[x] != 0xff)
279 break;
280 }
281 y = 0;
282 if (x < sizeof(*mask)) {
283 for (y = 0; y < 8; y++) {
284 if ((p[x] & (0x80 >> y)) == 0)
285 break;
286 }
287 }
288 return x * 8 + y;
289 }
290
291 static void
292 in_len2mask(mask, len)
293 struct in_addr *mask;
294 int len;
295 {
296 int i;
297 u_char *p;
298
299 p = (u_char *)mask;
300 bzero(mask, sizeof(*mask));
301 for (i = 0; i < len / 8; i++)
302 p[i] = 0xff;
303 if (len % 8)
304 p[i] = (0xff00 >> (len % 8)) & 0xff;
305 }
306
307 /*
308 * Generic internet control operations (ioctl's).
309 * Ifp is 0 if not an interface-specific ioctl.
310 */
311 /* ARGSUSED */
312 int
313 in_control(so, cmd, data, ifp, p)
314 struct socket *so;
315 u_long cmd;
316 caddr_t data;
317 struct ifnet *ifp;
318 struct proc *p;
319 {
320 struct ifreq *ifr = (struct ifreq *)data;
321 struct in_ifaddr *ia = 0;
322 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
323 struct sockaddr_in oldaddr;
324 int error, hostIsNew, maskIsNew;
325 int newifaddr;
326
327 switch (cmd) {
328 case SIOCALIFADDR:
329 case SIOCDLIFADDR:
330 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
331 return(EPERM);
332 /*fall through*/
333 case SIOCGLIFADDR:
334 if (!ifp)
335 return EINVAL;
336 return in_lifaddr_ioctl(so, cmd, data, ifp, p);
337 }
338
339 /*
340 * Find address for this interface, if it exists.
341 */
342 if (ifp)
343 IFP_TO_IA(ifp, ia);
344
345 switch (cmd) {
346
347 case SIOCAIFADDR:
348 case SIOCDIFADDR:
349 case SIOCGIFALIAS:
350 if (ifra->ifra_addr.sin_family == AF_INET)
351 LIST_FOREACH(ia,
352 &IN_IFADDR_HASH(ifra->ifra_addr.sin_addr.s_addr),
353 ia_hash) {
354 if (ia->ia_ifp == ifp &&
355 in_hosteq(ia->ia_addr.sin_addr,
356 ifra->ifra_addr.sin_addr))
357 break;
358 }
359 if (cmd == SIOCDIFADDR) {
360 if (ia == 0)
361 return (EADDRNOTAVAIL);
362 #if 1 /*def COMPAT_43*/
363 if (ifra->ifra_addr.sin_family == AF_UNSPEC)
364 ifra->ifra_addr.sin_family = AF_INET;
365 #endif
366 }
367 /* FALLTHROUGH */
368 case SIOCSIFADDR:
369 case SIOCSIFDSTADDR:
370 if (ifra->ifra_addr.sin_family != AF_INET)
371 return (EAFNOSUPPORT);
372 /* FALLTHROUGH */
373 case SIOCSIFNETMASK:
374 if (ifp == 0)
375 panic("in_control");
376
377 if (cmd == SIOCGIFALIAS)
378 break;
379
380 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
381 return (EPERM);
382
383 if (ia == 0) {
384 MALLOC(ia, struct in_ifaddr *, sizeof(*ia),
385 M_IFADDR, M_WAITOK);
386 if (ia == 0)
387 return (ENOBUFS);
388 bzero((caddr_t)ia, sizeof *ia);
389 TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
390 IFAREF(&ia->ia_ifa);
391 TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
392 ifa_list);
393 IFAREF(&ia->ia_ifa);
394 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
395 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
396 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
397 ia->ia_sockmask.sin_len = 8;
398 if (ifp->if_flags & IFF_BROADCAST) {
399 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
400 ia->ia_broadaddr.sin_family = AF_INET;
401 }
402 ia->ia_ifp = ifp;
403 LIST_INIT(&ia->ia_multiaddrs);
404 newifaddr = 1;
405 } else
406 newifaddr = 0;
407 break;
408
409 case SIOCSIFBRDADDR:
410 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
411 return (EPERM);
412 /* FALLTHROUGH */
413
414 case SIOCGIFADDR:
415 case SIOCGIFNETMASK:
416 case SIOCGIFDSTADDR:
417 case SIOCGIFBRDADDR:
418 if (ia == 0)
419 return (EADDRNOTAVAIL);
420 break;
421 }
422 switch (cmd) {
423
424 case SIOCGIFADDR:
425 *satosin(&ifr->ifr_addr) = ia->ia_addr;
426 break;
427
428 case SIOCGIFBRDADDR:
429 if ((ifp->if_flags & IFF_BROADCAST) == 0)
430 return (EINVAL);
431 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
432 break;
433
434 case SIOCGIFDSTADDR:
435 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
436 return (EINVAL);
437 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
438 break;
439
440 case SIOCGIFNETMASK:
441 *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
442 break;
443
444 case SIOCSIFDSTADDR:
445 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
446 return (EINVAL);
447 oldaddr = ia->ia_dstaddr;
448 ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
449 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
450 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
451 ia->ia_dstaddr = oldaddr;
452 return (error);
453 }
454 if (ia->ia_flags & IFA_ROUTE) {
455 ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
456 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
457 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
458 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
459 }
460 break;
461
462 case SIOCSIFBRDADDR:
463 if ((ifp->if_flags & IFF_BROADCAST) == 0)
464 return (EINVAL);
465 ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
466 break;
467
468 case SIOCSIFADDR:
469 error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
470 return error;
471
472 case SIOCSIFNETMASK:
473 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
474 ifra->ifra_addr.sin_addr.s_addr;
475 break;
476
477 case SIOCAIFADDR:
478 maskIsNew = 0;
479 hostIsNew = 1;
480 error = 0;
481 if (ia->ia_addr.sin_family == AF_INET) {
482 if (ifra->ifra_addr.sin_len == 0) {
483 ifra->ifra_addr = ia->ia_addr;
484 hostIsNew = 0;
485 } else if (in_hosteq(ia->ia_addr.sin_addr, ifra->ifra_addr.sin_addr))
486 hostIsNew = 0;
487 }
488 if (ifra->ifra_mask.sin_len) {
489 in_ifscrub(ifp, ia);
490 ia->ia_sockmask = ifra->ifra_mask;
491 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
492 maskIsNew = 1;
493 }
494 if ((ifp->if_flags & IFF_POINTOPOINT) &&
495 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
496 in_ifscrub(ifp, ia);
497 ia->ia_dstaddr = ifra->ifra_dstaddr;
498 maskIsNew = 1; /* We lie; but the effect's the same */
499 }
500 if (ifra->ifra_addr.sin_family == AF_INET &&
501 (hostIsNew || maskIsNew)) {
502 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
503 }
504 if ((ifp->if_flags & IFF_BROADCAST) &&
505 (ifra->ifra_broadaddr.sin_family == AF_INET))
506 ia->ia_broadaddr = ifra->ifra_broadaddr;
507 return (error);
508
509 case SIOCGIFALIAS:
510 ifra->ifra_mask = ia->ia_sockmask;
511 if ((ifp->if_flags & IFF_POINTOPOINT) &&
512 (ia->ia_dstaddr.sin_family == AF_INET))
513 ifra->ifra_dstaddr = ia->ia_dstaddr;
514 else if ((ifp->if_flags & IFF_BROADCAST) &&
515 (ia->ia_broadaddr.sin_family == AF_INET))
516 ifra->ifra_broadaddr = ia->ia_broadaddr;
517 else
518 bzero(&ifra->ifra_broadaddr,
519 sizeof(ifra->ifra_broadaddr));
520 return 0;
521
522 case SIOCDIFADDR:
523 in_purgeaddr(&ia->ia_ifa, ifp);
524 break;
525
526 #ifdef MROUTING
527 case SIOCGETVIFCNT:
528 case SIOCGETSGCNT:
529 return (mrt_ioctl(so, cmd, data));
530 #endif /* MROUTING */
531
532 default:
533 if (ifp == 0 || ifp->if_ioctl == 0)
534 return (EOPNOTSUPP);
535 error = (*ifp->if_ioctl)(ifp, cmd, data);
536 in_setmaxmtu();
537 return(error);
538 }
539 return (0);
540 }
541
542 void
543 in_purgeaddr(ifa, ifp)
544 struct ifaddr *ifa;
545 struct ifnet *ifp;
546 {
547 struct in_ifaddr *ia = (void *) ifa;
548
549 in_ifscrub(ifp, ia);
550 LIST_REMOVE(ia, ia_hash);
551 TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
552 IFAFREE(&ia->ia_ifa);
553 TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
554 if (ia->ia_allhosts != NULL)
555 in_delmulti(ia->ia_allhosts);
556 if (LIST_FIRST(&ia->ia_multiaddrs) != NULL &&
557 /*
558 * If the interface is going away, don't bother to save
559 * the multicast entries.
560 */
561 ifp->if_output != if_nulloutput)
562 in_savemkludge(ia);
563 IFAFREE(&ia->ia_ifa);
564 in_setmaxmtu();
565 }
566
567 void
568 in_purgeif(ifp)
569 struct ifnet *ifp;
570 {
571 struct ifaddr *ifa, *nifa;
572
573 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
574 nifa = TAILQ_NEXT(ifa, ifa_list);
575 if (ifa->ifa_addr->sa_family != AF_INET)
576 continue;
577 in_purgeaddr(ifa, ifp);
578 }
579 in_purgemkludge(ifp);
580 }
581
582 /*
583 * SIOC[GAD]LIFADDR.
584 * SIOCGLIFADDR: get first address. (???)
585 * SIOCGLIFADDR with IFLR_PREFIX:
586 * get first address that matches the specified prefix.
587 * SIOCALIFADDR: add the specified address.
588 * SIOCALIFADDR with IFLR_PREFIX:
589 * EINVAL since we can't deduce hostid part of the address.
590 * SIOCDLIFADDR: delete the specified address.
591 * SIOCDLIFADDR with IFLR_PREFIX:
592 * delete the first address that matches the specified prefix.
593 * return values:
594 * EINVAL on invalid parameters
595 * EADDRNOTAVAIL on prefix match failed/specified address not found
596 * other values may be returned from in_ioctl()
597 */
598 static int
599 in_lifaddr_ioctl(so, cmd, data, ifp, p)
600 struct socket *so;
601 u_long cmd;
602 caddr_t data;
603 struct ifnet *ifp;
604 struct proc *p;
605 {
606 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
607 struct ifaddr *ifa;
608 struct sockaddr *sa;
609
610 /* sanity checks */
611 if (!data || !ifp) {
612 panic("invalid argument to in_lifaddr_ioctl");
613 /*NOTRECHED*/
614 }
615
616 switch (cmd) {
617 case SIOCGLIFADDR:
618 /* address must be specified on GET with IFLR_PREFIX */
619 if ((iflr->flags & IFLR_PREFIX) == 0)
620 break;
621 /*FALLTHROUGH*/
622 case SIOCALIFADDR:
623 case SIOCDLIFADDR:
624 /* address must be specified on ADD and DELETE */
625 sa = (struct sockaddr *)&iflr->addr;
626 if (sa->sa_family != AF_INET)
627 return EINVAL;
628 if (sa->sa_len != sizeof(struct sockaddr_in))
629 return EINVAL;
630 /* XXX need improvement */
631 sa = (struct sockaddr *)&iflr->dstaddr;
632 if (sa->sa_family
633 && sa->sa_family != AF_INET)
634 return EINVAL;
635 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
636 return EINVAL;
637 break;
638 default: /*shouldn't happen*/
639 #if 0
640 panic("invalid cmd to in_lifaddr_ioctl");
641 /*NOTREACHED*/
642 #else
643 return EOPNOTSUPP;
644 #endif
645 }
646 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
647 return EINVAL;
648
649 switch (cmd) {
650 case SIOCALIFADDR:
651 {
652 struct in_aliasreq ifra;
653
654 if (iflr->flags & IFLR_PREFIX)
655 return EINVAL;
656
657 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
658 bzero(&ifra, sizeof(ifra));
659 bcopy(iflr->iflr_name, ifra.ifra_name,
660 sizeof(ifra.ifra_name));
661
662 bcopy(&iflr->addr, &ifra.ifra_addr,
663 ((struct sockaddr *)&iflr->addr)->sa_len);
664
665 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /*XXX*/
666 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
667 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
668 }
669
670 ifra.ifra_mask.sin_family = AF_INET;
671 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
672 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
673
674 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p);
675 }
676 case SIOCGLIFADDR:
677 case SIOCDLIFADDR:
678 {
679 struct in_ifaddr *ia;
680 struct in_addr mask, candidate, match;
681 struct sockaddr_in *sin;
682 int cmp;
683
684 bzero(&mask, sizeof(mask));
685 if (iflr->flags & IFLR_PREFIX) {
686 /* lookup a prefix rather than address. */
687 in_len2mask(&mask, iflr->prefixlen);
688
689 sin = (struct sockaddr_in *)&iflr->addr;
690 match.s_addr = sin->sin_addr.s_addr;
691 match.s_addr &= mask.s_addr;
692
693 /* if you set extra bits, that's wrong */
694 if (match.s_addr != sin->sin_addr.s_addr)
695 return EINVAL;
696
697 cmp = 1;
698 } else {
699 if (cmd == SIOCGLIFADDR) {
700 /* on getting an address, take the 1st match */
701 cmp = 0; /*XXX*/
702 } else {
703 /* on deleting an address, do exact match */
704 in_len2mask(&mask, 32);
705 sin = (struct sockaddr_in *)&iflr->addr;
706 match.s_addr = sin->sin_addr.s_addr;
707
708 cmp = 1;
709 }
710 }
711
712 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
713 if (ifa->ifa_addr->sa_family != AF_INET6)
714 continue;
715 if (!cmp)
716 break;
717 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
718 candidate.s_addr &= mask.s_addr;
719 if (candidate.s_addr == match.s_addr)
720 break;
721 }
722 if (!ifa)
723 return EADDRNOTAVAIL;
724 ia = (struct in_ifaddr *)ifa;
725
726 if (cmd == SIOCGLIFADDR) {
727 /* fill in the if_laddrreq structure */
728 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
729
730 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
731 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
732 ia->ia_dstaddr.sin_len);
733 } else
734 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
735
736 iflr->prefixlen =
737 in_mask2len(&ia->ia_sockmask.sin_addr);
738
739 iflr->flags = 0; /*XXX*/
740
741 return 0;
742 } else {
743 struct in_aliasreq ifra;
744
745 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
746 bzero(&ifra, sizeof(ifra));
747 bcopy(iflr->iflr_name, ifra.ifra_name,
748 sizeof(ifra.ifra_name));
749
750 bcopy(&ia->ia_addr, &ifra.ifra_addr,
751 ia->ia_addr.sin_len);
752 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
753 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
754 ia->ia_dstaddr.sin_len);
755 }
756 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
757 ia->ia_sockmask.sin_len);
758
759 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
760 ifp, p);
761 }
762 }
763 }
764
765 return EOPNOTSUPP; /*just for safety*/
766 }
767
768 /*
769 * Delete any existing route for an interface.
770 */
771 void
772 in_ifscrub(ifp, ia)
773 struct ifnet *ifp;
774 struct in_ifaddr *ia;
775 {
776
777 in_scrubprefix(ia);
778 }
779
780 /*
781 * Initialize an interface's internet address
782 * and routing table entry.
783 */
784 int
785 in_ifinit(ifp, ia, sin, scrub)
786 struct ifnet *ifp;
787 struct in_ifaddr *ia;
788 struct sockaddr_in *sin;
789 int scrub;
790 {
791 u_int32_t i = sin->sin_addr.s_addr;
792 struct sockaddr_in oldaddr;
793 int s = splnet(), flags = RTF_UP, error;
794
795 /*
796 * Set up new addresses.
797 */
798 oldaddr = ia->ia_addr;
799 if (ia->ia_addr.sin_family == AF_INET)
800 LIST_REMOVE(ia, ia_hash);
801 ia->ia_addr = *sin;
802 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
803
804 /*
805 * Give the interface a chance to initialize
806 * if this is its first address,
807 * and to validate the address if necessary.
808 */
809 if (ifp->if_ioctl &&
810 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
811 goto bad;
812 splx(s);
813 if (scrub) {
814 ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
815 in_ifscrub(ifp, ia);
816 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
817 }
818
819 if (IN_CLASSA(i))
820 ia->ia_netmask = IN_CLASSA_NET;
821 else if (IN_CLASSB(i))
822 ia->ia_netmask = IN_CLASSB_NET;
823 else
824 ia->ia_netmask = IN_CLASSC_NET;
825 /*
826 * The subnet mask usually includes at least the standard network part,
827 * but may may be smaller in the case of supernetting.
828 * If it is set, we believe it.
829 */
830 if (ia->ia_subnetmask == 0) {
831 ia->ia_subnetmask = ia->ia_netmask;
832 ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
833 } else
834 ia->ia_netmask &= ia->ia_subnetmask;
835
836 ia->ia_net = i & ia->ia_netmask;
837 ia->ia_subnet = i & ia->ia_subnetmask;
838 in_socktrim(&ia->ia_sockmask);
839 /* re-calculate the "in_maxmtu" value */
840 in_setmaxmtu();
841 /*
842 * Add route for the network.
843 */
844 ia->ia_ifa.ifa_metric = ifp->if_metric;
845 if (ifp->if_flags & IFF_BROADCAST) {
846 ia->ia_broadaddr.sin_addr.s_addr =
847 ia->ia_subnet | ~ia->ia_subnetmask;
848 ia->ia_netbroadcast.s_addr =
849 ia->ia_net | ~ia->ia_netmask;
850 } else if (ifp->if_flags & IFF_LOOPBACK) {
851 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
852 flags |= RTF_HOST;
853 } else if (ifp->if_flags & IFF_POINTOPOINT) {
854 if (ia->ia_dstaddr.sin_family != AF_INET)
855 return (0);
856 flags |= RTF_HOST;
857 }
858 error = in_addprefix(ia, flags);
859 /*
860 * recover multicast kludge entry, if there is.
861 */
862 if (ifp->if_flags & IFF_MULTICAST)
863 in_restoremkludge(ia, ifp);
864 /*
865 * If the interface supports multicast, join the "all hosts"
866 * multicast group on that interface.
867 */
868 if ((ifp->if_flags & IFF_MULTICAST) != 0 && ia->ia_allhosts == NULL) {
869 struct in_addr addr;
870
871 addr.s_addr = INADDR_ALLHOSTS_GROUP;
872 ia->ia_allhosts = in_addmulti(&addr, ifp);
873 }
874 return (error);
875 bad:
876 splx(s);
877 LIST_REMOVE(ia, ia_hash);
878 ia->ia_addr = oldaddr;
879 if (ia->ia_addr.sin_family == AF_INET)
880 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
881 ia, ia_hash);
882 return (error);
883 }
884
885 #define rtinitflags(x) \
886 ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
887 ? RTF_HOST : 0)
888
889 /*
890 * add a route to prefix ("connected route" in cisco terminology).
891 * does nothing if there's some interface address with the same prefix already.
892 */
893 static int
894 in_addprefix(target, flags)
895 struct in_ifaddr *target;
896 int flags;
897 {
898 struct in_ifaddr *ia;
899 struct in_addr prefix, mask, p;
900 int error;
901
902 if ((flags & RTF_HOST) != 0)
903 prefix = target->ia_dstaddr.sin_addr;
904 else
905 prefix = target->ia_addr.sin_addr;
906 mask = target->ia_sockmask.sin_addr;
907 prefix.s_addr &= mask.s_addr;
908
909 TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
910 /* easy one first */
911 if (mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
912 continue;
913
914 if (rtinitflags(ia))
915 p = ia->ia_dstaddr.sin_addr;
916 else
917 p = ia->ia_addr.sin_addr;
918 p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
919 if (prefix.s_addr != p.s_addr)
920 continue;
921
922 /*
923 * if we got a matching prefix route inserted by other
924 * interface address, we don't need to bother
925 */
926 if (ia->ia_flags & IFA_ROUTE)
927 return 0;
928 }
929
930 /*
931 * noone seem to have prefix route. insert it.
932 */
933 error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
934 if (!error)
935 target->ia_flags |= IFA_ROUTE;
936 return error;
937 }
938
939 /*
940 * remove a route to prefix ("connected route" in cisco terminology).
941 * re-installs the route by using another interface address, if there's one
942 * with the same prefix (otherwise we lose the route mistakenly).
943 */
944 static int
945 in_scrubprefix(target)
946 struct in_ifaddr *target;
947 {
948 struct in_ifaddr *ia;
949 struct in_addr prefix, mask, p;
950 int error;
951
952 if ((target->ia_flags & IFA_ROUTE) == 0)
953 return 0;
954
955 if (rtinitflags(target))
956 prefix = target->ia_dstaddr.sin_addr;
957 else
958 prefix = target->ia_addr.sin_addr;
959 mask = target->ia_sockmask.sin_addr;
960 prefix.s_addr &= mask.s_addr;
961
962 TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
963 /* easy one first */
964 if (mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
965 continue;
966
967 if (rtinitflags(ia))
968 p = ia->ia_dstaddr.sin_addr;
969 else
970 p = ia->ia_addr.sin_addr;
971 p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
972 if (prefix.s_addr != p.s_addr)
973 continue;
974
975 /*
976 * if we got a matching prefix route, move IFA_ROUTE to him
977 */
978 if ((ia->ia_flags & IFA_ROUTE) == 0) {
979 rtinit(&(target->ia_ifa), (int)RTM_DELETE,
980 rtinitflags(target));
981 target->ia_flags &= ~IFA_ROUTE;
982
983 error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
984 rtinitflags(ia) | RTF_UP);
985 if (error == 0)
986 ia->ia_flags |= IFA_ROUTE;
987 return error;
988 }
989 }
990
991 /*
992 * noone seem to have prefix route. remove it.
993 */
994 rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
995 target->ia_flags &= ~IFA_ROUTE;
996 return 0;
997 }
998
999 #undef rtinitflags
1000
1001 /*
1002 * Return 1 if the address might be a local broadcast address.
1003 */
1004 int
1005 in_broadcast(in, ifp)
1006 struct in_addr in;
1007 struct ifnet *ifp;
1008 {
1009 struct ifaddr *ifa;
1010
1011 if (in.s_addr == INADDR_BROADCAST ||
1012 in_nullhost(in))
1013 return 1;
1014 if ((ifp->if_flags & IFF_BROADCAST) == 0)
1015 return 0;
1016 /*
1017 * Look through the list of addresses for a match
1018 * with a broadcast address.
1019 */
1020 #define ia (ifatoia(ifa))
1021 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1022 if (ifa->ifa_addr->sa_family == AF_INET &&
1023 (in_hosteq(in, ia->ia_broadaddr.sin_addr) ||
1024 in_hosteq(in, ia->ia_netbroadcast) ||
1025 (hostzeroisbroadcast &&
1026 /*
1027 * Check for old-style (host 0) broadcast.
1028 */
1029 (in.s_addr == ia->ia_subnet ||
1030 in.s_addr == ia->ia_net))))
1031 return 1;
1032 return (0);
1033 #undef ia
1034 }
1035
1036 /*
1037 * Multicast address kludge:
1038 * If there were any multicast addresses attached to this interface address,
1039 * either move them to another address on this interface, or save them until
1040 * such time as this interface is reconfigured for IPv4.
1041 */
1042 void
1043 in_savemkludge(oia)
1044 struct in_ifaddr *oia;
1045 {
1046 struct in_ifaddr *ia;
1047 struct in_multi *inm, *next;
1048
1049 IFP_TO_IA(oia->ia_ifp, ia);
1050 if (ia) { /* there is another address */
1051 for (inm = LIST_FIRST(&oia->ia_multiaddrs); inm; inm = next){
1052 next = LIST_NEXT(inm, inm_list);
1053 IFAFREE(&inm->inm_ia->ia_ifa);
1054 IFAREF(&ia->ia_ifa);
1055 inm->inm_ia = ia;
1056 LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
1057 }
1058 } else { /* last address on this if deleted, save */
1059 TAILQ_INSERT_TAIL(&in_mk, oia, ia_list);
1060 IFAREF(&oia->ia_ifa);
1061 }
1062 }
1063
1064 /*
1065 * Continuation of multicast address hack:
1066 * If there was a multicast group list previously saved for this interface,
1067 * then we re-attach it to the first address configured on the i/f.
1068 */
1069 void
1070 in_restoremkludge(ia, ifp)
1071 struct in_ifaddr *ia;
1072 struct ifnet *ifp;
1073 {
1074 struct in_ifaddr *oia;
1075
1076 for (oia = TAILQ_FIRST(&in_mk); oia != NULL;
1077 oia = TAILQ_NEXT(oia, ia_list)) {
1078 if (oia->ia_ifp == ifp) {
1079 struct in_multi *inm, *next;
1080
1081 for (inm = LIST_FIRST(&oia->ia_multiaddrs);
1082 inm != NULL; inm = next) {
1083 next = LIST_NEXT(inm, inm_list);
1084 IFAFREE(&inm->inm_ia->ia_ifa);
1085 IFAREF(&ia->ia_ifa);
1086 inm->inm_ia = ia;
1087 LIST_INSERT_HEAD(&ia->ia_multiaddrs,
1088 inm, inm_list);
1089 }
1090 TAILQ_REMOVE(&in_mk, oia, ia_list);
1091 IFAFREE(&oia->ia_ifa);
1092 break;
1093 }
1094 }
1095 }
1096
1097 void
1098 in_purgemkludge(ifp)
1099 struct ifnet *ifp;
1100 {
1101 struct in_ifaddr *oia;
1102
1103 for (oia = TAILQ_FIRST(&in_mk); oia != NULL;
1104 oia = TAILQ_NEXT(oia, ia_list)) {
1105 if (oia->ia_ifp != ifp)
1106 continue;
1107
1108 /*
1109 * Leaving from all multicast groups joined through
1110 * this interface is done via in_pcbpurgeif().
1111 */
1112
1113 TAILQ_REMOVE(&in_mk, oia, ia_list);
1114 IFAFREE(&oia->ia_ifa);
1115 break;
1116 }
1117 }
1118
1119 /*
1120 * Add an address to the list of IP multicast addresses for a given interface.
1121 */
1122 struct in_multi *
1123 in_addmulti(ap, ifp)
1124 struct in_addr *ap;
1125 struct ifnet *ifp;
1126 {
1127 struct in_multi *inm;
1128 struct ifreq ifr;
1129 struct in_ifaddr *ia;
1130 int s = splsoftnet();
1131
1132 /*
1133 * See if address already in list.
1134 */
1135 IN_LOOKUP_MULTI(*ap, ifp, inm);
1136 if (inm != NULL) {
1137 /*
1138 * Found it; just increment the reference count.
1139 */
1140 ++inm->inm_refcount;
1141 } else {
1142 /*
1143 * New address; allocate a new multicast record
1144 * and link it into the interface's multicast list.
1145 */
1146 inm = (struct in_multi *)malloc(sizeof(*inm),
1147 M_IPMADDR, M_NOWAIT);
1148 if (inm == NULL) {
1149 splx(s);
1150 return (NULL);
1151 }
1152 inm->inm_addr = *ap;
1153 inm->inm_ifp = ifp;
1154 inm->inm_refcount = 1;
1155 IFP_TO_IA(ifp, ia);
1156 if (ia == NULL) {
1157 free(inm, M_IPMADDR);
1158 splx(s);
1159 return (NULL);
1160 }
1161 inm->inm_ia = ia;
1162 IFAREF(&inm->inm_ia->ia_ifa);
1163 LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
1164 /*
1165 * Ask the network driver to update its multicast reception
1166 * filter appropriately for the new address.
1167 */
1168 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
1169 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
1170 satosin(&ifr.ifr_addr)->sin_addr = *ap;
1171 if ((ifp->if_ioctl == NULL) ||
1172 (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
1173 LIST_REMOVE(inm, inm_list);
1174 free(inm, M_IPMADDR);
1175 splx(s);
1176 return (NULL);
1177 }
1178 /*
1179 * Let IGMP know that we have joined a new IP multicast group.
1180 */
1181 igmp_joingroup(inm);
1182 }
1183 splx(s);
1184 return (inm);
1185 }
1186
1187 /*
1188 * Delete a multicast address record.
1189 */
1190 void
1191 in_delmulti(inm)
1192 struct in_multi *inm;
1193 {
1194 struct ifreq ifr;
1195 int s = splsoftnet();
1196
1197 if (--inm->inm_refcount == 0) {
1198 /*
1199 * No remaining claims to this record; let IGMP know that
1200 * we are leaving the multicast group.
1201 */
1202 igmp_leavegroup(inm);
1203 /*
1204 * Unlink from list.
1205 */
1206 LIST_REMOVE(inm, inm_list);
1207 IFAFREE(&inm->inm_ia->ia_ifa);
1208 /*
1209 * Notify the network driver to update its multicast reception
1210 * filter.
1211 */
1212 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
1213 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
1214 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
1215 (caddr_t)&ifr);
1216 free(inm, M_IPMADDR);
1217 }
1218 splx(s);
1219 }
1220 #endif
1221