From 8a6390613225ec3f3e2d5bbf537d2e0737342e87 Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang-solutions.com>
Date: Fri, 11 Jul 2014 10:46:37 +0200
Subject: kernel: When doing an fdopen we now also bind the fd to the specified
 addr/port

---
 erts/emulator/drivers/common/inet_drv.c |  33 ++++++++++++++++++++++++--------
 erts/preloaded/ebin/prim_inet.beam      | Bin 72280 -> 72484 bytes
 erts/preloaded/src/prim_inet.erl        |   9 +++++++--
 erts/vsn.mk                             |   2 +-
 4 files changed, 33 insertions(+), 11 deletions(-)

(limited to 'erts')

diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 45fac69303..4f0bf1167e 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -4155,7 +4155,8 @@ static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type,
 
 /* as inet_open but pass in an open socket (MUST BE OF RIGHT TYPE) */
 static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
-				    SOCKET s, char** rbuf, ErlDrvSizeT rsize)
+				    SOCKET s, Uint32 bound,
+                                    char** rbuf, ErlDrvSizeT rsize)
 {
     inet_address name;
     unsigned int sz = sizeof(name);
@@ -4172,7 +4173,12 @@ static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
 #ifdef __WIN32__
     driver_select(desc->port, desc->event, ERL_DRV_READ, 1);
 #endif
-    desc->state = INET_STATE_BOUND; /* assume bound */
+
+    if (bound)
+        desc->state = INET_STATE_BOUND;
+    else
+        desc->state = INET_STATE_OPEN;
+
     if (type == SOCK_STREAM) { /* check if connected */
 	sz = sizeof(name);
 	if (!IS_SOCKET_ERROR(sock_peer(s, (struct sockaddr*) &name, &sz)))
@@ -8642,10 +8648,11 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
 	break;
     }
 
-    case INET_REQ_FDOPEN: {  /* pass in an open socket */
+    case INET_REQ_FDOPEN: {  /* pass in an open (and optionally bound) socket */
 	int domain;
+        int bound;
 	DEBUGF(("tcp_inet_ctl(%ld): FDOPEN\r\n", (long)desc->inet.port));
-	if (len != 6) return ctl_error(EINVAL, rbuf, rsize);
+	if (len != 6 && len != 10) return ctl_error(EINVAL, rbuf, rsize);
 	switch(buf[0]) {
 	case INET_AF_INET:
 	    domain = AF_INET;
@@ -8663,8 +8670,13 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
 	    return ctl_error(EINVAL, rbuf, rsize);
 	}
 	if (buf[1] != INET_TYPE_STREAM) return ctl_error(EINVAL, rbuf, rsize);
+
+        if (len == 6) bound = 1;
+        else bound = get_int32(buf+2+4);
+
 	return inet_ctl_fdopen(INETP(desc), domain, SOCK_STREAM,
-			       (SOCKET) get_int32(buf+2), rbuf, rsize);
+                               (SOCKET) get_int32(buf+2),
+                               bound, rbuf, rsize);
 	break;
     }
 
@@ -10409,10 +10421,11 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
 	return replen;
 
 
-    case INET_REQ_FDOPEN: {  /* pass in an open (and bound) socket */
+    case INET_REQ_FDOPEN: {  /* pass in an open (and optionally bound) socket */
 	SOCKET s;
+        int bound;
 	DEBUGF(("packet inet_ctl(%ld): FDOPEN\r\n", (long)desc->port));
-	if (len != 6) {
+	if (len != 6 && len != 10) {
 	    return ctl_error(EINVAL, rbuf, rsize);
 	}
 	switch (buf[0]) {
@@ -10437,7 +10450,11 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
 	    return ctl_error(EINVAL, rbuf, rsize);
 	}
 	s = (SOCKET)get_int32(buf+2);
-	replen = inet_ctl_fdopen(desc, af, type, s, rbuf, rsize);
+
+        if (len == 6) bound = 1;
+        else bound = get_int32(buf+2+4);
+
+	replen = inet_ctl_fdopen(desc, af, type, s, bound, rbuf, rsize);
 
 	if ((*rbuf)[0] != INET_REP_ERROR) {
 	    if (desc->active)
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index 656fbc6627..412ad8290b 100644
Binary files a/erts/preloaded/ebin/prim_inet.beam and b/erts/preloaded/ebin/prim_inet.beam differ
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index a9df75327c..e3ba8a328a 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -25,7 +25,7 @@
 
 %% Primitive inet_drv interface
 
--export([open/3, open/4, fdopen/4, close/1]).
+-export([open/3, open/4, fdopen/4, fdopen/5, close/1]).
 -export([bind/3, listen/1, listen/2, peeloff/2]).
 -export([connect/3, connect/4, async_connect/4]).
 -export([accept/1, accept/2, async_accept/2]).
@@ -70,7 +70,12 @@ open(Protocol, Family, Type, Opts) ->
     open(Protocol, Family, Type, Opts, ?INET_REQ_OPEN, []).
 
 fdopen(Protocol, Family, Type, Fd) when is_integer(Fd) ->
-    open(Protocol, Family, Type, [], ?INET_REQ_FDOPEN, ?int32(Fd)).
+    fdopen(Protocol, Family, Type, Fd, true).
+
+fdopen(Protocol, Family, Type, Fd, Bound)
+  when is_integer(Fd), Bound == true orelse Bound == false ->
+    open(Protocol, Family, Type, [], ?INET_REQ_FDOPEN,
+         [?int32(Fd), enc_value_2(bool, Bound)]).
 
 open(Protocol, Family, Type, Opts, Req, Data) ->
     Drv = protocol2drv(Protocol),
diff --git a/erts/vsn.mk b/erts/vsn.mk
index 0355901877..af74fb96c9 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -17,7 +17,7 @@
 # %CopyrightEnd%
 # 
 
-VSN = 5.10.4
+VSN = 5.10.4.1
 SYSTEM_VSN = R16B03-1
 
 # Port number 4365 in 4.2
-- 
cgit v1.2.3


From 03a1fcf5346233f76c8dc50844e132f4760154d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= <egil@erlang.org>
Date: Mon, 26 May 2014 19:33:24 +0200
Subject: erts: Fix inet close on prebound fds

Inet close must remove fd from select/poll without closing the fd.
---
 erts/emulator/drivers/common/inet_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'erts')

diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 4f0bf1167e..4cc31c1344 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -4053,7 +4053,7 @@ static int erl_inet_close(inet_descriptor* desc)
 	desc_close(desc);
 	desc->state = INET_STATE_CLOSED;
     } else if (desc->prebound && (desc->s != INVALID_SOCKET)) {
-	sock_select(desc, FD_READ | FD_WRITE | FD_CLOSE, 0);
+	sock_select(desc, FD_READ | FD_WRITE | FD_CLOSE | ERL_DRV_USE_NO_CALLBACK, 0);
 	desc->event_mask = 0;
 #ifdef __WIN32__
 	desc->forced_events = 0;
-- 
cgit v1.2.3


From 65e335e255cb76d979f605ed34700e4e02041139 Mon Sep 17 00:00:00 2001
From: Erlang/OTP <otp@erlang.org>
Date: Tue, 22 Jul 2014 18:01:29 +0200
Subject: Update release notes

---
 erts/doc/src/notes.xml | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

(limited to 'erts')

diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 8c008c493e..2fe8879b93 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -30,6 +30,27 @@
   </header>
   <p>This document describes the changes made to the ERTS application.</p>
 
+<section><title>Erts 5.10.4.1</title>
+
+    <section><title>Known Bugs and Problems</title>
+      <list>
+        <item>
+          <p>
+	    When using gen_tcp:connect and the <c>fd</c> option with
+	    <c>port</c> and/or <c>ip</c>, the <c>port</c> and
+	    <c>ip</c> options were ignored. This has been fixed so
+	    that if <c>port</c> and/or <c>ip</c> is specified
+	    together with <c>fd</c> a bind is requested for that
+	    <c>fd</c>. If <c>port</c> and/or <c>ip</c> is not
+	    specified bind will not be called.</p>
+          <p>
+	    Own Id: OTP-12061</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Erts 5.10.4</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
-- 
cgit v1.2.3