[erlang-patches] [PATCH 1/2] epmd: support IPv6 node registration
Michael Santos
michael.santos@REDACTED
Fri Jun 3 16:33:50 CEST 2011
Allow IPv6 nodes to register with and query epmd. epmd now listens on
an IPv6 socket by default (if IPv6 support is available).
Reported-By: Boris Mühmer
---
erts/epmd/src/epmd_int.h | 2 +-
erts/epmd/src/epmd_srv.c | 66 +++++++++++++++++++++++-------------
lib/kernel/src/erl_epmd.erl | 18 +++++++---
lib/kernel/src/inet6_tcp_dist.erl | 2 +-
4 files changed, 56 insertions(+), 32 deletions(-)
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index 2a0de4d..850607b 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -165,7 +165,7 @@
/* ************************************************************************ */
/* Macros that let us use IPv6 */
-#if defined(HAVE_IN6) && defined(AF_INET6) && defined(EPMD6)
+#if defined(HAVE_IN6) && defined(AF_INET6)
#define EPMD_SOCKADDR_IN sockaddr_in6
#define EPMD_IN_ADDR in6_addr
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index 4d9b454..ea7caf2 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -69,6 +69,7 @@ static time_t current_time(EpmdVars*);
static Connection *conn_init(EpmdVars*);
static int conn_open(EpmdVars*,int);
+static int conn_local_access_check(int fd);
static int conn_close_fd(EpmdVars*,int);
static void node_init(EpmdVars*);
@@ -122,7 +123,7 @@ void run(EpmdVars *g)
epmd_cleanup_exit(g,1);
}
else if (ret == 0)
-#elif !defined(EPMD6)
+#else
if ((addr.EPMD_S_ADDR = inet_addr(token)) == INADDR_NONE)
#endif
{
@@ -808,15 +809,6 @@ static int conn_open(EpmdVars *g,int fd)
for (i = 0; i < g->max_conn; i++) {
if (g->conn[i].open == EPMD_FALSE) {
- struct sockaddr_in si;
- struct sockaddr_in di;
-#ifdef HAVE_SOCKLEN_T
- socklen_t st;
-#else
- int st;
-#endif
- st = sizeof(si);
-
g->active_conn++;
s = &g->conn[i];
@@ -827,20 +819,7 @@ static int conn_open(EpmdVars *g,int fd)
s->open = EPMD_TRUE;
s->keep = EPMD_FALSE;
- /* Determine if connection is from localhost */
- if (getpeername(s->fd,(struct sockaddr*) &si,&st) ||
- st < sizeof(si)) {
- /* Failure to get peername is regarded as non local host */
- s->local_peer = EPMD_FALSE;
- } else {
- /* Only 127.x.x.x and connections from the host's IP address
- allowed, no false positives */
- s->local_peer =
- (((((unsigned) ntohl(si.sin_addr.s_addr)) & 0xFF000000U) ==
- 0x7F000000U) ||
- (getsockname(s->fd,(struct sockaddr*) &di,&st) ?
- EPMD_FALSE : si.sin_addr.s_addr == di.sin_addr.s_addr));
- }
+ s->local_peer = conn_local_access_check(s->fd);
dbg_tty_printf(g,2,(s->local_peer) ? "Local peer connected" :
"Non-local peer connected");
@@ -866,6 +845,45 @@ static int conn_open(EpmdVars *g,int fd)
return EPMD_FALSE;
}
+static int conn_local_access_check(int fd)
+{
+ struct EPMD_SOCKADDR_IN si;
+ struct EPMD_SOCKADDR_IN di;
+#ifdef HAVE_SOCKLEN_T
+ socklen_t st;
+#else
+ int st;
+#endif
+ st = sizeof(si);
+
+ /* Determine if connection is from localhost */
+ if (getpeername(fd,(struct sockaddr*) &si,&st) ||
+ st < sizeof(si)) {
+ /* Failure to get peername is regarded as non local host */
+ return EPMD_FALSE;
+ }
+
+ /* Only 127.x.x.x and connections from the host's IP address
+ allowed, no false positives */
+#if defined(HAVE_IN6) && defined(AF_INET6)
+ if (IN6_IS_ADDR_LOOPBACK(&si.sin6_addr))
+ return EPMD_TRUE;
+#else
+ if ((((unsigned) ntohl(si.sin_addr.s_addr)) & 0xFF000000U) ==
+ 0x7F000000U)
+ return EPMD_TRUE;
+#endif
+
+ if (getsockname(fd,(struct sockaddr*) &di,&st))
+ return EPMD_FALSE;
+
+#if defined(HAVE_IN6) && defined(AF_INET6)
+ return IN6_ARE_ADDR_EQUAL(&si.sin6_addr, &di.sin6_addr);
+#else
+ return si.sin_addr.s_addr == di.sin_addr.s_addr;
+#endif
+}
+
static int conn_close_fd(EpmdVars *g,int fd)
{
int i;
diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl
index 91af49f..e9d1caa 100644
--- a/lib/kernel/src/erl_epmd.erl
+++ b/lib/kernel/src/erl_epmd.erl
@@ -31,7 +31,7 @@
%% External exports
-export([start/0, start_link/0, stop/0, port_please/2,
port_please/3, names/0, names/1,
- register_node/2, open/0, open/1, open/2]).
+ register_node/2, register_node/3, open/0, open/1, open/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -106,7 +106,9 @@ names1(HostName) ->
register_node(Name, PortNo) ->
- gen_server:call(erl_epmd, {register, Name, PortNo}, infinity).
+ register_node(Name, PortNo, inet).
+register_node(Name, PortNo, Family) ->
+ gen_server:call(erl_epmd, {register, Name, PortNo, Family}, infinity).
%%%----------------------------------------------------------------------
%%% Callback functions from gen_server
@@ -124,10 +126,10 @@ init(_) ->
-spec handle_call(calls(), term(), state()) ->
{'reply', term(), state()} | {'stop', 'shutdown', 'ok', state()}.
-handle_call({register, Name, PortNo}, _From, State) ->
+handle_call({register, Name, PortNo, Family}, _From, State) ->
case State#state.socket of
P when P < 0 ->
- case do_register_node(Name, PortNo) of
+ case do_register_node(Name, PortNo, Family) of
{alive, Socket, Creation} ->
S = State#state{socket = Socket,
port_no = PortNo,
@@ -210,8 +212,12 @@ open({A,B,C,D,E,F,G,H}=EpmdAddr, Timeout) when ?ip6(A,B,C,D,E,F,G,H) ->
close(Socket) ->
gen_tcp:close(Socket).
-do_register_node(NodeName, TcpPort) ->
- case open() of
+do_register_node(NodeName, TcpPort, Family) ->
+ Register = case Family of
+ inet -> open({127,0,0,1});
+ inet6 -> open({0,0,0,0,0,0,0,1})
+ end,
+ case Register of
{ok, Socket} ->
Name = to_string(NodeName),
Extra = "",
diff --git a/lib/kernel/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl
index b9c4fa6..0b5fb44 100644
--- a/lib/kernel/src/inet6_tcp_dist.erl
+++ b/lib/kernel/src/inet6_tcp_dist.erl
@@ -71,7 +71,7 @@ listen(Name) ->
{ok, Socket} ->
TcpAddress = get_tcp_address(Socket),
{_,Port} = TcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
+ {ok, Creation} = erl_epmd:register_node(Name, Port, inet6),
{ok, {Socket, TcpAddress, Creation}};
Error ->
Error
--
1.7.0.4
More information about the erlang-patches
mailing list