1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/*
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include <stdlib.h>
#include <string.h>
#include "opal/constants.h"
#include "opal/mca/if/if.h"
#include "opal/util/output.h"
#include "opal/util/string_copy.h"
static int if_solaris_ipv6_open(void);
/* Discovers Solaris IPv6 interfaces */
opal_if_base_component_t mca_if_solaris_ipv6_component = {
/* First, the mca_component_t struct containing meta information
about the component itself */
{OPAL_IF_BASE_VERSION_2_0_0,
/* Component name and version */
"solaris_ipv6", OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, OPAL_RELEASE_VERSION,
/* Component open and close functions */
if_solaris_ipv6_open, NULL},
{/* This component is checkpointable */
MCA_BASE_METADATA_PARAM_CHECKPOINT},
};
/* configure using getifaddrs(3) */
static int if_solaris_ipv6_open(void)
{
#if OPAL_ENABLE_IPV6
int i;
int sd;
int error;
uint16_t kindex;
struct lifnum lifnum;
struct lifconf lifconf;
struct lifreq *lifreq, lifquery;
sd = socket(AF_INET6, SOCK_DGRAM, 0);
if (sd < 0) {
opal_output(0, "opal_ifinit: unable to open IPv6 socket\n");
return OPAL_ERROR;
}
/* we only ask for IPv6; IPv4 discovery has already been done */
lifnum.lifn_family = AF_INET6;
lifnum.lifn_flags = 0;
lifnum.lifn_count = 0;
/* get the number of interfaces in the system */
error = ioctl(sd, SIOCGLIFNUM, &lifnum);
if (error < 0) {
opal_output(0, "opal_ifinit: ioctl SIOCGLIFNUM failed with errno=%d\n", errno);
return OPAL_ERROR;
}
memset(&lifconf, 0, sizeof(struct lifconf));
memset(&lifquery, 0, sizeof(struct lifreq));
lifconf.lifc_family = AF_INET6;
lifconf.lifc_flags = 0;
lifconf.lifc_len = lifnum.lifn_count * sizeof(struct lifreq) * 2;
lifconf.lifc_buf = malloc(lifconf.lifc_len);
if (NULL == lifconf.lifc_buf) {
opal_output(0, "opal_ifinit: IPv6 discovery: malloc() failed\n");
return OPAL_ERR_OUT_OF_RESOURCE;
}
memset(lifconf.lifc_buf, 0, lifconf.lifc_len);
error = ioctl(sd, SIOCGLIFCONF, &lifconf);
if (error < 0) {
opal_output(0, "opal_ifinit: IPv6 SIOCGLIFCONF failed with errno=%d\n", errno);
}
for (i = 0; i + sizeof(struct lifreq) <= lifconf.lifc_len; i += sizeof(*lifreq)) {
lifreq = (struct lifreq *) ((caddr_t) lifconf.lifc_buf + i);
opal_string_copy(lifquery.lifr_name, lifreq->lifr_name, sizeof(lifquery.lifr_name));
/* lookup kernel index */
error = ioctl(sd, SIOCGLIFINDEX, &lifquery);
if (error < 0) {
opal_output(0, "opal_ifinit: SIOCGLIFINDEX failed with errno=%d\n", errno);
return OPAL_ERROR;
}
kindex = lifquery.lifr_index;
/* lookup interface flags */
error = ioctl(sd, SIOCGLIFFLAGS, &lifquery);
if (error < 0) {
opal_output(0, "opal_ifinit: SIOCGLIFFLAGS failed with errno=%d\n", errno);
return OPAL_ERROR;
}
if (AF_INET6 == lifreq->lifr_addr.ss_family) {
struct sockaddr_in6 *my_addr = (struct sockaddr_in6 *) &lifreq->lifr_addr;
/* we surely want to check for sin6_scope_id, but Solaris
does not set it correctly, so we have to look for
global scope. For now, global is anything which is
neither loopback nor link local.
Bug, FIXME: site-local, multicast, ... missing
Check for 2000::/3?
*/
if ((!opal_if_retain_loopback && !IN6_IS_ADDR_LOOPBACK(&my_addr->sin6_addr))
&& (!IN6_IS_ADDR_LINKLOCAL(&my_addr->sin6_addr))) {
/* create interface for newly found address */
opal_if_t *intf;
intf = OBJ_NEW(opal_if_t);
if (NULL == intf) {
opal_output(0, "opal_ifinit: unable to allocate %d bytes\n", sizeof(opal_if_t));
return OPAL_ERR_OUT_OF_RESOURCE;
}
intf->af_family = AF_INET6;
opal_string_copy(intf->if_name, lifreq->lifr_name, OPAL_IF_NAMESIZE);
intf->if_index = opal_list_get_size(&opal_if_list) + 1;
memcpy(&intf->if_addr, my_addr, sizeof(*my_addr));
intf->if_mask = 64;
/* lifrq flags are uint64_t */
intf->if_flags = (uint32_t)(0x00000000ffffffff) & lifquery.lifr_flags;
/* append to list */
opal_list_append(&opal_if_list, &(intf->super));
}
}
} /* for */
if (NULL != lifconf.lifc_buf) {
free(lifconf.lifc_buf);
}
#endif /* OPAL_ENABLE_IPV6 */
return OPAL_SUCCESS;
}
|