summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-05-13 12:21:53 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-05-13 12:21:53 +0000
commitdd4687313cf62f43fca2d9a8ceeb56ec5fa6841c (patch)
treed783fcbb6dfac97457cfa20aad7b174adc96c16b /win32
parentcb3fcdcdc3eeb4612c78d1fac10438214184642f (diff)
* 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')
-rw-r--r--win32/win32.c70
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);