blob: f24894f5aee1187490033160a226ba5ef433683c [file] [log] [blame]
/**
* @file wif.c Windows network interface code
*
* Copyright (C) 2010 Creytiv.com
*/
#include <winsock2.h>
#include <iphlpapi.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_net.h>
#include <re_sa.h>
#define DEBUG_MODULE "wif"
#define DEBUG_LEVEL 5
#include <re_dbg.h>
/**
* List interfaces using GetAdaptersAddresses, which handles both
* IPv4 and IPv6 address families.
*
* This is available from Windows XP and Windows Server 2003
*/
static int if_list_gaa(net_ifaddr_h *ifh, void *arg)
{
IP_ADAPTER_ADDRESSES addrv[64], *cur;
ULONG ret, len = sizeof(addrv);
const ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST;
HANDLE hLib;
union {
FARPROC proc;
ULONG (WINAPI *gaa)(ULONG, ULONG, PVOID,
PIP_ADAPTER_ADDRESSES, PULONG);
} u;
bool stop = false;
int err = 0;
hLib = LoadLibrary(TEXT("iphlpapi.dll"));
if (!hLib)
return ENOSYS;
u.proc = GetProcAddress(hLib, TEXT("GetAdaptersAddresses"));
if (!u.proc) {
err = ENOSYS;
goto out;
}
ret = (*u.gaa)(AF_UNSPEC, flags, NULL, addrv, &len);
if (ret != ERROR_SUCCESS) {
DEBUG_WARNING("if_list: GetAdaptersAddresses ret=%u\n", ret);
err = ENODEV;
goto out;
}
for (cur = addrv; cur && !stop; cur = cur->Next) {
PIP_ADAPTER_UNICAST_ADDRESS ip;
/* an interface can have many IP-addresses */
for (ip = cur->FirstUnicastAddress; ip; ip = ip->Next) {
struct sa sa;
sa_set_sa(&sa, ip->Address.lpSockaddr);
if (ifh && ifh(cur->AdapterName, &sa, arg)) {
stop = true;
break;
}
}
}
out:
FreeLibrary(hLib);
return err;
}
/**
* List interfaces using GetAdaptersInfo, which handles only IPv4 family.
*
* This is available from Windows 2000, and also works under Wine.
*/
static int if_list_gai(net_ifaddr_h *ifh, void *arg)
{
IP_ADAPTER_INFO info[32];
PIP_ADAPTER_INFO p = info;
ULONG ulOutBufLen = sizeof(info);
DWORD ret;
ret = GetAdaptersInfo(info, &ulOutBufLen);
if (ret != ERROR_SUCCESS) {
DEBUG_WARNING("if_list: GetAdaptersInfo ret=%u\n", ret);
return ENODEV;
}
for (p = info; p; p = p->Next) {
struct sa sa;
if (sa_set_str(&sa, p->IpAddressList.IpAddress.String, 0))
continue;
if (ifh && ifh(p->AdapterName, &sa, arg))
break;
}
return 0;
}
/**
* Enumerate all network interfaces
*
* @param ifh Interface handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*/
int net_if_list(net_ifaddr_h *ifh, void *arg)
{
/* Try both methods .. */
if (!if_list_gaa(ifh, arg))
return 0;
return if_list_gai(ifh, arg);
}