* Notifies other subsystems about address change/arrival: * 1) Notifies device handler on the first IPv6 address assignment * 2) Handle routing table changes for P2P links and route * 3) Handle routing table changes for address host route */
| 1442 | * 3) Handle routing table changes for address host route |
| 1443 | */ |
| 1444 | static int |
| 1445 | in6_notify_ifa(struct ifnet *ifp, struct in6_ifaddr *ia, |
| 1446 | struct in6_aliasreq *ifra, int hostIsNew) |
| 1447 | { |
| 1448 | int error = 0, ifacount = 0; |
| 1449 | struct ifaddr *ifa; |
| 1450 | struct sockaddr_in6 *pdst; |
| 1451 | char ip6buf[INET6_ADDRSTRLEN]; |
| 1452 | |
| 1453 | /* |
| 1454 | * Give the interface a chance to initialize |
| 1455 | * if this is its first address, |
| 1456 | */ |
| 1457 | if (hostIsNew != 0) { |
| 1458 | struct epoch_tracker et; |
| 1459 | |
| 1460 | NET_EPOCH_ENTER(et); |
| 1461 | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { |
| 1462 | if (ifa->ifa_addr->sa_family != AF_INET6) |
| 1463 | continue; |
| 1464 | ifacount++; |
| 1465 | } |
| 1466 | NET_EPOCH_EXIT(et); |
| 1467 | } |
| 1468 | |
| 1469 | if (ifacount <= 1 && ifp->if_ioctl) { |
| 1470 | error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia); |
| 1471 | if (error) |
| 1472 | goto done; |
| 1473 | } |
| 1474 | |
| 1475 | /* |
| 1476 | * If a new destination address is specified, scrub the old one and |
| 1477 | * install the new destination. Note that the interface must be |
| 1478 | * p2p or loopback. |
| 1479 | */ |
| 1480 | pdst = &ifra->ifra_dstaddr; |
| 1481 | if (pdst->sin6_family == AF_INET6 && |
| 1482 | !IN6_ARE_ADDR_EQUAL(&pdst->sin6_addr, &ia->ia_dstaddr.sin6_addr)) { |
| 1483 | if ((ia->ia_flags & IFA_ROUTE) != 0 && |
| 1484 | (in6_handle_dstaddr_rtrequest(RTM_DELETE, ia) != 0)) { |
| 1485 | nd6log((LOG_ERR, "in6_update_ifa_internal: failed to " |
| 1486 | "remove a route to the old destination: %s\n", |
| 1487 | ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); |
| 1488 | /* proceed anyway... */ |
| 1489 | } else |
| 1490 | ia->ia_flags &= ~IFA_ROUTE; |
| 1491 | ia->ia_dstaddr = *pdst; |
| 1492 | } |
| 1493 | |
| 1494 | /* |
| 1495 | * If a new destination address is specified for a point-to-point |
| 1496 | * interface, install a route to the destination as an interface |
| 1497 | * direct route. |
| 1498 | * XXX: the logic below rejects assigning multiple addresses on a p2p |
| 1499 | * interface that share the same destination. |
| 1500 | */ |
| 1501 | if (!(ia->ia_flags & IFA_ROUTE) && ifa_is_p2p(ia)) { |
no test coverage detected