/* ARGSUSED */ static int ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem, net_ifaddr_t type[], struct sockaddr *storage, ip_stack_t *ipst) { struct sockaddr_in6 *sin6; struct sockaddr_in *sin; lif_if_t ipifid; ipif_t *ipif; int i; ASSERT(type != NULL); ASSERT(storage != NULL); ipifid = UNMAP_IPIF_ID(ifdata); if (family == AF_INET) { if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, B_FALSE, ipst)) == NULL) return (1); sin = (struct sockaddr_in *)storage; for (i = 0; i < nelem; i++, sin++) { if (ip_getifaddr_type(AF_INET, ipif, type[i], &sin->sin_addr) < 0) { ip2dbg(("ip_getlifaddr_impl failed type %d\n", type[i])); ipif_refrele(ipif); return (1); } sin->sin_family = AF_INET; } } else { if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, B_TRUE, ipst)) == NULL) return (1); sin6 = (struct sockaddr_in6 *)storage; for (i = 0; i < nelem; i++, sin6++) { if (ip_getifaddr_type(AF_INET6, ipif, type[i], &sin6->sin6_addr) < 0) { ip2dbg(("ip_getlifaddr_impl failed type %d\n", type[i])); ipif_refrele(ipif); return (1); } sin6->sin6_family = AF_INET6; } } ipif_refrele(ipif); return (0); }
/* ARGSUSED */ static int ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, ip_stack_t *ipst) { lif_if_t ipifid; ipif_t *ipif; int mtu; ipifid = UNMAP_IPIF_ID(ifdata); ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, isv6, ipst); if (ipif == NULL) return (0); mtu = ipif->ipif_ill->ill_mtu; ipif_refrele(ipif); if (mtu == 0) { ill_t *ill; if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, ipst)) == NULL) { return (0); } mtu = ill->ill_mtu; ill_refrele(ill); } return (mtu); }
/* * Shared implementation to get next interface from the current list of * logical network interfaces */ static lif_if_t ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, ip_stack_t *ipst) { lif_if_t newidx, oldidx; boolean_t nextok; ipif_t *ipif; ill_t *ill; ill = ill_lookup_on_ifindex(phy_ifdata, isv6, ipst); if (ill == NULL) return (0); if (ifdata != 0) { oldidx = UNMAP_IPIF_ID(ifdata); nextok = B_FALSE; } else { oldidx = 0; nextok = B_TRUE; } mutex_enter(&ill->ill_lock); if (ill->ill_state_flags & ILL_CONDEMNED) { mutex_exit(&ill->ill_lock); ill_refrele(ill); return (0); } /* * It's safe to iterate the ill_ipif list when holding an ill_lock. * And it's also safe to access ipif_id without ipif refhold. * See the field access rules in ip.h. */ for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) { if (!IPIF_CAN_LOOKUP(ipif)) continue; if (nextok) { ipif_refhold_locked(ipif); break; } else if (oldidx == ipif->ipif_id) { nextok = B_TRUE; } } mutex_exit(&ill->ill_lock); ill_refrele(ill); if (ipif == NULL) return (0); newidx = ipif->ipif_id; ipif_refrele(ipif); return (MAP_IPIF_ID(newidx)); }
/* * Shared implementation to determine the zoneid associated with an IPv4/IPv6 * address */ static int ip_getlifzone_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, ip_stack_t *ipst, zoneid_t *zoneid) { ipif_t *ipif; ipif = ipif_getby_indexes((uint_t)phy_ifdata, UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); if (ipif == NULL) return (-1); *zoneid = IP_REAL_ZONEID(ipif->ipif_zoneid, ipst); ipif_refrele(ipif); return (0); }
/* * The behaviour here mirrors that for the SIOCFLIFFLAGS ioctl where the * union of all of the relevant flags is returned. */ static int ip_getlifflags_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, ip_stack_t *ipst, uint64_t *flags) { phyint_t *phyi; ipif_t *ipif; ill_t *ill; ill = ill_lookup_on_ifindex(phy_ifdata, (family == AF_INET6), ipst); if (ill == NULL) return (-1); phyi = ill->ill_phyint; ipif = ipif_getby_indexes((uint_t)phy_ifdata, UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); if (ipif == NULL) { ill_refrele(ill); return (-1); } *flags = ipif->ipif_flags | ill->ill_flags | phyi->phyint_flags; ipif_refrele(ipif); ill_refrele(ill); return (0); }
int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr, zoneid_t myzoneid) { ibcm_arp_prwqn_t *wqnp; ire_t *ire = NULL; ipif_t *ipif = NULL; ill_t *ill = NULL; ill_t *hwaddr_ill = NULL; ip_stack_t *ipst; ipaddr_t setsrcv4; in6_addr_t setsrcv6; IBCM_PRINT_IP("ibcm_arp_pr_lookup: SRC", src_addr); IBCM_PRINT_IP("ibcm_arp_pr_lookup: DST", dst_addr); if ((wqnp = ibcm_arp_create_prwqn(ib_s, dst_addr, src_addr)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_create_prwqn failed"); ib_s->status = ENOMEM; return (1); } ipst = netstack_find_by_zoneid(myzoneid)->netstack_ip; if (dst_addr->family == AF_INET) { /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. */ setsrcv4 = INADDR_ANY; ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL, myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv4, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v4 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } /* Pick a source address */ if (ip_select_source_v4(ill, setsrcv4, dst_addr->un.ip4addr, INADDR_ANY, myzoneid, ipst, &wqnp->src_addr.un.ip4addr, NULL, NULL) != 0) { ib_s->status = EADDRNOTAVAIL; goto fail; } wqnp->gateway.un.ip4addr = ire->ire_gateway_addr; wqnp->netmask.un.ip4addr = ire->ire_mask; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET; } else if (dst_addr->family == AF_INET6) { /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv6 = ipv6_all_zeros; ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL, myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv6, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v6 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } /* Pick a source address */ if (ip_select_source_v6(ill, &setsrcv6, &dst_addr->un.ip6addr, myzoneid, ipst, B_FALSE, IPV6_PREFER_SRC_DEFAULT, &wqnp->src_addr.un.ip6addr, NULL, NULL) != 0) { ib_s->status = EADDRNOTAVAIL; goto fail; } wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6; wqnp->netmask.un.ip6addr = ire->ire_mask_v6; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET6; } (void) strlcpy(wqnp->ifname, ill->ill_name, sizeof (wqnp->ifname)); /* * For IPMP data addresses, we need to use the hardware address of the * interface bound to the given address. */ if (IS_IPMP(ill)) { if (wqnp->src_addr.family == AF_INET) { ipif = ipif_lookup_addr(wqnp->src_addr.un.ip4addr, ill, myzoneid, ipst); } else { ipif = ipif_lookup_addr_v6(&wqnp->src_addr.un.ip6addr, ill, myzoneid, ipst); } if (ipif == NULL) { ib_s->status = ENETUNREACH; goto fail; } if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "no bound ill for IPMP interface %s", ill->ill_name); ib_s->status = EFAULT; goto fail; } } else { hwaddr_ill = ill; ill_refhold(hwaddr_ill); /* for symmetry */ } if ((ib_s->status = ibcm_arp_check_interface(hwaddr_ill)) != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_check_interface failed"); goto fail; } bcopy(hwaddr_ill->ill_phys_addr, &wqnp->src_mac, hwaddr_ill->ill_phys_addr_length); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: outgoing if:%s", wqnp->ifname); /* * at this stage, we have the source address and the IB * interface, now get the destination mac address from * arp or ipv6 drivers */ ib_s->status = ibcm_nce_lookup(wqnp, ill, myzoneid); if (ib_s->status != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_nce_lookup failed: %d", ib_s->status); goto fail; } ill_refrele(hwaddr_ill); ill_refrele(ill); ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); netstack_rele(ipst->ips_netstack); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp); return (0); fail: if (hwaddr_ill != NULL) ill_refrele(hwaddr_ill); if (ill != NULL) ill_refrele(ill); if (ire != NULL) ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); ibcm_arp_delete_prwqn(wqnp); netstack_rele(ipst->ips_netstack); return (1); }
int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr) { ibcm_arp_prwqn_t *wqnp; ire_t *ire = NULL; ipif_t *ipif = NULL; ill_t *ill = NULL; ill_t *hwaddr_ill = NULL; ip_stack_t *ipst; int len; ipaddr_t setsrcv4; in6_addr_t setsrcv6; IBCM_PRINT_IP("ibcm_arp_pr_lookup: SRC", src_addr); IBCM_PRINT_IP("ibcm_arp_pr_lookup: DST", dst_addr); if ((wqnp = ibcm_arp_create_prwqn(ib_s, dst_addr, src_addr)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_create_prwqn failed"); ib_s->status = ENOMEM; return (1); } ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip; if (dst_addr->family == AF_INET) { /* * A local address is always specified, and it is used * to find the zoneid. */ ipif = ipif_lookup_addr(src_addr->un.ip4addr, NULL, ALL_ZONES, ipst); if (ipif == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ipif_lookup_addr failed"); ib_s->status = EFAULT; goto fail; } /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv4 = INADDR_ANY; ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL, ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv4, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v4 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } if (ill != ipif->ipif_ill) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "wrong ill"); ib_s->status = EFAULT; goto fail; } wqnp->gateway.un.ip4addr = ire->ire_gateway_addr; wqnp->netmask.un.ip4addr = ire->ire_mask; wqnp->src_addr.un.ip4addr = src_addr->un.ip4addr; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET; } else if (dst_addr->family == AF_INET6) { /* * A local address is always specified, and it is used * to find the zoneid. * We should really match on scopeid for link locals here. */ ipif = ipif_lookup_addr_v6(&src_addr->un.ip6addr, NULL, ALL_ZONES, ipst); if (ipif == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ipif_lookup_addr_v6 failed"); ib_s->status = EFAULT; goto fail; } /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv6 = ipv6_all_zeros; ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL, ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv6, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v6 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } if (ill != ipif->ipif_ill) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "wrong ill"); ib_s->status = EFAULT; goto fail; } wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6; wqnp->netmask.un.ip6addr = ire->ire_mask_v6; wqnp->src_addr.un.ip6addr = src_addr->un.ip6addr; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET6; } (void) strlcpy(wqnp->ifname, ill->ill_name, sizeof (wqnp->ifname)); /* * For IPMP data addresses, we need to use the hardware address of the * interface bound to the given address. */ if (IS_IPMP(ill)) { if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "no bound ill for IPMP interface %s", ill->ill_name); ib_s->status = EFAULT; goto fail; } } else { hwaddr_ill = ill; ill_refhold(hwaddr_ill); /* for symmetry */ } if ((ib_s->status = ibcm_arp_check_interface(hwaddr_ill)) != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_check_interface failed"); goto fail; } bcopy(hwaddr_ill->ill_phys_addr, &wqnp->src_mac, hwaddr_ill->ill_phys_addr_length); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: outgoing if:%s", wqnp->ifname); /* * if the user supplied a address, then verify rts returned * the same address */ if (wqnp->usrc_addr.family) { len = (wqnp->usrc_addr.family == AF_INET) ? IP_ADDR_LEN : sizeof (in6_addr_t); if (bcmp(&wqnp->usrc_addr.un, &wqnp->src_addr.un, len)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "srcaddr mismatch:%d", ENETUNREACH); goto fail; } } /* * at this stage, we have the source address and the IB * interface, now get the destination mac address from * arp or ipv6 drivers */ ib_s->status = ibcm_nce_lookup(wqnp, ill, getzoneid()); if (ib_s->status != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_nce_lookup failed: %d", ib_s->status); goto fail; } ill_refrele(hwaddr_ill); ill_refrele(ill); ire_refrele(ire); ipif_refrele(ipif); netstack_rele(ipst->ips_netstack); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp); return (0); fail: if (hwaddr_ill != NULL) ill_refrele(hwaddr_ill); if (ill != NULL) ill_refrele(ill); if (ire != NULL) ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); ibcm_arp_delete_prwqn(wqnp); netstack_rele(ipst->ips_netstack); return (1); }