* Validate the specified scope zone ID in the sin6_scope_id field. If the ID * is unspecified (=0), needs to be specified, and the default zone ID can be * used, the default value will be used. * This routine then generates the kernel-internal form: if the address scope * of is interface-local or link-local, embed the interface index in the * address. */
| 315 | * address. |
| 316 | */ |
| 317 | int |
| 318 | sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok) |
| 319 | { |
| 320 | u_int32_t zoneid; |
| 321 | |
| 322 | if ((zoneid = sin6->sin6_scope_id) == 0 && defaultok) |
| 323 | zoneid = scope6_addr2default(&sin6->sin6_addr); |
| 324 | |
| 325 | if (zoneid != 0 && |
| 326 | (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) || |
| 327 | IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr))) { |
| 328 | /* |
| 329 | * At this moment, we only check interface-local and |
| 330 | * link-local scope IDs, and use interface indices as the |
| 331 | * zone IDs assuming a one-to-one mapping between interfaces |
| 332 | * and links. |
| 333 | */ |
| 334 | if (V_if_index < zoneid || ifnet_byindex(zoneid) == NULL) |
| 335 | return (ENXIO); |
| 336 | |
| 337 | /* XXX assignment to 16bit from 32bit variable */ |
| 338 | sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff); |
| 339 | sin6->sin6_scope_id = 0; |
| 340 | } |
| 341 | |
| 342 | return 0; |
| 343 | } |
| 344 | |
| 345 | /* |
| 346 | * generate standard sockaddr_in6 from embedded form. |
no test coverage detected