#include <net/if_types.h>
#endif
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
+
#include "ifenum.h"
+#include "ws2ipdef.h"
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
#define ifreq_len(ifr) \
return ret;
}
+#ifdef HAVE_IFADDRS_H
+ULONG v6addressesFromIndex(DWORD index, SOCKET_ADDRESS **addrs, ULONG *num_addrs)
+{
+ struct ifaddrs *ifa;
+ ULONG ret;
+
+ if (!getifaddrs(&ifa))
+ {
+ struct ifaddrs *p;
+ ULONG n;
+ char name[IFNAMSIZ];
+
+ getInterfaceNameByIndex(index, name);
+ for (p = ifa, n = 0; p; p = p->ifa_next)
+ if (p->ifa_addr->sa_family == AF_INET6 && !strcmp(name, p->ifa_name))
+ n++;
+ if (n)
+ {
+ *addrs = HeapAlloc(GetProcessHeap(), 0, n * (sizeof(SOCKET_ADDRESS) +
+ sizeof(struct WS_sockaddr_in6)));
+ if (*addrs)
+ {
+ struct WS_sockaddr_in6 *next_addr = (struct WS_sockaddr_in6 *)(
+ (BYTE *)*addrs + n * sizeof(SOCKET_ADDRESS));
+
+ for (p = ifa, n = 0; p; p = p->ifa_next)
+ {
+ if (p->ifa_addr->sa_family == AF_INET6 && !strcmp(name, p->ifa_name))
+ {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)p->ifa_addr;
+
+ next_addr->sin6_family = WS_AF_INET6;
+ next_addr->sin6_port = addr->sin6_port;
+ next_addr->sin6_flowinfo = addr->sin6_flowinfo;
+ memcpy(&next_addr->sin6_addr, &addr->sin6_addr,
+ sizeof(next_addr->sin6_addr));
+ next_addr->sin6_scope_id = addr->sin6_scope_id;
+ (*addrs)[n].lpSockaddr = (LPSOCKADDR)next_addr;
+ (*addrs)[n].iSockaddrLength = sizeof(struct WS_sockaddr_in6);
+ next_addr++;
+ n++;
+ }
+ }
+ *num_addrs = n;
+ ret = ERROR_SUCCESS;
+ }
+ else
+ ret = ERROR_OUTOFMEMORY;
+ }
+ else
+ {
+ *addrs = NULL;
+ *num_addrs = 0;
+ ret = ERROR_SUCCESS;
+ }
+ freeifaddrs(ifa);
+ }
+ else
+ ret = ERROR_NO_DATA;
+ return ret;
+}
+#else
+ULONG v6addressesFromIndex(DWORD index, SOCKET_ADDRESS **addrs, ULONG *num_addrs)
+{
+ *addrs = NULL;
+ *num_addrs = 0;
+ return ERROR_SUCCESS;
+}
+#endif
+
char *toIPAddressString(unsigned int addr, char string[16])
{
if (string) {
#include "winreg.h"
#define USE_WS_PREFIX
#include "winsock2.h"
+#include "ws2ipdef.h"
#include "iphlpapi.h"
#include "ifenum.h"
#include "ipstats.h"
static ULONG adapterAddressesFromIndex(ULONG family, DWORD index, IP_ADAPTER_ADDRESSES *aa, ULONG *size)
{
- ULONG ret, i, num_v4addrs = 0, total_size;
+ ULONG ret, i, num_v4addrs = 0, num_v6addrs = 0, total_size;
DWORD *v4addrs = NULL;
+ SOCKET_ADDRESS *v6addrs = NULL;
if (family == AF_INET)
ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
+ else if (family == AF_INET6)
+ ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs);
else if (family == AF_UNSPEC)
{
- WARN("no support for IPv6 addresses\n");
ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
+ if (!ret)
+ ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs);
}
else
{
- if (family == AF_INET6)
- FIXME("no support for IPv6 addresses\n");
- else
- FIXME("address family %u unsupported\n", family);
+ FIXME("address family %u unsupported\n", family);
ret = ERROR_NO_DATA;
}
if (ret) return ret;
total_size += IF_NAMESIZE * sizeof(WCHAR);
total_size += sizeof(IP_ADAPTER_UNICAST_ADDRESS) * num_v4addrs;
total_size += sizeof(struct sockaddr_in) * num_v4addrs;
+ total_size += sizeof(IP_ADAPTER_UNICAST_ADDRESS) * num_v6addrs;
+ total_size += sizeof(SOCKET_ADDRESS) * num_v6addrs;
+ for (i = 0; i < num_v6addrs; i++)
+ total_size += v6addrs[i].iSockaddrLength;
if (aa && *size >= total_size)
{
}
}
}
+ if (num_v6addrs)
+ {
+ IP_ADAPTER_UNICAST_ADDRESS *ua;
+ struct WS_sockaddr_in6 *sa;
+
+ if (aa->FirstUnicastAddress)
+ {
+ for (ua = aa->FirstUnicastAddress; ua->Next; ua = ua->Next)
+ ;
+ ua->Next = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ }
+ else
+ ua = aa->FirstUnicastAddress = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ for (i = 0; i < num_v6addrs; i++)
+ {
+ memset(ua, 0, sizeof(IP_ADAPTER_UNICAST_ADDRESS));
+ ua->u.s.Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
+ ua->Address.iSockaddrLength = v6addrs[i].iSockaddrLength;
+ ua->Address.lpSockaddr = (SOCKADDR *)((char *)ua + ua->u.s.Length);
+
+ sa = (struct WS_sockaddr_in6 *)ua->Address.lpSockaddr;
+ memcpy(sa, v6addrs[i].lpSockaddr, sizeof(*sa));
+
+ ptr += ua->u.s.Length + ua->Address.iSockaddrLength;
+ if (i < num_v6addrs - 1)
+ {
+ ua->Next = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ ua = ua->Next;
+ }
+ }
+ }
buflen = MAX_INTERFACE_PHYSADDR;
getInterfacePhysicalByIndex(index, &buflen, aa->PhysicalAddress, &type);
else aa->OperStatus = IfOperStatusUnknown;
}
*size = total_size;
+ HeapFree(GetProcessHeap(), 0, v6addrs);
HeapFree(GetProcessHeap(), 0, v4addrs);
return ERROR_SUCCESS;
}