aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/drivers/common
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2014-07-11 10:46:37 +0200
committerHenrik Nord <[email protected]>2014-07-22 09:29:22 +0200
commit8a6390613225ec3f3e2d5bbf537d2e0737342e87 (patch)
treea89fa6a8466484f4d3e91793659dc77763af5565 /erts/emulator/drivers/common
parent450f0f893b5d28e6d967b163111f8a8a6032b0e1 (diff)
downloadotp-8a6390613225ec3f3e2d5bbf537d2e0737342e87.tar.gz
otp-8a6390613225ec3f3e2d5bbf537d2e0737342e87.tar.bz2
otp-8a6390613225ec3f3e2d5bbf537d2e0737342e87.zip
kernel: When doing an fdopen we now also bind the fd to the specified addr/port
Diffstat (limited to 'erts/emulator/drivers/common')
-rw-r--r--erts/emulator/drivers/common/inet_drv.c33
1 files changed, 25 insertions, 8 deletions
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)