Skip to content

Commit

Permalink
Add IPv6 support into libfreeipmi API core
Browse files Browse the repository at this point in the history
  • Loading branch information
chu11 committed Jan 13, 2017
1 parent 6d004dd commit 6695611
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 110 deletions.
12 changes: 11 additions & 1 deletion libfreeipmi/api/ipmi-api-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
#define MAXHOSTNAMELEN 64
#endif

#define MAXPORTBUFLEN 16

struct ipmi_ctx_target
{
uint8_t channel_number; /* for ipmb */
Expand Down Expand Up @@ -121,7 +123,15 @@ struct ipmi_ctx

char hostname[MAXHOSTNAMELEN+1];

struct sockaddr_in remote_host;
struct sockaddr *remote_host;
socklen_t remote_host_len;
struct sockaddr_in remote_host4;
struct sockaddr_in6 remote_host6;

struct sockaddr *srcaddr;
socklen_t srcaddr_len;
struct sockaddr_in srcaddr4;
struct sockaddr_in6 srcaddr6;

/* Configured by User for IPMI 1.5 and IPMI 2.0*/
char username[IPMI_MAX_USER_NAME_LENGTH+1];
Expand Down
168 changes: 72 additions & 96 deletions libfreeipmi/api/ipmi-api.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@

#include "freeipmi-portability.h"
#include "debug-util.h"
#include "fi_hostlist.h"
#include "secure.h"

#define IPMI_POLL_INTERVAL_USECS 10
Expand Down Expand Up @@ -326,161 +327,136 @@ _ipmi_inband_free (ipmi_ctx_t ctx)
static int
_setup_hostname (ipmi_ctx_t ctx, const char *hostname)
{
struct hostent hent;
int h_errnop;
char buf[GETHOSTBYNAME_AUX_BUFLEN];
#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
struct hostent *hptr;
#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
#else /* !HAVE_FUNC_GETHOSTBYNAME_R */
struct hostent *hptr;
#endif /* !HAVE_FUNC_GETHOSTBYNAME_R */
char *hostname_copy = NULL;
char *hostname_ptr;
char *port_copy = NULL;
const char *hostname_ptr = NULL;
const char *port_ptr = NULL;
uint16_t port = RMCP_AUX_BUS_SHUNT;
struct addrinfo ai_hints, *ai_res = NULL, *ai = NULL;
char port_str[MAXPORTBUFLEN + 1];
int rv = -1;
int ret;

assert (ctx);
assert (ctx->magic == IPMI_CTX_MAGIC);
assert (hostname);

if (strchr (hostname, ':'))
if ((ret = fi_host_is_host_with_port (hostname, &hostname_copy, &port_copy)) < 0)
{
char *ptr;

if (!(hostname_copy = strdup ((char *)hostname)))
{
API_SET_ERRNUM (ctx, IPMI_ERR_OUT_OF_MEMORY);
goto cleanup;
}

if ((ptr = strchr (hostname_copy, ':')))
{
char *endptr;
int tmp;

*ptr = '\0';
ptr++;
API_SET_ERRNUM (ctx, IPMI_ERR_INTERNAL_ERROR);
goto cleanup;
}

if (strlen (hostname_copy) > MAXHOSTNAMELEN)
{
API_SET_ERRNUM (ctx, IPMI_ERR_PARAMETERS);
goto cleanup;
}

errno = 0;
tmp = strtol (ptr, &endptr, 0);
if (errno
|| endptr[0] != '\0'
|| tmp <= 0
|| tmp > USHRT_MAX)
{
API_SET_ERRNUM (ctx, IPMI_ERR_PARAMETERS);
goto cleanup;
}

port = tmp;
}
if (ret)
{
hostname_ptr = hostname_copy;
port_ptr = port_copy;
}
else
{
if (strlen (hostname) > MAXHOSTNAMELEN)
{
API_SET_ERRNUM (ctx, IPMI_ERR_PARAMETERS);
goto cleanup;
}
hostname_ptr = hostname;

hostname_ptr = (char *)hostname;
}

memset (&hent, '\0', sizeof (struct hostent));
#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
if (gethostbyname_r (hostname_ptr,
&hent,
buf,
GETHOSTBYNAME_AUX_BUFLEN,
&hptr,
&h_errnop))
if ((ret = fi_host_is_valid (hostname_ptr,
port_ptr,
&port)) < 0)
{
API_SET_ERRNUM (ctx, IPMI_ERR_HOSTNAME_INVALID);
API_SET_ERRNUM (ctx, IPMI_ERR_INTERNAL_ERROR);
goto cleanup;
}
if (!hptr)

if (!ret)
{
API_SET_ERRNUM (ctx, IPMI_ERR_HOSTNAME_INVALID);
API_SET_ERRNUM (ctx, IPMI_ERR_PARAMETERS);
goto cleanup;
}
#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
/* Jan Forch - Solaris gethostbyname_r returns ptr, not integer */
if (!gethostbyname_r (hostname_ptr,
&hent,
buf,
GETHOSTBYNAME_AUX_BUFLEN,
&h_errnop))

memset (port_str, '\0', MAXPORTBUFLEN + 1);
snprintf (port_str, MAXPORTBUFLEN, "%d", port);
memset (&ai_hints, 0, sizeof (struct addrinfo));
ai_hints.ai_family = AF_UNSPEC;
ai_hints.ai_socktype = SOCK_DGRAM;
ai_hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);

if (getaddrinfo (hostname_ptr, port_str, &ai_hints, &ai_res))
{
API_SET_ERRNUM (ctx, IPMI_ERR_HOSTNAME_INVALID);
goto cleanup;
}
#else /* !HAVE_FUNC_GETHOSTBYNAME_R */
if (freeipmi_gethostbyname_r (hostname_ptr,
&hent,
buf,
GETHOSTBYNAME_AUX_BUFLEN,
&hptr,
&h_errnop))

/* Try all of the different answers we got, until we succeed. */
for (ai = ai_res; ai != NULL; ai = ai->ai_next)
{
API_SET_ERRNUM (ctx, IPMI_ERR_HOSTNAME_INVALID);
goto cleanup;
if (ai->ai_family == AF_INET)
{
memcpy (&(ctx->io.outofband.remote_host4), ai->ai_addr, ai->ai_addrlen);
ctx->io.outofband.remote_host = (struct sockaddr *)&(ctx->io.outofband.remote_host4);
ctx->io.outofband.remote_host_len = sizeof (struct sockaddr_in);
}
else if (ai->ai_family == AF_INET6)
{
memcpy (&(ctx->io.outofband.remote_host6), ai->ai_addr, ai->ai_addrlen);
ctx->io.outofband.remote_host = (struct sockaddr *)&(ctx->io.outofband.remote_host6);
ctx->io.outofband.remote_host_len = sizeof (struct sockaddr_in6);
}
else
continue;
break;
}
if (!hptr)

if (!ai)
{
API_SET_ERRNUM (ctx, IPMI_ERR_HOSTNAME_INVALID);
goto cleanup;
}
#endif /* !HAVE_FUNC_GETHOSTBYNAME_R */

strncpy (ctx->io.outofband.hostname,
hostname_ptr,
MAXHOSTNAMELEN);

ctx->io.outofband.remote_host.sin_family = AF_INET;
ctx->io.outofband.remote_host.sin_port = htons (port);
ctx->io.outofband.remote_host.sin_addr = *(struct in_addr *) hent.h_addr;

rv = 0;
cleanup:
free (hostname_copy);
free (port_copy);
freeaddrinfo (ai_res);
return (rv);
}

static int
_setup_socket (ipmi_ctx_t ctx)
{
struct sockaddr_in addr;

assert (ctx);
assert (ctx->magic == IPMI_CTX_MAGIC);

/* Open client (local) UDP socket */
/* achu: ephemeral ports are > 1023, so no way we will bind to an IPMI port */

if ((ctx->io.outofband.sockfd = socket (AF_INET,
if ((ctx->io.outofband.sockfd = socket (ctx->io.outofband.remote_host->sa_family,
SOCK_DGRAM,
0)) < 0)
{
API_ERRNO_TO_API_ERRNUM (ctx, errno);
return (-1);
}

memset (&addr, 0, sizeof (struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons (0);
addr.sin_addr.s_addr = htonl (INADDR_ANY);
if (ctx->io.outofband.remote_host->sa_family == AF_INET)
{
/* zero everywhere, secure ephemeral port */
memset (&(ctx->io.outofband.srcaddr4), 0, sizeof (struct sockaddr_in));
ctx->io.outofband.srcaddr4.sin_family = AF_INET;
ctx->io.outofband.srcaddr = (struct sockaddr *)&(ctx->io.outofband.srcaddr4);
ctx->io.outofband.srcaddr_len = sizeof (struct sockaddr_in);
}
else
{
/* zero everywhere, secure ephemeral port */
memset (&(ctx->io.outofband.srcaddr6), 0, sizeof (struct sockaddr_in6));
ctx->io.outofband.srcaddr6.sin6_family = AF_INET6;
ctx->io.outofband.srcaddr = (struct sockaddr *)&(ctx->io.outofband.srcaddr6);
ctx->io.outofband.srcaddr_len = sizeof (struct sockaddr_in6);
}

if (bind (ctx->io.outofband.sockfd,
(struct sockaddr *)&addr,
sizeof (struct sockaddr_in)) < 0)
ctx->io.outofband.srcaddr,
ctx->io.outofband.srcaddr_len) < 0)
{
API_ERRNO_TO_API_ERRNUM (ctx, errno);
return (-1);
Expand Down
20 changes: 7 additions & 13 deletions libfreeipmi/api/ipmi-lan-session-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@ _api_lan_cmd_send (ipmi_ctx_t ctx,
pkt,
send_len,
0,
(struct sockaddr *)&(ctx->io.outofband.remote_host),
sizeof (struct sockaddr_in));
ctx->io.outofband.remote_host,
ctx->io.outofband.remote_host_len);
} while (ret < 0 && errno == EINTR);

if (ret < 0)
Expand Down Expand Up @@ -1030,7 +1030,6 @@ api_lan_cmd_wrapper (ipmi_ctx_t ctx,
if (internal_workaround_flags & IPMI_INTERNAL_WORKAROUND_FLAGS_GET_SESSION_CHALLENGE)
{
struct socket_to_close *s;
struct sockaddr_in addr;

if (!(s = (struct socket_to_close *)malloc (sizeof (struct socket_to_close))))
{
Expand All @@ -1041,22 +1040,17 @@ api_lan_cmd_wrapper (ipmi_ctx_t ctx,
s->next = sockets;
sockets = s;

if ((ctx->io.outofband.sockfd = socket (AF_INET,
if ((ctx->io.outofband.sockfd = socket (ctx->io.outofband.srcaddr->sa_family,
SOCK_DGRAM,
0)) < 0)
{
API_ERRNO_TO_API_ERRNUM (ctx, errno);
goto cleanup;
}

memset (&addr, 0, sizeof (struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons (0);
addr.sin_addr.s_addr = htonl (INADDR_ANY);

if (bind (ctx->io.outofband.sockfd,
(struct sockaddr *)&addr,
sizeof (struct sockaddr_in)) < 0)
ctx->io.outofband.srcaddr,
ctx->io.outofband.srcaddr_len) < 0)
{
API_ERRNO_TO_API_ERRNUM (ctx, errno);
goto cleanup;
Expand Down Expand Up @@ -2264,8 +2258,8 @@ _api_lan_2_0_cmd_send (ipmi_ctx_t ctx,
pkt,
send_len,
0,
(struct sockaddr *)&(ctx->io.outofband.remote_host),
sizeof (struct sockaddr_in));
ctx->io.outofband.remote_host,
ctx->io.outofband.remote_host_len);
} while (ret < 0 && errno == EINTR);

if (ret < 0)
Expand Down

0 comments on commit 6695611

Please sign in to comment.