1 /* $OpenBSD: in.c,v 1.186 2024/01/06 10:58:45 bluhm Exp $ */
2 /* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
3
4 /*
5 * Copyright (C) 2001 WIDE Project. 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) 1982, 1986, 1991, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)in.c 8.2 (Berkeley) 11/15/93
61 */
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/ioctl.h>
66 #include <sys/malloc.h>
67 #include <sys/socket.h>
68 #include <sys/socketvar.h>
69
70 #include <net/if.h>
71 #include <net/if_var.h>
72 #include <net/route.h>
73
74 #include <netinet/in.h>
75 #include <netinet/in_var.h>
76 #include <netinet/igmp_var.h>
77
78 #ifdef MROUTING
79 #include <netinet/ip_mroute.h>
80 #endif
81
82 #include "ether.h"
83
84
85 void in_socktrim(struct sockaddr_in *);
86
87 int in_ioctl_set_ifaddr(u_long, caddr_t, struct ifnet *);
88 int in_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *);
89 int in_ioctl_get(u_long, caddr_t, struct ifnet *);
90 void in_purgeaddr(struct ifaddr *);
91 int in_addhost(struct in_ifaddr *, struct sockaddr_in *);
92 int in_scrubhost(struct in_ifaddr *, struct sockaddr_in *);
93 int in_insert_prefix(struct in_ifaddr *);
94 void in_remove_prefix(struct in_ifaddr *);
95
96 /*
97 * Determine whether an IP address is in a reserved set of addresses
98 * that may not be forwarded, or whether datagrams to that destination
99 * may be forwarded.
100 */
101 int
in_canforward(struct in_addr in)102 in_canforward(struct in_addr in)
103 {
104 u_int32_t net;
105
106 if (IN_MULTICAST(in.s_addr))
107 return (0);
108 if (IN_CLASSA(in.s_addr)) {
109 net = in.s_addr & IN_CLASSA_NET;
110 if (net == 0 ||
111 net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
112 return (0);
113 }
114 return (1);
115 }
116
117 /*
118 * Trim a mask in a sockaddr
119 */
120 void
in_socktrim(struct sockaddr_in * ap)121 in_socktrim(struct sockaddr_in *ap)
122 {
123 char *cplim = (char *) &ap->sin_addr;
124 char *cp = (char *) (&ap->sin_addr + 1);
125
126 ap->sin_len = 0;
127 while (--cp >= cplim)
128 if (*cp) {
129 (ap)->sin_len = cp - (char *) (ap) + 1;
130 break;
131 }
132 }
133
134 int
in_mask2len(struct in_addr * mask)135 in_mask2len(struct in_addr *mask)
136 {
137 int x, y;
138 u_char *p;
139
140 p = (u_char *)mask;
141 for (x = 0; x < sizeof(*mask); x++) {
142 if (p[x] != 0xff)
143 break;
144 }
145 y = 0;
146 if (x < sizeof(*mask)) {
147 for (y = 0; y < 8; y++) {
148 if ((p[x] & (0x80 >> y)) == 0)
149 break;
150 }
151 }
152 return x * 8 + y;
153 }
154
155 void
in_len2mask(struct in_addr * mask,int len)156 in_len2mask(struct in_addr *mask, int len)
157 {
158 int i;
159 u_char *p;
160
161 p = (u_char *)mask;
162 bzero(mask, sizeof(*mask));
163 for (i = 0; i < len / 8; i++)
164 p[i] = 0xff;
165 if (len % 8)
166 p[i] = (0xff00 >> (len % 8)) & 0xff;
167 }
168
169 int
in_nam2sin(const struct mbuf * nam,struct sockaddr_in ** sin)170 in_nam2sin(const struct mbuf *nam, struct sockaddr_in **sin)
171 {
172 struct sockaddr *sa = mtod(nam, struct sockaddr *);
173
174 if (nam->m_len < offsetof(struct sockaddr, sa_data))
175 return EINVAL;
176 if (sa->sa_family != AF_INET)
177 return EAFNOSUPPORT;
178 if (sa->sa_len != nam->m_len)
179 return EINVAL;
180 if (sa->sa_len != sizeof(struct sockaddr_in))
181 return EINVAL;
182 *sin = satosin(sa);
183
184 return 0;
185 }
186
187 int
in_sa2sin(struct sockaddr * sa,struct sockaddr_in ** sin)188 in_sa2sin(struct sockaddr *sa, struct sockaddr_in **sin)
189 {
190 if (sa->sa_family != AF_INET)
191 return EAFNOSUPPORT;
192 if (sa->sa_len != sizeof(struct sockaddr_in))
193 return EINVAL;
194 *sin = satosin(sa);
195
196 return 0;
197 }
198
199 int
in_control(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp)200 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
201 {
202 int privileged;
203
204 privileged = 0;
205 if ((so->so_state & SS_PRIV) != 0)
206 privileged++;
207
208 switch (cmd) {
209 #ifdef MROUTING
210 case SIOCGETVIFCNT:
211 case SIOCGETSGCNT:
212 return mrt_ioctl(so, cmd, data);
213 #endif /* MROUTING */
214 default:
215 return in_ioctl(cmd, data, ifp, privileged);
216 }
217 }
218
219 int
in_ioctl(u_long cmd,caddr_t data,struct ifnet * ifp,int privileged)220 in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged)
221 {
222 struct ifreq *ifr = (struct ifreq *)data;
223 struct ifaddr *ifa;
224 struct in_ifaddr *ia = NULL;
225 struct sockaddr_in *sin = NULL, oldaddr;
226 int error = 0;
227
228 if (ifp == NULL)
229 return (ENXIO);
230
231 switch (cmd) {
232 case SIOCGIFADDR:
233 case SIOCGIFNETMASK:
234 case SIOCGIFDSTADDR:
235 case SIOCGIFBRDADDR:
236 return in_ioctl_get(cmd, data, ifp);
237 case SIOCSIFADDR:
238 if (!privileged)
239 return (EPERM);
240 return in_ioctl_set_ifaddr(cmd, data, ifp);
241 case SIOCAIFADDR:
242 case SIOCDIFADDR:
243 if (!privileged)
244 return (EPERM);
245 return in_ioctl_change_ifaddr(cmd, data, ifp);
246 case SIOCSIFNETMASK:
247 case SIOCSIFDSTADDR:
248 case SIOCSIFBRDADDR:
249 break;
250 default:
251 return (EOPNOTSUPP);
252 }
253
254 if (!privileged)
255 return (EPERM);
256
257 if (ifr->ifr_addr.sa_family == AF_INET) {
258 error = in_sa2sin(&ifr->ifr_addr, &sin);
259 if (error)
260 return (error);
261 }
262
263 NET_LOCK();
264 KERNEL_LOCK();
265
266 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
267 if (ifa->ifa_addr->sa_family != AF_INET)
268 continue;
269 /* find first address or exact match */
270 if (ia == NULL)
271 ia = ifatoia(ifa);
272 if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY)
273 break;
274 if (ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
275 sin->sin_addr.s_addr) {
276 ia = ifatoia(ifa);
277 break;
278 }
279 }
280 if (ia == NULL) {
281 error = EADDRNOTAVAIL;
282 goto err;
283 }
284
285 switch (cmd) {
286 case SIOCSIFDSTADDR:
287 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
288 error = EINVAL;
289 break;
290 }
291 error = in_sa2sin(&ifr->ifr_dstaddr, &sin);
292 if (error)
293 break;
294 oldaddr = ia->ia_dstaddr;
295 ia->ia_dstaddr = *sin;
296 error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (caddr_t)ia);
297 if (error) {
298 ia->ia_dstaddr = oldaddr;
299 break;
300 }
301 in_scrubhost(ia, &oldaddr);
302 in_addhost(ia, &ia->ia_dstaddr);
303 break;
304
305 case SIOCSIFBRDADDR:
306 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
307 error = EINVAL;
308 break;
309 }
310 error = in_sa2sin(&ifr->ifr_broadaddr, &sin);
311 if (error)
312 break;
313 ifa_update_broadaddr(ifp, &ia->ia_ifa, sintosa(sin));
314 break;
315
316 case SIOCSIFNETMASK:
317 if (ifr->ifr_addr.sa_len < 8) {
318 error = EINVAL;
319 break;
320 }
321 /* do not check inet family or strict len */
322 sin = satosin(&ifr->ifr_addr);
323 if (ntohl(sin->sin_addr.s_addr) &
324 (~ntohl(sin->sin_addr.s_addr) >> 1)) {
325 /* non-contiguous netmask */
326 error = EINVAL;
327 break;
328 }
329 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
330 sin->sin_addr.s_addr;
331 break;
332 }
333 err:
334 KERNEL_UNLOCK();
335 NET_UNLOCK();
336 return (error);
337 }
338
339 int
in_ioctl_set_ifaddr(u_long cmd,caddr_t data,struct ifnet * ifp)340 in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
341 {
342 struct ifreq *ifr = (struct ifreq *)data;
343 struct ifaddr *ifa;
344 struct in_ifaddr *ia = NULL;
345 struct sockaddr_in *sin;
346 int error = 0;
347 int newifaddr;
348
349 if (cmd != SIOCSIFADDR)
350 panic("%s: invalid ioctl %lu", __func__, cmd);
351
352 error = in_sa2sin(&ifr->ifr_addr, &sin);
353 if (error)
354 return (error);
355
356 NET_LOCK();
357 KERNEL_LOCK();
358
359 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
360 if (ifa->ifa_addr->sa_family != AF_INET)
361 continue;
362 /* find first address */
363 ia = ifatoia(ifa);
364 break;
365 }
366 if (ia == NULL) {
367 ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
368 refcnt_init_trace(&ia->ia_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR);
369 ia->ia_addr.sin_family = AF_INET;
370 ia->ia_addr.sin_len = sizeof(ia->ia_addr);
371 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
372 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
373 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
374 ia->ia_sockmask.sin_len = 8;
375 if (ifp->if_flags & IFF_BROADCAST) {
376 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
377 ia->ia_broadaddr.sin_family = AF_INET;
378 }
379 ia->ia_ifp = ifp;
380
381 newifaddr = 1;
382 } else
383 newifaddr = 0;
384
385 in_ifscrub(ifp, ia);
386 error = in_ifinit(ifp, ia, sin, newifaddr);
387 if (!error)
388 if_addrhooks_run(ifp);
389
390 KERNEL_UNLOCK();
391 NET_UNLOCK();
392 return error;
393 }
394
395 int
in_ioctl_change_ifaddr(u_long cmd,caddr_t data,struct ifnet * ifp)396 in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
397 {
398 struct ifaddr *ifa;
399 struct in_ifaddr *ia = NULL;
400 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
401 struct sockaddr_in *sin = NULL, *dstsin = NULL, *broadsin = NULL;
402 struct sockaddr_in *masksin = NULL;
403 int error = 0;
404 int newifaddr;
405
406 if (ifra->ifra_addr.sin_family == AF_INET) {
407 error = in_sa2sin(sintosa(&ifra->ifra_addr), &sin);
408 if (error)
409 return (error);
410 }
411
412 NET_LOCK();
413 KERNEL_LOCK();
414
415 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
416 if (ifa->ifa_addr->sa_family != AF_INET)
417 continue;
418 /* find first address, if no exact match wanted */
419 if (sin == NULL || sin->sin_addr.s_addr ==
420 ifatoia(ifa)->ia_addr.sin_addr.s_addr) {
421 ia = ifatoia(ifa);
422 break;
423 }
424 }
425
426 switch (cmd) {
427 case SIOCAIFADDR: {
428 int needinit = 0;
429
430 if (ifra->ifra_mask.sin_len) {
431 if (ifra->ifra_mask.sin_len < 8) {
432 error = EINVAL;
433 break;
434 }
435 /* do not check inet family or strict len */
436 masksin = &ifra->ifra_mask;
437 if (ntohl(masksin->sin_addr.s_addr) &
438 (~ntohl(masksin->sin_addr.s_addr) >> 1)) {
439 /* non-contiguous netmask */
440 error = EINVAL;
441 break;
442 }
443 }
444 if ((ifp->if_flags & IFF_POINTOPOINT) &&
445 ifra->ifra_dstaddr.sin_family == AF_INET) {
446 error = in_sa2sin(sintosa(&ifra->ifra_dstaddr),
447 &dstsin);
448 if (error)
449 break;
450 }
451 if ((ifp->if_flags & IFF_BROADCAST) &&
452 ifra->ifra_broadaddr.sin_family == AF_INET) {
453 error = in_sa2sin(sintosa(&ifra->ifra_broadaddr),
454 &broadsin);
455 if (error)
456 break;
457 }
458
459 if (ia == NULL) {
460 ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
461 refcnt_init_trace(&ia->ia_ifa.ifa_refcnt,
462 DT_REFCNT_IDX_IFADDR);
463 ia->ia_addr.sin_family = AF_INET;
464 ia->ia_addr.sin_len = sizeof(ia->ia_addr);
465 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
466 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
467 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
468 ia->ia_sockmask.sin_len = 8;
469 if (ifp->if_flags & IFF_BROADCAST) {
470 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
471 ia->ia_broadaddr.sin_family = AF_INET;
472 }
473 ia->ia_ifp = ifp;
474
475 newifaddr = 1;
476 } else
477 newifaddr = 0;
478
479 if (sin == NULL) {
480 sin = &ia->ia_addr;
481 } else if (newifaddr ||
482 sin->sin_addr.s_addr != ia->ia_addr.sin_addr.s_addr) {
483 needinit = 1;
484 }
485 if (masksin != NULL) {
486 in_ifscrub(ifp, ia);
487 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
488 masksin->sin_addr.s_addr;
489 needinit = 1;
490 }
491 if (dstsin != NULL) {
492 in_ifscrub(ifp, ia);
493 ia->ia_dstaddr = *dstsin;
494 needinit = 1;
495 }
496 if (broadsin != NULL) {
497 if (newifaddr)
498 ia->ia_broadaddr = *broadsin;
499 else
500 ifa_update_broadaddr(ifp, &ia->ia_ifa,
501 sintosa(broadsin));
502 }
503 if (needinit) {
504 error = in_ifinit(ifp, ia, sin, newifaddr);
505 if (error)
506 break;
507 }
508 if_addrhooks_run(ifp);
509 break;
510 }
511 case SIOCDIFADDR:
512 if (ia == NULL) {
513 error = EADDRNOTAVAIL;
514 break;
515 }
516 /*
517 * Even if the individual steps were safe, shouldn't
518 * these kinds of changes happen atomically? What
519 * should happen to a packet that was routed after
520 * the scrub but before the other steps?
521 */
522 in_purgeaddr(&ia->ia_ifa);
523 if_addrhooks_run(ifp);
524 break;
525
526 default:
527 panic("%s: invalid ioctl %lu", __func__, cmd);
528 }
529
530 KERNEL_UNLOCK();
531 NET_UNLOCK();
532 return (error);
533 }
534
535 int
in_ioctl_get(u_long cmd,caddr_t data,struct ifnet * ifp)536 in_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp)
537 {
538 struct ifreq *ifr = (struct ifreq *)data;
539 struct ifaddr *ifa;
540 struct in_ifaddr *ia = NULL;
541 struct sockaddr *sa;
542 struct sockaddr_in *sin = NULL;
543 int error = 0;
544
545 sa = &ifr->ifr_addr;
546 if (sa->sa_family == AF_INET) {
547 sa->sa_len = sizeof(struct sockaddr_in);
548 error = in_sa2sin(sa, &sin);
549 if (error)
550 return (error);
551 }
552
553 NET_LOCK_SHARED();
554
555 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
556 if (ifa->ifa_addr->sa_family != AF_INET)
557 continue;
558 /* find first address or exact match */
559 if (ia == NULL)
560 ia = ifatoia(ifa);
561 if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY)
562 break;
563 if (ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
564 sin->sin_addr.s_addr) {
565 ia = ifatoia(ifa);
566 break;
567 }
568 }
569 if (ia == NULL) {
570 error = EADDRNOTAVAIL;
571 goto err;
572 }
573
574 switch(cmd) {
575 case SIOCGIFADDR:
576 *satosin(&ifr->ifr_addr) = ia->ia_addr;
577 break;
578
579 case SIOCGIFBRDADDR:
580 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
581 error = EINVAL;
582 break;
583 }
584 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
585 break;
586
587 case SIOCGIFDSTADDR:
588 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
589 error = EINVAL;
590 break;
591 }
592 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
593 break;
594
595 case SIOCGIFNETMASK:
596 *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
597 break;
598
599 default:
600 panic("%s: invalid ioctl %lu", __func__, cmd);
601 }
602
603 err:
604 NET_UNLOCK_SHARED();
605 return (error);
606 }
607
608 /*
609 * Delete any existing route for an interface.
610 */
611 void
in_ifscrub(struct ifnet * ifp,struct in_ifaddr * ia)612 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
613 {
614 if (ISSET(ifp->if_flags, IFF_POINTOPOINT))
615 in_scrubhost(ia, &ia->ia_dstaddr);
616 else if (!ISSET(ifp->if_flags, IFF_LOOPBACK))
617 in_remove_prefix(ia);
618 }
619
620 /*
621 * Initialize an interface's internet address
622 * and routing table entry.
623 */
624 int
in_ifinit(struct ifnet * ifp,struct in_ifaddr * ia,struct sockaddr_in * sin,int newaddr)625 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
626 int newaddr)
627 {
628 u_int32_t i = sin->sin_addr.s_addr;
629 struct sockaddr_in oldaddr;
630 int error = 0, rterror;
631
632 NET_ASSERT_LOCKED();
633
634 /*
635 * Always remove the address from the tree to make sure its
636 * position gets updated in case the key changes.
637 */
638 if (!newaddr) {
639 rt_ifa_dellocal(&ia->ia_ifa);
640 ifa_del(ifp, &ia->ia_ifa);
641 }
642 oldaddr = ia->ia_addr;
643 ia->ia_addr = *sin;
644
645 if (ia->ia_netmask == 0) {
646 if (IN_CLASSA(i))
647 ia->ia_netmask = IN_CLASSA_NET;
648 else if (IN_CLASSB(i))
649 ia->ia_netmask = IN_CLASSB_NET;
650 else
651 ia->ia_netmask = IN_CLASSC_NET;
652 ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask;
653 }
654
655 /*
656 * Give the interface a chance to initialize
657 * if this is its first address,
658 * and to validate the address if necessary.
659 */
660 if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
661 ia->ia_addr = oldaddr;
662 }
663
664 /*
665 * Add the address to the local list and the global tree. If an
666 * error occurred, put back the original address.
667 */
668 ifa_add(ifp, &ia->ia_ifa);
669 rterror = rt_ifa_addlocal(&ia->ia_ifa);
670
671 if (rterror) {
672 if (!newaddr)
673 ifa_del(ifp, &ia->ia_ifa);
674 if (!error)
675 error = rterror;
676 goto out;
677 }
678 if (error)
679 goto out;
680
681
682 ia->ia_net = i & ia->ia_netmask;
683 in_socktrim(&ia->ia_sockmask);
684 /*
685 * Add route for the network.
686 */
687 ia->ia_ifa.ifa_metric = ifp->if_metric;
688 if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
689 if (IN_RFC3021_SUBNET(ia->ia_netmask))
690 ia->ia_broadaddr.sin_addr.s_addr = 0;
691 else {
692 ia->ia_broadaddr.sin_addr.s_addr =
693 ia->ia_net | ~ia->ia_netmask;
694 }
695 }
696
697 if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) {
698 /* XXX We should not even call in_ifinit() in this case. */
699 if (ia->ia_dstaddr.sin_family != AF_INET)
700 goto out;
701 error = in_addhost(ia, &ia->ia_dstaddr);
702 } else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) {
703 error = in_insert_prefix(ia);
704 }
705
706 /*
707 * If the interface supports multicast, join the "all hosts"
708 * multicast group on that interface.
709 */
710 if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
711 struct in_addr addr;
712
713 addr.s_addr = INADDR_ALLHOSTS_GROUP;
714 ia->ia_allhosts = in_addmulti(&addr, ifp);
715 }
716
717 out:
718 if (error && newaddr)
719 in_purgeaddr(&ia->ia_ifa);
720
721 return (error);
722 }
723
724 void
in_purgeaddr(struct ifaddr * ifa)725 in_purgeaddr(struct ifaddr *ifa)
726 {
727 struct ifnet *ifp = ifa->ifa_ifp;
728 struct in_ifaddr *ia = ifatoia(ifa);
729
730 NET_ASSERT_LOCKED();
731
732 in_ifscrub(ifp, ia);
733
734 rt_ifa_dellocal(&ia->ia_ifa);
735 rt_ifa_purge(&ia->ia_ifa);
736 ifa_del(ifp, &ia->ia_ifa);
737
738 if (ia->ia_allhosts != NULL) {
739 in_delmulti(ia->ia_allhosts);
740 ia->ia_allhosts = NULL;
741 }
742
743 ia->ia_ifp = NULL;
744 ifafree(&ia->ia_ifa);
745 }
746
747 int
in_addhost(struct in_ifaddr * ia,struct sockaddr_in * dst)748 in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
749 {
750 return rt_ifa_add(&ia->ia_ifa, RTF_HOST | RTF_MPATH,
751 sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain);
752 }
753
754 int
in_scrubhost(struct in_ifaddr * ia,struct sockaddr_in * dst)755 in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
756 {
757 return rt_ifa_del(&ia->ia_ifa, RTF_HOST,
758 sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain);
759 }
760
761 /*
762 * Insert the cloning and broadcast routes for this subnet.
763 */
764 int
in_insert_prefix(struct in_ifaddr * ia)765 in_insert_prefix(struct in_ifaddr *ia)
766 {
767 struct ifaddr *ifa = &ia->ia_ifa;
768 int error;
769
770 error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED | RTF_MPATH,
771 ifa->ifa_addr, ifa->ifa_ifp->if_rdomain);
772 if (error)
773 return (error);
774
775 if (ia->ia_broadaddr.sin_addr.s_addr != 0) {
776 error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST | RTF_MPATH,
777 ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain);
778 }
779
780 return (error);
781 }
782
783 void
in_remove_prefix(struct in_ifaddr * ia)784 in_remove_prefix(struct in_ifaddr *ia)
785 {
786 struct ifaddr *ifa = &ia->ia_ifa;
787
788 rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED,
789 ifa->ifa_addr, ifa->ifa_ifp->if_rdomain);
790
791 if (ia->ia_broadaddr.sin_addr.s_addr != 0) {
792 rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST,
793 ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain);
794 }
795 }
796
797 /*
798 * Return 1 if the address is a local broadcast address.
799 */
800 int
in_broadcast(struct in_addr in,u_int rtableid)801 in_broadcast(struct in_addr in, u_int rtableid)
802 {
803 struct ifnet *ifn;
804 struct ifaddr *ifa;
805 u_int rdomain;
806
807 rdomain = rtable_l2(rtableid);
808
809 #define ia (ifatoia(ifa))
810 TAILQ_FOREACH(ifn, &ifnetlist, if_list) {
811 if (ifn->if_rdomain != rdomain)
812 continue;
813 if ((ifn->if_flags & IFF_BROADCAST) == 0)
814 continue;
815 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
816 if (ifa->ifa_addr->sa_family == AF_INET &&
817 in.s_addr != ia->ia_addr.sin_addr.s_addr &&
818 in.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
819 return 1;
820 }
821 return (0);
822 #undef ia
823 }
824
825 /*
826 * Add an address to the list of IP multicast addresses for a given interface.
827 */
828 struct in_multi *
in_addmulti(struct in_addr * ap,struct ifnet * ifp)829 in_addmulti(struct in_addr *ap, struct ifnet *ifp)
830 {
831 struct in_multi *inm;
832 struct ifreq ifr;
833
834 /*
835 * See if address already in list.
836 */
837 IN_LOOKUP_MULTI(*ap, ifp, inm);
838 if (inm != NULL) {
839 /*
840 * Found it; just increment the reference count.
841 */
842 refcnt_take(&inm->inm_refcnt);
843 } else {
844 /*
845 * New address; allocate a new multicast record
846 * and link it into the interface's multicast list.
847 */
848 inm = malloc(sizeof(*inm), M_IPMADDR, M_WAITOK | M_ZERO);
849 inm->inm_sin.sin_len = sizeof(struct sockaddr_in);
850 inm->inm_sin.sin_family = AF_INET;
851 inm->inm_sin.sin_addr = *ap;
852 refcnt_init_trace(&inm->inm_refcnt, DT_REFCNT_IDX_IFMADDR);
853 inm->inm_ifidx = ifp->if_index;
854 inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin);
855
856 /*
857 * Ask the network driver to update its multicast reception
858 * filter appropriately for the new address.
859 */
860 memset(&ifr, 0, sizeof(ifr));
861 memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin));
862 KERNEL_LOCK();
863 if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
864 KERNEL_UNLOCK();
865 free(inm, M_IPMADDR, sizeof(*inm));
866 return (NULL);
867 }
868 KERNEL_UNLOCK();
869
870 TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma,
871 ifma_list);
872
873 /*
874 * Let IGMP know that we have joined a new IP multicast group.
875 */
876 igmp_joingroup(inm, ifp);
877 }
878
879 return (inm);
880 }
881
882 /*
883 * Delete a multicast address record.
884 */
885 void
in_delmulti(struct in_multi * inm)886 in_delmulti(struct in_multi *inm)
887 {
888 struct ifreq ifr;
889 struct ifnet *ifp;
890
891 NET_ASSERT_LOCKED();
892
893 if (refcnt_rele(&inm->inm_refcnt) == 0)
894 return;
895
896 ifp = if_get(inm->inm_ifidx);
897 if (ifp != NULL) {
898 /*
899 * No remaining claims to this record; let IGMP know that
900 * we are leaving the multicast group.
901 */
902 igmp_leavegroup(inm, ifp);
903
904 /*
905 * Notify the network driver to update its multicast
906 * reception filter.
907 */
908 memset(&ifr, 0, sizeof(ifr));
909 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
910 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
911 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
912 KERNEL_LOCK();
913 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
914 KERNEL_UNLOCK();
915
916 TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma, ifma_list);
917 }
918 if_put(ifp);
919
920 free(inm, M_IPMADDR, sizeof(*inm));
921 }
922
923 /*
924 * Return 1 if the multicast group represented by ``ap'' has been
925 * joined by interface ``ifp'', 0 otherwise.
926 */
927 int
in_hasmulti(struct in_addr * ap,struct ifnet * ifp)928 in_hasmulti(struct in_addr *ap, struct ifnet *ifp)
929 {
930 struct in_multi *inm;
931 int joined;
932
933 IN_LOOKUP_MULTI(*ap, ifp, inm);
934 joined = (inm != NULL);
935
936 return (joined);
937 }
938
939 void
in_ifdetach(struct ifnet * ifp)940 in_ifdetach(struct ifnet *ifp)
941 {
942 struct ifaddr *ifa, *next;
943
944 /* nuke any of IPv4 addresses we have */
945 TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) {
946 if (ifa->ifa_addr->sa_family != AF_INET)
947 continue;
948 in_purgeaddr(ifa);
949 if_addrhooks_run(ifp);
950 }
951
952 if (ifp->if_xflags & IFXF_AUTOCONF4)
953 ifp->if_xflags &= ~IFXF_AUTOCONF4;
954 }
955
956 void
in_prefixlen2mask(struct in_addr * maskp,int plen)957 in_prefixlen2mask(struct in_addr *maskp, int plen)
958 {
959 if (plen == 0)
960 maskp->s_addr = 0;
961 else
962 maskp->s_addr = htonl(0xffffffff << (32 - plen));
963 }
964