Ejemplo n.º 1
0
static ibcm_arp_ip_t *
ibcm_arp_lookup(ibcm_arp_ibd_insts_t *ibds, char *linkname)
{
	datalink_id_t	linkid;
	int		i;

	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lookup: linkname =  %s", linkname);

	/*
	 * If at first we don't succeed, try again, just in case it is in
	 * hiding. The first call requires the datalink management daemon
	 * (the authorative source of information about name to id mapping)
	 * to be present and answering upcalls, the second does not.
	 */
	if (dls_mgmt_get_linkid(linkname, &linkid) != 0) {
		if (dls_devnet_macname2linkid(linkname, &linkid) != 0) {
			IBTF_DPRINTF_L2(cmlog, "ibcm_arp_lookup: could not "
			    "get linkid from linkname (%s)", linkname);
			return (NULL);
		}
	}

	for (i = 0; i < ibds->ibcm_arp_ibd_cnt; i++) {
		if (ibds->ibcm_arp_ip[i].ip_linkid == linkid)
			return (&ibds->ibcm_arp_ip[i]);
	}

	IBTF_DPRINTF_L2(cmlog, "ibcm_arp_lookup: returning NULL for "
	    "linkname (%s)", linkname);
	return (NULL);
}
Ejemplo n.º 2
0
ibt_status_t
ibcm_arp_get_ibds(ibcm_arp_ibd_insts_t *ibdp, sa_family_t family_loc)
{
#ifdef DEBUG
	int i;
#endif

	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds(%p)", ibdp);

	ibcm_arp_get_ibd_insts(ibdp);

	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibds: Found %d ibd instances",
	    ibdp->ibcm_arp_ibd_cnt);

	if (ibdp->ibcm_arp_ibd_cnt == 0)
		return (IBT_SRC_IP_NOT_FOUND);

	/* Get the IP addresses of active ports. */
	if (!ibcm_arp_get_ibd_ipaddr(ibdp, family_loc)) {
		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: failed to get "
		    "ibd instance: IBT_SRC_IP_NOT_FOUND");
		ibcm_arp_free_ibds(ibdp);
		return (IBT_SRC_IP_NOT_FOUND);
	}

#ifdef DEBUG
	for (i = 0; i < ibdp->ibcm_arp_ibd_cnt; i++) {
		char    my_buf[INET6_ADDRSTRLEN];
		ibcm_arp_ip_t	*aip = &ibdp->ibcm_arp_ip[i];

		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: Linkid %d Family %d "
		    "PKey 0x%lX \n HCAGUID 0x%llX SGID %llX:%llX",
		    aip->ip_linkid, aip->ip_inet_family, aip->ip_pkey,
		    aip->ip_hca_guid, aip->ip_port_gid.gid_prefix,
		    aip->ip_port_gid.gid_guid);
		if (aip->ip_inet_family == AF_INET) {
			IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: IPV4: %s",
			    inet_ntop(AF_INET, &aip->ip_cm_sin.sin_addr, my_buf,
			    sizeof (my_buf)));
		} else if (aip->ip_inet_family == AF_INET6) {
			IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: IPV6: %s",
			    inet_ntop(AF_INET6, &aip->ip_cm_sin6.sin6_addr,
			    my_buf, sizeof (my_buf)));
		} else {
			IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: Unknown "
			    "Family %d", aip->ip_inet_family);
		}
	}
#endif

	return (IBT_SUCCESS);
}
Ejemplo n.º 3
0
/*
 * Query the neighbor cache for IPv4/IPv6 to mac address mapping.
 */
static int
ibcm_nce_lookup(ibcm_arp_prwqn_t *wqnp, ill_t *ill, zoneid_t zoneid)
{
	ip2mac_t	ip2m;
	sin_t		*sin;
	sin6_t		*sin6;
	ip2mac_id_t	ip2mid;
	int		err;

	if (wqnp->src_addr.family != wqnp->dst_addr.family) {
		IBTF_DPRINTF_L2(cmlog, "ibcm_nce_lookup: Mis-match SRC_ADDR "
		    "Family: %d, DST_ADDR Family %d", wqnp->src_addr.family,
		    wqnp->dst_addr.family);
		return (1);
	}
	bzero(&ip2m, sizeof (ip2m));

	if (wqnp->dst_addr.family == AF_INET) {
		sin = (sin_t *)&ip2m.ip2mac_pa;
		sin->sin_family = AF_INET;
		sin->sin_addr.s_addr = wqnp->dst_addr.un.ip4addr;
	} else if (wqnp->dst_addr.family == AF_INET6) {
		sin6 = (sin6_t *)&ip2m.ip2mac_pa;
		sin6->sin6_family = AF_INET6;
		sin6->sin6_addr = wqnp->dst_addr.un.ip6addr;
	} else {
		IBTF_DPRINTF_L2(cmlog, "ibcm_nce_lookup: Invalid DST_ADDR "
		    "Family: %d", wqnp->dst_addr.family);
		return (1);
	}

	ip2m.ip2mac_ifindex = ill->ill_phyint->phyint_ifindex;

	wqnp->flags |= IBCM_ARP_PR_RESOLVE_PENDING;

	/*
	 * issue the request to IP for Neighbor Discovery
	 */
	ip2mid = ip2mac(IP2MAC_RESOLVE, &ip2m, ibcm_resolver_ack, wqnp,
	    zoneid);
	err = ip2m.ip2mac_err;
	if (err == EINPROGRESS) {
		wqnp->ip2mac_id = ip2mid;
		wqnp->flags |= IBCM_ARP_PR_RESOLVE_PENDING;
		err = 0;
	} else if (err == 0) {
		ibcm_resolver_ack(&ip2m, wqnp);
	}
	return (err);
}
Ejemplo n.º 4
0
/*
 * Function:
 *	ibcm_ip_print
 * Input:
 *	label		Arbitrary qualifying string
 *	ipa		Pointer to IP Address to print
 */
void
ibcm_ip_print(char *label, ibt_ip_addr_t *ipaddr)
{
	char    buf[INET6_ADDRSTRLEN];

	if (ipaddr->family == AF_INET) {
		IBTF_DPRINTF_L2(cmlog, "%s: %s", label,
		    inet_ntop(AF_INET, &ipaddr->un.ip4addr, buf, sizeof (buf)));
	} else if (ipaddr->family == AF_INET6) {
		IBTF_DPRINTF_L2(cmlog, "%s: %s", label, inet_ntop(AF_INET6,
		    &ipaddr->un.ip6addr, buf, sizeof (buf)));
	} else {
		IBTF_DPRINTF_L2(cmlog, "%s: IP ADDR NOT SPECIFIED ", label);
	}
}
Ejemplo n.º 5
0
static void
ibcm_arp_get_ibd_insts(ibcm_arp_ibd_insts_t *ibds)
{
	ibcm_arp_ip_t	*ipp;
	ib_gid_t	port_gid;
	ibt_part_attr_t	*attr_list, *attr;
	int		nparts;

	if ((ibt_get_all_part_attr(&attr_list, &nparts) != IBT_SUCCESS) ||
	    (nparts == 0)) {
		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibd_insts: Failed to "
		    "IB Part List - %d", nparts);
		ibds->ibcm_arp_ibd_alloc = 0;
		ibds->ibcm_arp_ibd_cnt = 0;
		ibds->ibcm_arp_ip = NULL;
		return;
	}
	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibd_insts: Found %d IB Part List",
	    nparts);

	ibds->ibcm_arp_ibd_alloc = nparts;
	ibds->ibcm_arp_ibd_cnt = 0;
	ibds->ibcm_arp_ip = (ibcm_arp_ip_t *)kmem_zalloc(
	    nparts * sizeof (ibcm_arp_ip_t), KM_SLEEP);

	attr = attr_list;
	while (nparts--) {
		if (ibt_get_port_state_byguid(attr->pa_hca_guid,
		    attr->pa_port, &port_gid, NULL) == IBT_SUCCESS) {

			ipp = &ibds->ibcm_arp_ip[ibds->ibcm_arp_ibd_cnt];
			ipp->ip_linkid = attr->pa_plinkid;
			ipp->ip_pkey = attr->pa_pkey;
			ipp->ip_hca_guid = attr->pa_hca_guid;
			ipp->ip_port_gid = port_gid;
			ibds->ibcm_arp_ibd_cnt++;

			IBTF_DPRINTF_L4(cmlog, "PartAttr: p-linkid %lX, "
			    "d-linkid %lX, pkey 0x%lX", ipp->ip_linkid,
			    attr->pa_dlinkid, ipp->ip_pkey);
			IBTF_DPRINTF_L4(cmlog, "hca_guid 0x%llX, "
			    "port_gid %llX \n attr-port_guid %llX",
			    ipp->ip_hca_guid, ipp->ip_port_gid.gid_guid,
			    attr->pa_port_guid);
		}
		attr++;
	}

	(void) ibt_free_part_attr(attr_list, ibds->ibcm_arp_ibd_alloc);
}
Ejemplo n.º 6
0
/*
 * callback for resolver lookups, both for success and failure.
 * If Address resolution was succesful: return GID info.
 */
static void
ibcm_resolver_ack(ip2mac_t *ip2macp, void *arg)
{
	ibcm_arp_prwqn_t *wqnp = (ibcm_arp_prwqn_t *)arg;
	ibcm_arp_streams_t *ib_s;
	uchar_t *cp;
	int err = 0;

	IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_ack(%p, %p)", ip2macp, wqnp);

	ib_s = wqnp->ib_str;
	mutex_enter(&ib_s->lock);

	if (ip2macp->ip2mac_err != 0) {
		wqnp->flags &= ~IBCM_ARP_PR_RESOLVE_PENDING;
		cv_broadcast(&ib_s->cv);
		err = EHOSTUNREACH;
		goto user_callback;
	}

	if (!ibcm_check_sockdl(&ip2macp->ip2mac_ha)) {
		IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_ack: Error: "
		    "interface %s is not IB\n", wqnp->ifname);
		err = EHOSTUNREACH;
		goto user_callback;
	}

	cp = (uchar_t *)LLADDR(&ip2macp->ip2mac_ha);
	bcopy(cp, &wqnp->dst_mac, IPOIB_ADDRL);

	/*
	 * at this point we have src/dst gid's derived from the mac addresses
	 * now get the hca, port
	 */
	bcopy(&wqnp->src_mac.ipoib_gidpref, &wqnp->sgid, sizeof (ib_gid_t));
	bcopy(&wqnp->dst_mac.ipoib_gidpref, &wqnp->dgid, sizeof (ib_gid_t));

	IBCM_H2N_GID(wqnp->sgid);
	IBCM_H2N_GID(wqnp->dgid);

user_callback:

	ib_s->status = err;
	ib_s->done = B_TRUE;

	/* lock is held by the caller. */
	cv_signal(&ib_s->cv);
	mutex_exit(&ib_s->lock);
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
/*
 * Fill in `ibds' with IP addresses tied to IFT_IB IP interfaces.  Returns
 * B_TRUE if at least one address was filled in.
 */
static boolean_t
ibcm_arp_get_ibd_ipaddr(ibcm_arp_ibd_insts_t *ibds, sa_family_t family_loc)
{
	int i, nifs, naddr = 0;
	uint_t bufsize;
	struct lifconf lifc;
	struct lifreq *lifrp, lifr_copy;
	ibcm_arp_ip_t *ipp;
	lifgroupinfo_t	lifgr;
	int err;
	char    ifname[LIFNAMSIZ + 1];
	uint64_t	ifflags = 0;
	zoneid_t	ifzoneid;

	if (ibcm_do_lifconf(&lifc, &bufsize, family_loc) != 0)
		return (B_FALSE);

	nifs = lifc.lifc_len / sizeof (struct lifreq);

	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibd_ipaddr: Family %d, nifs %d",
	    family_loc, nifs);

	for (lifrp = lifc.lifc_req, i = 0; i < nifs; i++, lifrp++) {

		if (lifrp->lifr_type != IFT_IB)
			continue;

		IBTF_DPRINTF_L4(cmlog, "\nInterface# : %d", i);
		IBTF_DPRINTF_L4(cmlog, "lifr_name : %s, lifr_family :%X, "
		    "lifr_type : 0x%lX", lifrp->lifr_name,
		    lifrp->lifr_addr.ss_family, lifrp->lifr_type);

		(void) strlcpy(ifname, lifrp->lifr_name, LIFNAMSIZ);

		/* Get ZoneId. */
		lifr_copy = *lifrp;
		ifzoneid = 0;
		err = ibcm_do_ip_ioctl(SIOCGLIFZONE, sizeof (struct lifreq),
		    &lifr_copy);
		if (err != 0) {
			IBTF_DPRINTF_L2(cmlog, "IFZONE ioctl Failed: err = %d",
			    err);
		} else  {
			IBTF_DPRINTF_L4(cmlog, "lifr_zoneid     : 0x%X",
			    lifr_copy.lifr_zoneid);
			ifzoneid = lifr_copy.lifr_zoneid;
		}

		/* Get IfIndex. */
		lifr_copy = *lifrp;
		err = ibcm_do_ip_ioctl(SIOCGLIFINDEX, sizeof (struct lifreq),
		    &lifr_copy);
		if (err != 0) {
			IBTF_DPRINTF_L2(cmlog, "IFINDEX ioctl Failed: err = %d",
			    err);
		} else
			IBTF_DPRINTF_L4(cmlog, "lifr_index      : 0x%X",
			    lifr_copy.lifr_index);

		/* Get Interface flags. */
		lifr_copy = *lifrp;
		err = ibcm_do_ip_ioctl(SIOCGLIFFLAGS, sizeof (struct lifreq),
		    &lifr_copy);
		if (err != 0) {
			IBTF_DPRINTF_L2(cmlog, "IFFLAGS ioctl Failed: err = %d",
			    err);
		} else  {
			ifflags = lifr_copy.lifr_flags;
			IBTF_DPRINTF_L4(cmlog, "lifr_flags      : 0x%llX",
			    ifflags);
		}

		lifr_copy = *lifrp;
		err = ibcm_do_ip_ioctl(SIOCGLIFGROUPNAME,
		    sizeof (struct lifreq), &lifr_copy);
		if (err != 0) {
			IBTF_DPRINTF_L3(cmlog, "IFGroupName ioctl Failed: "
			    "err = %d", err);
		}

		if (lifr_copy.lifr_groupname[0] != '\0') {
			IBTF_DPRINTF_L4(cmlog, "lifr_groupname  : %s",
			    lifr_copy.lifr_groupname);
			(void) strlcpy(lifgr.gi_grname,
			    lifr_copy.lifr_groupname, LIFGRNAMSIZ);
			err = ibcm_do_ip_ioctl(SIOCGLIFGROUPINFO,
			    sizeof (struct lifgroupinfo), &lifgr);
			if (err != 0) {
				IBTF_DPRINTF_L2(cmlog, "IFGroupINFO ioctl "
				    "Failed: err = %d", err);
			} else {
				IBTF_DPRINTF_L4(cmlog, "lifgroupinfo details");
				IBTF_DPRINTF_L4(cmlog, "grname : %s, grifname :"
				    " %s, m4ifname : %s, m6ifname : %s",
				    lifgr.gi_grname, lifgr.gi_grifname,
				    lifgr.gi_m4ifname, lifgr.gi_m6ifname);
				IBTF_DPRINTF_L4(cmlog, "gi_bcifname  : %s",
				    lifgr.gi_bcifname);
				IBTF_DPRINTF_L4(cmlog, "gi_v4 %d, gi_v6 %d, "
				    "gi_nv4 %d, gi_nv6 %d, gi_mactype %d",
				    lifgr.gi_v4, lifgr.gi_v6, lifgr.gi_nv4,
				    lifgr.gi_nv6, lifgr.gi_mactype);

				(void) strlcpy(ifname, lifgr.gi_bcifname,
				    LIFNAMSIZ);
			}
		}

		if ((ipp = ibcm_arp_lookup(ibds, ifname)) == NULL)
			continue;

		ipp->ip_zoneid = ifzoneid;	/* Copy back the zoneid info */
		switch (lifrp->lifr_addr.ss_family) {
		case AF_INET:
			ipp->ip_inet_family = AF_INET;
			bcopy(&lifrp->lifr_addr, &ipp->ip_cm_sin,
			    sizeof (struct sockaddr_in));
			naddr++;
			break;
		case AF_INET6:
			ipp->ip_inet_family = AF_INET6;
			bcopy(&lifrp->lifr_addr, &ipp->ip_cm_sin6,
			    sizeof (struct sockaddr_in6));
			naddr++;
			break;
		}
	}

	kmem_free(lifc.lifc_buf, bufsize);
	return (naddr > 0);
}