push ab3cc77eb114d2bd400734a9dccad24563f936a6
[wine/hacks.git] / dlls / iphlpapi / ifenum.c
blob95900329fff3f00bc8e057b54b51dea587d5e539
1 /* Copyright (C) 2003,2006 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
17 * Implementation notes
18 * FIXME:
19 * - I don't support IPv6 addresses here, since SIOCGIFCONF can't return them
21 * There are three implemented methods for determining the MAC address of an
22 * interface:
23 * - a specific IOCTL (Linux)
24 * - looking in the ARP cache (at least Solaris)
25 * - using the sysctl interface (FreeBSD and Mac OS X)
26 * Solaris and some others have SIOCGENADDR, but I haven't gotten that to work
27 * on the Solaris boxes at SourceForge's compile farm, whereas SIOCGARP does.
30 #include "config.h"
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
41 #include <sys/types.h>
42 #ifdef HAVE_SYS_PARAM_H
43 #include <sys/param.h>
44 #endif
46 #ifdef HAVE_SYS_SOCKET_H
47 #include <sys/socket.h>
48 #endif
50 #ifdef HAVE_NETINET_IN_H
51 #include <netinet/in.h>
52 #endif
54 #ifdef HAVE_ARPA_INET_H
55 #include <arpa/inet.h>
56 #endif
58 #ifdef HAVE_NET_IF_H
59 #include <net/if.h>
60 #endif
62 #ifdef HAVE_NET_IF_ARP_H
63 #include <net/if_arp.h>
64 #endif
66 #ifdef HAVE_NET_ROUTE_H
67 #include <net/route.h>
68 #endif
70 #ifdef HAVE_SYS_IOCTL_H
71 #include <sys/ioctl.h>
72 #endif
74 #ifdef HAVE_SYS_SYSCTL_H
75 #include <sys/sysctl.h>
76 #endif
78 #ifdef HAVE_SYS_SOCKIO_H
79 #include <sys/sockio.h>
80 #endif
82 #ifdef HAVE_NET_IF_DL_H
83 #include <net/if_dl.h>
84 #endif
86 #ifdef HAVE_NET_IF_TYPES_H
87 #include <net/if_types.h>
88 #endif
90 #include "ifenum.h"
92 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
93 #define ifreq_len(ifr) \
94 max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len)
95 #else
96 #define ifreq_len(ifr) sizeof(struct ifreq)
97 #endif
99 #ifndef ETH_ALEN
100 #define ETH_ALEN 6
101 #endif
103 #ifndef IF_NAMESIZE
104 #define IF_NAMESIZE 16
105 #endif
107 #ifndef INADDR_NONE
108 #define INADDR_NONE (~0U)
109 #endif
111 #define INITIAL_INTERFACES_ASSUMED 4
113 #define INDEX_IS_LOOPBACK 0x00800000
115 /* Functions */
117 static int isLoopbackInterface(int fd, const char *name)
119 int ret = 0;
121 if (name) {
122 struct ifreq ifr;
124 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
125 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
126 ret = ifr.ifr_flags & IFF_LOOPBACK;
128 return ret;
131 /* The comments say MAX_ADAPTER_NAME is required, but really only IF_NAMESIZE
132 * bytes are necessary.
134 char *getInterfaceNameByIndex(DWORD index, char *name)
136 return if_indextoname(index, name);
139 DWORD getInterfaceIndexByName(const char *name, PDWORD index)
141 DWORD ret;
142 unsigned int idx;
144 if (!name)
145 return ERROR_INVALID_PARAMETER;
146 if (!index)
147 return ERROR_INVALID_PARAMETER;
148 idx = if_nametoindex(name);
149 if (idx) {
150 *index = idx;
151 ret = NO_ERROR;
153 else
154 ret = ERROR_INVALID_DATA;
155 return ret;
158 DWORD getNumNonLoopbackInterfaces(void)
160 DWORD numInterfaces;
161 int fd = socket(PF_INET, SOCK_DGRAM, 0);
163 if (fd != -1) {
164 struct if_nameindex *indexes = if_nameindex();
166 if (indexes) {
167 struct if_nameindex *p;
169 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
170 if (!isLoopbackInterface(fd, p->if_name))
171 numInterfaces++;
172 if_freenameindex(indexes);
174 else
175 numInterfaces = 0;
176 close(fd);
178 else
179 numInterfaces = 0;
180 return numInterfaces;
183 DWORD getNumInterfaces(void)
185 DWORD numInterfaces;
186 struct if_nameindex *indexes = if_nameindex();
188 if (indexes) {
189 struct if_nameindex *p;
191 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
192 numInterfaces++;
193 if_freenameindex(indexes);
195 else
196 numInterfaces = 0;
197 return numInterfaces;
200 InterfaceIndexTable *getInterfaceIndexTable(void)
202 DWORD numInterfaces;
203 InterfaceIndexTable *ret;
204 struct if_nameindex *indexes = if_nameindex();
206 if (indexes) {
207 struct if_nameindex *p;
209 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
210 numInterfaces++;
211 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
212 sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
213 if (ret) {
214 for (p = indexes; p && p->if_name; p++)
215 ret->indexes[ret->numIndexes++] = p->if_index;
217 if_freenameindex(indexes);
219 else
220 ret = NULL;
221 return ret;
224 InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void)
226 DWORD numInterfaces;
227 InterfaceIndexTable *ret;
228 int fd = socket(PF_INET, SOCK_DGRAM, 0);
230 if (fd != -1) {
231 struct if_nameindex *indexes = if_nameindex();
233 if (indexes) {
234 struct if_nameindex *p;
236 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
237 if (!isLoopbackInterface(fd, p->if_name))
238 numInterfaces++;
239 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
240 sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
241 if (ret) {
242 for (p = indexes; p && p->if_name; p++)
243 if (!isLoopbackInterface(fd, p->if_name))
244 ret->indexes[ret->numIndexes++] = p->if_index;
246 if_freenameindex(indexes);
248 else
249 ret = NULL;
250 close(fd);
252 else
253 ret = NULL;
254 return ret;
257 static DWORD getInterfaceBCastAddrByName(const char *name)
259 DWORD ret = INADDR_ANY;
261 if (name) {
262 int fd = socket(PF_INET, SOCK_DGRAM, 0);
264 if (fd != -1) {
265 struct ifreq ifr;
267 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
268 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) == 0)
269 memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
270 close(fd);
273 return ret;
276 static DWORD getInterfaceMaskByName(const char *name)
278 DWORD ret = INADDR_NONE;
280 if (name) {
281 int fd = socket(PF_INET, SOCK_DGRAM, 0);
283 if (fd != -1) {
284 struct ifreq ifr;
286 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
287 if (ioctl(fd, SIOCGIFNETMASK, &ifr) == 0)
288 memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
289 close(fd);
292 return ret;
295 #if defined (SIOCGIFHWADDR)
296 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
297 PDWORD type)
299 DWORD ret;
300 int fd;
302 if (!name || !len || !addr || !type)
303 return ERROR_INVALID_PARAMETER;
305 fd = socket(PF_INET, SOCK_DGRAM, 0);
306 if (fd != -1) {
307 struct ifreq ifr;
309 memset(&ifr, 0, sizeof(struct ifreq));
310 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
311 if ((ioctl(fd, SIOCGIFHWADDR, &ifr)))
312 ret = ERROR_INVALID_DATA;
313 else {
314 unsigned int addrLen;
316 switch (ifr.ifr_hwaddr.sa_family)
318 #ifdef ARPHRD_LOOPBACK
319 case ARPHRD_LOOPBACK:
320 addrLen = 0;
321 *type = MIB_IF_TYPE_LOOPBACK;
322 break;
323 #endif
324 #ifdef ARPHRD_ETHER
325 case ARPHRD_ETHER:
326 addrLen = ETH_ALEN;
327 *type = MIB_IF_TYPE_ETHERNET;
328 break;
329 #endif
330 #ifdef ARPHRD_FDDI
331 case ARPHRD_FDDI:
332 addrLen = ETH_ALEN;
333 *type = MIB_IF_TYPE_FDDI;
334 break;
335 #endif
336 #ifdef ARPHRD_IEEE802
337 case ARPHRD_IEEE802: /* 802.2 Ethernet && Token Ring, guess TR? */
338 addrLen = ETH_ALEN;
339 *type = MIB_IF_TYPE_TOKENRING;
340 break;
341 #endif
342 #ifdef ARPHRD_IEEE802_TR
343 case ARPHRD_IEEE802_TR: /* also Token Ring? */
344 addrLen = ETH_ALEN;
345 *type = MIB_IF_TYPE_TOKENRING;
346 break;
347 #endif
348 #ifdef ARPHRD_SLIP
349 case ARPHRD_SLIP:
350 addrLen = 0;
351 *type = MIB_IF_TYPE_SLIP;
352 break;
353 #endif
354 #ifdef ARPHRD_PPP
355 case ARPHRD_PPP:
356 addrLen = 0;
357 *type = MIB_IF_TYPE_PPP;
358 break;
359 #endif
360 default:
361 addrLen = min(MAX_INTERFACE_PHYSADDR, sizeof(ifr.ifr_hwaddr.sa_data));
362 *type = MIB_IF_TYPE_OTHER;
364 if (addrLen > *len) {
365 ret = ERROR_INSUFFICIENT_BUFFER;
366 *len = addrLen;
368 else {
369 if (addrLen > 0)
370 memcpy(addr, ifr.ifr_hwaddr.sa_data, addrLen);
371 /* zero out remaining bytes for broken implementations */
372 memset(addr + addrLen, 0, *len - addrLen);
373 *len = addrLen;
374 ret = NO_ERROR;
377 close(fd);
379 else
380 ret = ERROR_NO_MORE_FILES;
381 return ret;
383 #elif defined (SIOCGARP)
384 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
385 PDWORD type)
387 DWORD ret;
388 int fd;
390 if (!name || !len || !addr || !type)
391 return ERROR_INVALID_PARAMETER;
393 fd = socket(PF_INET, SOCK_DGRAM, 0);
394 if (fd != -1) {
395 if (isLoopbackInterface(fd, name)) {
396 *type = MIB_IF_TYPE_LOOPBACK;
397 memset(addr, 0, *len);
398 *len = 0;
399 ret=NOERROR;
401 else {
402 struct arpreq arp;
403 struct sockaddr_in *saddr;
404 struct ifreq ifr;
406 /* get IP addr */
407 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
408 ioctl(fd, SIOCGIFADDR, &ifr);
409 memset(&arp, 0, sizeof(struct arpreq));
410 arp.arp_pa.sa_family = AF_INET;
411 saddr = (struct sockaddr_in *)&arp; /* proto addr is first member */
412 saddr->sin_family = AF_INET;
413 memcpy(&saddr->sin_addr.s_addr, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
414 if ((ioctl(fd, SIOCGARP, &arp)))
415 ret = ERROR_INVALID_DATA;
416 else {
417 /* FIXME: heh: who said it was ethernet? */
418 int addrLen = ETH_ALEN;
420 if (addrLen > *len) {
421 ret = ERROR_INSUFFICIENT_BUFFER;
422 *len = addrLen;
424 else {
425 if (addrLen > 0)
426 memcpy(addr, &arp.arp_ha.sa_data[0], addrLen);
427 /* zero out remaining bytes for broken implementations */
428 memset(addr + addrLen, 0, *len - addrLen);
429 *len = addrLen;
430 *type = MIB_IF_TYPE_ETHERNET;
431 ret = NO_ERROR;
435 close(fd);
437 else
438 ret = ERROR_NO_MORE_FILES;
440 return ret;
442 #elif defined (HAVE_SYS_SYSCTL_H) && defined (HAVE_NET_IF_DL_H)
443 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
444 PDWORD type)
446 DWORD ret;
447 struct if_msghdr *ifm;
448 struct sockaddr_dl *sdl;
449 u_char *p, *buf;
450 size_t mibLen;
451 int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
452 int addrLen;
453 BOOL found = FALSE;
455 if (!name || !len || !addr || !type)
456 return ERROR_INVALID_PARAMETER;
458 if (sysctl(mib, 6, NULL, &mibLen, NULL, 0) < 0)
459 return ERROR_NO_MORE_FILES;
461 buf = HeapAlloc(GetProcessHeap(), 0, mibLen);
462 if (!buf)
463 return ERROR_NOT_ENOUGH_MEMORY;
465 if (sysctl(mib, 6, buf, &mibLen, NULL, 0) < 0) {
466 HeapFree(GetProcessHeap(), 0, buf);
467 return ERROR_NO_MORE_FILES;
470 ret = ERROR_INVALID_DATA;
471 for (p = buf; !found && p < buf + mibLen; p += ifm->ifm_msglen) {
472 ifm = (struct if_msghdr *)p;
473 sdl = (struct sockaddr_dl *)(ifm + 1);
475 if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0)
476 continue;
478 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
479 memcmp(sdl->sdl_data, name, max(sdl->sdl_nlen, strlen(name))) != 0)
480 continue;
482 found = TRUE;
483 addrLen = min(MAX_INTERFACE_PHYSADDR, sdl->sdl_alen);
484 if (addrLen > *len) {
485 ret = ERROR_INSUFFICIENT_BUFFER;
486 *len = addrLen;
488 else {
489 if (addrLen > 0)
490 memcpy(addr, LLADDR(sdl), addrLen);
491 /* zero out remaining bytes for broken implementations */
492 memset(addr + addrLen, 0, *len - addrLen);
493 *len = addrLen;
494 #if defined(HAVE_NET_IF_TYPES_H)
495 switch (sdl->sdl_type)
497 case IFT_ETHER:
498 *type = MIB_IF_TYPE_ETHERNET;
499 break;
500 case IFT_FDDI:
501 *type = MIB_IF_TYPE_FDDI;
502 break;
503 case IFT_ISO88024: /* Token Bus */
504 *type = MIB_IF_TYPE_TOKENRING;
505 break;
506 case IFT_ISO88025: /* Token Ring */
507 *type = MIB_IF_TYPE_TOKENRING;
508 break;
509 case IFT_PPP:
510 *type = MIB_IF_TYPE_PPP;
511 break;
512 case IFT_SLIP:
513 *type = MIB_IF_TYPE_SLIP;
514 break;
515 case IFT_LOOP:
516 *type = MIB_IF_TYPE_LOOPBACK;
517 break;
518 default:
519 *type = MIB_IF_TYPE_OTHER;
521 #else
522 /* default if we don't know */
523 *type = MIB_IF_TYPE_ETHERNET;
524 #endif
525 ret = NO_ERROR;
528 HeapFree(GetProcessHeap(), 0, buf);
529 return ret;
531 #endif
533 DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
534 PDWORD type)
536 char nameBuf[IF_NAMESIZE];
537 char *name = getInterfaceNameByIndex(index, nameBuf);
539 if (name)
540 return getInterfacePhysicalByName(name, len, addr, type);
541 else
542 return ERROR_INVALID_DATA;
545 static DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
547 DWORD ret;
548 int fd;
550 if (!name)
551 return ERROR_INVALID_PARAMETER;
552 if (!mtu)
553 return ERROR_INVALID_PARAMETER;
555 fd = socket(PF_INET, SOCK_DGRAM, 0);
556 if (fd != -1) {
557 struct ifreq ifr;
559 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
560 if ((ioctl(fd, SIOCGIFMTU, &ifr)))
561 ret = ERROR_INVALID_DATA;
562 else {
563 #ifndef __sun
564 *mtu = ifr.ifr_mtu;
565 #else
566 *mtu = ifr.ifr_metric;
567 #endif
568 ret = NO_ERROR;
570 close(fd);
572 else
573 ret = ERROR_NO_MORE_FILES;
574 return ret;
577 static DWORD getInterfaceStatusByName(const char *name, PDWORD status)
579 DWORD ret;
580 int fd;
582 if (!name)
583 return ERROR_INVALID_PARAMETER;
584 if (!status)
585 return ERROR_INVALID_PARAMETER;
587 fd = socket(PF_INET, SOCK_DGRAM, 0);
588 if (fd != -1) {
589 struct ifreq ifr;
591 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
592 if ((ioctl(fd, SIOCGIFFLAGS, &ifr)))
593 ret = ERROR_INVALID_DATA;
594 else {
595 if (ifr.ifr_flags & IFF_UP)
596 *status = MIB_IF_OPER_STATUS_OPERATIONAL;
597 else
598 *status = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
599 ret = NO_ERROR;
601 close(fd);
603 else
604 ret = ERROR_NO_MORE_FILES;
605 return ret;
608 DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
610 BYTE addr[MAX_INTERFACE_PHYSADDR];
611 DWORD ret, len = sizeof(addr), type;
613 if (!name)
614 return ERROR_INVALID_PARAMETER;
615 if (!entry)
616 return ERROR_INVALID_PARAMETER;
618 if (getInterfacePhysicalByName(name, &len, addr, &type) == NO_ERROR) {
619 WCHAR *assigner;
620 const char *walker;
622 memset(entry, 0, sizeof(MIB_IFROW));
623 for (assigner = entry->wszName, walker = name; *walker;
624 walker++, assigner++)
625 *assigner = *walker;
626 *assigner = 0;
627 getInterfaceIndexByName(name, &entry->dwIndex);
628 entry->dwPhysAddrLen = len;
629 memcpy(entry->bPhysAddr, addr, len);
630 memset(entry->bPhysAddr + len, 0, sizeof(entry->bPhysAddr) - len);
631 entry->dwType = type;
632 /* FIXME: how to calculate real speed? */
633 getInterfaceMtuByName(name, &entry->dwMtu);
634 /* lie, there's no "administratively down" here */
635 entry->dwAdminStatus = MIB_IF_ADMIN_STATUS_UP;
636 getInterfaceStatusByName(name, &entry->dwOperStatus);
637 /* punt on dwLastChange? */
638 entry->dwDescrLen = min(strlen(name), MAX_INTERFACE_DESCRIPTION - 1);
639 memcpy(entry->bDescr, name, entry->dwDescrLen);
640 entry->bDescr[entry->dwDescrLen] = '\0';
641 entry->dwDescrLen++;
642 ret = NO_ERROR;
644 else
645 ret = ERROR_INVALID_DATA;
646 return ret;
649 DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry)
651 char nameBuf[IF_NAMESIZE];
652 char *name = getInterfaceNameByIndex(index, nameBuf);
654 if (name)
655 return getInterfaceEntryByName(name, entry);
656 else
657 return ERROR_INVALID_DATA;
660 /* Enumerates the IP addresses in the system using SIOCGIFCONF, returning
661 * the count to you in *pcAddresses. It also returns to you the struct ifconf
662 * used by the call to ioctl, so that you may process the addresses further.
663 * Free ifc->ifc_buf using HeapFree.
664 * Returns NO_ERROR on success, something else on failure.
666 static DWORD enumIPAddresses(PDWORD pcAddresses, struct ifconf *ifc)
668 DWORD ret;
669 int fd;
671 fd = socket(PF_INET, SOCK_DGRAM, 0);
672 if (fd != -1) {
673 int ioctlRet = 0;
674 DWORD guessedNumAddresses = 0, numAddresses = 0;
675 caddr_t ifPtr;
676 int lastlen;
678 ret = NO_ERROR;
679 ifc->ifc_len = 0;
680 ifc->ifc_buf = NULL;
681 /* there is no way to know the interface count beforehand,
682 so we need to loop again and again upping our max each time
683 until returned is constant across 2 calls */
684 do {
685 lastlen = ifc->ifc_len;
686 HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
687 if (guessedNumAddresses == 0)
688 guessedNumAddresses = INITIAL_INTERFACES_ASSUMED;
689 else
690 guessedNumAddresses *= 2;
691 ifc->ifc_len = sizeof(struct ifreq) * guessedNumAddresses;
692 ifc->ifc_buf = HeapAlloc(GetProcessHeap(), 0, ifc->ifc_len);
693 ioctlRet = ioctl(fd, SIOCGIFCONF, ifc);
694 } while ((ioctlRet == 0) && (ifc->ifc_len != lastlen));
696 if (ioctlRet == 0) {
697 ifPtr = ifc->ifc_buf;
698 while (ifPtr && ifPtr < ifc->ifc_buf + ifc->ifc_len) {
699 struct ifreq *ifr = (struct ifreq *)ifPtr;
701 if (ifr->ifr_addr.sa_family == AF_INET)
702 numAddresses++;
704 ifPtr += ifreq_len((struct ifreq *)ifPtr);
707 else
708 ret = ERROR_INVALID_PARAMETER; /* FIXME: map from errno to Win32 */
709 if (!ret)
710 *pcAddresses = numAddresses;
711 else
713 HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
714 ifc->ifc_buf = NULL;
716 close(fd);
718 else
719 ret = ERROR_NO_SYSTEM_RESOURCES;
720 return ret;
723 DWORD getNumIPAddresses(void)
725 DWORD numAddresses = 0;
726 struct ifconf ifc;
728 if (!enumIPAddresses(&numAddresses, &ifc))
729 HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
730 return numAddresses;
733 DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
735 DWORD ret;
737 if (!ppIpAddrTable)
738 ret = ERROR_INVALID_PARAMETER;
739 else
741 DWORD numAddresses = 0;
742 struct ifconf ifc;
744 ret = enumIPAddresses(&numAddresses, &ifc);
745 if (!ret)
747 *ppIpAddrTable = HeapAlloc(heap, flags, sizeof(MIB_IPADDRTABLE) +
748 (numAddresses - 1) * sizeof(MIB_IPADDRROW));
749 if (*ppIpAddrTable) {
750 DWORD i = 0, bcast;
751 caddr_t ifPtr;
753 ret = NO_ERROR;
754 (*ppIpAddrTable)->dwNumEntries = numAddresses;
755 ifPtr = ifc.ifc_buf;
756 while (!ret && ifPtr && ifPtr < ifc.ifc_buf + ifc.ifc_len) {
757 struct ifreq *ifr = (struct ifreq *)ifPtr;
759 ifPtr += ifreq_len(ifr);
761 if (ifr->ifr_addr.sa_family != AF_INET)
762 continue;
764 ret = getInterfaceIndexByName(ifr->ifr_name,
765 &(*ppIpAddrTable)->table[i].dwIndex);
766 memcpy(&(*ppIpAddrTable)->table[i].dwAddr, ifr->ifr_addr.sa_data + 2,
767 sizeof(DWORD));
768 (*ppIpAddrTable)->table[i].dwMask =
769 getInterfaceMaskByName(ifr->ifr_name);
770 /* the dwBCastAddr member isn't the broadcast address, it indicates
771 * whether the interface uses the 1's broadcast address (1) or the
772 * 0's broadcast address (0).
774 bcast = getInterfaceBCastAddrByName(ifr->ifr_name);
775 (*ppIpAddrTable)->table[i].dwBCastAddr =
776 (bcast & (*ppIpAddrTable)->table[i].dwMask) ? 1 : 0;
777 /* FIXME: hardcoded reasm size, not sure where to get it */
778 (*ppIpAddrTable)->table[i].dwReasmSize = 65535;
780 (*ppIpAddrTable)->table[i].unused1 = 0;
781 (*ppIpAddrTable)->table[i].wType = 0;
782 i++;
785 else
786 ret = ERROR_OUTOFMEMORY;
787 HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
790 return ret;
793 char *toIPAddressString(unsigned int addr, char string[16])
795 if (string) {
796 struct in_addr iAddr;
798 iAddr.s_addr = addr;
799 /* extra-anal, just to make auditors happy */
800 lstrcpynA(string, inet_ntoa(iAddr), 16);
802 return string;