38 #pragma comment(lib, "iphlpapi.lib")
44 #elif defined(__linux__) && defined(HAVE_IFADDRS_H)
48 #if _WIN32 || (defined(__linux__) && defined(HAVE_IFADDRS_H))
49 static void io_addr_set(
io_addr_t *addr,
const struct sockaddr *address);
53 static NETIO_STATUS WINAPI ConvertLengthToIpv6Mask(
54 ULONG MaskLength, u_char Mask[16]);
57 #if _WIN32 || (defined(__linux__) && defined(HAVE_IFADDRS_H))
66 ULONG Flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
67 | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX
68 | GAA_FLAG_SKIP_FRIENDLY_NAME
69 | GAA_FLAG_INCLUDE_ALL_INTERFACES;
71 DWORD dwErrCode = GetAdaptersAddresses(
72 AF_UNSPEC, Flags, NULL, NULL, &Size);
73 if (dwErrCode != ERROR_BUFFER_OVERFLOW) {
74 SetLastError(dwErrCode);
78 PIP_ADAPTER_ADDRESSES pAdapterAddresses = malloc(Size);
79 if (!pAdapterAddresses)
82 dwErrCode = GetAdaptersAddresses(
83 AF_UNSPEC, Flags, NULL, pAdapterAddresses, &Size);
84 if (dwErrCode != ERROR_SUCCESS) {
85 free(pAdapterAddresses);
86 SetLastError(dwErrCode);
91 for (PIP_ADAPTER_ADDRESSES paa = pAdapterAddresses; paa;
95 paa->IfIndex ? paa->IfIndex : paa->Ipv6IfIndex;
101 if (paa->OperStatus == IfOperStatusUp)
103 if (paa->IfType == IF_TYPE_PPP)
105 else if (paa->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
109 if (!(paa->Flags & IP_ADAPTER_NO_MULTICAST))
113 for (PIP_ADAPTER_UNICAST_ADDRESS paua =
114 paa->FirstUnicastAddress;
115 paua; paua = paua->Next) {
116 LPSOCKADDR lpSockaddr = paua->Address.lpSockaddr;
122 switch (lpSockaddr->sa_family) {
128 if (++ninfo > maxinfo)
131 memset(info, 0,
sizeof(*info));
145 io_addr_set(&info->
addr, lpSockaddr);
150 ConvertLengthToIpv4Mask(
151 paua->OnLinkPrefixLength,
154 (uint8_t *)&Mask, 0);
159 ULONG BCast = ((
struct sockaddr_in *)lpSockaddr)
164 (uint8_t *)&BCast, 0);
169 ConvertLengthToIpv6Mask(
170 paua->OnLinkPrefixLength, Mask);
181 free(pAdapterAddresses);
183 struct ifaddrs *res = NULL;
184 if (getifaddrs(&res) == -1)
188 for (
struct ifaddrs *ifa = res; ifa; ifa = ifa->ifa_next) {
192 switch (ifa->ifa_addr->sa_family) {
201 if (++ninfo > maxinfo)
204 memset(info, 0,
sizeof(*info));
210 info->
index = if_nametoindex(ifa->ifa_name);
217 if (ifa->ifa_flags & IFF_UP)
219 if (ifa->ifa_flags & IFF_BROADCAST)
221 if (ifa->ifa_flags & IFF_LOOPBACK)
223 if (ifa->ifa_flags & IFF_POINTOPOINT)
225 if (ifa->ifa_flags & IFF_MULTICAST)
230 io_addr_set(&info->
addr, ifa->ifa_addr);
233 if (ifa->ifa_netmask)
234 io_addr_set(&info->
netmask, ifa->ifa_netmask);
237 if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr)
238 io_addr_set(&info->
broadaddr, ifa->ifa_broadaddr);
239 else if ((ifa->ifa_flags & IFF_POINTOPOINT) && ifa->ifa_dstaddr)
240 io_addr_set(&info->
broadaddr, ifa->ifa_dstaddr);
252 io_addr_set(
io_addr_t *addr,
const struct sockaddr *address)
257 switch (address->sa_family) {
258 #if defined(__linux__) && defined(HAVE_LINUX_CAN_H)
259 case AF_CAN: addr->
addrlen =
sizeof(
struct sockaddr_can);
break;
261 case AF_INET: addr->
addrlen =
sizeof(
struct sockaddr_in);
break;
262 case AF_INET6: addr->
addrlen =
sizeof(
struct sockaddr_in6);
break;
263 #if _POSIX_C_SOURCE >= 200112L
264 case AF_UNIX: addr->
addrlen =
sizeof(
struct sockaddr_un);
break;
266 default: addr->
addrlen = 0;
break;
271 #endif // _WIN32 || (__linux__ && HAVE_IFADDRS_H)
274 static NETIO_STATUS WINAPI
275 ConvertLengthToIpv6Mask(ULONG MaskLength, u_char Mask[16])
277 if (MaskLength > 128) {
278 for (
int i = 0; i < 16; i++)
280 return ERROR_INVALID_PARAMETER;
283 for (LONG i = MaskLength, j = 0; i > 0; i -= 8, j++)
284 Mask[j] = i >= 8 ? 0xff : ((0xff << (8 - i)) & 0xff);
289 #endif // !LELY_NO_STDIO