1 /* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * Implementation notes
18 * Interface index fun:
19 * - Windows may rely on an index being cleared in the topmost 8 bits in some
20 * APIs; see GetFriendlyIfIndex and the mention of "backward compatible"
21 * indexes. It isn't clear which APIs might fail with non-backward-compatible
22 * indexes, but I'll keep them bits clear just in case.
23 * - Even though if_nametoindex and if_indextoname seem to be pretty portable,
24 * Linux, at any rate, uses the same interface index for all virtual
25 * interfaces of a real interface as well as for the real interface itself.
26 * If I used the Linux index as my index, this would break my statement that
27 * an index is a key, and that an interface has 0 or 1 IP addresses.
28 * If that behavior were consistent across UNIXen (I don't know), it could
29 * help me implement multiple IP addresses more in the Windows way.
30 * I used to assert I could not use UNIX interface indexes as my iphlpapi
31 * indexes due to restrictions in netapi32 and wsock32, but I have removed
32 * those restrictions, so using if_nametoindex and if_indextoname rather
33 * than my current mess would probably be better.
35 * - I don't support IPv6 addresses here, since SIOCGIFCONF can't return them
37 * There are three implemened methods for determining the MAC address of an
39 * - a specific IOCTL (Linux)
40 * - looking in the ARP cache (at least Solaris)
41 * - using the sysctl interface (FreeBSD and MacOSX)
42 * Solaris and some others have SIOCGENADDR, but I haven't gotten that to work
43 * on the Solaris boxes at SourceForge's compile farm, whereas SIOCGARP does.
57 #include <sys/types.h>
59 #ifdef HAVE_SYS_SOCKET_H
60 #include <sys/socket.h>
63 #ifdef HAVE_NETINET_IN_H
64 #include <netinet/in.h>
67 #ifdef HAVE_ARPA_INET_H
68 #include <arpa/inet.h>
75 #ifdef HAVE_NET_IF_ARP_H
76 #include <net/if_arp.h>
79 #ifdef HAVE_NET_ROUTE_H
80 #include <net/route.h>
83 #ifdef HAVE_SYS_IOCTL_H
84 #include <sys/ioctl.h>
87 #ifdef HAVE_SYS_SYSCTL_H
88 #include <sys/sysctl.h>
91 #ifdef HAVE_SYS_SOCKIO_H
92 #include <sys/sockio.h>
95 #ifdef HAVE_NET_IF_DL_H
96 #include <net/if_dl.h>
99 #ifdef HAVE_NET_IF_TYPES_H
100 #include <net/if_types.h>
105 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
106 #define ifreq_len(ifr) \
107 max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len)
109 #define ifreq_len(ifr) sizeof(struct ifreq)
117 #define INADDR_NONE (~0U)
120 #define INITIAL_INTERFACES_ASSUMED 4
122 #define INDEX_IS_LOOPBACK 0x00800000
124 /* Type declarations */
126 typedef struct _InterfaceNameMapEntry {
130 } InterfaceNameMapEntry;
132 typedef struct _InterfaceNameMap {
136 InterfaceNameMapEntry table[1];
139 /* Global variables */
141 static CRITICAL_SECTION mapCS;
142 static InterfaceNameMap *gNonLoopbackInterfaceMap = NULL;
143 static InterfaceNameMap *gLoopbackInterfaceMap = NULL;
147 void interfaceMapInit(void)
149 InitializeCriticalSection(&mapCS);
152 void interfaceMapFree(void)
154 DeleteCriticalSection(&mapCS);
155 if (gNonLoopbackInterfaceMap)
156 HeapFree(GetProcessHeap(), 0, gNonLoopbackInterfaceMap);
157 if (gLoopbackInterfaceMap)
158 HeapFree(GetProcessHeap(), 0, gLoopbackInterfaceMap);
161 /* Sizes the passed-in map to have enough space for numInterfaces interfaces.
162 * If map is NULL, allocates a new map. If it is not, may reallocate the
163 * existing map and return a map of increased size. Returns the allocated map,
164 * or NULL if it could not allocate a map of the requested size.
166 static InterfaceNameMap *sizeMap(InterfaceNameMap *map, DWORD numInterfaces)
169 numInterfaces = max(numInterfaces, INITIAL_INTERFACES_ASSUMED);
170 map = (InterfaceNameMap *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
171 sizeof(InterfaceNameMap) +
172 (numInterfaces - 1) * sizeof(InterfaceNameMapEntry));
174 map->numAllocated = numInterfaces;
177 if (map->numAllocated < numInterfaces) {
178 map = (InterfaceNameMap *)HeapReAlloc(GetProcessHeap(), 0, map,
179 sizeof(InterfaceNameMap) +
180 (numInterfaces - 1) * sizeof(InterfaceNameMapEntry));
182 memset(&map->table[map->numAllocated], 0,
183 (numInterfaces - map->numAllocated) * sizeof(InterfaceNameMapEntry));
189 static int isLoopbackInterface(int fd, const char *name)
196 strncpy(ifr.ifr_name, name, IFNAMSIZ);
197 ifr.ifr_name[IFNAMSIZ-1] = '\0';
198 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
199 ret = ifr.ifr_flags & IFF_LOOPBACK;
204 static void countInterfaces(int fd, caddr_t buf, size_t len)
207 DWORD numNonLoopbackInterfaces = 0, numLoopbackInterfaces = 0;
209 while (ifPtr && ifPtr < buf + len) {
210 struct ifreq *ifr = (struct ifreq *)ifPtr;
212 if (isLoopbackInterface(fd, ifr->ifr_name))
213 numLoopbackInterfaces++;
215 numNonLoopbackInterfaces++;
216 ifPtr += ifreq_len(ifr);
218 gNonLoopbackInterfaceMap = sizeMap(gNonLoopbackInterfaceMap,
219 numNonLoopbackInterfaces);
220 gLoopbackInterfaceMap = sizeMap(gLoopbackInterfaceMap,
221 numLoopbackInterfaces);
224 /* Stores the name in the given map, and increments the map's numInterfaces
225 * member if stored successfully. Will store in the same slot as previously if
226 * usedLastPass is set, otherwise will store in a new slot.
227 * Assumes map and name are not NULL, and the usedLastPass flag is set
228 * correctly for each entry in the map, and that map->numInterfaces <
230 * FIXME: this is kind of expensive, doing a linear scan of the map with a
231 * string comparison of each entry to find the old slot.
233 static void storeInterfaceInMap(InterfaceNameMap *map, const char *name)
239 /* look for previous slot, mark in use if so */
240 for (ndx = 0; !stored && ndx < map->nextAvailable; ndx++) {
241 if (map->table[ndx].usedLastPass && !strncmp(map->table[ndx].name, name,
242 sizeof(map->table[ndx].name))) {
243 map->table[ndx].inUse = TRUE;
247 /* look for new slot */
248 for (ndx = 0; !stored && ndx < map->numAllocated; ndx++) {
249 if (!map->table[ndx].inUse) {
250 strncpy(map->table[ndx].name, name, IFNAMSIZ);
251 map->table[ndx].name[IFNAMSIZ-1] = '\0';
252 map->table[ndx].inUse = TRUE;
254 if (ndx >= map->nextAvailable)
255 map->nextAvailable = ndx + 1;
259 map->numInterfaces++;
263 /* Sets all used entries' usedLastPass flag to their inUse flag, clears
264 * their inUse flag, and clears their numInterfaces member.
266 static void markOldInterfaces(InterfaceNameMap *map)
271 map->numInterfaces = 0;
272 for (ndx = 0; ndx < map->nextAvailable; ndx++) {
273 map->table[ndx].usedLastPass = map->table[ndx].inUse;
274 map->table[ndx].inUse = FALSE;
279 static void classifyInterfaces(int fd, caddr_t buf, size_t len)
283 markOldInterfaces(gNonLoopbackInterfaceMap);
284 markOldInterfaces(gLoopbackInterfaceMap);
285 while (ifPtr && ifPtr < buf + len) {
286 struct ifreq *ifr = (struct ifreq *)ifPtr;
288 if (ifr->ifr_addr.sa_family == AF_INET) {
289 if (isLoopbackInterface(fd, ifr->ifr_name))
290 storeInterfaceInMap(gLoopbackInterfaceMap, ifr->ifr_name);
292 storeInterfaceInMap(gNonLoopbackInterfaceMap, ifr->ifr_name);
294 ifPtr += ifreq_len(ifr);
298 static void enumerateInterfaces(void)
302 fd = socket(PF_INET, SOCK_DGRAM, 0);
304 int ret, guessedNumInterfaces;
307 /* try to avoid silly heap action by starting with the right size buffer */
308 guessedNumInterfaces = 0;
309 if (gNonLoopbackInterfaceMap)
310 guessedNumInterfaces += gNonLoopbackInterfaceMap->numInterfaces;
311 if (gLoopbackInterfaceMap)
312 guessedNumInterfaces += gLoopbackInterfaceMap->numInterfaces;
315 memset(&ifc, 0, sizeof(ifc));
316 /* there is no way to know the interface count beforehand,
317 so we need to loop again and again upping our max each time
318 until returned < max */
320 if (guessedNumInterfaces == 0)
321 guessedNumInterfaces = INITIAL_INTERFACES_ASSUMED;
323 guessedNumInterfaces *= 2;
325 HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
326 ifc.ifc_len = sizeof(struct ifreq) * guessedNumInterfaces;
327 ifc.ifc_buf = (char *)HeapAlloc(GetProcessHeap(), 0, ifc.ifc_len);
328 ret = ioctl(fd, SIOCGIFCONF, &ifc);
330 ifc.ifc_len == (sizeof(struct ifreq) * guessedNumInterfaces));
333 EnterCriticalSection(&mapCS);
334 countInterfaces(fd, ifc.ifc_buf, ifc.ifc_len);
335 classifyInterfaces(fd, ifc.ifc_buf, ifc.ifc_len);
336 LeaveCriticalSection(&mapCS);
340 HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
345 DWORD getNumNonLoopbackInterfaces(void)
347 enumerateInterfaces();
348 return gNonLoopbackInterfaceMap ? gNonLoopbackInterfaceMap->numInterfaces : 0;
351 DWORD getNumInterfaces(void)
353 DWORD ret = getNumNonLoopbackInterfaces();
355 ret += gLoopbackInterfaceMap ? gLoopbackInterfaceMap->numInterfaces : 0;
359 const char *getInterfaceNameByIndex(DWORD index)
362 InterfaceNameMap *map;
363 const char *ret = NULL;
365 EnterCriticalSection(&mapCS);
366 if (index & INDEX_IS_LOOPBACK) {
367 realIndex = index ^ INDEX_IS_LOOPBACK;
368 map = gLoopbackInterfaceMap;
372 map = gNonLoopbackInterfaceMap;
374 if (map && realIndex < map->nextAvailable)
375 ret = map->table[realIndex].name;
376 LeaveCriticalSection(&mapCS);
380 DWORD getInterfaceIndexByName(const char *name, PDWORD index)
386 return ERROR_INVALID_PARAMETER;
388 return ERROR_INVALID_PARAMETER;
390 EnterCriticalSection(&mapCS);
391 for (ndx = 0; !found && gNonLoopbackInterfaceMap &&
392 ndx < gNonLoopbackInterfaceMap->nextAvailable; ndx++)
393 if (!strncmp(gNonLoopbackInterfaceMap->table[ndx].name, name, IFNAMSIZ)) {
397 for (ndx = 0; !found && gLoopbackInterfaceMap &&
398 ndx < gLoopbackInterfaceMap->nextAvailable; ndx++)
399 if (!strncmp(gLoopbackInterfaceMap->table[ndx].name, name, IFNAMSIZ)) {
401 *index = ndx | INDEX_IS_LOOPBACK;
403 LeaveCriticalSection(&mapCS);
407 ret = ERROR_INVALID_DATA;
411 static void addMapEntriesToIndexTable(InterfaceIndexTable *table,
412 const InterfaceNameMap *map)
417 for (ndx = 0; ndx < map->nextAvailable &&
418 table->numIndexes < table->numAllocated; ndx++)
419 if (map->table[ndx].inUse) {
420 DWORD externalNdx = ndx;
422 if (map == gLoopbackInterfaceMap)
423 externalNdx |= INDEX_IS_LOOPBACK;
424 table->indexes[table->numIndexes++] = externalNdx;
429 InterfaceIndexTable *getInterfaceIndexTable(void)
432 InterfaceIndexTable *ret;
434 EnterCriticalSection(&mapCS);
435 numInterfaces = getNumInterfaces();
436 ret = (InterfaceIndexTable *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
437 sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
439 ret->numAllocated = numInterfaces;
440 addMapEntriesToIndexTable(ret, gNonLoopbackInterfaceMap);
441 addMapEntriesToIndexTable(ret, gLoopbackInterfaceMap);
443 LeaveCriticalSection(&mapCS);
447 InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void)
450 InterfaceIndexTable *ret;
452 EnterCriticalSection(&mapCS);
453 numInterfaces = getNumNonLoopbackInterfaces();
454 ret = (InterfaceIndexTable *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
455 sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
457 ret->numAllocated = numInterfaces;
458 addMapEntriesToIndexTable(ret, gNonLoopbackInterfaceMap);
460 LeaveCriticalSection(&mapCS);
464 DWORD getInterfaceIPAddrByName(const char *name)
466 DWORD ret = INADDR_ANY;
469 int fd = socket(PF_INET, SOCK_DGRAM, 0);
474 strncpy(ifr.ifr_name, name, IFNAMSIZ);
475 ifr.ifr_name[IFNAMSIZ-1] = '\0';
476 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0)
477 memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
484 DWORD getInterfaceIPAddrByIndex(DWORD index)
487 const char *name = getInterfaceNameByIndex(index);
490 ret = getInterfaceIPAddrByName(name);
496 DWORD getInterfaceBCastAddrByName(const char *name)
498 DWORD ret = INADDR_ANY;
501 int fd = socket(PF_INET, SOCK_DGRAM, 0);
506 strncpy(ifr.ifr_name, name, IFNAMSIZ);
507 ifr.ifr_name[IFNAMSIZ-1] = '\0';
508 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) == 0)
509 memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
516 DWORD getInterfaceBCastAddrByIndex(DWORD index)
519 const char *name = getInterfaceNameByIndex(index);
522 ret = getInterfaceBCastAddrByName(name);
528 DWORD getInterfaceMaskByName(const char *name)
530 DWORD ret = INADDR_NONE;
533 int fd = socket(PF_INET, SOCK_DGRAM, 0);
538 strncpy(ifr.ifr_name, name, IFNAMSIZ);
539 ifr.ifr_name[IFNAMSIZ-1] = '\0';
540 if (ioctl(fd, SIOCGIFNETMASK, &ifr) == 0)
541 memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
548 DWORD getInterfaceMaskByIndex(DWORD index)
551 const char *name = getInterfaceNameByIndex(index);
554 ret = getInterfaceMaskByName(name);
560 #if defined (SIOCGIFHWADDR)
561 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
567 if (!name || !len || !addr || !type)
568 return ERROR_INVALID_PARAMETER;
570 fd = socket(PF_INET, SOCK_DGRAM, 0);
574 memset(&ifr, 0, sizeof(struct ifreq));
575 strncpy(ifr.ifr_name, name, IFNAMSIZ);
576 ifr.ifr_name[IFNAMSIZ-1] = '\0';
577 if ((ioctl(fd, SIOCGIFHWADDR, &ifr)))
578 ret = ERROR_INVALID_DATA;
580 unsigned int addrLen;
582 switch (ifr.ifr_hwaddr.sa_family)
584 #ifdef ARPHRD_LOOPBACK
585 case ARPHRD_LOOPBACK:
587 *type = MIB_IF_TYPE_LOOPBACK;
593 *type = MIB_IF_TYPE_ETHERNET;
599 *type = MIB_IF_TYPE_FDDI;
602 #ifdef ARPHRD_IEEE802
603 case ARPHRD_IEEE802: /* 802.2 Ethernet && Token Ring, guess TR? */
605 *type = MIB_IF_TYPE_TOKENRING;
608 #ifdef ARPHRD_IEEE802_TR
609 case ARPHRD_IEEE802_TR: /* also Token Ring? */
611 *type = MIB_IF_TYPE_TOKENRING;
617 *type = MIB_IF_TYPE_SLIP;
623 *type = MIB_IF_TYPE_PPP;
627 addrLen = min(MAX_INTERFACE_PHYSADDR, sizeof(ifr.ifr_hwaddr.sa_data));
628 *type = MIB_IF_TYPE_OTHER;
630 if (addrLen > *len) {
631 ret = ERROR_INSUFFICIENT_BUFFER;
636 memcpy(addr, ifr.ifr_hwaddr.sa_data, addrLen);
637 /* zero out remaining bytes for broken implementations */
638 memset(addr + addrLen, 0, *len - addrLen);
646 ret = ERROR_NO_MORE_FILES;
649 #elif defined (SIOCGARP)
650 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
656 if (!name || !len || !addr || !type)
657 return ERROR_INVALID_PARAMETER;
659 fd = socket(PF_INET, SOCK_DGRAM, 0);
661 if (isLoopbackInterface(fd, name)) {
662 *type = MIB_IF_TYPE_LOOPBACK;
663 memset(addr, 0, *len);
669 struct sockaddr_in *saddr;
671 memset(&arp, 0, sizeof(struct arpreq));
672 arp.arp_pa.sa_family = AF_INET;
673 saddr = (struct sockaddr_in *)&arp; /* proto addr is first member */
674 saddr->sin_family = AF_INET;
675 saddr->sin_addr.s_addr = getInterfaceIPAddrByName(name);
676 if ((ioctl(fd, SIOCGARP, &arp)))
677 ret = ERROR_INVALID_DATA;
679 /* FIXME: heh: who said it was ethernet? */
680 int addrLen = ETH_ALEN;
682 if (addrLen > *len) {
683 ret = ERROR_INSUFFICIENT_BUFFER;
688 memcpy(addr, &arp.arp_ha.sa_data[0], addrLen);
689 /* zero out remaining bytes for broken implementations */
690 memset(addr + addrLen, 0, *len - addrLen);
692 *type = MIB_IF_TYPE_ETHERNET;
700 ret = ERROR_NO_MORE_FILES;
704 #elif defined (HAVE_SYS_SYSCTL_H) && defined (HAVE_NET_IF_DL_H)
705 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
709 struct if_msghdr *ifm;
710 struct sockaddr_dl *sdl;
713 int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
717 if (!name || !len || !addr || !type)
718 return ERROR_INVALID_PARAMETER;
720 if (sysctl(mib, 6, NULL, &mibLen, NULL, 0) < 0)
721 return ERROR_NO_MORE_FILES;
723 buf = (u_char *)HeapAlloc(GetProcessHeap(), 0, mibLen);
725 return ERROR_NOT_ENOUGH_MEMORY;
727 if (sysctl(mib, 6, buf, &mibLen, NULL, 0) < 0) {
728 HeapFree(GetProcessHeap(), 0, buf);
729 return ERROR_NO_MORE_FILES;
732 ret = ERROR_INVALID_DATA;
733 for (p = buf; !found && p < buf + mibLen; p += ifm->ifm_msglen) {
734 ifm = (struct if_msghdr *)p;
735 sdl = (struct sockaddr_dl *)(ifm + 1);
737 if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0)
740 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
741 memcmp(sdl->sdl_data, name, max(sdl->sdl_nlen, strlen(name))) != 0)
745 addrLen = min(MAX_INTERFACE_PHYSADDR, sdl->sdl_alen);
746 if (addrLen > *len) {
747 ret = ERROR_INSUFFICIENT_BUFFER;
752 memcpy(addr, LLADDR(sdl), addrLen);
753 /* zero out remaining bytes for broken implementations */
754 memset(addr + addrLen, 0, *len - addrLen);
756 #if defined(HAVE_NET_IF_TYPES_H)
757 switch (sdl->sdl_type)
760 *type = MIB_IF_TYPE_ETHERNET;
763 *type = MIB_IF_TYPE_FDDI;
765 case IFT_ISO88024: /* Token Bus */
766 *type = MIB_IF_TYPE_TOKENRING;
768 case IFT_ISO88025: /* Token Ring */
769 *type = MIB_IF_TYPE_TOKENRING;
772 *type = MIB_IF_TYPE_PPP;
775 *type = MIB_IF_TYPE_SLIP;
778 *type = MIB_IF_TYPE_LOOPBACK;
781 *type = MIB_IF_TYPE_OTHER;
784 /* default if we don't know */
785 *type = MIB_IF_TYPE_ETHERNET;
790 HeapFree(GetProcessHeap(), 0, buf);
795 DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
798 const char *name = getInterfaceNameByIndex(index);
801 return getInterfacePhysicalByName(name, len, addr, type);
803 return ERROR_INVALID_DATA;
806 DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
812 return ERROR_INVALID_PARAMETER;
814 return ERROR_INVALID_PARAMETER;
816 fd = socket(PF_INET, SOCK_DGRAM, 0);
820 strncpy(ifr.ifr_name, name, IFNAMSIZ);
821 ifr.ifr_name[IFNAMSIZ-1] = '\0';
822 if ((ioctl(fd, SIOCGIFMTU, &ifr)))
823 ret = ERROR_INVALID_DATA;
828 *mtu = ifr.ifr_metric;
834 ret = ERROR_NO_MORE_FILES;
838 DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu)
840 const char *name = getInterfaceNameByIndex(index);
843 return getInterfaceMtuByName(name, mtu);
845 return ERROR_INVALID_DATA;
848 DWORD getInterfaceStatusByName(const char *name, PDWORD status)
854 return ERROR_INVALID_PARAMETER;
856 return ERROR_INVALID_PARAMETER;
858 fd = socket(PF_INET, SOCK_DGRAM, 0);
862 strncpy(ifr.ifr_name, name, IFNAMSIZ);
863 ifr.ifr_name[IFNAMSIZ-1] = '\0';
864 if ((ioctl(fd, SIOCGIFFLAGS, &ifr)))
865 ret = ERROR_INVALID_DATA;
867 if (ifr.ifr_flags & IFF_UP)
868 *status = MIB_IF_OPER_STATUS_OPERATIONAL;
870 *status = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
875 ret = ERROR_NO_MORE_FILES;
879 DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status)
881 const char *name = getInterfaceNameByIndex(index);
884 return getInterfaceStatusByName(name, status);
886 return ERROR_INVALID_DATA;
889 DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
891 BYTE addr[MAX_INTERFACE_PHYSADDR];
892 DWORD ret, len = sizeof(addr), type;
895 return ERROR_INVALID_PARAMETER;
897 return ERROR_INVALID_PARAMETER;
899 if (getInterfacePhysicalByName(name, &len, addr, &type) == NO_ERROR) {
903 memset(entry, 0, sizeof(MIB_IFROW));
904 for (assigner = entry->wszName, walker = name; *walker;
905 walker++, assigner++)
908 getInterfaceIndexByName(name, &entry->dwIndex);
909 entry->dwPhysAddrLen = len;
910 memcpy(entry->bPhysAddr, addr, len);
911 memset(entry->bPhysAddr + len, 0, sizeof(entry->bPhysAddr) - len);
912 entry->dwType = type;
913 /* FIXME: how to calculate real speed? */
914 getInterfaceMtuByName(name, &entry->dwMtu);
915 /* lie, there's no "administratively down" here */
916 entry->dwAdminStatus = MIB_IF_ADMIN_STATUS_UP;
917 getInterfaceStatusByName(name, &entry->dwOperStatus);
918 /* punt on dwLastChange? */
919 entry->dwDescrLen = min(strlen(name), MAX_INTERFACE_DESCRIPTION - 1);
920 memcpy(entry->bDescr, name, entry->dwDescrLen);
921 entry->bDescr[entry->dwDescrLen] = '\0';
926 ret = ERROR_INVALID_DATA;
930 DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry)
932 const char *name = getInterfaceNameByIndex(index);
935 return getInterfaceEntryByName(name, entry);
937 return ERROR_INVALID_DATA;
940 char *toIPAddressString(unsigned int addr, char string[16])
943 struct in_addr iAddr;
946 /* extra-anal, just to make auditors happy */
947 strncpy(string, inet_ntoa(iAddr), 16);