diff options
author | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-13 12:21:53 +0000 |
---|---|---|
committer | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-13 12:21:53 +0000 |
commit | dd4687313cf62f43fca2d9a8ceeb56ec5fa6841c (patch) | |
tree | d783fcbb6dfac97457cfa20aad7b174adc96c16b /win32/win32.c | |
parent | cb3fcdcdc3eeb4612c78d1fac10438214184642f (diff) | |
download | ruby-dd4687313cf62f43fca2d9a8ceeb56ec5fa6841c.tar.gz |
* win32/win32.c (getipaddrs): use alternamtive interface name if
available, because if_nametoindex() requires them.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40694 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'win32/win32.c')
-rw-r--r-- | win32/win32.c | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/win32/win32.c b/win32/win32.c index c960bd4a8f..2489942e4d 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -3737,6 +3737,46 @@ socketpair(int af, int type, int protocol, int *sv) } /* License: Ruby's */ +static void +str2guid(const char *str, GUID *guid) +{ +#define hex2byte(str) \ + ((isdigit(*(str)) ? *(str) - '0' : toupper(*(str)) - 'A' + 10) << 4 | (isdigit(*((str) + 1)) ? *((str) + 1) - '0' : toupper(*((str) + 1)) - 'A' + 10)) + char *end; + int i; + if (*str == '{') str++; + guid->Data1 = (long)strtoul(str, &end, 16); + str += 9; + guid->Data2 = (unsigned short)strtoul(str, &end, 16); + str += 5; + guid->Data3 = (unsigned short)strtoul(str, &end, 16); + str += 5; + guid->Data4[0] = hex2byte(str); + str += 2; + guid->Data4[1] = hex2byte(str); + str += 3; + for (i = 0; i < 6; i++) { + guid->Data4[i + 2] = hex2byte(str); + str += 2; + } +} + +/* License: Ruby's */ +#ifndef _IFDEF_ + typedef struct { + uint64_t Value; + struct { + uint64_t Reserved :24; + uint64_t NetLuidIndex :24; + uint64_t IfType :16; + } Info; + } NET_LUID; +#endif +typedef DWORD (WINAPI *cigl_t)(const GUID *, NET_LUID *); +typedef DWORD (WINAPI *cilnA_t)(const NET_LUID *, char *, size_t); +static cigl_t pConvertInterfaceGuidToLuid = NULL; +static cilnA_t pConvertInterfaceLuidToNameA = NULL; + int getifaddrs(struct ifaddrs **ifap) { @@ -3758,15 +3798,37 @@ getifaddrs(struct ifaddrs **ifap) return -1; } + if (!pConvertInterfaceGuidToLuid) + pConvertInterfaceGuidToLuid = + (cigl_t)get_proc_address("iphlpapi.dll", + "ConvertInterfaceGuidToLuid", NULL); + if (!pConvertInterfaceLuidToNameA) + pConvertInterfaceLuidToNameA = + (cilnA_t)get_proc_address("iphlpapi.dll", + "ConvertInterfaceLuidToNameA", NULL); + for (prev = NULL, addr = root; addr; addr = addr->Next) { struct ifaddrs *ifa = ruby_xcalloc(1, sizeof(*ifa)); + char name[IFNAMSIZ]; + GUID guid; + NET_LUID luid; + if (prev) prev->ifa_next = ifa; else *ifap = ifa; - ifa->ifa_name = ruby_xmalloc(lstrlen(addr->AdapterName) + 1); - lstrcpy(ifa->ifa_name, addr->AdapterName); + str2guid(addr->AdapterName, &guid); + if (pConvertInterfaceGuidToLuid && pConvertInterfaceLuidToNameA && + pConvertInterfaceGuidToLuid(&guid, &luid) == NO_ERROR && + pConvertInterfaceLuidToNameA(&luid, name, sizeof(name)) == NO_ERROR) { + ifa->ifa_name = ruby_xmalloc(lstrlen(name) + 1); + lstrcpy(ifa->ifa_name, name); + } + else { + ifa->ifa_name = ruby_xmalloc(lstrlen(addr->AdapterName) + 1); + lstrcpy(ifa->ifa_name, addr->AdapterName); + } if (addr->IfType & IF_TYPE_SOFTWARE_LOOPBACK) ifa->ifa_flags |= IFF_LOOPBACK; @@ -3786,8 +3848,8 @@ getifaddrs(struct ifaddrs **ifap) ifa = ruby_xcalloc(1, sizeof(*ifa)); prev->ifa_next = ifa; ifa->ifa_name = - ruby_xmalloc(lstrlen(addr->AdapterName) + 1); - lstrcpy(ifa->ifa_name, addr->AdapterName); + ruby_xmalloc(lstrlen(prev->ifa_name) + 1); + lstrcpy(ifa->ifa_name, prev->ifa_name); ifa->ifa_flags = prev->ifa_flags; } ifa->ifa_addr = ruby_xmalloc(cur->Address.iSockaddrLength); |