| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: in.c,v 1.184 2016/09/29 15:04:17 roy Exp $ */ | | 1 | /* $NetBSD: in.c,v 1.185 2016/09/29 15:18:18 roy Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -81,27 +81,27 @@ | | | @@ -81,27 +81,27 @@ |
81 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 81 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
82 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 82 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
83 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 83 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
84 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 84 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
85 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 85 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
86 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 86 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
87 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 87 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
88 | * SUCH DAMAGE. | | 88 | * SUCH DAMAGE. |
89 | * | | 89 | * |
90 | * @(#)in.c 8.4 (Berkeley) 1/9/95 | | 90 | * @(#)in.c 8.4 (Berkeley) 1/9/95 |
91 | */ | | 91 | */ |
92 | | | 92 | |
93 | #include <sys/cdefs.h> | | 93 | #include <sys/cdefs.h> |
94 | __KERNEL_RCSID(0, "$NetBSD: in.c,v 1.184 2016/09/29 15:04:17 roy Exp $"); | | 94 | __KERNEL_RCSID(0, "$NetBSD: in.c,v 1.185 2016/09/29 15:18:18 roy Exp $"); |
95 | | | 95 | |
96 | #include "arp.h" | | 96 | #include "arp.h" |
97 | | | 97 | |
98 | #ifdef _KERNEL_OPT | | 98 | #ifdef _KERNEL_OPT |
99 | #include "opt_inet.h" | | 99 | #include "opt_inet.h" |
100 | #include "opt_inet_conf.h" | | 100 | #include "opt_inet_conf.h" |
101 | #include "opt_mrouting.h" | | 101 | #include "opt_mrouting.h" |
102 | #endif | | 102 | #endif |
103 | | | 103 | |
104 | #include <sys/param.h> | | 104 | #include <sys/param.h> |
105 | #include <sys/ioctl.h> | | 105 | #include <sys/ioctl.h> |
106 | #include <sys/errno.h> | | 106 | #include <sys/errno.h> |
107 | #include <sys/kernel.h> | | 107 | #include <sys/kernel.h> |
| @@ -598,56 +598,49 @@ in_control0(struct socket *so, u_long cm | | | @@ -598,56 +598,49 @@ in_control0(struct socket *so, u_long cm |
598 | mutex_enter(&in_ifaddr_lock); | | 598 | mutex_enter(&in_ifaddr_lock); |
599 | LIST_REMOVE(ia, ia_hash); | | 599 | LIST_REMOVE(ia, ia_hash); |
600 | IN_ADDRHASH_WRITER_REMOVE(ia); | | 600 | IN_ADDRHASH_WRITER_REMOVE(ia); |
601 | mutex_exit(&in_ifaddr_lock); | | 601 | mutex_exit(&in_ifaddr_lock); |
602 | need_reinsert = true; | | 602 | need_reinsert = true; |
603 | } | | 603 | } |
604 | error = in_ifinit(ifp, ia, satocsin(ifreq_getaddr(cmd, ifr)), | | 604 | error = in_ifinit(ifp, ia, satocsin(ifreq_getaddr(cmd, ifr)), |
605 | NULL, 1); | | 605 | NULL, 1); |
606 | | | 606 | |
607 | run_hook = true; | | 607 | run_hook = true; |
608 | break; | | 608 | break; |
609 | | | 609 | |
610 | case SIOCSIFNETMASK: | | 610 | case SIOCSIFNETMASK: |
611 | in_ifscrub(ifp, ia); | | 611 | in_scrubprefix(ia); |
612 | ia->ia_sockmask = *satocsin(ifreq_getaddr(cmd, ifr)); | | 612 | ia->ia_sockmask = *satocsin(ifreq_getaddr(cmd, ifr)); |
613 | ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr; | | 613 | ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr; |
614 | if (!newifaddr) { | | 614 | if (!newifaddr) { |
615 | mutex_enter(&in_ifaddr_lock); | | 615 | mutex_enter(&in_ifaddr_lock); |
616 | LIST_REMOVE(ia, ia_hash); | | 616 | LIST_REMOVE(ia, ia_hash); |
617 | IN_ADDRHASH_WRITER_REMOVE(ia); | | 617 | IN_ADDRHASH_WRITER_REMOVE(ia); |
618 | mutex_exit(&in_ifaddr_lock); | | 618 | mutex_exit(&in_ifaddr_lock); |
619 | need_reinsert = true; | | 619 | need_reinsert = true; |
620 | } | | 620 | } |
621 | error = in_ifinit(ifp, ia, NULL, NULL, 0); | | 621 | error = in_ifinit(ifp, ia, NULL, NULL, 0); |
622 | break; | | 622 | break; |
623 | | | 623 | |
624 | case SIOCAIFADDR: | | 624 | case SIOCAIFADDR: |
625 | maskIsNew = 0; | | 625 | maskIsNew = 0; |
626 | if (ifra->ifra_mask.sin_len) { | | 626 | if (ifra->ifra_mask.sin_len) { |
627 | /* Only scrub if we control the prefix route, | | 627 | in_scrubprefix(ia); |
628 | * otherwise userland gets a bogus message */ | | | |
629 | if ((ia->ia_flags & IFA_ROUTE)) | | | |
630 | in_ifscrub(ifp, ia); | | | |
631 | ia->ia_sockmask = ifra->ifra_mask; | | 628 | ia->ia_sockmask = ifra->ifra_mask; |
632 | ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr; | | 629 | ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr; |
633 | maskIsNew = 1; | | 630 | maskIsNew = 1; |
634 | } | | 631 | } |
635 | if ((ifp->if_flags & IFF_POINTOPOINT) && | | 632 | if ((ifp->if_flags & IFF_POINTOPOINT) && |
636 | (ifra->ifra_dstaddr.sin_family == AF_INET)) { | | 633 | (ifra->ifra_dstaddr.sin_family == AF_INET)) { |
637 | /* Only scrub if we control the prefix route, | | | |
638 | * otherwise userland gets a bogus message */ | | | |
639 | if ((ia->ia_flags & IFA_ROUTE)) | | | |
640 | in_ifscrub(ifp, ia); | | | |
641 | new_dstaddr = &ifra->ifra_dstaddr; | | 634 | new_dstaddr = &ifra->ifra_dstaddr; |
642 | maskIsNew = 1; /* We lie; but the effect's the same */ | | 635 | maskIsNew = 1; /* We lie; but the effect's the same */ |
643 | } else | | 636 | } else |
644 | new_dstaddr = NULL; | | 637 | new_dstaddr = NULL; |
645 | if (ifra->ifra_addr.sin_family == AF_INET && | | 638 | if (ifra->ifra_addr.sin_family == AF_INET && |
646 | (hostIsNew || maskIsNew)) { | | 639 | (hostIsNew || maskIsNew)) { |
647 | if (!newifaddr) { | | 640 | if (!newifaddr) { |
648 | mutex_enter(&in_ifaddr_lock); | | 641 | mutex_enter(&in_ifaddr_lock); |
649 | LIST_REMOVE(ia, ia_hash); | | 642 | LIST_REMOVE(ia, ia_hash); |
650 | IN_ADDRHASH_WRITER_REMOVE(ia); | | 643 | IN_ADDRHASH_WRITER_REMOVE(ia); |
651 | mutex_exit(&in_ifaddr_lock); | | 644 | mutex_exit(&in_ifaddr_lock); |
652 | need_reinsert = true; | | 645 | need_reinsert = true; |
653 | } | | 646 | } |
| @@ -801,28 +794,29 @@ in_ifremlocal(struct ifaddr *ifa) | | | @@ -801,28 +794,29 @@ in_ifremlocal(struct ifaddr *ifa) |
801 | ifa_release(alt_ifa, &psref); | | 794 | ifa_release(alt_ifa, &psref); |
802 | out: | | 795 | out: |
803 | curlwp_bindx(bound); | | 796 | curlwp_bindx(bound); |
804 | } | | 797 | } |
805 | | | 798 | |
806 | static void | | 799 | static void |
807 | in_scrubaddr(struct in_ifaddr *ia) | | 800 | in_scrubaddr(struct in_ifaddr *ia) |
808 | { | | 801 | { |
809 | | | 802 | |
810 | /* stop DAD processing */ | | 803 | /* stop DAD processing */ |
811 | if (ia->ia_dad_stop != NULL) | | 804 | if (ia->ia_dad_stop != NULL) |
812 | ia->ia_dad_stop(&ia->ia_ifa); | | 805 | ia->ia_dad_stop(&ia->ia_ifa); |
813 | | | 806 | |
814 | in_ifscrub(ia->ia_ifp, ia); | | 807 | in_scrubprefix(ia); |
815 | in_ifremlocal(&ia->ia_ifa); | | 808 | in_ifremlocal(&ia->ia_ifa); |
| | | 809 | |
816 | if (ia->ia_allhosts != NULL) { | | 810 | if (ia->ia_allhosts != NULL) { |
817 | in_delmulti(ia->ia_allhosts); | | 811 | in_delmulti(ia->ia_allhosts); |
818 | ia->ia_allhosts = NULL; | | 812 | ia->ia_allhosts = NULL; |
819 | } | | 813 | } |
820 | } | | 814 | } |
821 | | | 815 | |
822 | /* | | 816 | /* |
823 | * Depends on it isn't called in concurrent. It should be guaranteed | | 817 | * Depends on it isn't called in concurrent. It should be guaranteed |
824 | * by ifa->ifa_ifp's ioctl lock. The possible callers are in_control | | 818 | * by ifa->ifa_ifp's ioctl lock. The possible callers are in_control |
825 | * and if_purgeaddrs; the former is called iva ifa->ifa_ifp's ioctl | | 819 | * and if_purgeaddrs; the former is called iva ifa->ifa_ifp's ioctl |
826 | * and the latter is called via ifa->ifa_ifp's if_detach. The functions | | 820 | * and the latter is called via ifa->ifa_ifp's if_detach. The functions |
827 | * never be executed in concurrent. | | 821 | * never be executed in concurrent. |
828 | */ | | 822 | */ |
| @@ -1037,36 +1031,26 @@ in_lifaddr_ioctl(struct socket *so, u_lo | | | @@ -1037,36 +1031,26 @@ in_lifaddr_ioctl(struct socket *so, u_lo |
1037 | memcpy(&ifra.ifra_dstaddr, &ia->ia_sockmask, | | 1031 | memcpy(&ifra.ifra_dstaddr, &ia->ia_sockmask, |
1038 | ia->ia_sockmask.sin_len); | | 1032 | ia->ia_sockmask.sin_len); |
1039 | pserialize_read_exit(s); | | 1033 | pserialize_read_exit(s); |
1040 | | | 1034 | |
1041 | return in_control(so, SIOCDIFADDR, &ifra, ifp); | | 1035 | return in_control(so, SIOCDIFADDR, &ifra, ifp); |
1042 | } | | 1036 | } |
1043 | } | | 1037 | } |
1044 | } | | 1038 | } |
1045 | | | 1039 | |
1046 | return EOPNOTSUPP; /*just for safety*/ | | 1040 | return EOPNOTSUPP; /*just for safety*/ |
1047 | } | | 1041 | } |
1048 | | | 1042 | |
1049 | /* | | 1043 | /* |
1050 | * Delete any existing route for an interface. | | | |
1051 | */ | | | |
1052 | void | | | |
1053 | in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia) | | | |
1054 | { | | | |
1055 | | | | |
1056 | in_scrubprefix(ia); | | | |
1057 | } | | | |
1058 | | | | |
1059 | /* | | | |
1060 | * Initialize an interface's internet address | | 1044 | * Initialize an interface's internet address |
1061 | * and routing table entry. | | 1045 | * and routing table entry. |
1062 | */ | | 1046 | */ |
1063 | int | | 1047 | int |
1064 | in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, | | 1048 | in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, |
1065 | const struct sockaddr_in *sin, const struct sockaddr_in *dst, int scrub) | | 1049 | const struct sockaddr_in *sin, const struct sockaddr_in *dst, int scrub) |
1066 | { | | 1050 | { |
1067 | u_int32_t i; | | 1051 | u_int32_t i; |
1068 | struct sockaddr_in oldaddr, olddst; | | 1052 | struct sockaddr_in oldaddr, olddst; |
1069 | int s, oldflags, flags = RTF_UP, error, hostIsNew; | | 1053 | int s, oldflags, flags = RTF_UP, error, hostIsNew; |
1070 | | | 1054 | |
1071 | if (sin == NULL) | | 1055 | if (sin == NULL) |
1072 | sin = &ia->ia_addr; | | 1056 | sin = &ia->ia_addr; |
| @@ -1118,27 +1102,27 @@ in_ifinit(struct ifnet *ifp, struct in_i | | | @@ -1118,27 +1102,27 @@ in_ifinit(struct ifnet *ifp, struct in_i |
1118 | ia->ia4_flags = oldflags; | | 1102 | ia->ia4_flags = oldflags; |
1119 | return error; | | 1103 | return error; |
1120 | } | | 1104 | } |
1121 | | | 1105 | |
1122 | if (scrub || hostIsNew) { | | 1106 | if (scrub || hostIsNew) { |
1123 | int newflags = ia->ia4_flags; | | 1107 | int newflags = ia->ia4_flags; |
1124 | | | 1108 | |
1125 | ia->ia_ifa.ifa_addr = sintosa(&oldaddr); | | 1109 | ia->ia_ifa.ifa_addr = sintosa(&oldaddr); |
1126 | ia->ia_ifa.ifa_dstaddr = sintosa(&olddst); | | 1110 | ia->ia_ifa.ifa_dstaddr = sintosa(&olddst); |
1127 | ia->ia4_flags = oldflags; | | 1111 | ia->ia4_flags = oldflags; |
1128 | if (hostIsNew) | | 1112 | if (hostIsNew) |
1129 | in_scrubaddr(ia); | | 1113 | in_scrubaddr(ia); |
1130 | else if (scrub) | | 1114 | else if (scrub) |
1131 | in_ifscrub(ifp, ia); | | 1115 | in_scrubprefix(ia); |
1132 | ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); | | 1116 | ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); |
1133 | ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); | | 1117 | ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); |
1134 | ia->ia4_flags = newflags; | | 1118 | ia->ia4_flags = newflags; |
1135 | } | | 1119 | } |
1136 | | | 1120 | |
1137 | /* Add the local route to the address */ | | 1121 | /* Add the local route to the address */ |
1138 | in_ifaddlocal(&ia->ia_ifa); | | 1122 | in_ifaddlocal(&ia->ia_ifa); |
1139 | | | 1123 | |
1140 | i = ia->ia_addr.sin_addr.s_addr; | | 1124 | i = ia->ia_addr.sin_addr.s_addr; |
1141 | if (IN_CLASSA(i)) | | 1125 | if (IN_CLASSA(i)) |
1142 | ia->ia_netmask = IN_CLASSA_NET; | | 1126 | ia->ia_netmask = IN_CLASSA_NET; |
1143 | else if (IN_CLASSB(i)) | | 1127 | else if (IN_CLASSB(i)) |
1144 | ia->ia_netmask = IN_CLASSB_NET; | | 1128 | ia->ia_netmask = IN_CLASSB_NET; |