* Get interface identifier for the specified interface. If it is not * available on ifp0, borrow interface identifier from other information * sources. * * altifp - secondary EUI64 source */
| 355 | * altifp - secondary EUI64 source |
| 356 | */ |
| 357 | static int |
| 358 | get_ifid(struct ifnet *ifp0, struct ifnet *altifp, |
| 359 | struct in6_addr *in6) |
| 360 | { |
| 361 | struct ifnet *ifp; |
| 362 | |
| 363 | NET_EPOCH_ASSERT(); |
| 364 | |
| 365 | /* first, try to get it from the interface itself */ |
| 366 | if (in6_get_hw_ifid(ifp0, in6) == 0) { |
| 367 | nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", |
| 368 | if_name(ifp0))); |
| 369 | goto success; |
| 370 | } |
| 371 | |
| 372 | /* try secondary EUI64 source. this basically is for ATM PVC */ |
| 373 | if (altifp && in6_get_hw_ifid(altifp, in6) == 0) { |
| 374 | nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n", |
| 375 | if_name(ifp0), if_name(altifp))); |
| 376 | goto success; |
| 377 | } |
| 378 | |
| 379 | /* next, try to get it from some other hardware interface */ |
| 380 | CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { |
| 381 | if (ifp == ifp0) |
| 382 | continue; |
| 383 | if (in6_get_hw_ifid(ifp, in6) != 0) |
| 384 | continue; |
| 385 | |
| 386 | /* |
| 387 | * to borrow ifid from other interface, ifid needs to be |
| 388 | * globally unique |
| 389 | */ |
| 390 | if (IFID_UNIVERSAL(in6)) { |
| 391 | nd6log((LOG_DEBUG, |
| 392 | "%s: borrow interface identifier from %s\n", |
| 393 | if_name(ifp0), if_name(ifp))); |
| 394 | goto success; |
| 395 | } |
| 396 | } |
| 397 | |
| 398 | /* last resort: get from random number source */ |
| 399 | if (get_rand_ifid(ifp, in6) == 0) { |
| 400 | nd6log((LOG_DEBUG, |
| 401 | "%s: interface identifier generated by random number\n", |
| 402 | if_name(ifp0))); |
| 403 | goto success; |
| 404 | } |
| 405 | |
| 406 | printf("%s: failed to get interface identifier\n", if_name(ifp0)); |
| 407 | return -1; |
| 408 | |
| 409 | success: |
| 410 | nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| 411 | if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10], |
| 412 | in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13], |
| 413 | in6->s6_addr[14], in6->s6_addr[15])); |
| 414 | return 0; |
no test coverage detected