dapl_name_service.c revision 9e39c5ba00a55fa05777cc94b148296af305e135
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
*
* MODULE: dapl_name_service.c
*
* PURPOSE: Provide simple, file base name services in the absence
* of DNS hooks for a particular transport type. If an
* InfiniBand implementation supports IPoIB, this should
* not be used.
*
* Description: Interfaces in this file are completely described in
*/
/*
* Include files for setting up a network name
*/
#include "dapl.h"
#include "dapl_name_service.h"
#include <net/if_types.h>
#include <poll.h>
#ifdef IBHOSTS_NAMING
#define MAX_GID_ENTRIES 32
#endif /* IBHOSTS_NAMING */
/*
* dapls_ns_init
*
* Initialize naming services
*
* Input:
* none
*
* Output:
* none
*
* Returns:
* DAT_SUCCESS
* DAT_INVALID_PARAMETER
*/
dapls_ns_init(void)
{
#ifdef IBHOSTS_NAMING
#endif /* IBHOSTS_NAMING */
return (dat_status);
}
#ifdef IBHOSTS_NAMING
/*
* dapls_create_gid_map()
*
* Create a table containing IP addresses and GIDs which can
* be used for lookups.
*
* This implementation is a simple method providing name services
* when more advanced mechanisms do not exist. The proper way
* to obtain these mappings is to use a name service such as is
* provided by IPoIB on InfiniBand.
*
* Input:
* device_name Name of device as reported by the provider
*
* Output:
* none
*
* Returns:
* char * to string number
*/
dapli_ns_create_gid_map(void)
{
FILE *f;
char hostname[128];
int rc;
struct sockaddr_in *si;
if (f == NULL) {
return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
}
if (rc != 0) {
/*
* hostname not registered in DNS,
* provide a dummy value
*/
"WARNING: <%s> not registered in "
"DNS, using dummy IP value\n", hostname);
} else {
/*
*/
} else {
"WARNING: <%s> Address family "
"not supported, using dummy "
"IP value\n", hostname);
}
}
}
(void) fclose(f);
return (DAT_SUCCESS);
}
/*
* dapli_ns_add_address
*
* Add a table entry to the gid_map_table.
*
* Input:
* remote_ia_address remote IP address
* gid pointer to output gid
*
* Output:
* gid filled in GID
*
* Returns:
* DAT_SUCCESS
* DAT_INSUFFICIENT_RESOURCES
* DAT_INVALID_PARAMETER
*/
{
int count;
count++;
}
if (count > MAX_GID_ENTRIES) {
return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 0));
}
return (DAT_SUCCESS);
}
/*
* dapls_ns_lookup_address
*
* Look up the provided IA_ADDRESS in the gid_map_table. Return
* the gid if found.
*
* Input:
* remote_ia_address remote IP address
* gid pointer to output gid
* timeout timeout in microseconds
*
* Output:
* gid filled in GID
*
* Returns:
* DAT_SUCCESS
* DAT_INSUFFICIENT_RESOURCES
* DAT_INVALID_PARAMETER
*/
{
struct sockaddr_in *si;
/* unused here */
return (DAT_SUCCESS);
}
}
return (DAT_ERROR(DAT_INVALID_PARAMETER, 0));
}
#endif /* IBHOSTS_NAMING */
/*
* utility function for printing a socket
*/
char *
{
void *addr_ptr;
/* LINTED: E_BAD_PTR_CAST_ALIGN */
/* LINTED: E_BAD_PTR_CAST_ALIGN */
} else {
}
return (buf);
}
}
/*
* dapls_ns_lookup_address
*
* translates an IP address into a GID
*
* Input:
* ia_ptr pointer to IA object
* remote_ia_address remote IP address
* gid pointer to output gid
* timeout timeout in microseconds
*
* Output:
* gid filled in GID
*
* Returns:
* DAT_SUCCESS
* DAT_INVALID_ADDRRESS
* DAT_INVALID_PARAMETER
* DAT_INTERNAL_ERROR
*/
#define IBD_NAME "ibd"
#define NS_MAX_RETRIES 60
struct sockaddr_in *addr);
struct sockaddr_in6 *addr);
{
/* LINTED: E_BAD_PTR_CAST_ALIGN */
/* LINTED: E_BAD_PTR_CAST_ALIGN */
} else {
}
return (dat_status);
}
{
struct sockaddr_in *sin;
int s, retries = 0;
if (s < 0) {
return (DAT_INTERNAL_ERROR);
}
(void) close(s);
return (DAT_INVALID_ADDRESS);
}
again:;
/*
* if SIOCGXARP failed, we force the ARP
* cache to be filled by connecting to the
* destination IP address.
*/
if (retries <= NS_MAX_RETRIES &&
timeout) == 0) {
retries++;
goto again;
}
(void) close(s);
return (DAT_ERROR(DAT_INVALID_ADDRESS,
}
/*
* we get here if arp resolution is still incomplete
*/
retries++;
(void) sleep(1);
goto again;
}
(void) close(s);
/* LINTED: E_BAD_PTR_CAST_ALIGN */
(void) dapl_os_memcpy(&tmp_gid,
/*
* gids from the ARP table are in network order, convert
* the gids from network order to host byte order
*/
} else {
int i, len;
"ns_lookup_v4: failed, non IB address: "
"len = %d, addr = 0x", len);
if (len > 0) {
for (i = 0; i < len; i++) {
}
} else {
}
return (DAT_INVALID_ADDRESS);
}
return (DAT_SUCCESS);
}
{
int s, retries = 0;
if (s < 0) {
return (DAT_INTERNAL_ERROR);
}
(void) close(s);
return (DAT_INVALID_ADDRESS);
}
again:;
/*
* if SIOCLIFGETND failed, we force the ND
* cache to be filled by connecting to the
* destination IP address.
*/
if (retries < NS_MAX_RETRIES &&
dapls_ns_send_packet_v6(s, addr) == 0 &&
timeout) == 0) {
retries++;
goto again;
}
(void) close(s);
return (DAT_ERROR(DAT_INVALID_ADDRESS,
}
/*
* lnr_hdw_len == 0 means that the ND entry
* is still incomplete. we need to retry the ioctl.
*/
retries++;
(void) sleep(1);
goto again;
}
(void) close(s);
/* LINTED: E_BAD_PTR_CAST_ALIGN */
(void) dapl_os_memcpy(&tmp_gid,
/*
* gids from the ND table are in network order, convert
* the gids from network order to host byte order
*/
} else {
int i, len;
"ns_lookup_v6: failed, non IB address: "
"len = %d, addr = 0x", len);
if (len > 0) {
for (i = 0; i < len; i++) {
}
} else {
}
return (DAT_INVALID_ADDRESS);
}
return (DAT_SUCCESS);
}
static int
{
sizeof (*addr)) < 0) {
return (-1);
}
return (0);
}
static int
{
int retval;
if (retval < 0) {
"ns_subnet_match_v4: cannot get netmask: %s\n",
return (-1);
}
/*
* we need to get the interface address here because the
* address in ia_ptr->hca_ptr->hca_address might not
* necessarily be an IPv4 address.
*/
if (retval < 0) {
"ns_subnet_match_v4: cannot get local addr: %s\n",
return (-1);
}
if (netaddr != netaddr_dest) {
"ns_subnet_match_v4: netaddrs don't match: "
return (-1);
}
return (0);
}
static int
{
struct sockaddr_in6 netmask_sock;
int i, retval;
if (retval < 0) {
"ns_subnet_match_v6: cannot get netmask: %s\n",
return (-1);
}
sizeof (netmask_sock));
/*
* we need to get the interface address here because the
* address in ia_ptr->hca_ptr->hca_address might not
* necessarily be an IPv6 address.
*/
if (retval < 0) {
"ns_subnet_match_v6: cannot get local addr: %s\n",
return (-1);
}
"ns_subnet_match_v6: subnets do not match\n");
return (-1);
}
}
return (0);
}
static int
{
struct sockaddr_storage sock;
struct sockaddr_in *v4dest;
struct sockaddr_in6 *v6dest;
int tmo;
int ip_version;
ip_version = 4;
ip_version = 6;
} else {
"ns_resolve_addr: invalid af %d\n", af);
return (-1);
}
if (fd < 0) {
"ns_resolve_addr: ipv%d, cannot create socket %s\n",
return (-1);
}
/*
* set socket to non-blocking mode
*/
if (retval < 0) {
"ns_resolve_addr: ipv%d, fcntl failed: %s\n",
return (-1);
}
/*
* connect to the discard port (9) at the dest IP
*/
/* LINTED: E_BAD_PTR_CAST_ALIGN */
sizeof (struct sockaddr_in));
} else {
/* LINTED: E_BAD_PTR_CAST_ALIGN */
sizeof (struct sockaddr_in6));
sizeof (struct sockaddr_in6));
}
/*
* we can return immediately if connect succeeds
*/
if (retval == 0) {
return (0);
}
/*
* already be resolved
*/
errno = 0;
return (0);
}
/*
* for all other cases, we poll on the fd
*/
if (timeout == DAT_TIMEOUT_INFINITE ||
timeout == 0) {
/*
* -1 means infinite
*/
tmo = -1;
} else {
/*
* convert timeout from usecs to msecs
*/
}
if (retval > 0) {
if (retval == 0) {
/*
* we only return 0 if so_error == 0 or
* so_error == ECONNREFUSED. for all other
* cases retval is non-zero.
*/
retval = -1;
"ns_resolve_addr: ipv%d, so_error: %s\n",
}
} else {
/*
* if retval != 0, it must be -1. and errno must
* have been set by getsockopt.
*/
"ns_resolve_addr: ipv%d, getsockopt: %s\n",
}
} else {
if (retval == 0) {
}
retval = -1;
"ns_resolve_addr: ipv%d, poll: %s\n",
}
return (retval);
}