This source file includes following definitions.
- in_localaddr
- in_canforward
- in_socktrim
- in_mask2len
- in_len2mask
- in_control
- in_lifaddr_ioctl
- in_ifscrub
- in_ifinit
- in_addprefix
- in_scrubprefix
- in_broadcast
- in_addmulti
- in_delmulti
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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/route.h>
72
73 #include "carp.h"
74 #if NCARP > 0
75 #include <net/if_types.h>
76 #endif
77
78 #include <netinet/in.h>
79 #include <netinet/in_var.h>
80 #include <netinet/igmp_var.h>
81
82 #ifdef MROUTING
83 #include <netinet/ip_mroute.h>
84 #endif
85
86 #include "ether.h"
87
88 #ifdef INET
89
90 int in_mask2len(struct in_addr *);
91 void in_len2mask(struct in_addr *, int);
92 int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
93 struct ifnet *);
94
95 int in_addprefix(struct in_ifaddr *, int);
96 int in_scrubprefix(struct in_ifaddr *);
97
98 #ifndef SUBNETSARELOCAL
99 #define SUBNETSARELOCAL 0
100 #endif
101
102 #ifndef HOSTZEROBROADCAST
103 #define HOSTZEROBROADCAST 1
104 #endif
105
106 int subnetsarelocal = SUBNETSARELOCAL;
107 int hostzeroisbroadcast = HOSTZEROBROADCAST;
108
109
110
111
112
113
114
115 int
116 in_localaddr(in)
117 struct in_addr in;
118 {
119 struct in_ifaddr *ia;
120
121 if (subnetsarelocal) {
122 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
123 if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
124 return (1);
125 } else {
126 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
127 if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
128 return (1);
129 }
130 return (0);
131 }
132
133
134
135
136
137
138 int
139 in_canforward(in)
140 struct in_addr in;
141 {
142 u_int32_t net;
143
144 if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
145 return (0);
146 if (IN_CLASSA(in.s_addr)) {
147 net = in.s_addr & IN_CLASSA_NET;
148 if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
149 return (0);
150 }
151 return (1);
152 }
153
154
155
156
157 void
158 in_socktrim(ap)
159 struct sockaddr_in *ap;
160 {
161 char *cplim = (char *) &ap->sin_addr;
162 char *cp = (char *) (&ap->sin_addr + 1);
163
164 ap->sin_len = 0;
165 while (--cp >= cplim)
166 if (*cp) {
167 (ap)->sin_len = cp - (char *) (ap) + 1;
168 break;
169 }
170 }
171
172 int
173 in_mask2len(mask)
174 struct in_addr *mask;
175 {
176 int x, y;
177 u_char *p;
178
179 p = (u_char *)mask;
180 for (x = 0; x < sizeof(*mask); x++) {
181 if (p[x] != 0xff)
182 break;
183 }
184 y = 0;
185 if (x < sizeof(*mask)) {
186 for (y = 0; y < 8; y++) {
187 if ((p[x] & (0x80 >> y)) == 0)
188 break;
189 }
190 }
191 return x * 8 + y;
192 }
193
194 void
195 in_len2mask(mask, len)
196 struct in_addr *mask;
197 int len;
198 {
199 int i;
200 u_char *p;
201
202 p = (u_char *)mask;
203 bzero(mask, sizeof(*mask));
204 for (i = 0; i < len / 8; i++)
205 p[i] = 0xff;
206 if (len % 8)
207 p[i] = (0xff00 >> (len % 8)) & 0xff;
208 }
209
210 int in_interfaces;
211
212
213
214
215
216
217 int
218 in_control(so, cmd, data, ifp)
219 struct socket *so;
220 u_long cmd;
221 caddr_t data;
222 struct ifnet *ifp;
223 {
224 struct ifreq *ifr = (struct ifreq *)data;
225 struct in_ifaddr *ia = 0;
226 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
227 struct sockaddr_in oldaddr;
228 int error, hostIsNew, maskIsNew;
229 int newifaddr;
230 int s;
231
232 switch (cmd) {
233 case SIOCALIFADDR:
234 case SIOCDLIFADDR:
235 if ((so->so_state & SS_PRIV) == 0)
236 return (EPERM);
237
238 case SIOCGLIFADDR:
239 if (!ifp)
240 return EINVAL;
241 return in_lifaddr_ioctl(so, cmd, data, ifp);
242 }
243
244
245
246
247 if (ifp)
248 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
249 if (ia->ia_ifp == ifp)
250 break;
251
252 switch (cmd) {
253
254 case SIOCAIFADDR:
255 case SIOCDIFADDR:
256 if (ifra->ifra_addr.sin_family == AF_INET)
257 for (; ia != TAILQ_END(&in_ifaddr);
258 ia = TAILQ_NEXT(ia, ia_list)) {
259 if (ia->ia_ifp == ifp &&
260 ia->ia_addr.sin_addr.s_addr ==
261 ifra->ifra_addr.sin_addr.s_addr)
262 break;
263 }
264 if (cmd == SIOCDIFADDR && ia == 0)
265 return (EADDRNOTAVAIL);
266
267 case SIOCSIFADDR:
268 case SIOCSIFNETMASK:
269 case SIOCSIFDSTADDR:
270 if ((so->so_state & SS_PRIV) == 0)
271 return (EPERM);
272
273 if (ifp == 0)
274 panic("in_control");
275 if (ia == (struct in_ifaddr *)0) {
276 ia = (struct in_ifaddr *)
277 malloc(sizeof *ia, M_IFADDR, M_WAITOK);
278 bzero((caddr_t)ia, sizeof *ia);
279 s = splsoftnet();
280 TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
281 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
282 ifa_list);
283 ia->ia_addr.sin_family = AF_INET;
284 ia->ia_addr.sin_len = sizeof(ia->ia_addr);
285 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
286 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
287 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
288 ia->ia_sockmask.sin_len = 8;
289 if (ifp->if_flags & IFF_BROADCAST) {
290 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
291 ia->ia_broadaddr.sin_family = AF_INET;
292 }
293 ia->ia_ifp = ifp;
294 LIST_INIT(&ia->ia_multiaddrs);
295 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
296 in_interfaces++;
297 splx(s);
298
299 newifaddr = 1;
300 } else
301 newifaddr = 0;
302 break;
303
304 case SIOCSIFBRDADDR:
305 if ((so->so_state & SS_PRIV) == 0)
306 return (EPERM);
307
308
309 case SIOCGIFADDR:
310 case SIOCGIFNETMASK:
311 case SIOCGIFDSTADDR:
312 case SIOCGIFBRDADDR:
313 if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
314 struct in_ifaddr *ia2;
315
316 for (ia2 = ia; ia2 != TAILQ_END(&in_ifaddr);
317 ia2 = TAILQ_NEXT(ia2, ia_list)) {
318 if (ia2->ia_ifp == ifp &&
319 ia2->ia_addr.sin_addr.s_addr ==
320 satosin(&ifr->ifr_addr)->sin_addr.s_addr)
321 break;
322 }
323 if (ia2 && ia2->ia_ifp == ifp)
324 ia = ia2;
325 }
326 if (ia == (struct in_ifaddr *)0)
327 return (EADDRNOTAVAIL);
328 break;
329 }
330 switch (cmd) {
331
332 case SIOCGIFADDR:
333 *satosin(&ifr->ifr_addr) = ia->ia_addr;
334 break;
335
336 case SIOCGIFBRDADDR:
337 if ((ifp->if_flags & IFF_BROADCAST) == 0)
338 return (EINVAL);
339 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
340 break;
341
342 case SIOCGIFDSTADDR:
343 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
344 return (EINVAL);
345 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
346 break;
347
348 case SIOCGIFNETMASK:
349 *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
350 break;
351
352 case SIOCSIFDSTADDR:
353 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
354 return (EINVAL);
355 s = splsoftnet();
356 oldaddr = ia->ia_dstaddr;
357 ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
358 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
359 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
360 ia->ia_dstaddr = oldaddr;
361 splx(s);
362 return (error);
363 }
364 if (ia->ia_flags & IFA_ROUTE) {
365 ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
366 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
367 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
368 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
369 }
370 splx(s);
371 break;
372
373 case SIOCSIFBRDADDR:
374 if ((ifp->if_flags & IFF_BROADCAST) == 0)
375 return (EINVAL);
376 ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
377 break;
378
379 case SIOCSIFADDR:
380 s = splsoftnet();
381 error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
382 if (!error)
383 dohooks(ifp->if_addrhooks, 0);
384 else if (newifaddr) {
385 splx(s);
386 goto cleanup;
387 }
388 splx(s);
389 return error;
390
391 case SIOCSIFNETMASK:
392 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
393 ifra->ifra_addr.sin_addr.s_addr;
394 break;
395
396 case SIOCAIFADDR:
397 maskIsNew = 0;
398 hostIsNew = 1;
399 error = 0;
400 s = splsoftnet();
401 if (ia->ia_addr.sin_family == AF_INET) {
402 if (ifra->ifra_addr.sin_len == 0) {
403 ifra->ifra_addr = ia->ia_addr;
404 hostIsNew = 0;
405 } else if (ifra->ifra_addr.sin_addr.s_addr ==
406 ia->ia_addr.sin_addr.s_addr)
407 hostIsNew = 0;
408 }
409 if (ifra->ifra_mask.sin_len) {
410 in_ifscrub(ifp, ia);
411 ia->ia_sockmask = ifra->ifra_mask;
412 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
413 maskIsNew = 1;
414 }
415 if ((ifp->if_flags & IFF_POINTOPOINT) &&
416 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
417 in_ifscrub(ifp, ia);
418 ia->ia_dstaddr = ifra->ifra_dstaddr;
419 maskIsNew = 1;
420 }
421 if (ifra->ifra_addr.sin_family == AF_INET &&
422 (hostIsNew || maskIsNew)) {
423 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
424 }
425 if ((ifp->if_flags & IFF_BROADCAST) &&
426 (ifra->ifra_broadaddr.sin_family == AF_INET))
427 ia->ia_broadaddr = ifra->ifra_broadaddr;
428 if (!error)
429 dohooks(ifp->if_addrhooks, 0);
430 else if (newifaddr) {
431 splx(s);
432 goto cleanup;
433 }
434 splx(s);
435 return (error);
436
437 case SIOCDIFADDR: {
438
439 error = 0;
440 cleanup:
441
442
443
444
445
446
447 s = splsoftnet();
448 in_ifscrub(ifp, ia);
449 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
450 TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
451 if (ia->ia_allhosts != NULL) {
452 in_delmulti(ia->ia_allhosts);
453 ia->ia_allhosts = NULL;
454 }
455 IFAFREE((&ia->ia_ifa));
456 dohooks(ifp->if_addrhooks, 0);
457 splx(s);
458 return (error);
459 }
460
461 #ifdef MROUTING
462 case SIOCGETVIFCNT:
463 case SIOCGETSGCNT:
464 return (mrt_ioctl(so, cmd, data));
465 #endif
466
467 default:
468 if (ifp == 0 || ifp->if_ioctl == 0)
469 return (EOPNOTSUPP);
470 return ((*ifp->if_ioctl)(ifp, cmd, data));
471 }
472 return (0);
473 }
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491 int
492 in_lifaddr_ioctl(so, cmd, data, ifp)
493 struct socket *so;
494 u_long cmd;
495 caddr_t data;
496 struct ifnet *ifp;
497 {
498 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
499 struct ifaddr *ifa;
500 struct sockaddr *sa;
501
502
503 if (!data || !ifp) {
504 panic("invalid argument to in_lifaddr_ioctl");
505
506 }
507
508 switch (cmd) {
509 case SIOCGLIFADDR:
510
511 if ((iflr->flags & IFLR_PREFIX) == 0)
512 break;
513
514 case SIOCALIFADDR:
515 case SIOCDLIFADDR:
516
517 sa = (struct sockaddr *)&iflr->addr;
518 if (sa->sa_family != AF_INET)
519 return EINVAL;
520 if (sa->sa_len != sizeof(struct sockaddr_in))
521 return EINVAL;
522
523 sa = (struct sockaddr *)&iflr->dstaddr;
524 if (sa->sa_family
525 && sa->sa_family != AF_INET)
526 return EINVAL;
527 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
528 return EINVAL;
529 break;
530 default:
531 #if 0
532 panic("invalid cmd to in_lifaddr_ioctl");
533
534 #else
535 return EOPNOTSUPP;
536 #endif
537 }
538 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
539 return EINVAL;
540
541 switch (cmd) {
542 case SIOCALIFADDR:
543 {
544 struct in_aliasreq ifra;
545
546 if (iflr->flags & IFLR_PREFIX)
547 return EINVAL;
548
549
550 bzero(&ifra, sizeof(ifra));
551 bcopy(iflr->iflr_name, ifra.ifra_name,
552 sizeof(ifra.ifra_name));
553
554 bcopy(&iflr->addr, &ifra.ifra_addr,
555 ((struct sockaddr *)&iflr->addr)->sa_len);
556
557 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {
558 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
559 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
560 }
561
562 ifra.ifra_mask.sin_family = AF_INET;
563 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
564 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
565
566 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp);
567 }
568 case SIOCGLIFADDR:
569 case SIOCDLIFADDR:
570 {
571 struct in_ifaddr *ia;
572 struct in_addr mask, candidate, match;
573 struct sockaddr_in *sin;
574 int cmp;
575
576 bzero(&mask, sizeof(mask));
577 if (iflr->flags & IFLR_PREFIX) {
578
579 in_len2mask(&mask, iflr->prefixlen);
580
581 sin = (struct sockaddr_in *)&iflr->addr;
582 match.s_addr = sin->sin_addr.s_addr;
583 match.s_addr &= mask.s_addr;
584
585
586 if (match.s_addr != sin->sin_addr.s_addr)
587 return EINVAL;
588
589 cmp = 1;
590 } else {
591 if (cmd == SIOCGLIFADDR) {
592
593 cmp = 0;
594 } else {
595
596 in_len2mask(&mask, 32);
597 sin = (struct sockaddr_in *)&iflr->addr;
598 match.s_addr = sin->sin_addr.s_addr;
599
600 cmp = 1;
601 }
602 }
603
604 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
605 if (ifa->ifa_addr->sa_family != AF_INET)
606 continue;
607 if (!cmp)
608 break;
609 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
610 candidate.s_addr &= mask.s_addr;
611 if (candidate.s_addr == match.s_addr)
612 break;
613 }
614 if (!ifa)
615 return EADDRNOTAVAIL;
616 ia = (struct in_ifaddr *)ifa;
617
618 if (cmd == SIOCGLIFADDR) {
619
620 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
621
622 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
623 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
624 ia->ia_dstaddr.sin_len);
625 } else
626 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
627
628 iflr->prefixlen =
629 in_mask2len(&ia->ia_sockmask.sin_addr);
630
631 iflr->flags = 0;
632
633 return 0;
634 } else {
635 struct in_aliasreq ifra;
636
637
638 bzero(&ifra, sizeof(ifra));
639 bcopy(iflr->iflr_name, ifra.ifra_name,
640 sizeof(ifra.ifra_name));
641
642 bcopy(&ia->ia_addr, &ifra.ifra_addr,
643 ia->ia_addr.sin_len);
644 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
645 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
646 ia->ia_dstaddr.sin_len);
647 }
648 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
649 ia->ia_sockmask.sin_len);
650
651 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp);
652 }
653 }
654 }
655
656 return EOPNOTSUPP;
657 }
658
659
660
661
662 void
663 in_ifscrub(ifp, ia)
664 struct ifnet *ifp;
665 struct in_ifaddr *ia;
666 {
667 in_scrubprefix(ia);
668 }
669
670
671
672
673
674 int
675 in_ifinit(ifp, ia, sin, scrub)
676 struct ifnet *ifp;
677 struct in_ifaddr *ia;
678 struct sockaddr_in *sin;
679 int scrub;
680 {
681 u_int32_t i = sin->sin_addr.s_addr;
682 struct sockaddr_in oldaddr;
683 int s = splnet(), flags = RTF_UP, error;
684
685 oldaddr = ia->ia_addr;
686 ia->ia_addr = *sin;
687
688
689
690
691
692 if (ifp->if_ioctl &&
693 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
694 ia->ia_addr = oldaddr;
695 splx(s);
696 return (error);
697 }
698 splx(s);
699
700
701
702
703
704
705
706 splassert(IPL_SOFTNET);
707
708 if (scrub) {
709 ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
710 in_ifscrub(ifp, ia);
711 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
712 }
713 if (IN_CLASSA(i))
714 ia->ia_netmask = IN_CLASSA_NET;
715 else if (IN_CLASSB(i))
716 ia->ia_netmask = IN_CLASSB_NET;
717 else
718 ia->ia_netmask = IN_CLASSC_NET;
719
720
721
722
723
724 if (ia->ia_subnetmask == 0) {
725 ia->ia_subnetmask = ia->ia_netmask;
726 ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
727 } else
728 ia->ia_netmask &= ia->ia_subnetmask;
729 ia->ia_net = i & ia->ia_netmask;
730 ia->ia_subnet = i & ia->ia_subnetmask;
731 in_socktrim(&ia->ia_sockmask);
732
733
734
735 ia->ia_ifa.ifa_metric = ifp->if_metric;
736 if (ifp->if_flags & IFF_BROADCAST) {
737 ia->ia_broadaddr.sin_addr.s_addr =
738 ia->ia_subnet | ~ia->ia_subnetmask;
739 ia->ia_netbroadcast.s_addr =
740 ia->ia_net | ~ia->ia_netmask;
741 } else if (ifp->if_flags & IFF_LOOPBACK) {
742 ia->ia_dstaddr = ia->ia_addr;
743 flags |= RTF_HOST;
744 } else if (ifp->if_flags & IFF_POINTOPOINT) {
745 if (ia->ia_dstaddr.sin_family != AF_INET)
746 return (0);
747 flags |= RTF_HOST;
748 }
749 error = in_addprefix(ia, flags);
750
751
752
753
754 if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
755 struct in_addr addr;
756
757 addr.s_addr = INADDR_ALLHOSTS_GROUP;
758 ia->ia_allhosts = in_addmulti(&addr, ifp);
759 }
760 return (error);
761 }
762
763 #define rtinitflags(x) \
764 ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
765 ? RTF_HOST : 0)
766
767
768
769
770
771 int
772 in_addprefix(target, flags)
773 struct in_ifaddr *target;
774 int flags;
775 {
776 struct in_ifaddr *ia;
777 struct in_addr prefix, mask, p;
778 int error;
779
780 if ((flags & RTF_HOST) != 0)
781 prefix = target->ia_dstaddr.sin_addr;
782 else {
783 prefix = target->ia_addr.sin_addr;
784 mask = target->ia_sockmask.sin_addr;
785 prefix.s_addr &= mask.s_addr;
786 }
787
788 TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
789 if (rtinitflags(ia)) {
790 p = ia->ia_dstaddr.sin_addr;
791 if (prefix.s_addr != p.s_addr)
792 continue;
793 } else {
794 p = ia->ia_addr.sin_addr;
795 p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
796 if (prefix.s_addr != p.s_addr ||
797 mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
798 continue;
799 }
800 if ((ia->ia_flags & IFA_ROUTE) == 0)
801 continue;
802 #if NCARP > 0
803
804 if (ia->ia_ifp->if_type == IFT_CARP &&
805 target->ia_ifp->if_type != IFT_CARP) {
806 rtinit(&(ia->ia_ifa), (int)RTM_DELETE,
807 rtinitflags(ia));
808 ia->ia_flags &= ~IFA_ROUTE;
809 break;
810 }
811 #endif
812
813
814
815
816 return 0;
817 }
818
819
820
821
822 error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
823 if (!error)
824 target->ia_flags |= IFA_ROUTE;
825 return error;
826 }
827
828
829
830
831
832
833 int
834 in_scrubprefix(target)
835 struct in_ifaddr *target;
836 {
837 struct in_ifaddr *ia;
838 struct in_addr prefix, mask, p;
839 int error;
840
841 if ((target->ia_flags & IFA_ROUTE) == 0)
842 return 0;
843
844 if (rtinitflags(target))
845 prefix = target->ia_dstaddr.sin_addr;
846 else {
847 prefix = target->ia_addr.sin_addr;
848 mask = target->ia_sockmask.sin_addr;
849 prefix.s_addr &= mask.s_addr;
850 }
851
852 TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
853 if (rtinitflags(ia))
854 p = ia->ia_dstaddr.sin_addr;
855 else {
856 p = ia->ia_addr.sin_addr;
857 p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
858 }
859
860 if (prefix.s_addr != p.s_addr)
861 continue;
862
863
864
865
866 if ((ia->ia_flags & IFA_ROUTE) == 0) {
867 rtinit(&(target->ia_ifa), (int)RTM_DELETE,
868 rtinitflags(target));
869 target->ia_flags &= ~IFA_ROUTE;
870
871 error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
872 rtinitflags(ia) | RTF_UP);
873 if (error == 0)
874 ia->ia_flags |= IFA_ROUTE;
875 return error;
876 }
877 }
878
879
880
881
882 rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
883 target->ia_flags &= ~IFA_ROUTE;
884 return 0;
885 }
886
887 #undef rtinitflags
888
889
890
891
892 int
893 in_broadcast(in, ifp)
894 struct in_addr in;
895 struct ifnet *ifp;
896 {
897 struct ifnet *ifn, *if_first, *if_target;
898 struct ifaddr *ifa;
899
900 if (in.s_addr == INADDR_BROADCAST ||
901 in.s_addr == INADDR_ANY)
902 return 1;
903
904 if (ifp == NULL) {
905 if_first = TAILQ_FIRST(&ifnet);
906 if_target = 0;
907 } else {
908 if_first = ifp;
909 if_target = TAILQ_NEXT(ifp, if_list);
910 }
911
912 #define ia (ifatoia(ifa))
913
914
915
916
917
918 for (ifn = if_first; ifn != if_target; ifn = TAILQ_NEXT(ifn, if_list)) {
919 if ((ifn->if_flags & IFF_BROADCAST) == 0)
920 continue;
921 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
922 if (ifa->ifa_addr->sa_family == AF_INET &&
923 in.s_addr != ia->ia_addr.sin_addr.s_addr &&
924 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
925 in.s_addr == ia->ia_netbroadcast.s_addr ||
926 (hostzeroisbroadcast &&
927
928
929
930 (in.s_addr == ia->ia_subnet ||
931 in.s_addr == ia->ia_net))))
932 return 1;
933 }
934 return (0);
935 #undef ia
936 }
937
938
939
940
941 struct in_multi *
942 in_addmulti(ap, ifp)
943 struct in_addr *ap;
944 struct ifnet *ifp;
945 {
946 struct in_multi *inm;
947 struct ifreq ifr;
948 struct in_ifaddr *ia;
949 int s = splsoftnet();
950
951
952
953
954 IN_LOOKUP_MULTI(*ap, ifp, inm);
955 if (inm != NULL) {
956
957
958
959 ++inm->inm_refcount;
960 } else {
961
962
963
964
965 inm = (struct in_multi *)malloc(sizeof(*inm),
966 M_IPMADDR, M_NOWAIT);
967 if (inm == NULL) {
968 splx(s);
969 return (NULL);
970 }
971 inm->inm_addr = *ap;
972 inm->inm_refcount = 1;
973 IFP_TO_IA(ifp, ia);
974 if (ia == NULL) {
975 free(inm, M_IPMADDR);
976 splx(s);
977 return (NULL);
978 }
979 inm->inm_ia = ia;
980 ia->ia_ifa.ifa_refcnt++;
981 LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
982
983
984
985
986 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
987 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
988 satosin(&ifr.ifr_addr)->sin_addr = *ap;
989 if ((ifp->if_ioctl == NULL) ||
990 (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
991 LIST_REMOVE(inm, inm_list);
992 IFAFREE(&inm->inm_ia->ia_ifa);
993 free(inm, M_IPMADDR);
994 splx(s);
995 return (NULL);
996 }
997
998
999
1000 igmp_joingroup(inm);
1001 }
1002 splx(s);
1003 return (inm);
1004 }
1005
1006
1007
1008
1009 void
1010 in_delmulti(inm)
1011 struct in_multi *inm;
1012 {
1013 struct ifreq ifr;
1014 struct ifnet *ifp;
1015 int s = splsoftnet();
1016
1017 if (--inm->inm_refcount == 0) {
1018
1019
1020
1021
1022 igmp_leavegroup(inm);
1023
1024
1025
1026 LIST_REMOVE(inm, inm_list);
1027 ifp = inm->inm_ia->ia_ifp;
1028 IFAFREE(&inm->inm_ia->ia_ifa);
1029
1030 if (ifp) {
1031
1032
1033
1034
1035 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
1036 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
1037 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
1038 }
1039 free(inm, M_IPMADDR);
1040 }
1041 splx(s);
1042 }
1043
1044 #endif