From 50b7cf0433559987c050129d2830dd73e2e525d5 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Sun, 30 Nov 2003 06:03:21 +0000 Subject: [PATCH] - fixes thread safety issues - fixes problems with non-IP (e.g. IPX) addresses - updates comments to reflect winsock, netapi32 changes --- dlls/iphlpapi/ifenum.c | 91 ++++++++++++++++++++--------------- dlls/iphlpapi/ifenum.h | 5 ++ dlls/iphlpapi/iphlpapi_main.c | 14 ++++++ 3 files changed, 72 insertions(+), 38 deletions(-) diff --git a/dlls/iphlpapi/ifenum.c b/dlls/iphlpapi/ifenum.c index 052fa49e1f2..e5749d9aeef 100644 --- a/dlls/iphlpapi/ifenum.c +++ b/dlls/iphlpapi/ifenum.c @@ -27,27 +27,13 @@ * an index is a key, and that an interface has 0 or 1 IP addresses. * If that behavior were consistent across UNIXen (I don't know), it could * help me implement multiple IP addresses more in the Windows way. - * But here's a problem with doing so: - * - Netbios() has a concept of an LAN adapter number (LANA), which is an 8-bit - * number in the range 0-254, inclusive. The MSDN pages for Netbios() says - * the original Netbios() spec allowed only 0 or 1 to be used, though "new" - * applications should enumerate available adapters rather than assuming 0 - * is the default adapter. - * I'm concerned that some old application might depend on being able to get - * "the" MAC address of a machine by opening LANA 0 and getting its MAC - * address. This also implies LANA 0 should correspond to a non-loopback - * interface. - * On Linux, the if_nametoindex index is 1-based, and "lo" typically has - * index 1. - * I could make netapi32 do its own LANA map, independent of my index - * assignment, but it seems simpler just to assign 0-based indexes and put - * non-loopback adapters first, so the first 255 indexes (!) on a system will - * automatically map to LANA numbers without difficulty. - * - One more argument for doing it this way, if you don't buy the Netbios() - * argument: WsControl() (in wsock32) uses the same index to refer to an IP - * address and an interface. If I assigned multiple IP addresses to an - * interface, wsock32 would have to maintain a table of IP addresses with its - * own indexing scheme. No thanks. + * I used to assert I could not use UNIX interface indexes as my iphlpapi + * indexes due to restrictions in netapi32 and wsock32, but I have removed + * those restrictions, so using if_nametoindex and if_indextoname rather + * than my current mess would probably be better. + * FIXME: + * - I don't support IPv6 addresses here, since SIOCGIFCONF can't return them + * - the memory interface uses malloc/free; it should be using HeapAlloc instead * * There are three implemened methods for determining the MAC address of an * interface: @@ -115,9 +101,6 @@ #include #endif -#include "windef.h" -#include "winbase.h" -#include "iprtrmib.h" #include "ifenum.h" #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN @@ -156,17 +139,32 @@ typedef struct _InterfaceNameMap { /* Global variables */ +static CRITICAL_SECTION mapCS; static InterfaceNameMap *gNonLoopbackInterfaceMap = NULL; static InterfaceNameMap *gLoopbackInterfaceMap = NULL; /* Functions */ +void interfaceMapInit(void) +{ + InitializeCriticalSection(&mapCS); +} + +void interfaceMapFree(void) +{ + DeleteCriticalSection(&mapCS); + if (gNonLoopbackInterfaceMap) + free(gNonLoopbackInterfaceMap); + if (gLoopbackInterfaceMap) + free(gLoopbackInterfaceMap); +} + /* Sizes the passed-in map to have enough space for numInterfaces interfaces. * If map is NULL, allocates a new map. If it is not, may reallocate the * existing map and return a map of increased size. Returns the allocated map, * or NULL if it could not allocate a map of the requested size. */ -InterfaceNameMap *sizeMap(InterfaceNameMap *map, DWORD numInterfaces) +static InterfaceNameMap *sizeMap(InterfaceNameMap *map, DWORD numInterfaces) { if (!map) { numInterfaces = max(numInterfaces, INITIAL_INTERFACES_ASSUMED); @@ -286,10 +284,12 @@ static void classifyInterfaces(int fd, caddr_t buf, size_t len) while (ifPtr && ifPtr < buf + len) { struct ifreq *ifr = (struct ifreq *)ifPtr; - if (isLoopbackInterface(fd, ifr->ifr_name)) - storeInterfaceInMap(gLoopbackInterfaceMap, ifr->ifr_name); - else - storeInterfaceInMap(gNonLoopbackInterfaceMap, ifr->ifr_name); + if (ifr->ifr_addr.sa_family == AF_INET) { + if (isLoopbackInterface(fd, ifr->ifr_name)) + storeInterfaceInMap(gLoopbackInterfaceMap, ifr->ifr_name); + else + storeInterfaceInMap(gNonLoopbackInterfaceMap, ifr->ifr_name); + } ifPtr += ifreq_len(ifr); } } @@ -329,8 +329,10 @@ static void enumerateInterfaces(void) ifc.ifc_len == (sizeof(struct ifreq) * guessedNumInterfaces)); if (ret == 0) { + EnterCriticalSection(&mapCS); countInterfaces(fd, ifc.ifc_buf, ifc.ifc_len); classifyInterfaces(fd, ifc.ifc_buf, ifc.ifc_len); + LeaveCriticalSection(&mapCS); } if (ifc.ifc_buf) @@ -359,6 +361,7 @@ const char *getInterfaceNameByIndex(DWORD index) InterfaceNameMap *map; const char *ret = NULL; + EnterCriticalSection(&mapCS); if (index & INDEX_IS_LOOPBACK) { realIndex = index ^ INDEX_IS_LOOPBACK; map = gLoopbackInterfaceMap; @@ -369,12 +372,13 @@ const char *getInterfaceNameByIndex(DWORD index) } if (map && realIndex < map->nextAvailable) ret = map->table[realIndex].name; + LeaveCriticalSection(&mapCS); return ret; } DWORD getInterfaceIndexByName(const char *name, PDWORD index) { - DWORD ndx; + DWORD ndx, ret; BOOL found = FALSE; if (!name) @@ -382,6 +386,7 @@ DWORD getInterfaceIndexByName(const char *name, PDWORD index) if (!index) return ERROR_INVALID_PARAMETER; + EnterCriticalSection(&mapCS); for (ndx = 0; !found && gNonLoopbackInterfaceMap && ndx < gNonLoopbackInterfaceMap->nextAvailable; ndx++) if (!strncmp(gNonLoopbackInterfaceMap->table[ndx].name, name, IFNAMSIZ)) { @@ -394,10 +399,12 @@ DWORD getInterfaceIndexByName(const char *name, PDWORD index) found = TRUE; *index = ndx | INDEX_IS_LOOPBACK; } + LeaveCriticalSection(&mapCS); if (found) - return NO_ERROR; + ret = NO_ERROR; else - return ERROR_INVALID_DATA; + ret = ERROR_INVALID_DATA; + return ret; } static void addMapEntriesToIndexTable(InterfaceIndexTable *table, @@ -420,28 +427,36 @@ static void addMapEntriesToIndexTable(InterfaceIndexTable *table, InterfaceIndexTable *getInterfaceIndexTable(void) { - DWORD numInterfaces = getNumInterfaces(); - InterfaceIndexTable *ret = (InterfaceIndexTable *)calloc(1, + DWORD numInterfaces; + InterfaceIndexTable *ret; + + EnterCriticalSection(&mapCS); + numInterfaces = getNumInterfaces(); + ret = (InterfaceIndexTable *)calloc(1, sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD)); - if (ret) { ret->numAllocated = numInterfaces; addMapEntriesToIndexTable(ret, gNonLoopbackInterfaceMap); addMapEntriesToIndexTable(ret, gLoopbackInterfaceMap); } + LeaveCriticalSection(&mapCS); return ret; } InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void) { - DWORD numInterfaces = getNumNonLoopbackInterfaces(); - InterfaceIndexTable *ret = (InterfaceIndexTable *)calloc(1, - sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD)); + DWORD numInterfaces; + InterfaceIndexTable *ret; + EnterCriticalSection(&mapCS); + numInterfaces = getNumNonLoopbackInterfaces(); + ret = (InterfaceIndexTable *)calloc(1, + sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD)); if (ret) { ret->numAllocated = numInterfaces; addMapEntriesToIndexTable(ret, gNonLoopbackInterfaceMap); } + LeaveCriticalSection(&mapCS); return ret; } diff --git a/dlls/iphlpapi/ifenum.h b/dlls/iphlpapi/ifenum.h index 14fd659d506..1d6964a9c4e 100644 --- a/dlls/iphlpapi/ifenum.h +++ b/dlls/iphlpapi/ifenum.h @@ -47,6 +47,11 @@ #define MAX_INTERFACE_PHYSADDR 8 #define MAX_INTERFACE_DESCRIPTION 256 +/* Call before using the functions in this module */ +void interfaceMapInit(void); +/* Call to free resources allocated in interfaceMapInit() */ +void interfaceMapFree(void); + DWORD getNumInterfaces(void); DWORD getNumNonLoopbackInterfaces(void); diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 2f6c14d5a72..d8e77628feb 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -43,6 +43,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); +BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( hinstDLL ); + interfaceMapInit(); + break; + + case DLL_PROCESS_DETACH: + interfaceMapFree(); + break; + } + return TRUE; +} /****************************************************************** * AddIPAddress (IPHLPAPI.@)