diff options
author | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-01-29 02:25:39 +0000 |
---|---|---|
committer | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-01-29 02:25:39 +0000 |
commit | 68db4a346417a4544399dbe1643a8e945c69755a (patch) | |
tree | 6f161bc05687e5e04a6ef5acb718c5e191e01b04 /ext/socket | |
parent | d899ed632189db0d07c7fa7729f2e3124900f84c (diff) | |
download | ruby-68db4a346417a4544399dbe1643a8e945c69755a.tar.gz |
* ext/socket/spclet.c (socket_s_ip_address_list): support Windows XP
or later. (Win2k or earlier is still not supported)
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21863 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket')
-rw-r--r-- | ext/socket/raddrinfo.c | 2 | ||||
-rw-r--r-- | ext/socket/socket.c | 93 |
2 files changed, 93 insertions, 2 deletions
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index f5ea91af85..8966518dfd 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -914,7 +914,7 @@ inspect_sockaddr(VALUE addrinfo, VALUE ret) break; } -#ifdef INET6 +#ifdef AF_INET6 case AF_INET6: { struct sockaddr_in6 *addr; diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 20631e9da7..6ef0b3d4d8 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -1386,7 +1386,7 @@ sock_s_unpack_sockaddr_un(VALUE self, VALUE addr) } #endif -#if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) +#if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) || defined(_WIN32) static VALUE sockaddr_obj(struct sockaddr *addr) { @@ -1612,6 +1612,97 @@ socket_s_ip_address_list(VALUE self) return list; #undef EXTRA_SPACE +#elif defined(_WIN32) + typedef struct ip_adapter_unicast_address_st { + unsigned LONG_LONG dummy0; + struct ip_adapter_unicast_address_st *Next; + struct { + struct sockaddr *lpSockaddr; + int iSockaddrLength; + } Address; + int dummy1; + int dummy2; + int dummy3; + long dummy4; + long dummy5; + long dummy6; + } ip_adapter_unicast_address_t; + typedef struct ip_adapter_anycast_address_st { + unsigned LONG_LONG dummy0; + struct ip_adapter_anycast_address_st *Next; + struct { + struct sockaddr *lpSockaddr; + int iSockaddrLength; + } Address; + } ip_adapter_anycast_address_t; + typedef struct ip_adapter_addresses_st { + unsigned LONG_LONG dummy0; + struct ip_adapter_addresses_st *Next; + void *dummy1; + ip_adapter_unicast_address_t *FirstUnicastAddress; + ip_adapter_anycast_address_t *FirstAnycastAddress; + void *dummy2; + void *dummy3; + void *dummy4; + void *dummy5; + void *dummy6; + BYTE dummy7[8]; + DWORD dummy8; + DWORD dummy9; + DWORD dummy10; + DWORD IfType; + int dummy11; + DWORD dummy12; + DWORD dummy13[16]; + void *dummy14; + } ip_adapter_addresses_t; + typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG); + HMODULE h; + GetAdaptersAddresses_t pGetAdaptersAddresses; + ULONG len; + DWORD ret; + ip_adapter_addresses_t *adapters; + VALUE list; + + h = LoadLibrary("iphlpapi.dll"); + if (!h) + rb_notimplement(); + pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses"); + if (!pGetAdaptersAddresses) { + CloseHandle(h); + rb_notimplement(); + } + + ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len); + if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) { + errno = rb_w32_map_errno(ret); + CloseHandle(h); + rb_sys_fail("GetAdaptersAddresses"); + } + adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len); + ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len); + if (ret != ERROR_SUCCESS) { + errno = rb_w32_map_errno(ret); + CloseHandle(h); + rb_sys_fail("GetAdaptersAddresses"); + } + + list = rb_ary_new(); + for (; adapters; adapters = adapters->Next) { + ip_adapter_unicast_address_t *uni; + ip_adapter_anycast_address_t *any; + for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) { + if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family)) + rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr)); + } + for (any = adapters->FirstAnycastAddress; any; any = any->Next) { + if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family)) + rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr)); + } + } + + CloseHandle(h); + return list; #else rb_notimplement(); #endif |