35 #pragma comment(lib, "iphlpapi.lib")
41 #elif defined(__linux__) && defined(HAVE_IFADDRS_H)
45 #if defined(_WIN32) || (defined(__linux__) && defined(HAVE_IFADDRS_H))
46 static void io_addr_set(
io_addr_t *addr,
const struct sockaddr *address);
50 static NETIO_STATUS WINAPI ConvertLengthToIpv6Mask(
51 ULONG MaskLength, u_char Mask[16]);
54 #if defined(_WIN32) || (defined(__linux__) && defined(HAVE_IFADDRS_H))
63 ULONG Flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
64 | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX
65 | GAA_FLAG_SKIP_FRIENDLY_NAME
66 | GAA_FLAG_INCLUDE_ALL_INTERFACES;
68 DWORD dwErrCode = GetAdaptersAddresses(
69 AF_UNSPEC, Flags, NULL, NULL, &Size);
70 if (dwErrCode != ERROR_BUFFER_OVERFLOW) {
71 SetLastError(dwErrCode);
75 PIP_ADAPTER_ADDRESSES pAdapterAddresses = malloc(Size);
76 if (!pAdapterAddresses)
79 dwErrCode = GetAdaptersAddresses(
80 AF_UNSPEC, Flags, NULL, pAdapterAddresses, &Size);
81 if (dwErrCode != ERROR_SUCCESS) {
82 free(pAdapterAddresses);
83 SetLastError(dwErrCode);
88 for (PIP_ADAPTER_ADDRESSES paa = pAdapterAddresses; paa;
92 paa->IfIndex ? paa->IfIndex : paa->Ipv6IfIndex;
98 if (paa->OperStatus == IfOperStatusUp)
100 if (paa->IfType == IF_TYPE_PPP)
102 else if (paa->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
106 if (!(paa->Flags & IP_ADAPTER_NO_MULTICAST))
110 for (PIP_ADAPTER_UNICAST_ADDRESS paua =
111 paa->FirstUnicastAddress;
112 paua; paua = paua->Next) {
113 LPSOCKADDR lpSockaddr = paua->Address.lpSockaddr;
119 switch (lpSockaddr->sa_family) {
125 if (++ninfo > maxinfo)
128 memset(info, 0,
sizeof(*info));
142 io_addr_set(&info->
addr, lpSockaddr);
147 ConvertLengthToIpv4Mask(
148 paua->OnLinkPrefixLength,
151 (uint8_t *)&Mask, 0);
156 ULONG BCast = ((
struct sockaddr_in *)lpSockaddr)
161 (uint8_t *)&BCast, 0);
166 ConvertLengthToIpv6Mask(
167 paua->OnLinkPrefixLength, Mask);
178 free(pAdapterAddresses);
180 struct ifaddrs *res = NULL;
181 if (getifaddrs(&res) == -1)
185 for (
struct ifaddrs *ifa = res; ifa; ifa = ifa->ifa_next) {
189 switch (ifa->ifa_addr->sa_family) {
198 if (++ninfo > maxinfo)
201 memset(info, 0,
sizeof(*info));
207 info->
index = if_nametoindex(ifa->ifa_name);
214 if (ifa->ifa_flags & IFF_UP)
216 if (ifa->ifa_flags & IFF_BROADCAST)
218 if (ifa->ifa_flags & IFF_LOOPBACK)
220 if (ifa->ifa_flags & IFF_POINTOPOINT)
222 if (ifa->ifa_flags & IFF_MULTICAST)
227 io_addr_set(&info->
addr, ifa->ifa_addr);
230 if (ifa->ifa_netmask)
231 io_addr_set(&info->
netmask, ifa->ifa_netmask);
234 if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr)
235 io_addr_set(&info->
broadaddr, ifa->ifa_broadaddr);
236 else if ((ifa->ifa_flags & IFF_POINTOPOINT) && ifa->ifa_dstaddr)
237 io_addr_set(&info->
broadaddr, ifa->ifa_dstaddr);
249 io_addr_set(
io_addr_t *addr,
const struct sockaddr *address)
254 switch (address->sa_family) {
255 #if defined(__linux__) && defined(HAVE_LINUX_CAN_H)
256 case AF_CAN: addr->
addrlen =
sizeof(
struct sockaddr_can);
break;
258 case AF_INET: addr->
addrlen =
sizeof(
struct sockaddr_in);
break;
259 case AF_INET6: addr->
addrlen =
sizeof(
struct sockaddr_in6);
break;
260 #if _POSIX_C_SOURCE >= 200112L
261 case AF_UNIX: addr->
addrlen =
sizeof(
struct sockaddr_un);
break;
263 default: addr->
addrlen = 0;
break;
268 #endif // _WIN32 || (__linux__ && HAVE_IFADDRS_H)
271 static NETIO_STATUS WINAPI
272 ConvertLengthToIpv6Mask(ULONG MaskLength, u_char Mask[16])
274 if (MaskLength > 128) {
275 for (
int i = 0; i < 16; i++)
277 return ERROR_INVALID_PARAMETER;
280 for (LONG i = MaskLength, j = 0; i > 0; i -= 8, j++)
281 Mask[j] = i >= 8 ? 0xff : ((0xff << (8 - i)) & 0xff);