From 030a334125e5752f516475058630e0bd16c00bc0 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 13 Oct 2015 03:14:13 +0000 Subject: rsock_addrinfo: specify address family * ext/socket/rsock_addrinfo (rsock_addrinfo): specify address family. [Fix GH-1052] * ext/socket/udpsocket.c (udp_connect, udp_bind, udp_send): address family by the receiver. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52117 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/socket/ipsocket.c | 11 +++++++---- ext/socket/raddrinfo.c | 16 ++++++++++++++-- ext/socket/rubysocket.h | 3 ++- ext/socket/socket.c | 6 ++++-- ext/socket/tcpsocket.c | 5 +++-- ext/socket/udpsocket.c | 6 +++--- 6 files changed, 33 insertions(+), 14 deletions(-) (limited to 'ext/socket') diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c index 8d8d6335d1..9981fd43ad 100644 --- a/ext/socket/ipsocket.c +++ b/ext/socket/ipsocket.c @@ -45,16 +45,19 @@ init_inetsock_internal(struct inetsock_arg *arg) int type = arg->type; struct addrinfo *res, *lres; int fd, status = 0, local = 0; + int family = AF_UNSPEC; const char *syscall = 0; - arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0); + arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, + family, SOCK_STREAM, + (type == INET_SERVER) ? AI_PASSIVE : 0); /* * Maybe also accept a local address */ if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) { - arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0); + arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, + family, SOCK_STREAM, 0); } arg->fd = fd = -1; @@ -308,7 +311,7 @@ static VALUE ip_s_getaddress(VALUE obj, VALUE host) { union_sockaddr addr; - struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, SOCK_STREAM, 0); + struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0); socklen_t len = res->ai->ai_addrlen; /* just take the first one */ diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index 7aaa83128e..b42707454a 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -518,13 +518,25 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h return res; } +int +rsock_fd_family(int fd) +{ + struct sockaddr sa = { 0 }; + socklen_t sa_len = sizeof(sa); + + if (fd < 0 || getsockname(fd, &sa, &sa_len) != 0) { + return AF_UNSPEC; + } + return sa.sa_family; +} + struct rb_addrinfo* -rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags) +rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags) { struct addrinfo hints; MEMZERO(&hints, struct addrinfo, 1); - hints.ai_family = AF_UNSPEC; + hints.ai_family = family; hints.ai_socktype = socktype; hints.ai_flags = flags; return rsock_getaddrinfo(host, port, &hints, 1); diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 79dd78324f..22a61e3777 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -295,7 +295,8 @@ int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo void rb_freeaddrinfo(struct rb_addrinfo *ai); VALUE rsock_freeaddrinfo(VALUE arg); int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); -struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags); +int rsock_fd_family(int fd); +struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags); struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack); VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len); VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len); diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 2e7bf96c87..6da47e8199 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -1140,7 +1140,9 @@ sock_sockaddr(struct sockaddr *addr, socklen_t len) static VALUE sock_s_gethostbyname(VALUE obj, VALUE host) { - return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr); + struct rb_addrinfo *res = + rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME); + return rsock_make_hostent(host, res, sock_sockaddr); } /* @@ -1518,7 +1520,7 @@ sock_s_getnameinfo(int argc, VALUE *argv) static VALUE sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host) { - struct rb_addrinfo *res = rsock_addrinfo(host, port, 0, 0); + struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0); VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen); rb_freeaddrinfo(res); diff --git a/ext/socket/tcpsocket.c b/ext/socket/tcpsocket.c index 65943a7a59..a7a82fd880 100644 --- a/ext/socket/tcpsocket.c +++ b/ext/socket/tcpsocket.c @@ -50,8 +50,9 @@ tcp_sockaddr(struct sockaddr *addr, socklen_t len) static VALUE tcp_s_gethostbyname(VALUE obj, VALUE host) { - return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), - tcp_sockaddr); + struct rb_addrinfo *res = + rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME); + return rsock_make_hostent(host, res, tcp_sockaddr); } void diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c index d31930275f..d55ddfe6bb 100644 --- a/ext/socket/udpsocket.c +++ b/ext/socket/udpsocket.c @@ -87,7 +87,7 @@ udp_connect(VALUE sock, VALUE host, VALUE port) VALUE ret; GetOpenFile(sock, arg.fptr); - arg.res = rsock_addrinfo(host, port, SOCK_DGRAM, 0); + arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0); ret = rb_ensure(udp_connect_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); if (!ret) rsock_sys_fail_host_port("connect(2)", host, port); @@ -131,7 +131,7 @@ udp_bind(VALUE sock, VALUE host, VALUE port) VALUE ret; GetOpenFile(sock, arg.fptr); - arg.res = rsock_addrinfo(host, port, SOCK_DGRAM, 0); + arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0); ret = rb_ensure(udp_bind_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); if (!ret) rsock_sys_fail_host_port("bind(2)", host, port); @@ -207,7 +207,7 @@ udp_send(int argc, VALUE *argv, VALUE sock) GetOpenFile(sock, arg.fptr); arg.sarg.fd = arg.fptr->fd; arg.sarg.flags = NUM2INT(flags); - arg.res = rsock_addrinfo(host, port, SOCK_DGRAM, 0); + arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0); ret = rb_ensure(udp_send_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); if (!ret) rsock_sys_fail_host_port("sendto(2)", host, port); -- cgit v1.2.3