1 /* Copyright (C) 2003,2006,2011 Juan Lang
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include <sys/types.h>
30 #ifdef HAVE_SYS_PARAM_H
31 #include <sys/param.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
38 #ifdef HAVE_NETINET_IN_H
39 #include <netinet/in.h>
42 #ifdef HAVE_ARPA_INET_H
43 #include <arpa/inet.h>
50 #ifdef HAVE_NET_IF_ARP_H
51 #include <net/if_arp.h>
54 #ifdef HAVE_NET_ROUTE_H
55 #include <net/route.h>
58 #ifdef HAVE_SYS_IOCTL_H
59 #include <sys/ioctl.h>
62 #ifdef HAVE_SYS_SYSCTL_H
63 #include <sys/sysctl.h>
66 #ifdef HAVE_SYS_SOCKIO_H
67 #include <sys/sockio.h>
70 #ifdef HAVE_NET_IF_DL_H
71 #include <net/if_dl.h>
74 #ifdef HAVE_NET_IF_TYPES_H
75 #include <net/if_types.h>
85 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
86 #define ifreq_len(ifr) \
87 max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len)
89 #define ifreq_len(ifr) sizeof(struct ifreq)
97 #define IF_NAMESIZE 16
101 #define INADDR_NONE (~0U)
104 #define INITIAL_INTERFACES_ASSUMED 4
108 static int isLoopbackInterface(int fd
, const char *name
)
115 lstrcpynA(ifr
.ifr_name
, name
, IFNAMSIZ
);
116 if (ioctl(fd
, SIOCGIFFLAGS
, &ifr
) == 0)
117 ret
= ifr
.ifr_flags
& IFF_LOOPBACK
;
122 /* The comments say MAX_ADAPTER_NAME is required, but really only IF_NAMESIZE
123 * bytes are necessary.
125 char *getInterfaceNameByIndex(IF_INDEX index
, char *name
)
127 return if_indextoname(index
, name
);
130 DWORD
getInterfaceIndexByName(const char *name
, IF_INDEX
*index
)
136 return ERROR_INVALID_PARAMETER
;
138 return ERROR_INVALID_PARAMETER
;
139 idx
= if_nametoindex(name
);
145 ret
= ERROR_INVALID_DATA
;
149 BOOL
isIfIndexLoopback(ULONG idx
)
155 getInterfaceNameByIndex(idx
, name
);
156 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
158 ret
= isLoopbackInterface(fd
, name
);
164 DWORD
getNumNonLoopbackInterfaces(void)
167 int fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
170 struct if_nameindex
*indexes
= if_nameindex();
173 struct if_nameindex
*p
;
175 for (p
= indexes
, numInterfaces
= 0; p
&& p
->if_name
; p
++)
176 if (!isLoopbackInterface(fd
, p
->if_name
))
178 if_freenameindex(indexes
);
186 return numInterfaces
;
189 DWORD
getNumInterfaces(void)
192 struct if_nameindex
*indexes
= if_nameindex();
195 struct if_nameindex
*p
;
197 for (p
= indexes
, numInterfaces
= 0; p
&& p
->if_name
; p
++)
199 if_freenameindex(indexes
);
203 return numInterfaces
;
206 InterfaceIndexTable
*getInterfaceIndexTable(void)
209 InterfaceIndexTable
*ret
;
210 struct if_nameindex
*indexes
= if_nameindex();
213 struct if_nameindex
*p
;
214 DWORD size
= sizeof(InterfaceIndexTable
);
216 for (p
= indexes
, numInterfaces
= 0; p
&& p
->if_name
; p
++)
218 if (numInterfaces
> 1)
219 size
+= (numInterfaces
- 1) * sizeof(DWORD
);
220 ret
= HeapAlloc(GetProcessHeap(), 0, size
);
223 for (p
= indexes
; p
&& p
->if_name
; p
++)
224 ret
->indexes
[ret
->numIndexes
++] = p
->if_index
;
226 if_freenameindex(indexes
);
233 InterfaceIndexTable
*getNonLoopbackInterfaceIndexTable(void)
236 InterfaceIndexTable
*ret
;
237 int fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
240 struct if_nameindex
*indexes
= if_nameindex();
243 struct if_nameindex
*p
;
244 DWORD size
= sizeof(InterfaceIndexTable
);
246 for (p
= indexes
, numInterfaces
= 0; p
&& p
->if_name
; p
++)
247 if (!isLoopbackInterface(fd
, p
->if_name
))
249 if (numInterfaces
> 1)
250 size
+= (numInterfaces
- 1) * sizeof(DWORD
);
251 ret
= HeapAlloc(GetProcessHeap(), 0, size
);
254 for (p
= indexes
; p
&& p
->if_name
; p
++)
255 if (!isLoopbackInterface(fd
, p
->if_name
))
256 ret
->indexes
[ret
->numIndexes
++] = p
->if_index
;
258 if_freenameindex(indexes
);
269 static DWORD
getInterfaceBCastAddrByName(const char *name
)
271 DWORD ret
= INADDR_ANY
;
274 int fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
279 lstrcpynA(ifr
.ifr_name
, name
, IFNAMSIZ
);
280 if (ioctl(fd
, SIOCGIFBRDADDR
, &ifr
) == 0)
281 memcpy(&ret
, ifr
.ifr_addr
.sa_data
+ 2, sizeof(DWORD
));
288 static DWORD
getInterfaceMaskByName(const char *name
)
290 DWORD ret
= INADDR_NONE
;
293 int fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
298 lstrcpynA(ifr
.ifr_name
, name
, IFNAMSIZ
);
299 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
) == 0)
300 memcpy(&ret
, ifr
.ifr_addr
.sa_data
+ 2, sizeof(DWORD
));
307 #if defined (SIOCGIFHWADDR) && defined (HAVE_STRUCT_IFREQ_IFR_HWADDR)
308 static DWORD
getInterfacePhysicalByName(const char *name
, PDWORD len
, PBYTE addr
,
314 if (!name
|| !len
|| !addr
|| !type
)
315 return ERROR_INVALID_PARAMETER
;
317 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
321 memset(&ifr
, 0, sizeof(struct ifreq
));
322 lstrcpynA(ifr
.ifr_name
, name
, IFNAMSIZ
);
323 if ((ioctl(fd
, SIOCGIFHWADDR
, &ifr
)))
324 ret
= ERROR_INVALID_DATA
;
326 unsigned int addrLen
;
328 switch (ifr
.ifr_hwaddr
.sa_family
)
330 #ifdef ARPHRD_LOOPBACK
331 case ARPHRD_LOOPBACK
:
333 *type
= MIB_IF_TYPE_LOOPBACK
;
339 *type
= MIB_IF_TYPE_ETHERNET
;
345 *type
= MIB_IF_TYPE_FDDI
;
348 #ifdef ARPHRD_IEEE802
349 case ARPHRD_IEEE802
: /* 802.2 Ethernet && Token Ring, guess TR? */
351 *type
= MIB_IF_TYPE_TOKENRING
;
354 #ifdef ARPHRD_IEEE802_TR
355 case ARPHRD_IEEE802_TR
: /* also Token Ring? */
357 *type
= MIB_IF_TYPE_TOKENRING
;
363 *type
= MIB_IF_TYPE_SLIP
;
369 *type
= MIB_IF_TYPE_PPP
;
373 addrLen
= min(MAX_INTERFACE_PHYSADDR
, sizeof(ifr
.ifr_hwaddr
.sa_data
));
374 *type
= MIB_IF_TYPE_OTHER
;
376 if (addrLen
> *len
) {
377 ret
= ERROR_INSUFFICIENT_BUFFER
;
382 memcpy(addr
, ifr
.ifr_hwaddr
.sa_data
, addrLen
);
383 /* zero out remaining bytes for broken implementations */
384 memset(addr
+ addrLen
, 0, *len
- addrLen
);
392 ret
= ERROR_NO_MORE_FILES
;
395 #elif defined (SIOCGARP)
396 static DWORD
getInterfacePhysicalByName(const char *name
, PDWORD len
, PBYTE addr
,
402 if (!name
|| !len
|| !addr
|| !type
)
403 return ERROR_INVALID_PARAMETER
;
405 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
407 if (isLoopbackInterface(fd
, name
)) {
408 *type
= MIB_IF_TYPE_LOOPBACK
;
409 memset(addr
, 0, *len
);
415 struct sockaddr_in
*saddr
;
419 lstrcpynA(ifr
.ifr_name
, name
, IFNAMSIZ
);
420 ioctl(fd
, SIOCGIFADDR
, &ifr
);
421 memset(&arp
, 0, sizeof(struct arpreq
));
422 arp
.arp_pa
.sa_family
= AF_INET
;
423 saddr
= (struct sockaddr_in
*)&arp
; /* proto addr is first member */
424 saddr
->sin_family
= AF_INET
;
425 memcpy(&saddr
->sin_addr
.s_addr
, ifr
.ifr_addr
.sa_data
+ 2, sizeof(DWORD
));
426 if ((ioctl(fd
, SIOCGARP
, &arp
)))
427 ret
= ERROR_INVALID_DATA
;
429 /* FIXME: heh: who said it was ethernet? */
430 int addrLen
= ETH_ALEN
;
432 if (addrLen
> *len
) {
433 ret
= ERROR_INSUFFICIENT_BUFFER
;
438 memcpy(addr
, &arp
.arp_ha
.sa_data
[0], addrLen
);
439 /* zero out remaining bytes for broken implementations */
440 memset(addr
+ addrLen
, 0, *len
- addrLen
);
442 *type
= MIB_IF_TYPE_ETHERNET
;
450 ret
= ERROR_NO_MORE_FILES
;
454 #elif defined (HAVE_SYS_SYSCTL_H) && defined (HAVE_NET_IF_DL_H)
455 static DWORD
getInterfacePhysicalByName(const char *name
, PDWORD len
, PBYTE addr
,
459 struct if_msghdr
*ifm
;
460 struct sockaddr_dl
*sdl
;
463 int mib
[] = { CTL_NET
, AF_ROUTE
, 0, AF_LINK
, NET_RT_IFLIST
, 0 };
467 if (!name
|| !len
|| !addr
|| !type
)
468 return ERROR_INVALID_PARAMETER
;
470 if (sysctl(mib
, 6, NULL
, &mibLen
, NULL
, 0) < 0)
471 return ERROR_NO_MORE_FILES
;
473 buf
= HeapAlloc(GetProcessHeap(), 0, mibLen
);
475 return ERROR_NOT_ENOUGH_MEMORY
;
477 if (sysctl(mib
, 6, buf
, &mibLen
, NULL
, 0) < 0) {
478 HeapFree(GetProcessHeap(), 0, buf
);
479 return ERROR_NO_MORE_FILES
;
482 ret
= ERROR_INVALID_DATA
;
483 for (p
= buf
; !found
&& p
< buf
+ mibLen
; p
+= ifm
->ifm_msglen
) {
484 ifm
= (struct if_msghdr
*)p
;
485 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
487 if (ifm
->ifm_type
!= RTM_IFINFO
|| (ifm
->ifm_addrs
& RTA_IFP
) == 0)
490 if (sdl
->sdl_family
!= AF_LINK
|| sdl
->sdl_nlen
== 0 ||
491 memcmp(sdl
->sdl_data
, name
, max(sdl
->sdl_nlen
, strlen(name
))) != 0)
495 addrLen
= min(MAX_INTERFACE_PHYSADDR
, sdl
->sdl_alen
);
496 if (addrLen
> *len
) {
497 ret
= ERROR_INSUFFICIENT_BUFFER
;
502 memcpy(addr
, LLADDR(sdl
), addrLen
);
503 /* zero out remaining bytes for broken implementations */
504 memset(addr
+ addrLen
, 0, *len
- addrLen
);
506 #if defined(HAVE_NET_IF_TYPES_H)
507 switch (sdl
->sdl_type
)
510 *type
= MIB_IF_TYPE_ETHERNET
;
513 *type
= MIB_IF_TYPE_FDDI
;
515 case IFT_ISO88024
: /* Token Bus */
516 *type
= MIB_IF_TYPE_TOKENRING
;
518 case IFT_ISO88025
: /* Token Ring */
519 *type
= MIB_IF_TYPE_TOKENRING
;
522 *type
= MIB_IF_TYPE_PPP
;
525 *type
= MIB_IF_TYPE_SLIP
;
528 *type
= MIB_IF_TYPE_LOOPBACK
;
531 *type
= MIB_IF_TYPE_OTHER
;
534 /* default if we don't know */
535 *type
= MIB_IF_TYPE_ETHERNET
;
540 HeapFree(GetProcessHeap(), 0, buf
);
545 DWORD
getInterfacePhysicalByIndex(IF_INDEX index
, PDWORD len
, PBYTE addr
,
548 char nameBuf
[IF_NAMESIZE
];
549 char *name
= getInterfaceNameByIndex(index
, nameBuf
);
552 return getInterfacePhysicalByName(name
, len
, addr
, type
);
554 return ERROR_INVALID_DATA
;
557 DWORD
getInterfaceMtuByName(const char *name
, PDWORD mtu
)
563 return ERROR_INVALID_PARAMETER
;
565 return ERROR_INVALID_PARAMETER
;
567 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
571 lstrcpynA(ifr
.ifr_name
, name
, IFNAMSIZ
);
572 if ((ioctl(fd
, SIOCGIFMTU
, &ifr
)))
573 ret
= ERROR_INVALID_DATA
;
578 *mtu
= ifr
.ifr_metric
;
585 ret
= ERROR_NO_MORE_FILES
;
589 DWORD
getInterfaceStatusByName(const char *name
, INTERNAL_IF_OPER_STATUS
*status
)
595 return ERROR_INVALID_PARAMETER
;
597 return ERROR_INVALID_PARAMETER
;
599 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
603 lstrcpynA(ifr
.ifr_name
, name
, IFNAMSIZ
);
604 if ((ioctl(fd
, SIOCGIFFLAGS
, &ifr
)))
605 ret
= ERROR_INVALID_DATA
;
607 if (ifr
.ifr_flags
& IFF_UP
)
608 *status
= MIB_IF_OPER_STATUS_OPERATIONAL
;
610 *status
= MIB_IF_OPER_STATUS_NON_OPERATIONAL
;
616 ret
= ERROR_NO_MORE_FILES
;
620 DWORD
getInterfaceEntryByName(const char *name
, PMIB_IFROW entry
)
622 BYTE addr
[MAX_INTERFACE_PHYSADDR
];
623 DWORD ret
, len
= sizeof(addr
), type
;
626 return ERROR_INVALID_PARAMETER
;
628 return ERROR_INVALID_PARAMETER
;
630 if (getInterfacePhysicalByName(name
, &len
, addr
, &type
) == NO_ERROR
) {
634 memset(entry
, 0, sizeof(MIB_IFROW
));
635 for (assigner
= entry
->wszName
, walker
= name
; *walker
;
636 walker
++, assigner
++)
639 getInterfaceIndexByName(name
, &entry
->dwIndex
);
640 entry
->dwPhysAddrLen
= len
;
641 memcpy(entry
->bPhysAddr
, addr
, len
);
642 memset(entry
->bPhysAddr
+ len
, 0, sizeof(entry
->bPhysAddr
) - len
);
643 entry
->dwType
= type
;
644 /* FIXME: how to calculate real speed? */
645 getInterfaceMtuByName(name
, &entry
->dwMtu
);
646 /* lie, there's no "administratively down" here */
647 entry
->dwAdminStatus
= MIB_IF_ADMIN_STATUS_UP
;
648 getInterfaceStatusByName(name
, &entry
->dwOperStatus
);
649 /* punt on dwLastChange? */
650 entry
->dwDescrLen
= min(strlen(name
), MAX_INTERFACE_DESCRIPTION
- 1);
651 memcpy(entry
->bDescr
, name
, entry
->dwDescrLen
);
652 entry
->bDescr
[entry
->dwDescrLen
] = '\0';
657 ret
= ERROR_INVALID_DATA
;
661 static DWORD
getIPAddrRowByName(PMIB_IPADDRROW ipAddrRow
, const char *ifName
,
662 const struct sockaddr
*sa
)
666 ret
= getInterfaceIndexByName(ifName
, &ipAddrRow
->dwIndex
);
667 memcpy(&ipAddrRow
->dwAddr
, sa
->sa_data
+ 2, sizeof(DWORD
));
668 ipAddrRow
->dwMask
= getInterfaceMaskByName(ifName
);
669 /* the dwBCastAddr member isn't the broadcast address, it indicates whether
670 * the interface uses the 1's broadcast address (1) or the 0's broadcast
673 bcast
= getInterfaceBCastAddrByName(ifName
);
674 ipAddrRow
->dwBCastAddr
= (bcast
& ipAddrRow
->dwMask
) ? 1 : 0;
675 /* FIXME: hardcoded reasm size, not sure where to get it */
676 ipAddrRow
->dwReasmSize
= 65535;
677 ipAddrRow
->unused1
= 0;
678 ipAddrRow
->wType
= 0;
682 #ifdef HAVE_IFADDRS_H
684 /* Counts the IPv4 addresses in the system using the return value from
685 * getifaddrs, returning the count.
687 static DWORD
countIPv4Addresses(struct ifaddrs
*ifa
)
689 DWORD numAddresses
= 0;
691 for (; ifa
; ifa
= ifa
->ifa_next
)
692 if (ifa
->ifa_addr
&& ifa
->ifa_addr
->sa_family
== AF_INET
)
697 DWORD
getNumIPAddresses(void)
699 DWORD numAddresses
= 0;
702 if (!getifaddrs(&ifa
))
704 numAddresses
= countIPv4Addresses(ifa
);
710 DWORD
getIPAddrTable(PMIB_IPADDRTABLE
*ppIpAddrTable
, HANDLE heap
, DWORD flags
)
715 ret
= ERROR_INVALID_PARAMETER
;
720 if (!getifaddrs(&ifa
))
722 DWORD size
= sizeof(MIB_IPADDRTABLE
);
723 DWORD numAddresses
= countIPv4Addresses(ifa
);
725 if (numAddresses
> 1)
726 size
+= (numAddresses
- 1) * sizeof(MIB_IPADDRROW
);
727 *ppIpAddrTable
= HeapAlloc(heap
, flags
, size
);
734 (*ppIpAddrTable
)->dwNumEntries
= numAddresses
;
735 for (ifp
= ifa
; !ret
&& ifp
; ifp
= ifp
->ifa_next
)
737 if (!ifp
->ifa_addr
|| ifp
->ifa_addr
->sa_family
!= AF_INET
)
740 ret
= getIPAddrRowByName(&(*ppIpAddrTable
)->table
[i
], ifp
->ifa_name
,
746 ret
= ERROR_OUTOFMEMORY
;
750 ret
= ERROR_INVALID_PARAMETER
;
755 ULONG
v6addressesFromIndex(IF_INDEX index
, SOCKET_ADDRESS
**addrs
, ULONG
*num_addrs
)
760 if (!getifaddrs(&ifa
))
766 getInterfaceNameByIndex(index
, name
);
767 for (p
= ifa
, n
= 0; p
; p
= p
->ifa_next
)
768 if (p
->ifa_addr
&& p
->ifa_addr
->sa_family
== AF_INET6
&&
769 !strcmp(name
, p
->ifa_name
))
773 *addrs
= HeapAlloc(GetProcessHeap(), 0, n
* (sizeof(SOCKET_ADDRESS
) +
774 sizeof(struct WS_sockaddr_in6
)));
777 struct WS_sockaddr_in6
*next_addr
= (struct WS_sockaddr_in6
*)(
778 (BYTE
*)*addrs
+ n
* sizeof(SOCKET_ADDRESS
));
780 for (p
= ifa
, n
= 0; p
; p
= p
->ifa_next
)
782 if (p
->ifa_addr
&& p
->ifa_addr
->sa_family
== AF_INET6
&&
783 !strcmp(name
, p
->ifa_name
))
785 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)p
->ifa_addr
;
787 next_addr
->sin6_family
= WS_AF_INET6
;
788 next_addr
->sin6_port
= addr
->sin6_port
;
789 next_addr
->sin6_flowinfo
= addr
->sin6_flowinfo
;
790 memcpy(&next_addr
->sin6_addr
, &addr
->sin6_addr
,
791 sizeof(next_addr
->sin6_addr
));
792 next_addr
->sin6_scope_id
= addr
->sin6_scope_id
;
793 (*addrs
)[n
].lpSockaddr
= (LPSOCKADDR
)next_addr
;
794 (*addrs
)[n
].iSockaddrLength
= sizeof(struct WS_sockaddr_in6
);
803 ret
= ERROR_OUTOFMEMORY
;
820 /* Enumerates the IP addresses in the system using SIOCGIFCONF, returning
821 * the count to you in *pcAddresses. It also returns to you the struct ifconf
822 * used by the call to ioctl, so that you may process the addresses further.
823 * Free ifc->ifc_buf using HeapFree.
824 * Returns NO_ERROR on success, something else on failure.
826 static DWORD
enumIPAddresses(PDWORD pcAddresses
, struct ifconf
*ifc
)
831 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
834 DWORD guessedNumAddresses
= 0, numAddresses
= 0;
841 /* there is no way to know the interface count beforehand,
842 so we need to loop again and again upping our max each time
843 until returned is constant across 2 calls */
845 lastlen
= ifc
->ifc_len
;
846 HeapFree(GetProcessHeap(), 0, ifc
->ifc_buf
);
847 if (guessedNumAddresses
== 0)
848 guessedNumAddresses
= INITIAL_INTERFACES_ASSUMED
;
850 guessedNumAddresses
*= 2;
851 ifc
->ifc_len
= sizeof(struct ifreq
) * guessedNumAddresses
;
852 ifc
->ifc_buf
= HeapAlloc(GetProcessHeap(), 0, ifc
->ifc_len
);
853 ioctlRet
= ioctl(fd
, SIOCGIFCONF
, ifc
);
854 } while ((ioctlRet
== 0) && (ifc
->ifc_len
!= lastlen
));
857 ifPtr
= ifc
->ifc_buf
;
858 while (ifPtr
&& ifPtr
< ifc
->ifc_buf
+ ifc
->ifc_len
) {
859 struct ifreq
*ifr
= (struct ifreq
*)ifPtr
;
861 if (ifr
->ifr_addr
.sa_family
== AF_INET
)
864 ifPtr
+= ifreq_len((struct ifreq
*)ifPtr
);
868 ret
= ERROR_INVALID_PARAMETER
; /* FIXME: map from errno to Win32 */
870 *pcAddresses
= numAddresses
;
873 HeapFree(GetProcessHeap(), 0, ifc
->ifc_buf
);
879 ret
= ERROR_NO_SYSTEM_RESOURCES
;
883 DWORD
getNumIPAddresses(void)
885 DWORD numAddresses
= 0;
888 if (!enumIPAddresses(&numAddresses
, &ifc
))
889 HeapFree(GetProcessHeap(), 0, ifc
.ifc_buf
);
893 DWORD
getIPAddrTable(PMIB_IPADDRTABLE
*ppIpAddrTable
, HANDLE heap
, DWORD flags
)
898 ret
= ERROR_INVALID_PARAMETER
;
901 DWORD numAddresses
= 0;
904 ret
= enumIPAddresses(&numAddresses
, &ifc
);
907 DWORD size
= sizeof(MIB_IPADDRTABLE
);
909 if (numAddresses
> 1)
910 size
+= (numAddresses
- 1) * sizeof(MIB_IPADDRROW
);
911 *ppIpAddrTable
= HeapAlloc(heap
, flags
, size
);
912 if (*ppIpAddrTable
) {
917 (*ppIpAddrTable
)->dwNumEntries
= numAddresses
;
919 while (!ret
&& ifPtr
&& ifPtr
< ifc
.ifc_buf
+ ifc
.ifc_len
) {
920 struct ifreq
*ifr
= (struct ifreq
*)ifPtr
;
922 ifPtr
+= ifreq_len(ifr
);
924 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
927 ret
= getIPAddrRowByName(&(*ppIpAddrTable
)->table
[i
], ifr
->ifr_name
,
933 ret
= ERROR_OUTOFMEMORY
;
934 HeapFree(GetProcessHeap(), 0, ifc
.ifc_buf
);
940 ULONG
v6addressesFromIndex(IF_INDEX index
, SOCKET_ADDRESS
**addrs
, ULONG
*num_addrs
)
944 return ERROR_SUCCESS
;
949 char *toIPAddressString(unsigned int addr
, char string
[16])
952 struct in_addr iAddr
;
955 /* extra-anal, just to make auditors happy */
956 lstrcpynA(string
, inet_ntoa(iAddr
), 16);