configure: Make the font warning more explicit about what package is missing.
[wine/multimedia.git] / dlls / iphlpapi / ifenum.c
blob8e7e9292c946e1ecea0773c4ec83688e932a6e74
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 MacOSX)
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>
43 #ifdef HAVE_SYS_SOCKET_H
44 #include <sys/socket.h>
45 #endif
47 #ifdef HAVE_NETINET_IN_H
48 #include <netinet/in.h>
49 #endif
51 #ifdef HAVE_ARPA_INET_H
52 #include <arpa/inet.h>
53 #endif
55 #ifdef HAVE_NET_IF_H
56 #include <net/if.h>
57 #endif
59 #ifdef HAVE_NET_IF_ARP_H
60 #include <net/if_arp.h>
61 #endif
63 #ifdef HAVE_NET_ROUTE_H
64 #include <net/route.h>
65 #endif
67 #ifdef HAVE_SYS_IOCTL_H
68 #include <sys/ioctl.h>
69 #endif
71 #ifdef HAVE_SYS_SYSCTL_H
72 #include <sys/sysctl.h>
73 #endif
75 #ifdef HAVE_SYS_SOCKIO_H
76 #include <sys/sockio.h>
77 #endif
79 #ifdef HAVE_NET_IF_DL_H
80 #include <net/if_dl.h>
81 #endif
83 #ifdef HAVE_NET_IF_TYPES_H
84 #include <net/if_types.h>
85 #endif
87 #include "ifenum.h"
89 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
90 #define ifreq_len(ifr) \
91 max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len)
92 #else
93 #define ifreq_len(ifr) sizeof(struct ifreq)
94 #endif
96 #ifndef ETH_ALEN
97 #define ETH_ALEN 6
98 #endif
100 #ifndef IF_NAMESIZE
101 #define IF_NAMESIZE 16
102 #endif
104 #ifndef INADDR_NONE
105 #define INADDR_NONE (~0U)
106 #endif
108 #define INITIAL_INTERFACES_ASSUMED 4
110 #define INDEX_IS_LOOPBACK 0x00800000
112 /* Functions */
114 static int isLoopbackInterface(int fd, const char *name)
116 int ret = 0;
118 if (name) {
119 struct ifreq ifr;
121 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
122 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
123 ret = ifr.ifr_flags & IFF_LOOPBACK;
125 return ret;
128 /* The comments say MAX_ADAPTER_NAME is required, but really only IF_NAMESIZE
129 * bytes are necessary.
131 char *getInterfaceNameByIndex(DWORD index, char *name)
133 return if_indextoname(index, name);
136 DWORD getInterfaceIndexByName(const char *name, PDWORD index)
138 DWORD ret;
139 unsigned int idx;
141 if (!name)
142 return ERROR_INVALID_PARAMETER;
143 if (!index)
144 return ERROR_INVALID_PARAMETER;
145 idx = if_nametoindex(name);
146 if (idx) {
147 *index = idx;
148 ret = NO_ERROR;
150 else
151 ret = ERROR_INVALID_DATA;
152 return ret;
155 DWORD getNumNonLoopbackInterfaces(void)
157 DWORD numInterfaces;
158 int fd = socket(PF_INET, SOCK_DGRAM, 0);
160 if (fd != -1) {
161 struct if_nameindex *indexes = if_nameindex();
163 if (indexes) {
164 struct if_nameindex *p;
166 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
167 if (!isLoopbackInterface(fd, p->if_name))
168 numInterfaces++;
169 if_freenameindex(indexes);
171 else
172 numInterfaces = 0;
173 close(fd);
175 else
176 numInterfaces = 0;
177 return numInterfaces;
180 DWORD getNumInterfaces(void)
182 DWORD numInterfaces;
183 struct if_nameindex *indexes = if_nameindex();
185 if (indexes) {
186 struct if_nameindex *p;
188 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
189 numInterfaces++;
190 if_freenameindex(indexes);
192 else
193 numInterfaces = 0;
194 return numInterfaces;
197 InterfaceIndexTable *getInterfaceIndexTable(void)
199 DWORD numInterfaces;
200 InterfaceIndexTable *ret;
201 struct if_nameindex *indexes = if_nameindex();
203 if (indexes) {
204 struct if_nameindex *p;
206 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
207 numInterfaces++;
208 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
209 sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
210 if (ret) {
211 for (p = indexes; p && p->if_name; p++)
212 ret->indexes[ret->numIndexes++] = p->if_index;
214 if_freenameindex(indexes);
216 else
217 ret = NULL;
218 return ret;
221 InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void)
223 DWORD numInterfaces;
224 InterfaceIndexTable *ret;
225 int fd = socket(PF_INET, SOCK_DGRAM, 0);
227 if (fd != -1) {
228 struct if_nameindex *indexes = if_nameindex();
230 if (indexes) {
231 struct if_nameindex *p;
233 for (p = indexes, numInterfaces = 0; p && p->if_name; p++)
234 if (!isLoopbackInterface(fd, p->if_name))
235 numInterfaces++;
236 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
237 sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
238 if (ret) {
239 for (p = indexes; p && p->if_name; p++)
240 if (!isLoopbackInterface(fd, p->if_name))
241 ret->indexes[ret->numIndexes++] = p->if_index;
243 if_freenameindex(indexes);
245 else
246 ret = NULL;
247 close(fd);
249 else
250 ret = NULL;
251 return ret;
254 static DWORD getInterfaceBCastAddrByName(const char *name)
256 DWORD ret = INADDR_ANY;
258 if (name) {
259 int fd = socket(PF_INET, SOCK_DGRAM, 0);
261 if (fd != -1) {
262 struct ifreq ifr;
264 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
265 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) == 0)
266 memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
267 close(fd);
270 return ret;
273 static DWORD getInterfaceMaskByName(const char *name)
275 DWORD ret = INADDR_NONE;
277 if (name) {
278 int fd = socket(PF_INET, SOCK_DGRAM, 0);
280 if (fd != -1) {
281 struct ifreq ifr;
283 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
284 if (ioctl(fd, SIOCGIFNETMASK, &ifr) == 0)
285 memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
286 close(fd);
289 return ret;
292 #if defined (SIOCGIFHWADDR)
293 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
294 PDWORD type)
296 DWORD ret;
297 int fd;
299 if (!name || !len || !addr || !type)
300 return ERROR_INVALID_PARAMETER;
302 fd = socket(PF_INET, SOCK_DGRAM, 0);
303 if (fd != -1) {
304 struct ifreq ifr;
306 memset(&ifr, 0, sizeof(struct ifreq));
307 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
308 if ((ioctl(fd, SIOCGIFHWADDR, &ifr)))
309 ret = ERROR_INVALID_DATA;
310 else {
311 unsigned int addrLen;
313 switch (ifr.ifr_hwaddr.sa_family)
315 #ifdef ARPHRD_LOOPBACK
316 case ARPHRD_LOOPBACK:
317 addrLen = 0;
318 *type = MIB_IF_TYPE_LOOPBACK;
319 break;
320 #endif
321 #ifdef ARPHRD_ETHER
322 case ARPHRD_ETHER:
323 addrLen = ETH_ALEN;
324 *type = MIB_IF_TYPE_ETHERNET;
325 break;
326 #endif
327 #ifdef ARPHRD_FDDI
328 case ARPHRD_FDDI:
329 addrLen = ETH_ALEN;
330 *type = MIB_IF_TYPE_FDDI;
331 break;
332 #endif
333 #ifdef ARPHRD_IEEE802
334 case ARPHRD_IEEE802: /* 802.2 Ethernet && Token Ring, guess TR? */
335 addrLen = ETH_ALEN;
336 *type = MIB_IF_TYPE_TOKENRING;
337 break;
338 #endif
339 #ifdef ARPHRD_IEEE802_TR
340 case ARPHRD_IEEE802_TR: /* also Token Ring? */
341 addrLen = ETH_ALEN;
342 *type = MIB_IF_TYPE_TOKENRING;
343 break;
344 #endif
345 #ifdef ARPHRD_SLIP
346 case ARPHRD_SLIP:
347 addrLen = 0;
348 *type = MIB_IF_TYPE_SLIP;
349 break;
350 #endif
351 #ifdef ARPHRD_PPP
352 case ARPHRD_PPP:
353 addrLen = 0;
354 *type = MIB_IF_TYPE_PPP;
355 break;
356 #endif
357 default:
358 addrLen = min(MAX_INTERFACE_PHYSADDR, sizeof(ifr.ifr_hwaddr.sa_data));
359 *type = MIB_IF_TYPE_OTHER;
361 if (addrLen > *len) {
362 ret = ERROR_INSUFFICIENT_BUFFER;
363 *len = addrLen;
365 else {
366 if (addrLen > 0)
367 memcpy(addr, ifr.ifr_hwaddr.sa_data, addrLen);
368 /* zero out remaining bytes for broken implementations */
369 memset(addr + addrLen, 0, *len - addrLen);
370 *len = addrLen;
371 ret = NO_ERROR;
374 close(fd);
376 else
377 ret = ERROR_NO_MORE_FILES;
378 return ret;
380 #elif defined (SIOCGARP)
381 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
382 PDWORD type)
384 DWORD ret;
385 int fd;
387 if (!name || !len || !addr || !type)
388 return ERROR_INVALID_PARAMETER;
390 fd = socket(PF_INET, SOCK_DGRAM, 0);
391 if (fd != -1) {
392 if (isLoopbackInterface(fd, name)) {
393 *type = MIB_IF_TYPE_LOOPBACK;
394 memset(addr, 0, *len);
395 *len = 0;
396 ret=NOERROR;
398 else {
399 struct arpreq arp;
400 struct sockaddr_in *saddr;
401 struct ifreq ifr;
403 /* get IP addr */
404 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
405 ioctl(fd, SIOCGIFADDR, &ifr);
406 memset(&arp, 0, sizeof(struct arpreq));
407 arp.arp_pa.sa_family = AF_INET;
408 saddr = (struct sockaddr_in *)&arp; /* proto addr is first member */
409 saddr->sin_family = AF_INET;
410 memcpy(&saddr->sin_addr.s_addr, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
411 if ((ioctl(fd, SIOCGARP, &arp)))
412 ret = ERROR_INVALID_DATA;
413 else {
414 /* FIXME: heh: who said it was ethernet? */
415 int addrLen = ETH_ALEN;
417 if (addrLen > *len) {
418 ret = ERROR_INSUFFICIENT_BUFFER;
419 *len = addrLen;
421 else {
422 if (addrLen > 0)
423 memcpy(addr, &arp.arp_ha.sa_data[0], addrLen);
424 /* zero out remaining bytes for broken implementations */
425 memset(addr + addrLen, 0, *len - addrLen);
426 *len = addrLen;
427 *type = MIB_IF_TYPE_ETHERNET;
428 ret = NO_ERROR;
432 close(fd);
434 else
435 ret = ERROR_NO_MORE_FILES;
437 return ret;
439 #elif defined (HAVE_SYS_SYSCTL_H) && defined (HAVE_NET_IF_DL_H)
440 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
441 PDWORD type)
443 DWORD ret;
444 struct if_msghdr *ifm;
445 struct sockaddr_dl *sdl;
446 u_char *p, *buf;
447 size_t mibLen;
448 int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
449 int addrLen;
450 BOOL found = FALSE;
452 if (!name || !len || !addr || !type)
453 return ERROR_INVALID_PARAMETER;
455 if (sysctl(mib, 6, NULL, &mibLen, NULL, 0) < 0)
456 return ERROR_NO_MORE_FILES;
458 buf = HeapAlloc(GetProcessHeap(), 0, mibLen);
459 if (!buf)
460 return ERROR_NOT_ENOUGH_MEMORY;
462 if (sysctl(mib, 6, buf, &mibLen, NULL, 0) < 0) {
463 HeapFree(GetProcessHeap(), 0, buf);
464 return ERROR_NO_MORE_FILES;
467 ret = ERROR_INVALID_DATA;
468 for (p = buf; !found && p < buf + mibLen; p += ifm->ifm_msglen) {
469 ifm = (struct if_msghdr *)p;
470 sdl = (struct sockaddr_dl *)(ifm + 1);
472 if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0)
473 continue;
475 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
476 memcmp(sdl->sdl_data, name, max(sdl->sdl_nlen, strlen(name))) != 0)
477 continue;
479 found = TRUE;
480 addrLen = min(MAX_INTERFACE_PHYSADDR, sdl->sdl_alen);
481 if (addrLen > *len) {
482 ret = ERROR_INSUFFICIENT_BUFFER;
483 *len = addrLen;
485 else {
486 if (addrLen > 0)
487 memcpy(addr, LLADDR(sdl), addrLen);
488 /* zero out remaining bytes for broken implementations */
489 memset(addr + addrLen, 0, *len - addrLen);
490 *len = addrLen;
491 #if defined(HAVE_NET_IF_TYPES_H)
492 switch (sdl->sdl_type)
494 case IFT_ETHER:
495 *type = MIB_IF_TYPE_ETHERNET;
496 break;
497 case IFT_FDDI:
498 *type = MIB_IF_TYPE_FDDI;
499 break;
500 case IFT_ISO88024: /* Token Bus */
501 *type = MIB_IF_TYPE_TOKENRING;
502 break;
503 case IFT_ISO88025: /* Token Ring */
504 *type = MIB_IF_TYPE_TOKENRING;
505 break;
506 case IFT_PPP:
507 *type = MIB_IF_TYPE_PPP;
508 break;
509 case IFT_SLIP:
510 *type = MIB_IF_TYPE_SLIP;
511 break;
512 case IFT_LOOP:
513 *type = MIB_IF_TYPE_LOOPBACK;
514 break;
515 default:
516 *type = MIB_IF_TYPE_OTHER;
518 #else
519 /* default if we don't know */
520 *type = MIB_IF_TYPE_ETHERNET;
521 #endif
522 ret = NO_ERROR;
525 HeapFree(GetProcessHeap(), 0, buf);
526 return ret;
528 #endif
530 DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
531 PDWORD type)
533 char nameBuf[IF_NAMESIZE];
534 char *name = getInterfaceNameByIndex(index, nameBuf);
536 if (name)
537 return getInterfacePhysicalByName(name, len, addr, type);
538 else
539 return ERROR_INVALID_DATA;
542 static DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
544 DWORD ret;
545 int fd;
547 if (!name)
548 return ERROR_INVALID_PARAMETER;
549 if (!mtu)
550 return ERROR_INVALID_PARAMETER;
552 fd = socket(PF_INET, SOCK_DGRAM, 0);
553 if (fd != -1) {
554 struct ifreq ifr;
556 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
557 if ((ioctl(fd, SIOCGIFMTU, &ifr)))
558 ret = ERROR_INVALID_DATA;
559 else {
560 #ifndef __sun
561 *mtu = ifr.ifr_mtu;
562 #else
563 *mtu = ifr.ifr_metric;
564 #endif
565 ret = NO_ERROR;
567 close(fd);
569 else
570 ret = ERROR_NO_MORE_FILES;
571 return ret;
574 static DWORD getInterfaceStatusByName(const char *name, PDWORD status)
576 DWORD ret;
577 int fd;
579 if (!name)
580 return ERROR_INVALID_PARAMETER;
581 if (!status)
582 return ERROR_INVALID_PARAMETER;
584 fd = socket(PF_INET, SOCK_DGRAM, 0);
585 if (fd != -1) {
586 struct ifreq ifr;
588 lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
589 if ((ioctl(fd, SIOCGIFFLAGS, &ifr)))
590 ret = ERROR_INVALID_DATA;
591 else {
592 if (ifr.ifr_flags & IFF_UP)
593 *status = MIB_IF_OPER_STATUS_OPERATIONAL;
594 else
595 *status = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
596 ret = NO_ERROR;
598 close(fd);
600 else
601 ret = ERROR_NO_MORE_FILES;
602 return ret;
605 DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
607 BYTE addr[MAX_INTERFACE_PHYSADDR];
608 DWORD ret, len = sizeof(addr), type;
610 if (!name)
611 return ERROR_INVALID_PARAMETER;
612 if (!entry)
613 return ERROR_INVALID_PARAMETER;
615 if (getInterfacePhysicalByName(name, &len, addr, &type) == NO_ERROR) {
616 WCHAR *assigner;
617 const char *walker;
619 memset(entry, 0, sizeof(MIB_IFROW));
620 for (assigner = entry->wszName, walker = name; *walker;
621 walker++, assigner++)
622 *assigner = *walker;
623 *assigner = 0;
624 getInterfaceIndexByName(name, &entry->dwIndex);
625 entry->dwPhysAddrLen = len;
626 memcpy(entry->bPhysAddr, addr, len);
627 memset(entry->bPhysAddr + len, 0, sizeof(entry->bPhysAddr) - len);
628 entry->dwType = type;
629 /* FIXME: how to calculate real speed? */
630 getInterfaceMtuByName(name, &entry->dwMtu);
631 /* lie, there's no "administratively down" here */
632 entry->dwAdminStatus = MIB_IF_ADMIN_STATUS_UP;
633 getInterfaceStatusByName(name, &entry->dwOperStatus);
634 /* punt on dwLastChange? */
635 entry->dwDescrLen = min(strlen(name), MAX_INTERFACE_DESCRIPTION - 1);
636 memcpy(entry->bDescr, name, entry->dwDescrLen);
637 entry->bDescr[entry->dwDescrLen] = '\0';
638 entry->dwDescrLen++;
639 ret = NO_ERROR;
641 else
642 ret = ERROR_INVALID_DATA;
643 return ret;
646 DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry)
648 char nameBuf[IF_NAMESIZE];
649 char *name = getInterfaceNameByIndex(index, nameBuf);
651 if (name)
652 return getInterfaceEntryByName(name, entry);
653 else
654 return ERROR_INVALID_DATA;
657 /* Enumerates the IP addresses in the system using SIOCGIFCONF, returning
658 * the count to you in *pcAddresses. It also returns to you the struct ifconf
659 * used by the call to ioctl, so that you may process the addresses further.
660 * Free ifc->ifc_buf using HeapFree.
661 * Returns NO_ERROR on success, something else on failure.
663 static DWORD enumIPAddresses(PDWORD pcAddresses, struct ifconf *ifc)
665 DWORD ret;
666 int fd;
668 fd = socket(PF_INET, SOCK_DGRAM, 0);
669 if (fd != -1) {
670 int ioctlRet = 0;
671 DWORD guessedNumAddresses = 0, numAddresses = 0;
672 caddr_t ifPtr;
674 ret = NO_ERROR;
675 ifc->ifc_len = 0;
676 ifc->ifc_buf = NULL;
677 /* there is no way to know the interface count beforehand,
678 so we need to loop again and again upping our max each time
679 until returned < max */
680 do {
681 HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
682 if (guessedNumAddresses == 0)
683 guessedNumAddresses = INITIAL_INTERFACES_ASSUMED;
684 else
685 guessedNumAddresses *= 2;
686 ifc->ifc_len = sizeof(struct ifreq) * guessedNumAddresses;
687 ifc->ifc_buf = HeapAlloc(GetProcessHeap(), 0, ifc->ifc_len);
688 ioctlRet = ioctl(fd, SIOCGIFCONF, ifc);
689 } while (ioctlRet == 0 &&
690 ifc->ifc_len == (sizeof(struct ifreq) * guessedNumAddresses));
692 if (ioctlRet == 0) {
693 ifPtr = ifc->ifc_buf;
694 while (ifPtr && ifPtr < ifc->ifc_buf + ifc->ifc_len) {
695 numAddresses++;
696 ifPtr += ifreq_len((struct ifreq *)ifPtr);
699 else
700 ret = ERROR_INVALID_PARAMETER; /* FIXME: map from errno to Win32 */
701 if (!ret)
702 *pcAddresses = numAddresses;
703 else
705 HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
706 ifc->ifc_buf = NULL;
708 close(fd);
710 else
711 ret = ERROR_NO_SYSTEM_RESOURCES;
712 return ret;
715 DWORD getNumIPAddresses(void)
717 DWORD numAddresses = 0;
718 struct ifconf ifc;
720 if (!enumIPAddresses(&numAddresses, &ifc))
721 HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
722 return numAddresses;
725 DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
727 DWORD ret;
729 if (!ppIpAddrTable)
730 ret = ERROR_INVALID_PARAMETER;
731 else
733 DWORD numAddresses = 0;
734 struct ifconf ifc;
736 ret = enumIPAddresses(&numAddresses, &ifc);
737 if (!ret)
739 *ppIpAddrTable = HeapAlloc(heap, flags, sizeof(MIB_IPADDRTABLE) +
740 (numAddresses - 1) * sizeof(MIB_IPADDRROW));
741 if (*ppIpAddrTable) {
742 DWORD i = 0, bcast;
743 caddr_t ifPtr;
745 ret = NO_ERROR;
746 (*ppIpAddrTable)->dwNumEntries = numAddresses;
747 ifPtr = ifc.ifc_buf;
748 while (!ret && ifPtr && ifPtr < ifc.ifc_buf + ifc.ifc_len) {
749 struct ifreq *ifr = (struct ifreq *)ifPtr;
751 ret = getInterfaceIndexByName(ifr->ifr_name,
752 &(*ppIpAddrTable)->table[i].dwIndex);
753 memcpy(&(*ppIpAddrTable)->table[i].dwAddr, ifr->ifr_addr.sa_data + 2,
754 sizeof(DWORD));
755 (*ppIpAddrTable)->table[i].dwMask =
756 getInterfaceMaskByName(ifr->ifr_name);
757 /* the dwBCastAddr member isn't the broadcast address, it indicates
758 * whether the interface uses the 1's broadcast address (1) or the
759 * 0's broadcast address (0).
761 bcast = getInterfaceBCastAddrByName(ifr->ifr_name);
762 (*ppIpAddrTable)->table[i].dwBCastAddr =
763 (bcast & (*ppIpAddrTable)->table[i].dwMask) ? 1 : 0;
764 /* FIXME: hardcoded reasm size, not sure where to get it */
765 (*ppIpAddrTable)->table[i].dwReasmSize = 65535;
767 (*ppIpAddrTable)->table[i].unused1 = 0;
768 (*ppIpAddrTable)->table[i].wType = 0;
769 ifPtr += ifreq_len(ifr);
770 i++;
773 else
774 ret = ERROR_OUTOFMEMORY;
775 HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
778 return ret;
781 char *toIPAddressString(unsigned int addr, char string[16])
783 if (string) {
784 struct in_addr iAddr;
786 iAddr.s_addr = addr;
787 /* extra-anal, just to make auditors happy */
788 lstrcpynA(string, inet_ntoa(iAddr), 16);
790 return string;