aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Santos <[email protected]>2010-07-21 14:50:58 -0400
committerRaimo Niskanen <[email protected]>2010-09-03 16:52:28 +0200
commit8393c5d5b682f8acbdc0ecf5b0e6f87589a314cb (patch)
tree969d5157e09771f4743cfa52987abb62a2fc9a28
parentd61d41e235bc464a15925e6fd1b7e9138477d3b3 (diff)
downloadotp-8393c5d5b682f8acbdc0ecf5b0e6f87589a314cb.tar.gz
otp-8393c5d5b682f8acbdc0ecf5b0e6f87589a314cb.tar.bz2
otp-8393c5d5b682f8acbdc0ecf5b0e6f87589a314cb.zip
inet: support retrieving MAC address on BSD
On systems supporting getaddrinfo(), support looking up the MAC address from inet:ifget/2. The results have the same quirks as with Linux: if the MAC address is longer than 6 bytes (e.g., fw0 under Mac OS X), the address is truncated; if the interface does not have a MAC address (e.g., lo0), an address consisting of 0's is returned.
-rw-r--r--erts/configure.in3
-rw-r--r--erts/emulator/drivers/common/inet_drv.c40
-rw-r--r--lib/kernel/test/inet_SUITE.erl11
3 files changed, 50 insertions, 4 deletions
diff --git a/erts/configure.in b/erts/configure.in
index 63bf548c89..74cb9533f3 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -1764,6 +1764,9 @@ AC_CHECK_FUNCS([fdatasync])
dnl Find which C libraries are required to use fdatasync
AC_SEARCH_LIBS(fdatasync, [rt])
+AC_CHECK_HEADERS(net/if_dl.h ifaddrs.h)
+AC_CHECK_FUNCS([getifaddrs])
+
dnl ----------------------------------------------------------------------
dnl Checks for features/quirks in the system that affects Erlang.
dnl ----------------------------------------------------------------------
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 8e312c0292..dfa3814d78 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -48,6 +48,12 @@
#include <sys/uio.h>
#endif
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
/* All platforms fail on malloc errors. */
#define FATAL_MALLOC
@@ -4089,6 +4095,10 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
}
+/* FIXME: temporary hack */
+#ifndef IFHWADDRLEN
+#define IFHWADDRLEN 6
+#endif
static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
char** rbuf, int rsize)
@@ -4128,6 +4138,32 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
/* raw memcpy (fix include autoconf later) */
sys_memcpy(sptr, (char*)(&ifreq.ifr_hwaddr.sa_data), IFHWADDRLEN);
sptr += IFHWADDRLEN;
+#elif defined(HAVE_GETIFADDRS)
+ struct ifaddrs *ifa, *ifp;
+ int found = 0;
+
+ if (getifaddrs(&ifa) == -1)
+ goto error;
+
+ for (ifp = ifa; ifp; ifp = ifp->ifa_next) {
+ if ((ifp->ifa_addr->sa_family == AF_LINK) &&
+ (sys_strcmp(ifp->ifa_name, ifreq.ifr_name) == 0)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ freeifaddrs(ifa);
+ break;
+ }
+
+ buf_check(sptr, s_end, 1+IFHWADDRLEN);
+ *sptr++ = INET_IFOPT_HWADDR;
+ sys_memcpy(sptr, ((struct sockaddr_dl *)ifp->ifa_addr)->sdl_data +
+ ((struct sockaddr_dl *)ifp->ifa_addr)->sdl_nlen, IFHWADDRLEN);
+ freeifaddrs(ifa);
+ sptr += IFHWADDRLEN;
#endif
break;
}
@@ -4240,10 +4276,6 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
return ctl_error(EINVAL, rbuf, rsize);
}
-/* FIXME: temporary hack */
-#ifndef IFHWADDRLEN
-#define IFHWADDRLEN 6
-#endif
static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
char** rbuf, int rsize)
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 86c2a0cbca..f4f27933a5 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -877,6 +877,17 @@ getif(Config) when is_list(Config) ->
?line {ok,Address} = inet:getaddr(Hostname, inet),
?line {ok,Loopback} = inet:getaddr("localhost", inet),
?line {ok,Interfaces} = inet:getiflist(),
+ ?line HWAs =
+ lists:sort(
+ lists:foldl(
+ fun (I, Acc) ->
+ case inet:ifget(I, [hwaddr]) of
+ {ok,[{hwaddr,A}]} -> [A|Acc];
+ {ok,[]} -> Acc
+ end
+ end, [], Interfaces)),
+ ?line io:format("HWAs = ~p~n", [HWAs]),
+ ?line length(HWAs) > 0 orelse ?t:fail(no_HWAs),
?line Addresses =
lists:sort(
lists:foldl(