summaryrefslogtreecommitdiff
path: root/deps/uv/src/unix/sunos.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src/unix/sunos.c')
-rw-r--r--deps/uv/src/unix/sunos.c75
1 files changed, 52 insertions, 23 deletions
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index e67be8fcf8..3e7a7592d9 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -33,6 +33,8 @@
#endif
#include <net/if.h>
#include <net/if_dl.h>
+#include <net/if_arp.h>
+#include <sys/sockio.h>
#include <sys/loadavg.h>
#include <sys/time.h>
@@ -540,9 +542,10 @@ int uv_set_process_title(const char* title) {
int uv_get_process_title(char* buffer, size_t size) {
- if (size > 0) {
- buffer[0] = '\0';
- }
+ if (buffer == NULL || size == 0)
+ return -EINVAL;
+
+ buffer[0] = '\0';
return 0;
}
@@ -692,13 +695,57 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
+/*
+ * Inspired By:
+ * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris
+ * http://www.pauliesworld.org/project/getmac.c
+ */
+static int uv__set_phys_addr(uv_interface_address_t* address,
+ struct ifaddrs* ent) {
+
+ struct sockaddr_dl* sa_addr;
+ int sockfd;
+ int i;
+ struct arpreq arpreq;
+
+ /* This appears to only work as root */
+ sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
+ memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
+ for (i = 0; i < sizeof(address->phys_addr); i++) {
+ if (address->phys_addr[i] != 0)
+ return 0;
+ }
+ memset(&arpreq, 0, sizeof(arpreq));
+ if (address->address.address4.sin_family == AF_INET) {
+ struct sockaddr_in* sin = ((struct sockaddr_in*)&arpreq.arp_pa);
+ sin->sin_addr.s_addr = address->address.address4.sin_addr.s_addr;
+ } else if (address->address.address4.sin_family == AF_INET6) {
+ struct sockaddr_in6* sin = ((struct sockaddr_in6*)&arpreq.arp_pa);
+ memcpy(sin->sin6_addr.s6_addr,
+ address->address.address6.sin6_addr.s6_addr,
+ sizeof(address->address.address6.sin6_addr.s6_addr));
+ } else {
+ return 0;
+ }
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ return -errno;
+
+ if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) {
+ uv__close(sockfd);
+ return -errno;
+ }
+ memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr));
+ uv__close(sockfd);
+ return 0;
+}
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#ifdef SUNOS_NO_IFADDRS
return -ENOSYS;
#else
uv_interface_address_t* address;
- struct sockaddr_dl* sa_addr;
struct ifaddrs* addrs;
struct ifaddrs* ent;
int i;
@@ -751,28 +798,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address->is_internal = !!((ent->ifa_flags & IFF_PRIVATE) ||
(ent->ifa_flags & IFF_LOOPBACK));
+ uv__set_phys_addr(address, ent);
address++;
}
- /* Fill in physical addresses for each interface */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != AF_LINK)) {
- continue;
- }
-
- address = *addresses;
-
- for (i = 0; i < (*count); i++) {
- if (strcmp(address->name, ent->ifa_name) == 0) {
- sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
- memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
- }
- address++;
- }
- }
-
freeifaddrs(addrs);
return 0;