in.c revision 1.52 1 /* $NetBSD: in.c,v 1.52 2000/02/25 07:11:38 itojun 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 "opt_inet.h"
105 #include "opt_inet_conf.h"
106 #include "opt_mrouting.h"
107
108 #include <sys/param.h>
109 #include <sys/ioctl.h>
110 #include <sys/errno.h>
111 #include <sys/malloc.h>
112 #include <sys/socket.h>
113 #include <sys/socketvar.h>
114 #include <sys/systm.h>
115 #include <sys/proc.h>
116
117 #include <net/if.h>
118 #include <net/if_types.h>
119 #include <net/route.h>
120 #include "gif.h"
121 #if NGIF > 0
122 #include <net/if_gif.h>
123 #endif
124
125 #include <net/if_ether.h>
126
127 #include <netinet/in_systm.h>
128 #include <netinet/in.h>
129 #include <netinet/in_var.h>
130 #include <netinet/if_inarp.h>
131 #include <netinet/ip_mroute.h>
132 #include <netinet/igmp_var.h>
133
134 #ifdef INET
135
136 static int in_mask2len __P((struct in_addr *));
137 static void in_len2mask __P((struct in_addr *, int));
138 static int in_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
139 struct ifnet *, struct proc *));
140
141 #ifndef SUBNETSARELOCAL
142 #define SUBNETSARELOCAL 1
143 #endif
144
145 #ifndef HOSTZEROBROADCAST
146 #define HOSTZEROBROADCAST 1
147 #endif
148
149 int subnetsarelocal = SUBNETSARELOCAL;
150 int hostzeroisbroadcast = HOSTZEROBROADCAST;
151
152 /*
153 * Return 1 if an internet address is for a ``local'' host
154 * (one to which we have a connection). If subnetsarelocal
155 * is true, this includes other subnets of the local net.
156 * Otherwise, it includes only the directly-connected (sub)nets.
157 */
158 int
159 in_localaddr(in)
160 struct in_addr in;
161 {
162 register struct in_ifaddr *ia;
163
164 if (subnetsarelocal) {
165 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
166 if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
167 return (1);
168 } else {
169 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
170 if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
171 return (1);
172 }
173 return (0);
174 }
175
176 /*
177 * Determine whether an IP address is in a reserved set of addresses
178 * that may not be forwarded, or whether datagrams to that destination
179 * may be forwarded.
180 */
181 int
182 in_canforward(in)
183 struct in_addr in;
184 {
185 register u_int32_t net;
186
187 if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
188 return (0);
189 if (IN_CLASSA(in.s_addr)) {
190 net = in.s_addr & IN_CLASSA_NET;
191 if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
192 return (0);
193 }
194 return (1);
195 }
196
197 /*
198 * Trim a mask in a sockaddr
199 */
200 void
201 in_socktrim(ap)
202 struct sockaddr_in *ap;
203 {
204 register char *cplim = (char *) &ap->sin_addr;
205 register char *cp = (char *) (&ap->sin_addr + 1);
206
207 ap->sin_len = 0;
208 while (--cp >= cplim)
209 if (*cp) {
210 (ap)->sin_len = cp - (char *) (ap) + 1;
211 break;
212 }
213 }
214
215 /*
216 * Routine to take an Internet address and convert into a
217 * "dotted quad" representation for printing.
218 */
219 const char *
220 in_fmtaddr(addr)
221 struct in_addr addr;
222 {
223 static char buf[sizeof("123.456.789.123")];
224
225 addr.s_addr = ntohl(addr.s_addr);
226
227 sprintf(buf, "%d.%d.%d.%d",
228 (addr.s_addr >> 24) & 0xFF,
229 (addr.s_addr >> 16) & 0xFF,
230 (addr.s_addr >> 8) & 0xFF,
231 (addr.s_addr >> 0) & 0xFF);
232 return buf;
233 }
234
235 /*
236 * Maintain the "in_maxmtu" variable, which is the largest
237 * mtu for non-local interfaces with AF_INET addresses assigned
238 * to them that are up.
239 */
240 unsigned long in_maxmtu;
241
242 void
243 in_setmaxmtu()
244 {
245 register struct in_ifaddr *ia;
246 register struct ifnet *ifp;
247 unsigned long maxmtu = 0;
248
249 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) {
250 if ((ifp = ia->ia_ifp) == 0)
251 continue;
252 if ((ifp->if_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
253 continue;
254 if (ifp->if_mtu > maxmtu)
255 maxmtu = ifp->if_mtu;
256 }
257 if (maxmtu)
258 in_maxmtu = maxmtu;
259 }
260
261 static int
262 in_mask2len(mask)
263 struct in_addr *mask;
264 {
265 int x, y;
266 u_char *p;
267
268 p = (u_char *)mask;
269 for (x = 0; x < sizeof(*mask); x++) {
270 if (p[x] != 0xff)
271 break;
272 }
273 y = 0;
274 if (x < sizeof(*mask)) {
275 for (y = 0; y < 8; y++) {
276 if ((p[x] & (0x80 >> y)) == 0)
277 break;
278 }
279 }
280 return x * 8 + y;
281 }
282
283 static void
284 in_len2mask(mask, len)
285 struct in_addr *mask;
286 int len;
287 {
288 int i;
289 u_char *p;
290
291 p = (u_char *)mask;
292 bzero(mask, sizeof(*mask));
293 for (i = 0; i < len / 8; i++)
294 p[i] = 0xff;
295 if (len % 8)
296 p[i] = (0xff00 >> (len % 8)) & 0xff;
297 }
298
299 int in_interfaces; /* number of external internet interfaces */
300
301 /*
302 * Generic internet control operations (ioctl's).
303 * Ifp is 0 if not an interface-specific ioctl.
304 */
305 /* ARGSUSED */
306 int
307 in_control(so, cmd, data, ifp, p)
308 struct socket *so;
309 u_long cmd;
310 caddr_t data;
311 register struct ifnet *ifp;
312 struct proc *p;
313 {
314 register struct ifreq *ifr = (struct ifreq *)data;
315 register struct in_ifaddr *ia = 0;
316 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
317 struct sockaddr_in oldaddr;
318 int error, hostIsNew, maskIsNew;
319
320 #if NGIF > 0
321 if (ifp && ifp->if_type == IFT_GIF) {
322 switch (cmd) {
323 case SIOCSIFPHYADDR:
324 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
325 return(EPERM);
326 case SIOCGIFPSRCADDR:
327 case SIOCGIFPDSTADDR:
328 return gif_ioctl(ifp, cmd, data);
329 }
330 }
331 #endif
332
333 switch (cmd) {
334 case SIOCALIFADDR:
335 case SIOCDLIFADDR:
336 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
337 return(EPERM);
338 /*fall through*/
339 case SIOCGLIFADDR:
340 if (!ifp)
341 return EINVAL;
342 return in_lifaddr_ioctl(so, cmd, data, ifp, p);
343 }
344
345 /*
346 * Find address for this interface, if it exists.
347 */
348 if (ifp)
349 IFP_TO_IA(ifp, ia);
350
351 switch (cmd) {
352
353 case SIOCAIFADDR:
354 case SIOCDIFADDR:
355 case SIOCGIFALIAS:
356 if (ifra->ifra_addr.sin_family == AF_INET)
357 for (ia = IN_IFADDR_HASH(ifra->ifra_addr.sin_addr.s_addr).lh_first;
358 ia != 0; ia = ia->ia_hash.le_next) {
359 if (ia->ia_ifp == ifp &&
360 in_hosteq(ia->ia_addr.sin_addr,
361 ifra->ifra_addr.sin_addr))
362 break;
363 }
364 if (cmd == SIOCDIFADDR && ia == 0)
365 return (EADDRNOTAVAIL);
366 /* FALLTHROUGH */
367 case SIOCSIFADDR:
368 case SIOCSIFDSTADDR:
369 if (ifra->ifra_addr.sin_family != AF_INET)
370 return (EAFNOSUPPORT);
371 /* FALLTHROUGH */
372 case SIOCSIFNETMASK:
373 if (ifp == 0)
374 panic("in_control");
375
376 if (cmd == SIOCGIFALIAS)
377 break;
378
379 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
380 return (EPERM);
381
382 if (ia == 0) {
383 MALLOC(ia, struct in_ifaddr *, sizeof(*ia),
384 M_IFADDR, M_WAITOK);
385 if (ia == 0)
386 return (ENOBUFS);
387 bzero((caddr_t)ia, sizeof *ia);
388 TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
389 IFAREF(&ia->ia_ifa);
390 TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
391 ifa_list);
392 IFAREF(&ia->ia_ifa);
393 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
394 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
395 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
396 ia->ia_sockmask.sin_len = 8;
397 if (ifp->if_flags & IFF_BROADCAST) {
398 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
399 ia->ia_broadaddr.sin_family = AF_INET;
400 }
401 ia->ia_ifp = ifp;
402 LIST_INIT(&ia->ia_multiaddrs);
403 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
404 in_interfaces++;
405 }
406 break;
407
408 case SIOCSIFBRDADDR:
409 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
410 return (EPERM);
411 /* FALLTHROUGH */
412
413 case SIOCGIFADDR:
414 case SIOCGIFNETMASK:
415 case SIOCGIFDSTADDR:
416 case SIOCGIFBRDADDR:
417 if (ia == 0)
418 return (EADDRNOTAVAIL);
419 break;
420 }
421 switch (cmd) {
422
423 case SIOCGIFADDR:
424 *satosin(&ifr->ifr_addr) = ia->ia_addr;
425 break;
426
427 case SIOCGIFBRDADDR:
428 if ((ifp->if_flags & IFF_BROADCAST) == 0)
429 return (EINVAL);
430 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
431 break;
432
433 case SIOCGIFDSTADDR:
434 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
435 return (EINVAL);
436 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
437 break;
438
439 case SIOCGIFNETMASK:
440 *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
441 break;
442
443 case SIOCSIFDSTADDR:
444 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
445 return (EINVAL);
446 oldaddr = ia->ia_dstaddr;
447 ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
448 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
449 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
450 ia->ia_dstaddr = oldaddr;
451 return (error);
452 }
453 if (ia->ia_flags & IFA_ROUTE) {
454 ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
455 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
456 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
457 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
458 }
459 break;
460
461 case SIOCSIFBRDADDR:
462 if ((ifp->if_flags & IFF_BROADCAST) == 0)
463 return (EINVAL);
464 ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
465 break;
466
467 case SIOCSIFADDR:
468 return (in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1));
469
470 case SIOCSIFNETMASK:
471 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
472 ifra->ifra_addr.sin_addr.s_addr;
473 break;
474
475 case SIOCAIFADDR:
476 maskIsNew = 0;
477 hostIsNew = 1;
478 error = 0;
479 if (ia->ia_addr.sin_family == AF_INET) {
480 if (ifra->ifra_addr.sin_len == 0) {
481 ifra->ifra_addr = ia->ia_addr;
482 hostIsNew = 0;
483 } else if (in_hosteq(ia->ia_addr.sin_addr, ifra->ifra_addr.sin_addr))
484 hostIsNew = 0;
485 }
486 if (ifra->ifra_mask.sin_len) {
487 in_ifscrub(ifp, ia);
488 ia->ia_sockmask = ifra->ifra_mask;
489 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
490 maskIsNew = 1;
491 }
492 if ((ifp->if_flags & IFF_POINTOPOINT) &&
493 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
494 in_ifscrub(ifp, ia);
495 ia->ia_dstaddr = ifra->ifra_dstaddr;
496 maskIsNew = 1; /* We lie; but the effect's the same */
497 }
498 if (ifra->ifra_addr.sin_family == AF_INET &&
499 (hostIsNew || maskIsNew))
500 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
501 if ((ifp->if_flags & IFF_BROADCAST) &&
502 (ifra->ifra_broadaddr.sin_family == AF_INET))
503 ia->ia_broadaddr = ifra->ifra_broadaddr;
504 return (error);
505
506 case SIOCGIFALIAS:
507 ifra->ifra_mask = ia->ia_sockmask;
508 if ((ifp->if_flags & IFF_POINTOPOINT) &&
509 (ia->ia_dstaddr.sin_family == AF_INET))
510 ifra->ifra_dstaddr = ia->ia_dstaddr;
511 else if ((ifp->if_flags & IFF_BROADCAST) &&
512 (ia->ia_broadaddr.sin_family == AF_INET))
513 ifra->ifra_broadaddr = ia->ia_broadaddr;
514 else
515 bzero(&ifra->ifra_broadaddr,
516 sizeof(ifra->ifra_broadaddr));
517 return 0;
518
519 case SIOCDIFADDR:
520 in_purgeaddr(&ia->ia_ifa, ifp);
521 break;
522
523 #ifdef MROUTING
524 case SIOCGETVIFCNT:
525 case SIOCGETSGCNT:
526 return (mrt_ioctl(so, cmd, data));
527 #endif /* MROUTING */
528
529 default:
530 if (ifp == 0 || ifp->if_ioctl == 0)
531 return (EOPNOTSUPP);
532 error = (*ifp->if_ioctl)(ifp, cmd, data);
533 in_setmaxmtu();
534 return(error);
535 }
536 return (0);
537 }
538
539 void
540 in_purgeaddr(ifa, ifp)
541 struct ifaddr *ifa;
542 struct ifnet *ifp;
543 {
544 struct in_ifaddr *ia = (void *) ifa;
545
546 in_ifscrub(ifp, ia);
547 LIST_REMOVE(ia, ia_hash);
548 TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
549 IFAFREE(&ia->ia_ifa);
550 TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
551 IFAFREE(&ia->ia_ifa);
552 in_setmaxmtu();
553 }
554
555 void
556 in_purgeif(ifp)
557 struct ifnet *ifp;
558 {
559 struct ifaddr *ifa, *nifa;
560
561 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
562 nifa = TAILQ_NEXT(ifa, ifa_list);
563 if (ifa->ifa_addr->sa_family != AF_INET)
564 continue;
565 in_purgeaddr(ifa, ifp);
566 }
567 }
568
569 /*
570 * SIOC[GAD]LIFADDR.
571 * SIOCGLIFADDR: get first address. (???)
572 * SIOCGLIFADDR with IFLR_PREFIX:
573 * get first address that matches the specified prefix.
574 * SIOCALIFADDR: add the specified address.
575 * SIOCALIFADDR with IFLR_PREFIX:
576 * EINVAL since we can't deduce hostid part of the address.
577 * SIOCDLIFADDR: delete the specified address.
578 * SIOCDLIFADDR with IFLR_PREFIX:
579 * delete the first address that matches the specified prefix.
580 * return values:
581 * EINVAL on invalid parameters
582 * EADDRNOTAVAIL on prefix match failed/specified address not found
583 * other values may be returned from in_ioctl()
584 */
585 static int
586 in_lifaddr_ioctl(so, cmd, data, ifp, p)
587 struct socket *so;
588 u_long cmd;
589 caddr_t data;
590 struct ifnet *ifp;
591 struct proc *p;
592 {
593 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
594 struct ifaddr *ifa;
595 struct sockaddr *sa;
596
597 /* sanity checks */
598 if (!data || !ifp) {
599 panic("invalid argument to in_lifaddr_ioctl");
600 /*NOTRECHED*/
601 }
602
603 switch (cmd) {
604 case SIOCGLIFADDR:
605 /* address must be specified on GET with IFLR_PREFIX */
606 if ((iflr->flags & IFLR_PREFIX) == 0)
607 break;
608 /*FALLTHROUGH*/
609 case SIOCALIFADDR:
610 case SIOCDLIFADDR:
611 /* address must be specified on ADD and DELETE */
612 sa = (struct sockaddr *)&iflr->addr;
613 if (sa->sa_family != AF_INET)
614 return EINVAL;
615 if (sa->sa_len != sizeof(struct sockaddr_in))
616 return EINVAL;
617 /* XXX need improvement */
618 sa = (struct sockaddr *)&iflr->dstaddr;
619 if (sa->sa_family
620 && sa->sa_family != AF_INET)
621 return EINVAL;
622 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
623 return EINVAL;
624 break;
625 default: /*shouldn't happen*/
626 #if 0
627 panic("invalid cmd to in_lifaddr_ioctl");
628 /*NOTREACHED*/
629 #else
630 return EOPNOTSUPP;
631 #endif
632 }
633 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
634 return EINVAL;
635
636 switch (cmd) {
637 case SIOCALIFADDR:
638 {
639 struct in_aliasreq ifra;
640
641 if (iflr->flags & IFLR_PREFIX)
642 return EINVAL;
643
644 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
645 bzero(&ifra, sizeof(ifra));
646 bcopy(iflr->iflr_name, ifra.ifra_name,
647 sizeof(ifra.ifra_name));
648
649 bcopy(&iflr->addr, &ifra.ifra_addr,
650 ((struct sockaddr *)&iflr->addr)->sa_len);
651
652 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /*XXX*/
653 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
654 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
655 }
656
657 ifra.ifra_mask.sin_family = AF_INET;
658 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
659 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
660
661 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p);
662 }
663 case SIOCGLIFADDR:
664 case SIOCDLIFADDR:
665 {
666 struct in_ifaddr *ia;
667 struct in_addr mask, candidate, match;
668 struct sockaddr_in *sin;
669 int cmp;
670
671 bzero(&mask, sizeof(mask));
672 if (iflr->flags & IFLR_PREFIX) {
673 /* lookup a prefix rather than address. */
674 in_len2mask(&mask, iflr->prefixlen);
675
676 sin = (struct sockaddr_in *)&iflr->addr;
677 match.s_addr = sin->sin_addr.s_addr;
678 match.s_addr &= mask.s_addr;
679
680 /* if you set extra bits, that's wrong */
681 if (match.s_addr != sin->sin_addr.s_addr)
682 return EINVAL;
683
684 cmp = 1;
685 } else {
686 if (cmd == SIOCGLIFADDR) {
687 /* on getting an address, take the 1st match */
688 cmp = 0; /*XXX*/
689 } else {
690 /* on deleting an address, do exact match */
691 in_len2mask(&mask, 32);
692 sin = (struct sockaddr_in *)&iflr->addr;
693 match.s_addr = sin->sin_addr.s_addr;
694
695 cmp = 1;
696 }
697 }
698
699 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) {
700 if (ifa->ifa_addr->sa_family != AF_INET6)
701 continue;
702 if (!cmp)
703 break;
704 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
705 candidate.s_addr &= mask.s_addr;
706 if (candidate.s_addr == match.s_addr)
707 break;
708 }
709 if (!ifa)
710 return EADDRNOTAVAIL;
711 ia = (struct in_ifaddr *)ifa;
712
713 if (cmd == SIOCGLIFADDR) {
714 /* fill in the if_laddrreq structure */
715 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
716
717 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
718 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
719 ia->ia_dstaddr.sin_len);
720 } else
721 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
722
723 iflr->prefixlen =
724 in_mask2len(&ia->ia_sockmask.sin_addr);
725
726 iflr->flags = 0; /*XXX*/
727
728 return 0;
729 } else {
730 struct in_aliasreq ifra;
731
732 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
733 bzero(&ifra, sizeof(ifra));
734 bcopy(iflr->iflr_name, ifra.ifra_name,
735 sizeof(ifra.ifra_name));
736
737 bcopy(&ia->ia_addr, &ifra.ifra_addr,
738 ia->ia_addr.sin_len);
739 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
740 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
741 ia->ia_dstaddr.sin_len);
742 }
743 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
744 ia->ia_sockmask.sin_len);
745
746 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
747 ifp, p);
748 }
749 }
750 }
751
752 return EOPNOTSUPP; /*just for safety*/
753 }
754
755 /*
756 * Delete any existing route for an interface.
757 */
758 void
759 in_ifscrub(ifp, ia)
760 register struct ifnet *ifp;
761 register struct in_ifaddr *ia;
762 {
763
764 if ((ia->ia_flags & IFA_ROUTE) == 0)
765 return;
766 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
767 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
768 else
769 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
770 ia->ia_flags &= ~IFA_ROUTE;
771 }
772
773 /*
774 * Initialize an interface's internet address
775 * and routing table entry.
776 */
777 int
778 in_ifinit(ifp, ia, sin, scrub)
779 register struct ifnet *ifp;
780 register struct in_ifaddr *ia;
781 struct sockaddr_in *sin;
782 int scrub;
783 {
784 register u_int32_t i = sin->sin_addr.s_addr;
785 struct sockaddr_in oldaddr;
786 int s = splimp(), flags = RTF_UP, error;
787
788 /*
789 * Set up new addresses.
790 */
791 oldaddr = ia->ia_addr;
792 if (ia->ia_addr.sin_family == AF_INET)
793 LIST_REMOVE(ia, ia_hash);
794 ia->ia_addr = *sin;
795 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
796
797 /*
798 * Give the interface a chance to initialize
799 * if this is its first address,
800 * and to validate the address if necessary.
801 */
802 if (ifp->if_ioctl &&
803 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
804 goto bad;
805 splx(s);
806 if (scrub) {
807 ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
808 in_ifscrub(ifp, ia);
809 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
810 }
811
812 if (IN_CLASSA(i))
813 ia->ia_netmask = IN_CLASSA_NET;
814 else if (IN_CLASSB(i))
815 ia->ia_netmask = IN_CLASSB_NET;
816 else
817 ia->ia_netmask = IN_CLASSC_NET;
818 /*
819 * The subnet mask usually includes at least the standard network part,
820 * but may may be smaller in the case of supernetting.
821 * If it is set, we believe it.
822 */
823 if (ia->ia_subnetmask == 0) {
824 ia->ia_subnetmask = ia->ia_netmask;
825 ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
826 } else
827 ia->ia_netmask &= ia->ia_subnetmask;
828
829 ia->ia_net = i & ia->ia_netmask;
830 ia->ia_subnet = i & ia->ia_subnetmask;
831 in_socktrim(&ia->ia_sockmask);
832 /* re-calculate the "in_maxmtu" value */
833 in_setmaxmtu();
834 /*
835 * Add route for the network.
836 */
837 ia->ia_ifa.ifa_metric = ifp->if_metric;
838 if (ifp->if_flags & IFF_BROADCAST) {
839 ia->ia_broadaddr.sin_addr.s_addr =
840 ia->ia_subnet | ~ia->ia_subnetmask;
841 ia->ia_netbroadcast.s_addr =
842 ia->ia_net | ~ia->ia_netmask;
843 } else if (ifp->if_flags & IFF_LOOPBACK) {
844 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
845 flags |= RTF_HOST;
846 } else if (ifp->if_flags & IFF_POINTOPOINT) {
847 if (ia->ia_dstaddr.sin_family != AF_INET)
848 return (0);
849 flags |= RTF_HOST;
850 }
851 error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags);
852 if (!error)
853 ia->ia_flags |= IFA_ROUTE;
854 /*
855 * If the interface supports multicast, join the "all hosts"
856 * multicast group on that interface.
857 */
858 if (ifp->if_flags & IFF_MULTICAST) {
859 struct in_addr addr;
860
861 addr.s_addr = INADDR_ALLHOSTS_GROUP;
862 in_addmulti(&addr, ifp);
863 }
864 return (error);
865 bad:
866 splx(s);
867 LIST_REMOVE(ia, ia_hash);
868 ia->ia_addr = oldaddr;
869 if (ia->ia_addr.sin_family == AF_INET)
870 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
871 ia, ia_hash);
872 return (error);
873 }
874
875 /*
876 * Return 1 if the address might be a local broadcast address.
877 */
878 int
879 in_broadcast(in, ifp)
880 struct in_addr in;
881 struct ifnet *ifp;
882 {
883 register struct ifaddr *ifa;
884
885 if (in.s_addr == INADDR_BROADCAST ||
886 in_nullhost(in))
887 return 1;
888 if ((ifp->if_flags & IFF_BROADCAST) == 0)
889 return 0;
890 /*
891 * Look through the list of addresses for a match
892 * with a broadcast address.
893 */
894 #define ia (ifatoia(ifa))
895 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
896 if (ifa->ifa_addr->sa_family == AF_INET &&
897 (in_hosteq(in, ia->ia_broadaddr.sin_addr) ||
898 in_hosteq(in, ia->ia_netbroadcast) ||
899 (hostzeroisbroadcast &&
900 /*
901 * Check for old-style (host 0) broadcast.
902 */
903 (in.s_addr == ia->ia_subnet ||
904 in.s_addr == ia->ia_net))))
905 return 1;
906 return (0);
907 #undef ia
908 }
909
910 /*
911 * Add an address to the list of IP multicast addresses for a given interface.
912 */
913 struct in_multi *
914 in_addmulti(ap, ifp)
915 register struct in_addr *ap;
916 register struct ifnet *ifp;
917 {
918 register struct in_multi *inm;
919 struct ifreq ifr;
920 struct in_ifaddr *ia;
921 int s = splsoftnet();
922
923 /*
924 * See if address already in list.
925 */
926 IN_LOOKUP_MULTI(*ap, ifp, inm);
927 if (inm != NULL) {
928 /*
929 * Found it; just increment the reference count.
930 */
931 ++inm->inm_refcount;
932 } else {
933 /*
934 * New address; allocate a new multicast record
935 * and link it into the interface's multicast list.
936 */
937 inm = (struct in_multi *)malloc(sizeof(*inm),
938 M_IPMADDR, M_NOWAIT);
939 if (inm == NULL) {
940 splx(s);
941 return (NULL);
942 }
943 inm->inm_addr = *ap;
944 inm->inm_ifp = ifp;
945 inm->inm_refcount = 1;
946 IFP_TO_IA(ifp, ia);
947 if (ia == NULL) {
948 free(inm, M_IPMADDR);
949 splx(s);
950 return (NULL);
951 }
952 inm->inm_ia = ia;
953 LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
954 /*
955 * Ask the network driver to update its multicast reception
956 * filter appropriately for the new address.
957 */
958 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
959 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
960 satosin(&ifr.ifr_addr)->sin_addr = *ap;
961 if ((ifp->if_ioctl == NULL) ||
962 (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
963 LIST_REMOVE(inm, inm_list);
964 free(inm, M_IPMADDR);
965 splx(s);
966 return (NULL);
967 }
968 /*
969 * Let IGMP know that we have joined a new IP multicast group.
970 */
971 igmp_joingroup(inm);
972 }
973 splx(s);
974 return (inm);
975 }
976
977 /*
978 * Delete a multicast address record.
979 */
980 void
981 in_delmulti(inm)
982 register struct in_multi *inm;
983 {
984 struct ifreq ifr;
985 int s = splsoftnet();
986
987 if (--inm->inm_refcount == 0) {
988 /*
989 * No remaining claims to this record; let IGMP know that
990 * we are leaving the multicast group.
991 */
992 igmp_leavegroup(inm);
993 /*
994 * Unlink from list.
995 */
996 LIST_REMOVE(inm, inm_list);
997 /*
998 * Notify the network driver to update its multicast reception
999 * filter.
1000 */
1001 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
1002 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
1003 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
1004 (caddr_t)&ifr);
1005 free(inm, M_IPMADDR);
1006 }
1007 splx(s);
1008 }
1009 #endif
1010