[erlang-patches] [PATCH 1/2] epmd: support IPv6 node registration

Michael Santos <>
Fri Jun 3 16:49:25 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) ->
+    Localhost = case Family of
+        inet -> {127,0,0,1};
+        inet6 -> {0,0,0,0,0,0,0,1}
+    end,
+    case open(Localhost) 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