Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solaris: implement equivalent of getifaddrs() with ioctl() #1514

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ endif
if SUNOS
include_HEADERS += include/uv-sunos.h
libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
if SUNOS_NO_IFADDRS
libuv_la_CFLAGS += -DSUNOS_NO_IFADDRS
endif

libuv_la_SOURCES += src/unix/no-proctitle.c \
src/unix/sunos.c
endif
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ AS_CASE([$host_os],[mingw*], [
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32"
])
AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])])
AM_CONDITIONAL([SUNOS_NO_IFADDRS], [AS_CASE([$host_os],[solaris*], [AC_CHECK_LIB([socket], [getifaddrs])], [false])])
AC_CHECK_HEADERS([sys/ahafs_evProds.h])
AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes)
AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"])
Expand Down
178 changes: 177 additions & 1 deletion src/unix/sunos.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,9 +691,185 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
}

#ifdef SUNOS_NO_IFADDRS
struct __uv_solaris_testsocket {
int sock;
int type;
int domain;
int nb_ifaces;
};

int __solaris_get_nb_ifaces(int sock, int domain) {
int err;
struct lifnum lifnum_info;
lifnum_info.lifn_flags = 0;

if (domain == AF_INET) {
lifnum_info.lifn_family = AF_INET;
} else {
lifnum_info.lifn_family = AF_INET6;
}

if ((err = ioctl(sock, SIOCGLIFNUM, &lifnum_info)) < 0) {
/*fprintf(stderr, "ioctl(): error %d, %s\n", err, strerror(errno));*/
return err;
}
return lifnum_info.lifn_count;
}

int __solaris_gethwaddr(const struct __uv_solaris_testsocket* sock, uv_interface_address_t *uv_address)
{
int err = 0;
struct arpreq arpreq_info;
if (sock->domain == AF_INET) {
memcpy(&arpreq_info.arp_pa, &uv_address->address.address4, sizeof(struct sockaddr_in));
} else {
memcpy(&arpreq_info.arp_pa, &uv_address->address.address6, sizeof(struct sockaddr_in6));
}

if (!uv_address->is_internal) {
if ((err = ioctl(sock->sock, SIOCGARP, &arpreq_info)) < 0) {
/*fprintf(stderr, "ioctl(): error %d, %s\n", errno, strerror(errno));*/
return err;
}
memcpy(uv_address->phys_addr, &arpreq_info.arp_ha.sa_data, 6);
}
return err;
}

int __solaris_getnetmask(const struct __uv_solaris_testsocket* sock, uv_interface_address_t *uv_address)
{
int err;
struct lifreq lifreq_info;
strncpy(lifreq_info.lifr_name, uv_address->name, LIFNAMSIZ - 1);
lifreq_info.lifr_name[LIFNAMSIZ - 1] = '\0';

if ((err = ioctl(sock->sock, SIOCGLIFNETMASK, &lifreq_info)) < 0) {
/*fprintf(stderr, "ioctl(): error %d, %s\n", errno, strerror(errno));*/
return err;
}

if (sock->domain == AF_INET) {
struct sockaddr_in *sockaddr = (struct sockaddr_in*) &lifreq_info.lifr_subnet;
uv_address->netmask.netmask4 = *sockaddr;
} else {
struct sockaddr_in6 *sockaddr6 = (struct sockaddr_in6*) &lifreq_info.lifr_subnet;
uv_address->netmask.netmask6 = *sockaddr6;
}
return err;
}

int __solaris_getifflags(const char* ifname, int sock, uint64_t *flags)
{
int err;
struct lifreq lifreq_info;
strncpy(lifreq_info.lifr_name, ifname, LIFNAMSIZ - 1);
lifreq_info.lifr_name[LIFNAMSIZ - 1] = '\0';
if ((err = ioctl(sock, SIOCGLIFFLAGS, &lifreq_info)) < 0) {
/*fprintf(stderr, "ioctl(): error %d, %s\n", errno, strerror(errno));*/
*flags = 0;
return err;
}
*flags = lifreq_info.lifr_flags;
return err;
}

int __solaris_ifaddr_exclude(uint64_t ifflags)
{
return !((ifflags & IFF_UP) && (ifflags & IFF_RUNNING));
}

int __solaris_getiflist(const struct __uv_solaris_testsocket *sock, uv_interface_address_t *addresses, int *n)
{
int err, i, n_ifaces = 0;
struct lifconf lifconf_info;
lifconf_info.lifc_family = sock->domain;
lifconf_info.lifc_flags = 0;
lifconf_info.lifc_len = sock->nb_ifaces * sizeof(struct lifreq);
lifconf_info.lifc_req = calloc(sock->nb_ifaces, sizeof(struct lifreq));

if ((err = ioctl(sock->sock, SIOCGLIFCONF, &lifconf_info)) < 0) {
/*fprintf(stderr, "ioctl(): error %d, %s\n", err, strerror(errno));*/
return err;
}

for (i = 0; i < sock->nb_ifaces; ++i) {
uint64_t ifflags = 0;
struct lifreq* iface = &lifconf_info.lifc_req[i];
if ((__solaris_getifflags(iface->lifr_name, sock->sock, &ifflags) == 0)
&& !__solaris_ifaddr_exclude(ifflags)) {
addresses[n_ifaces].name = iface->lifr_name;
addresses[n_ifaces].is_internal = (ifflags & IFF_LOOPBACK) ? 1 : 0;
if (sock->domain == AF_INET) {
struct sockaddr_in *sockaddr = (struct sockaddr_in*) &iface->lifr_addr;
addresses[n_ifaces].address.address4 = *sockaddr;
} else {
struct sockaddr_in6 *sockaddr6 = (struct sockaddr_in6*) &iface->lifr_addr;
addresses[n_ifaces].address.address6 = *sockaddr6;
}
err = __solaris_getnetmask(sock, &addresses[n_ifaces]);
err = __solaris_gethwaddr(sock, &addresses[n_ifaces]);
++n_ifaces;
}
}

free(lifconf_info.lifc_req);
*n += n_ifaces;
return err;
}

#define NB_TEST_SOCKETS 2
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return -ENOSYS;
int i, detected_ifaces = 0, upandrunning = 0;
struct __uv_solaris_testsocket socks[NB_TEST_SOCKETS];
for (i = 0; i < NB_TEST_SOCKETS; ++i) {
socks[i].sock = -1;
socks[i].type = SOCK_DGRAM;
socks[i].domain = (i == 0) ? AF_INET : AF_INET6;
socks[i].nb_ifaces = 0;
}

for (i = 0; i < NB_TEST_SOCKETS; ++i) {
if ((socks[i].sock = socket(socks[i].domain, socks[i].type, 0)) < 0) {
/*fprintf(stderr, "socket(): error creating %s socket %d\n",
(socks[i].domain == AF_INET) ? "AF_INET" : "AF_INET6",
socks[i].sock);*/
return socks[i].sock;
}

socks[i].nb_ifaces = __solaris_get_nb_ifaces(socks[i].sock, socks[i].domain);
if (socks[i].nb_ifaces < 0) {
/*fprintf(stderr, "__solaris_get_nb_ifaces(%d, %s)\n",
socks[i].sock,
(socks[i].domain == AF_INET) ? "AF_INET" : "AF_INET6");*/
socks[i].nb_ifaces = 0;
}
}

for (i = 0; i < NB_TEST_SOCKETS; ++i) {
detected_ifaces += socks[i].nb_ifaces;
}

*addresses = calloc(detected_ifaces, sizeof(uv_interface_address_t));
if (!addresses) {
return -ENOMEM;
}

for (i = 0; i < NB_TEST_SOCKETS; ++i) {
if (socks[i].nb_ifaces > 0) {
__solaris_getiflist(&socks[i], &(*addresses)[upandrunning], &upandrunning);
}
}
*count = upandrunning;

for (i = 0; i < NB_TEST_SOCKETS; ++i) {
if (socks[i].sock > 0) {
close(socks[i].sock);
}
}

return EXIT_SUCCESS;
}

#else /* SUNOS_NO_IFADDRS */
/*
* Inspired By:
Expand Down
18 changes: 10 additions & 8 deletions test/test-platform-output.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,16 @@ TEST_IMPL(platform_output) {
for (i = 0; i < count; i++) {
printf(" name: %s\n", interfaces[i].name);
printf(" internal: %d\n", interfaces[i].is_internal);
printf(" physical address: ");
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
(unsigned char)interfaces[i].phys_addr[0],
(unsigned char)interfaces[i].phys_addr[1],
(unsigned char)interfaces[i].phys_addr[2],
(unsigned char)interfaces[i].phys_addr[3],
(unsigned char)interfaces[i].phys_addr[4],
(unsigned char)interfaces[i].phys_addr[5]);
if (!interfaces[i].is_internal) {
printf(" physical address: ");
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
(unsigned char)interfaces[i].phys_addr[0],
(unsigned char)interfaces[i].phys_addr[1],
(unsigned char)interfaces[i].phys_addr[2],
(unsigned char)interfaces[i].phys_addr[3],
(unsigned char)interfaces[i].phys_addr[4],
(unsigned char)interfaces[i].phys_addr[5]);
}

if (interfaces[i].address.address4.sin_family == AF_INET) {
uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer));
Expand Down