| 140 | } |
| 141 | |
| 142 | static int |
| 143 | scope6_set(struct ifnet *ifp, struct scope6_id *idlist) |
| 144 | { |
| 145 | int i; |
| 146 | int error = 0; |
| 147 | struct scope6_id *sid = NULL; |
| 148 | |
| 149 | IF_AFDATA_WLOCK(ifp); |
| 150 | sid = SID(ifp); |
| 151 | |
| 152 | if (!sid) { /* paranoid? */ |
| 153 | IF_AFDATA_WUNLOCK(ifp); |
| 154 | return (EINVAL); |
| 155 | } |
| 156 | |
| 157 | /* |
| 158 | * XXX: We need more consistency checks of the relationship among |
| 159 | * scopes (e.g. an organization should be larger than a site). |
| 160 | */ |
| 161 | |
| 162 | /* |
| 163 | * TODO(XXX): after setting, we should reflect the changes to |
| 164 | * interface addresses, routing table entries, PCB entries... |
| 165 | */ |
| 166 | |
| 167 | for (i = 0; i < 16; i++) { |
| 168 | if (idlist->s6id_list[i] && |
| 169 | idlist->s6id_list[i] != sid->s6id_list[i]) { |
| 170 | /* |
| 171 | * An interface zone ID must be the corresponding |
| 172 | * interface index by definition. |
| 173 | */ |
| 174 | if (i == IPV6_ADDR_SCOPE_INTFACELOCAL && |
| 175 | idlist->s6id_list[i] != ifp->if_index) { |
| 176 | IF_AFDATA_WUNLOCK(ifp); |
| 177 | return (EINVAL); |
| 178 | } |
| 179 | |
| 180 | if (i == IPV6_ADDR_SCOPE_LINKLOCAL && |
| 181 | idlist->s6id_list[i] > V_if_index) { |
| 182 | /* |
| 183 | * XXX: theoretically, there should be no |
| 184 | * relationship between link IDs and interface |
| 185 | * IDs, but we check the consistency for |
| 186 | * safety in later use. |
| 187 | */ |
| 188 | IF_AFDATA_WUNLOCK(ifp); |
| 189 | return (EINVAL); |
| 190 | } |
| 191 | |
| 192 | /* |
| 193 | * XXX: we must need lots of work in this case, |
| 194 | * but we simply set the new value in this initial |
| 195 | * implementation. |
| 196 | */ |
| 197 | sid->s6id_list[i] = idlist->s6id_list[i]; |
| 198 | } |
| 199 | } |