Changed wsock32 to use the new iphlpapi for interface and route
enumeration in WsControl.
This commit is contained in:
parent
090f5974b8
commit
6dae7c2da8
|
@ -3,7 +3,7 @@ TOPOBJDIR = ../..
|
||||||
SRCDIR = @srcdir@
|
SRCDIR = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
MODULE = wsock32.dll
|
MODULE = wsock32.dll
|
||||||
IMPORTS = ws2_32 kernel32
|
IMPORTS = ws2_32 iphlpapi kernel32
|
||||||
|
|
||||||
LDDLLFLAGS = @LDDLLFLAGS@
|
LDDLLFLAGS = @LDDLLFLAGS@
|
||||||
SYMBOLFILE = $(MODULE).tmp.o
|
SYMBOLFILE = $(MODULE).tmp.o
|
||||||
|
|
|
@ -19,80 +19,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: This hack is fixing a problem in WsControl. When we call socket(),
|
|
||||||
* it will call into ws2_32's WSOCK32_socket (because of the redirection in
|
|
||||||
* our own .spec file).
|
|
||||||
* The problem is that socket() is predefined in a linux system header that
|
|
||||||
* we are including, which is different from the WINE definition.
|
|
||||||
* (cdecl vs. stdapi). The result is stack corruption.
|
|
||||||
* Furthermore WsControl uses Unix macros and types. This forces us to include
|
|
||||||
* the Unix headers which then conflict with the winsock headers. This forces
|
|
||||||
* us to use USE_WS_PREFIX but then ioctlsocket is called WS_ioctlsocket,
|
|
||||||
* which causes link problems. The correct solution is to implement
|
|
||||||
* WsControl using calls to WSAIoctl. Then we should no longer need to use the
|
|
||||||
* Unix headers. This would also have the advantage of reducing code
|
|
||||||
* duplication.
|
|
||||||
* Until that happens we need this ugly hack.
|
|
||||||
*/
|
|
||||||
#define USE_WS_PREFIX
|
|
||||||
|
|
||||||
#define socket linux_socket
|
|
||||||
#define recv linux_recv
|
|
||||||
/* */
|
|
||||||
|
|
||||||
#define setsockopt linux_setsockopt
|
|
||||||
#define getsockopt linux_getsockopt
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_IOCTL_H
|
|
||||||
# include <sys/ioctl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SOCKIO_H
|
|
||||||
# include <sys/sockio.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_NET_IF_H
|
|
||||||
# include <net/if.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "winsock2.h"
|
#include "winsock2.h"
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
#include "wscontrol.h"
|
#include "wscontrol.h"
|
||||||
|
#include "iphlpapi.h"
|
||||||
/* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
|
|
||||||
* discussed above.
|
|
||||||
*/
|
|
||||||
#undef socket
|
|
||||||
#undef recv
|
|
||||||
extern SOCKET WINAPI socket(INT af, INT type, INT protocol);
|
|
||||||
extern SOCKET WINAPI recv(SOCKET,char*,int,int);
|
|
||||||
/* Plus some missing prototypes, due to the WS_ prefixing */
|
|
||||||
extern int WINAPI closesocket(SOCKET);
|
|
||||||
extern int WINAPI ioctlsocket(SOCKET,long,u_long*);
|
|
||||||
/* */
|
|
||||||
|
|
||||||
/* for the get/setsockopt forwarders */
|
|
||||||
#undef setsockopt
|
|
||||||
#undef getsockopt
|
|
||||||
extern int WINAPI setsockopt(SOCKET s, INT level, INT optname ,char* optval, INT optlen);
|
|
||||||
extern int WINAPI getsockopt(SOCKET s, INT level, INT optname ,char* optval, INT* optlen);
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(winsock);
|
WINE_DEFAULT_DEBUG_CHANNEL(winsock);
|
||||||
|
|
||||||
|
@ -100,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(winsock);
|
||||||
static INT _remap_optname(INT level, INT optname)
|
static INT _remap_optname(INT level, INT optname)
|
||||||
{
|
{
|
||||||
TRACE("level=%d, optname=%d\n", level, optname);
|
TRACE("level=%d, optname=%d\n", level, optname);
|
||||||
if (level == WS_IPPROTO_IP) {
|
if (level == IPPROTO_IP) {
|
||||||
switch (optname) { /***** from value *****/
|
switch (optname) { /***** from value *****/
|
||||||
case 2: return 9; /* IP_MULTICAST_IF */
|
case 2: return 9; /* IP_MULTICAST_IF */
|
||||||
case 3: return 10; /* IP_MULTICAST_TTL */
|
case 3: return 10; /* IP_MULTICAST_TTL */
|
||||||
|
@ -169,6 +103,7 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
||||||
LPVOID pResponseInfo,
|
LPVOID pResponseInfo,
|
||||||
LPDWORD pcbResponseInfoLen)
|
LPDWORD pcbResponseInfoLen)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Get the command structure into a pointer we can use,
|
/* Get the command structure into a pointer we can use,
|
||||||
rather than void */
|
rather than void */
|
||||||
TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
|
TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
|
||||||
|
@ -192,7 +127,8 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
||||||
case ENTITY_LIST_ID:
|
case ENTITY_LIST_ID:
|
||||||
{
|
{
|
||||||
TDIEntityID *baseptr = pResponseInfo;
|
TDIEntityID *baseptr = pResponseInfo;
|
||||||
int numInt = 0, i;
|
DWORD numInt, i, ipAddrTableSize;
|
||||||
|
PMIB_IPADDRTABLE table;
|
||||||
|
|
||||||
if (pcommand->toi_class != INFO_CLASS_GENERIC &&
|
if (pcommand->toi_class != INFO_CLASS_GENERIC &&
|
||||||
pcommand->toi_type != INFO_TYPE_PROVIDER)
|
pcommand->toi_type != INFO_TYPE_PROVIDER)
|
||||||
|
@ -202,32 +138,37 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
||||||
return (WSAEOPNOTSUPP);
|
return (WSAEOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
|
GetNumberOfInterfaces(&numInt);
|
||||||
if (numInt < 0)
|
|
||||||
{
|
|
||||||
ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
|
if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
|
||||||
{
|
{
|
||||||
return (STATUS_BUFFER_TOO_SMALL);
|
return (STATUS_BUFFER_TOO_SMALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0 it out first */
|
/* expect a 1:1 correspondence between interfaces and IP
|
||||||
memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2));
|
addresses, so use the cheaper (less memory allocated)
|
||||||
|
GetIpAddrTable rather than GetIfTable */
|
||||||
|
ipAddrTableSize = 0;
|
||||||
|
GetIpAddrTable(NULL, &ipAddrTableSize, FALSE);
|
||||||
|
table = (PMIB_IPADDRTABLE)calloc(1, ipAddrTableSize);
|
||||||
|
if (!table) return -1; /* FIXME: better error code */
|
||||||
|
GetIpAddrTable(table, &ipAddrTableSize, FALSE);
|
||||||
|
|
||||||
for (i=0; i<numInt; i++)
|
/* 0 it out first */
|
||||||
|
memset(baseptr, 0, sizeof(TDIEntityID)*(table->dwNumEntries*2));
|
||||||
|
|
||||||
|
for (i=0; i<table->dwNumEntries; i++)
|
||||||
{
|
{
|
||||||
/* tei_instance is an network interface identifier.
|
/* tei_instance is an network interface identifier.
|
||||||
I'm not quite sure what the difference is between tei_entity values of
|
I'm not quite sure what the difference is between tei_entity values of
|
||||||
CL_NL_ENTITY and IF_ENTITY */
|
CL_NL_ENTITY and IF_ENTITY */
|
||||||
baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = i; baseptr++;
|
baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++;
|
||||||
baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = i; baseptr++;
|
baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate size of out buffer */
|
/* Calculate size of out buffer */
|
||||||
*pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
|
*pcbResponseInfoLen = sizeof(TDIEntityID)*(table->dwNumEntries*2);
|
||||||
|
free(table);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -261,155 +202,44 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
||||||
{
|
{
|
||||||
if (pcommand->toi_entity.tei_entity == IF_ENTITY)
|
if (pcommand->toi_entity.tei_entity == IF_ENTITY)
|
||||||
{
|
{
|
||||||
/* In this case, we are requesting specific information about a
|
MIB_IFROW row;
|
||||||
a particular network adapter. (MAC Address, speed, data transmitted/received,
|
DWORD index = pcommand->toi_entity.tei_instance, ret;
|
||||||
etc.)
|
DWORD size = sizeof(row) - sizeof(row.wszName) -
|
||||||
*/
|
sizeof(row.bDescr);
|
||||||
IFEntry *IntInfo = (IFEntry *) pResponseInfo;
|
|
||||||
char ifName[512];
|
|
||||||
#if defined(SIOCGIFHWADDR) || defined(SIOCGENADDR)
|
|
||||||
struct ifreq ifInfo;
|
|
||||||
#endif
|
|
||||||
SOCKET sock;
|
|
||||||
|
|
||||||
|
if (*pcbResponseInfoLen < size)
|
||||||
if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
|
|
||||||
{
|
|
||||||
ERR ("Unable to parse /proc filesystem!\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a socket so that we can use ioctl */
|
|
||||||
if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
ERR ("Error creating socket!\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 0 out return structure first */
|
|
||||||
memset (IntInfo, 0, sizeof(IFEntry));
|
|
||||||
|
|
||||||
/* Interface ID */
|
|
||||||
IntInfo->if_index = pcommand->toi_entity.tei_instance;
|
|
||||||
|
|
||||||
/* MAC Address - Let's try to do this in a cross-platform way... */
|
|
||||||
#if defined(SIOCGIFHWADDR) /* Linux */
|
|
||||||
strcpy(ifInfo.ifr_name, ifName);
|
|
||||||
if (ioctlsocket(sock, SIOCGIFHWADDR, (ULONG*)&ifInfo) < 0)
|
|
||||||
{
|
|
||||||
ERR ("Error obtaining MAC Address!\n");
|
|
||||||
closesocket(sock);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: Is it correct to assume size of 6? */
|
|
||||||
memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
|
|
||||||
IntInfo->if_physaddrlen=6;
|
|
||||||
}
|
|
||||||
#elif defined(SIOCGENADDR) /* Solaris */
|
|
||||||
if (ioctlsocket(sock, SIOCGENADDR, (ULONG*)&ifInfo) < 0)
|
|
||||||
{
|
|
||||||
ERR ("Error obtaining MAC Address!\n");
|
|
||||||
closesocket(sock);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: Is it correct to assume size of 6? */
|
|
||||||
memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
|
|
||||||
IntInfo->if_physaddrlen=6;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
memset (IntInfo->if_physaddr, 0, 6);
|
|
||||||
ERR ("Unable to determine MAC Address on your platform!\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Interface name and length */
|
|
||||||
strcpy (IntInfo->if_descr, ifName);
|
|
||||||
IntInfo->if_descrlen= strlen (IntInfo->if_descr);
|
|
||||||
|
|
||||||
/* Obtain bytes transmitted/received for interface */
|
|
||||||
if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance,
|
|
||||||
&IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
|
|
||||||
{
|
|
||||||
ERR ("Error obtaining transmit/receive stats for the network interface!\n");
|
|
||||||
closesocket(sock);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: How should the below be properly calculated? ******************/
|
|
||||||
IntInfo->if_type = 0x6; /* Ethernet (?) */
|
|
||||||
IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
closesocket(sock);
|
|
||||||
*pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen;
|
|
||||||
}
|
|
||||||
else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
|
|
||||||
{
|
|
||||||
IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
|
|
||||||
int numInt, numRoutes;
|
|
||||||
|
|
||||||
/* This case is used to obtain general statistics about the
|
|
||||||
network */
|
|
||||||
|
|
||||||
if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
|
|
||||||
{
|
{
|
||||||
return (STATUS_BUFFER_TOO_SMALL);
|
return (STATUS_BUFFER_TOO_SMALL);
|
||||||
}
|
}
|
||||||
else
|
row.dwIndex = index;
|
||||||
|
ret = GetIfEntry(&row);
|
||||||
|
if (ret != NO_ERROR)
|
||||||
{
|
{
|
||||||
/* 0 it out first */
|
ERR ("Error retrieving data for interface index %lu\n", index);
|
||||||
memset(infoStruc, 0, sizeof(IPSNMPInfo));
|
return -1; /* FIXME: better error code */
|
||||||
|
|
||||||
/* Get the number of interfaces */
|
|
||||||
numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
|
|
||||||
if (numInt < 0)
|
|
||||||
{
|
|
||||||
ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
/* Get the number of routes */
|
|
||||||
numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
|
|
||||||
if (numRoutes < 0)
|
|
||||||
{
|
|
||||||
ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
infoStruc->ipsi_numif = numInt; /* # of interfaces */
|
|
||||||
infoStruc->ipsi_numaddr = numInt; /* # of addresses */
|
|
||||||
infoStruc->ipsi_numroutes = numRoutes; /* # of routes */
|
|
||||||
|
|
||||||
/* FIXME: How should the below be properly calculated? ******************/
|
|
||||||
infoStruc->ipsi_forwarding = 0x0;
|
|
||||||
infoStruc->ipsi_defaultttl = 0x0;
|
|
||||||
infoStruc->ipsi_inreceives = 0x0;
|
|
||||||
infoStruc->ipsi_inhdrerrors = 0x0;
|
|
||||||
infoStruc->ipsi_inaddrerrors = 0x0;
|
|
||||||
infoStruc->ipsi_forwdatagrams = 0x0;
|
|
||||||
infoStruc->ipsi_inunknownprotos = 0x0;
|
|
||||||
infoStruc->ipsi_indiscards = 0x0;
|
|
||||||
infoStruc->ipsi_indelivers = 0x0;
|
|
||||||
infoStruc->ipsi_outrequests = 0x0;
|
|
||||||
infoStruc->ipsi_routingdiscards = 0x0;
|
|
||||||
infoStruc->ipsi_outdiscards = 0x0;
|
|
||||||
infoStruc->ipsi_outnoroutes = 0x0;
|
|
||||||
infoStruc->ipsi_reasmtimeout = 0x0;
|
|
||||||
infoStruc->ipsi_reasmreqds = 0x0;
|
|
||||||
infoStruc->ipsi_reasmoks = 0x0;
|
|
||||||
infoStruc->ipsi_reasmfails = 0x0;
|
|
||||||
infoStruc->ipsi_fragoks = 0x0;
|
|
||||||
infoStruc->ipsi_fragfails = 0x0;
|
|
||||||
infoStruc->ipsi_fragcreates = 0x0;
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
/* Calculate size of out buffer */
|
|
||||||
*pcbResponseInfoLen = sizeof(IPSNMPInfo);
|
|
||||||
}
|
}
|
||||||
|
size = sizeof(row) - sizeof(row.wszName) -
|
||||||
|
sizeof(row.bDescr) + row.dwDescrLen;
|
||||||
|
if (*pcbResponseInfoLen < size)
|
||||||
|
{
|
||||||
|
return (STATUS_BUFFER_TOO_SMALL);
|
||||||
|
}
|
||||||
|
memcpy(pResponseInfo, &row.dwIndex, size);
|
||||||
|
*pcbResponseInfoLen = size;
|
||||||
|
}
|
||||||
|
else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
|
||||||
|
{
|
||||||
|
/* This case is used to obtain general statistics about the
|
||||||
|
network */
|
||||||
|
|
||||||
|
if (*pcbResponseInfoLen < sizeof(MIB_IPSTATS))
|
||||||
|
{
|
||||||
|
return (STATUS_BUFFER_TOO_SMALL);
|
||||||
|
}
|
||||||
|
GetIpStatistics((PMIB_IPSTATS)pResponseInfo);
|
||||||
|
|
||||||
|
/* Calculate size of out buffer */
|
||||||
|
*pcbResponseInfoLen = sizeof(MIB_IPSTATS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -428,172 +258,97 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
||||||
particular network adapter */
|
particular network adapter */
|
||||||
case IP_MIB_ADDRTABLE_ENTRY_ID:
|
case IP_MIB_ADDRTABLE_ENTRY_ID:
|
||||||
{
|
{
|
||||||
IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
|
DWORD index = pcommand->toi_entity.tei_instance;
|
||||||
char ifName[IFNAMSIZ+1];
|
PMIB_IPADDRROW baseIPInfo = (PMIB_IPADDRROW) pResponseInfo;
|
||||||
struct ifreq ifInfo;
|
PMIB_IPADDRTABLE table;
|
||||||
SOCKET sock;
|
DWORD tableSize, i;
|
||||||
|
|
||||||
if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
|
if (*pcbResponseInfoLen < sizeof(MIB_IPADDRROW))
|
||||||
{
|
{
|
||||||
return (STATUS_BUFFER_TOO_SMALL);
|
return (STATUS_BUFFER_TOO_SMALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
|
/* overkill, get entire table, because there isn't an
|
||||||
|
exported function that gets just one entry, and don't
|
||||||
|
necessarily want our own private export. */
|
||||||
|
tableSize = 0;
|
||||||
|
GetIpAddrTable(NULL, &tableSize, FALSE);
|
||||||
|
table = (PMIB_IPADDRTABLE)calloc(1, tableSize);
|
||||||
|
if (!table) return -1; /* FIXME: better error code */
|
||||||
|
GetIpAddrTable(table, &tableSize, FALSE);
|
||||||
|
for (i = 0; i < table->dwNumEntries; i++)
|
||||||
{
|
{
|
||||||
ERR ("Unable to parse /proc filesystem!\n");
|
if (table->table[i].dwIndex == index)
|
||||||
return (-1);
|
{
|
||||||
|
memcpy(baseIPInfo, &table->table[i],
|
||||||
|
sizeof(MIB_IPADDRROW));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
free(table);
|
||||||
|
|
||||||
|
|
||||||
/* Get a socket so we can use ioctl */
|
|
||||||
if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
ERR ("Error creating socket!\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 0 it out first */
|
|
||||||
memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
|
|
||||||
|
|
||||||
/* Interface Id */
|
|
||||||
baseIPInfo->iae_index = pcommand->toi_entity.tei_instance;
|
|
||||||
|
|
||||||
/* IP Address */
|
|
||||||
strcpy (ifInfo.ifr_name, ifName);
|
|
||||||
ifInfo.ifr_addr.sa_family = AF_INET;
|
|
||||||
if (ioctlsocket(sock, SIOCGIFADDR, (ULONG*)&ifInfo) < 0)
|
|
||||||
{
|
|
||||||
baseIPInfo->iae_addr = 0x0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_addr;
|
|
||||||
baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Broadcast Address */
|
|
||||||
strcpy (ifInfo.ifr_name, ifName);
|
|
||||||
if (ioctlsocket(sock, SIOCGIFBRDADDR, (ULONG *)&ifInfo) < 0)
|
|
||||||
{
|
|
||||||
baseIPInfo->iae_bcastaddr = 0x0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_broadaddr;
|
|
||||||
baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Subnet Mask */
|
|
||||||
strcpy(ifInfo.ifr_name, ifName);
|
|
||||||
if (ioctlsocket(sock, SIOCGIFNETMASK, (ULONG *)&ifInfo) < 0)
|
|
||||||
{
|
|
||||||
baseIPInfo->iae_mask = 0x0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Trying to avoid some compile problems across platforms.
|
|
||||||
(Linux, FreeBSD, Solaris...) */
|
|
||||||
#ifndef ifr_netmask
|
|
||||||
#ifndef ifr_addr
|
|
||||||
baseIPInfo->iae_mask = 0;
|
|
||||||
ERR ("Unable to determine Netmask on your platform!\n");
|
|
||||||
#else
|
|
||||||
struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_addr;
|
|
||||||
baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_netmask;
|
|
||||||
baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: How should the below be properly calculated? ******************/
|
|
||||||
baseIPInfo->iae_reasmsize = 0x0;
|
|
||||||
baseIPInfo->iae_context = 0x0;
|
|
||||||
baseIPInfo->iae_pad = 0x0;
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
/* Calculate size of out buffer */
|
/* Calculate size of out buffer */
|
||||||
*pcbResponseInfoLen = sizeof(IPAddrEntry);
|
*pcbResponseInfoLen = sizeof(MIB_IPADDRROW);
|
||||||
closesocket(sock);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This call returns the routing table.
|
/* This call returns the routing table.
|
||||||
* No official documentation found, even the name of the command is unknown.
|
* No official documentation found, even the name of the command is unknown.
|
||||||
* Work is based on
|
* Work is based on
|
||||||
* http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
|
* http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
|
||||||
* and testings done with winipcfg.exe, route.exe and ipconfig.exe.
|
* and testings done with winipcfg.exe, route.exe and ipconfig.exe.
|
||||||
* pcommand->toi_entity.tei_instance seems to be the interface number
|
* pcommand->toi_entity.tei_instance seems to be the interface number
|
||||||
* but route.exe outputs only the information for the last interface
|
* but route.exe outputs only the information for the last interface
|
||||||
* if only the routes for the pcommand->toi_entity.tei_instance
|
* if only the routes for the pcommand->toi_entity.tei_instance
|
||||||
* interface are returned. */
|
* interface are returned. */
|
||||||
case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
|
case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
|
||||||
{
|
{
|
||||||
int numRoutes, foundRoutes;
|
DWORD routeTableSize, numRoutes, ndx;
|
||||||
wscntl_routeentry *routeTable, *routePtr; /* route table */
|
PMIB_IPFORWARDTABLE table;
|
||||||
|
|
||||||
IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
|
IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
|
||||||
|
|
||||||
/* Get the number of routes */
|
GetIpForwardTable(NULL, &routeTableSize, FALSE);
|
||||||
numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
|
numRoutes = min(routeTableSize - sizeof(MIB_IPFORWARDTABLE), 0)
|
||||||
if (numRoutes < 0)
|
/ sizeof(MIB_IPFORWARDROW) + 1;
|
||||||
{
|
if (*pcbResponseInfoLen < sizeof(IPRouteEntry) * numRoutes)
|
||||||
ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
|
{
|
||||||
return (-1);
|
return (STATUS_BUFFER_TOO_SMALL);
|
||||||
}
|
}
|
||||||
|
table = (PMIB_IPFORWARDTABLE)calloc(1, routeTableSize);
|
||||||
|
if (!table) return -1; /* FIXME: better return value */
|
||||||
|
GetIpForwardTable(table, &routeTableSize, FALSE);
|
||||||
|
|
||||||
if (*pcbResponseInfoLen < (sizeof(IPRouteEntry) * numRoutes))
|
memset(pResponseInfo, 0, sizeof(IPRouteEntry) * numRoutes);
|
||||||
{
|
for (ndx = 0; ndx < table->dwNumEntries; ndx++)
|
||||||
return (STATUS_BUFFER_TOO_SMALL);
|
{
|
||||||
}
|
winRouteTable->ire_addr =
|
||||||
|
table->table[ndx].dwForwardDest;
|
||||||
|
winRouteTable->ire_index =
|
||||||
|
table->table[ndx].dwForwardIfIndex;
|
||||||
|
winRouteTable->ire_metric =
|
||||||
|
table->table[ndx].dwForwardMetric1;
|
||||||
|
/* winRouteTable->ire_option4 =
|
||||||
|
winRouteTable->ire_option5 =
|
||||||
|
winRouteTable->ire_option6 = */
|
||||||
|
winRouteTable->ire_gw = table->table[ndx].dwForwardNextHop;
|
||||||
|
/* winRouteTable->ire_option8 =
|
||||||
|
winRouteTable->ire_option9 =
|
||||||
|
winRouteTable->ire_option10 = */
|
||||||
|
winRouteTable->ire_mask = table->table[ndx].dwForwardMask;
|
||||||
|
/* winRouteTable->ire_option12 = */
|
||||||
|
winRouteTable++;
|
||||||
|
}
|
||||||
|
|
||||||
/* malloc space for the routeTable */
|
/* calculate the length of the data in the output buffer */
|
||||||
routeTable = (wscntl_routeentry *) malloc(sizeof(wscntl_routeentry) * numRoutes);
|
*pcbResponseInfoLen = sizeof(IPRouteEntry) *
|
||||||
if (!routeTable)
|
table->dwNumEntries;
|
||||||
{
|
|
||||||
ERR ("couldn't malloc space for routeTable!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the route table */
|
free(table);
|
||||||
foundRoutes = WSCNTL_GetRouteTable(numRoutes, routeTable);
|
|
||||||
if (foundRoutes < 0)
|
|
||||||
{
|
|
||||||
ERR ("Unable to open /proc filesystem to parse the route entries!\n");
|
|
||||||
free(routeTable);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
routePtr = routeTable;
|
|
||||||
|
|
||||||
/* first 0 out the output buffer */
|
|
||||||
memset(winRouteTable, 0, *pcbResponseInfoLen);
|
|
||||||
|
|
||||||
/* calculate the length of the data in the output buffer */
|
|
||||||
*pcbResponseInfoLen = sizeof(IPRouteEntry) * foundRoutes;
|
|
||||||
|
|
||||||
for ( ; foundRoutes > 0; foundRoutes--)
|
|
||||||
{
|
|
||||||
winRouteTable->ire_addr = routePtr->wre_dest;
|
|
||||||
winRouteTable->ire_index = routePtr->wre_intf;
|
|
||||||
winRouteTable->ire_metric = routePtr->wre_metric;
|
|
||||||
/* winRouteTable->ire_option4 =
|
|
||||||
winRouteTable->ire_option5 =
|
|
||||||
winRouteTable->ire_option6 = */
|
|
||||||
winRouteTable->ire_gw = routePtr->wre_gw;
|
|
||||||
/* winRouteTable->ire_option8 =
|
|
||||||
winRouteTable->ire_option9 =
|
|
||||||
winRouteTable->ire_option10 = */
|
|
||||||
winRouteTable->ire_mask = routePtr->wre_mask;
|
|
||||||
/* winRouteTable->ire_option12 = */
|
|
||||||
|
|
||||||
winRouteTable++;
|
|
||||||
routePtr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(routeTable);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -641,385 +396,6 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Helper function for WsControl - Get count of the number of interfaces
|
|
||||||
or routes by parsing /proc filesystem.
|
|
||||||
*/
|
|
||||||
int WSCNTL_GetEntryCount(const int entrytype)
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
int fd;
|
|
||||||
char buf[512]; /* Size optimized for a typical workstation */
|
|
||||||
char *ptr;
|
|
||||||
int count;
|
|
||||||
int chrread;
|
|
||||||
|
|
||||||
|
|
||||||
switch (entrytype)
|
|
||||||
{
|
|
||||||
case WSCNTL_COUNT_INTERFACES:
|
|
||||||
{
|
|
||||||
filename = PROCFS_NETDEV_FILE;
|
|
||||||
count = -2; /* two haeder lines */
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
case WSCNTL_COUNT_ROUTES:
|
|
||||||
{
|
|
||||||
filename = PROCFS_ROUTE_FILE;
|
|
||||||
count = -1; /* one haeder line */
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* open /proc filesystem file */
|
|
||||||
fd = open(filename, O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read the file and count the EOL's */
|
|
||||||
while ((chrread = read(fd, buf, sizeof(buf))) != 0)
|
|
||||||
{
|
|
||||||
ptr = buf;
|
|
||||||
if (chrread < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
{
|
|
||||||
continue; /* read interupted by a signal, try to read again */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((ptr = memchr(ptr, '\n', chrread - (int) (ptr - buf))) > 0)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Helper function for WsControl - Get name of device from interface number
|
|
||||||
by parsing /proc filesystem.
|
|
||||||
*/
|
|
||||||
int WSCNTL_GetInterfaceName(int intNumber, char *intName)
|
|
||||||
{
|
|
||||||
FILE *procfs;
|
|
||||||
char buf[512]; /* Size doesn't matter, something big */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Open /proc filesystem file for network devices */
|
|
||||||
procfs = fopen(PROCFS_NETDEV_FILE, "r");
|
|
||||||
if (!procfs)
|
|
||||||
{
|
|
||||||
/* If we can't open the file, return an error */
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Omit first two lines, they are only headers */
|
|
||||||
fgets(buf, sizeof(buf), procfs);
|
|
||||||
fgets(buf, sizeof(buf), procfs);
|
|
||||||
|
|
||||||
for (i=0; i<intNumber; i++)
|
|
||||||
{
|
|
||||||
/* Skip the lines that don't interest us. */
|
|
||||||
fgets(buf, sizeof(buf), procfs);
|
|
||||||
}
|
|
||||||
fgets(buf, sizeof(buf), procfs); /* This is the line we want */
|
|
||||||
|
|
||||||
|
|
||||||
/* Parse out the line, grabbing only the name of the device
|
|
||||||
to the intName variable
|
|
||||||
|
|
||||||
The Line comes in like this: (we only care about the device name)
|
|
||||||
lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
|
|
||||||
*/
|
|
||||||
i=0;
|
|
||||||
while (isspace(buf[i])) /* Skip initial space(s) */
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (buf[i])
|
|
||||||
{
|
|
||||||
if (isspace(buf[i]))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
|
|
||||||
{
|
|
||||||
/* This interface could be an alias... */
|
|
||||||
int hold = i;
|
|
||||||
char *dotname = intName;
|
|
||||||
*intName++ = buf[i++];
|
|
||||||
|
|
||||||
while (isdigit(buf[i]))
|
|
||||||
{
|
|
||||||
*intName++ = buf[i++];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[i] != ':')
|
|
||||||
{
|
|
||||||
/* ... It wasn't, so back up */
|
|
||||||
i = hold;
|
|
||||||
intName = dotname;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[i] == '\0')
|
|
||||||
{
|
|
||||||
fclose(procfs);
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*intName++ = buf[i++];
|
|
||||||
}
|
|
||||||
*intName++ = '\0';
|
|
||||||
|
|
||||||
fclose(procfs);
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Helper function for WsControl - This function returns the bytes (octets) transmitted
|
|
||||||
and received for the supplied interface number from the /proc fs.
|
|
||||||
*/
|
|
||||||
int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
|
|
||||||
{
|
|
||||||
FILE *procfs;
|
|
||||||
char buf[512], result[512]; /* Size doesn't matter, something big */
|
|
||||||
int i, bufPos, resultPos;
|
|
||||||
|
|
||||||
/* Open /proc filesystem file for network devices */
|
|
||||||
procfs = fopen(PROCFS_NETDEV_FILE, "r");
|
|
||||||
if (!procfs)
|
|
||||||
{
|
|
||||||
/* If we can't open the file, return an error */
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Omit first two lines, they are only headers */
|
|
||||||
fgets(buf, sizeof(buf), procfs);
|
|
||||||
fgets(buf, sizeof(buf), procfs);
|
|
||||||
|
|
||||||
for (i=0; i<intNumber; i++)
|
|
||||||
{
|
|
||||||
/* Skip the lines that don't interest us. */
|
|
||||||
fgets(buf, sizeof(buf), procfs);
|
|
||||||
}
|
|
||||||
fgets(buf, sizeof(buf), procfs); /* This is the line we want */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Parse out the line, grabbing the number of bytes transmitted
|
|
||||||
and received on the interface.
|
|
||||||
|
|
||||||
The Line comes in like this: (we care about columns 2 and 10)
|
|
||||||
lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Start at character 0 in the buffer */
|
|
||||||
bufPos=0;
|
|
||||||
|
|
||||||
/* Skip initial space(s) */
|
|
||||||
while (isspace(buf[bufPos]))
|
|
||||||
bufPos++;
|
|
||||||
|
|
||||||
|
|
||||||
/* Skip the name and its trailing spaces (if any) */
|
|
||||||
while (buf[bufPos])
|
|
||||||
{
|
|
||||||
if (isspace(buf[bufPos]))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (buf[bufPos] == ':') /* Could be an alias */
|
|
||||||
{
|
|
||||||
int hold = bufPos;
|
|
||||||
|
|
||||||
while(isdigit (buf[bufPos]))
|
|
||||||
bufPos++;
|
|
||||||
if (buf[bufPos] != ':')
|
|
||||||
bufPos = hold;
|
|
||||||
if (buf[bufPos] == '\0')
|
|
||||||
{
|
|
||||||
fclose(procfs);
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bufPos++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bufPos++;
|
|
||||||
}
|
|
||||||
while (isspace(buf[bufPos]))
|
|
||||||
bufPos++;
|
|
||||||
|
|
||||||
|
|
||||||
/* This column (#2) is the number of bytes received. */
|
|
||||||
resultPos = 0;
|
|
||||||
while (!isspace(buf[bufPos]))
|
|
||||||
{
|
|
||||||
result[resultPos] = buf[bufPos];
|
|
||||||
result[resultPos+1]='\0';
|
|
||||||
resultPos++; bufPos++;
|
|
||||||
}
|
|
||||||
*recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
|
|
||||||
|
|
||||||
|
|
||||||
/* Skip columns #3 to #9 (Don't need them) */
|
|
||||||
for (i=0; i<7; i++)
|
|
||||||
{
|
|
||||||
while (isspace(buf[bufPos]))
|
|
||||||
bufPos++;
|
|
||||||
while (!isspace(buf[bufPos]))
|
|
||||||
bufPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This column (#10) is the number of bytes transmitted */
|
|
||||||
while (isspace(buf[bufPos]))
|
|
||||||
bufPos++;
|
|
||||||
|
|
||||||
resultPos = 0;
|
|
||||||
while (!isspace(buf[bufPos]))
|
|
||||||
{
|
|
||||||
result[resultPos] = buf[bufPos];
|
|
||||||
result[resultPos+1]='\0';
|
|
||||||
resultPos++; bufPos++;
|
|
||||||
}
|
|
||||||
*transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
|
|
||||||
|
|
||||||
|
|
||||||
fclose(procfs);
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Parse the procfs route file and put the datas into routeTable.
|
|
||||||
* Return value is the number of found routes */
|
|
||||||
int WSCNTL_GetRouteTable(int numRoutes, wscntl_routeentry *routeTable)
|
|
||||||
{
|
|
||||||
int nrIntf; /* total number of interfaces */
|
|
||||||
char buf[256]; /* temporary buffer */
|
|
||||||
char *ptr; /* pointer to temporary buffer */
|
|
||||||
FILE *file; /* file handle for procfs route file */
|
|
||||||
int foundRoutes = 0; /* number of found routes */
|
|
||||||
typedef struct interface_t {
|
|
||||||
char intfName[IFNAMSIZ+1]; /* the name of the interface */
|
|
||||||
int intfNameLen; /* length of interface name */
|
|
||||||
} interface_t;
|
|
||||||
interface_t *interface;
|
|
||||||
int intfNr; /* the interface number */
|
|
||||||
|
|
||||||
wscntl_routeentry *routePtr = routeTable;
|
|
||||||
|
|
||||||
/* get the number of interfaces */
|
|
||||||
nrIntf = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
|
|
||||||
if (nrIntf < 0)
|
|
||||||
{
|
|
||||||
ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* malloc space for the interface struct array */
|
|
||||||
interface = (interface_t *) malloc(sizeof(interface_t) * nrIntf);
|
|
||||||
if (!routeTable)
|
|
||||||
{
|
|
||||||
ERR ("couldn't malloc space for interface!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (intfNr = 0; intfNr < nrIntf; intfNr++) {
|
|
||||||
if (WSCNTL_GetInterfaceName(intfNr, interface[intfNr].intfName) < 0)
|
|
||||||
{
|
|
||||||
ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
|
|
||||||
free(interface);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
interface[intfNr].intfNameLen = strlen(interface[intfNr].intfName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open /proc filesystem file for routes */
|
|
||||||
file = fopen(PROCFS_ROUTE_FILE, "r");
|
|
||||||
if (!file)
|
|
||||||
{
|
|
||||||
/* If we can't open the file, return an error */
|
|
||||||
free(interface);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip the header line */
|
|
||||||
fgets(buf, sizeof(buf), file);
|
|
||||||
|
|
||||||
/* parse the rest of the file and put the matching entries into routeTable.
|
|
||||||
Format of procfs route entry:
|
|
||||||
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
|
||||||
lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
|
|
||||||
*/
|
|
||||||
while (fgets(buf, sizeof(buf), file)) {
|
|
||||||
intfNr = 0;
|
|
||||||
/* find the interface of the route */
|
|
||||||
while ((strncmp(buf, interface[intfNr].intfName, interface[intfNr].intfNameLen) != 0)
|
|
||||||
&& (intfNr < nrIntf))
|
|
||||||
{
|
|
||||||
intfNr++;
|
|
||||||
}
|
|
||||||
if (intfNr < nrIntf) {
|
|
||||||
foundRoutes++;
|
|
||||||
if (foundRoutes > numRoutes) {
|
|
||||||
/* output buffer is to small */
|
|
||||||
ERR("buffer to small to fit all routes found into it!\n");
|
|
||||||
free(interface);
|
|
||||||
fclose(file);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ptr = buf;
|
|
||||||
ptr += interface[intfNr].intfNameLen;
|
|
||||||
routePtr->wre_intf = intfNr;
|
|
||||||
routePtr->wre_dest = strtoul(ptr, &ptr, 16); /* destination */
|
|
||||||
routePtr->wre_gw = strtoul(ptr, &ptr, 16); /* gateway */
|
|
||||||
strtoul(ptr, &ptr, 16); /* Flags; unused */
|
|
||||||
strtoul(ptr, &ptr, 16); /* RefCnt; unused */
|
|
||||||
strtoul(ptr, &ptr, 16); /* Use; unused */
|
|
||||||
routePtr->wre_metric = strtoul(ptr, &ptr, 16); /* metric */
|
|
||||||
routePtr->wre_mask = strtoul(ptr, &ptr, 16); /* mask */
|
|
||||||
/* strtoul(ptr, &ptr, 16); MTU; unused */
|
|
||||||
/* strtoul(ptr, &ptr, 16); Window; unused */
|
|
||||||
/* strtoul(ptr, &ptr, 16); IRTT; unused */
|
|
||||||
|
|
||||||
routePtr++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* this should never happen */
|
|
||||||
WARN("Skipping route with unknown interface\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(interface);
|
|
||||||
fclose(file);
|
|
||||||
return foundRoutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* WSARecvEx (WSOCK32.1107)
|
* WSARecvEx (WSOCK32.1107)
|
||||||
*
|
*
|
||||||
|
|
|
@ -31,30 +31,6 @@
|
||||||
typedef unsigned char uchar; /* This doesn't seem to be in any standard headers */
|
typedef unsigned char uchar; /* This doesn't seem to be in any standard headers */
|
||||||
|
|
||||||
#define WSCTL_SUCCESS 0
|
#define WSCTL_SUCCESS 0
|
||||||
#define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
|
|
||||||
that lists the network devices.
|
|
||||||
Do we need an #ifdef LINUX for this? */
|
|
||||||
#define PROCFS_ROUTE_FILE "/proc/net/route" /* Points to the file in the /proc fs
|
|
||||||
that contains the routing table */
|
|
||||||
#define WSCNTL_COUNT_INTERFACES 1
|
|
||||||
#define WSCNTL_COUNT_ROUTES 2
|
|
||||||
|
|
||||||
/* struct contains a routing table entry */
|
|
||||||
typedef struct wscntl_routeentry
|
|
||||||
{
|
|
||||||
unsigned long wre_intf;
|
|
||||||
unsigned long wre_dest;
|
|
||||||
unsigned long wre_gw;
|
|
||||||
unsigned long wre_mask;
|
|
||||||
unsigned long wre_metric;
|
|
||||||
} wscntl_routeentry;
|
|
||||||
|
|
||||||
/* WsControl Helper Functions */
|
|
||||||
int WSCNTL_GetEntryCount(const int); /* Obtains the number of network interfaces/routes */
|
|
||||||
int WSCNTL_GetInterfaceName(int, char *); /* Obtains the name of an interface */
|
|
||||||
int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes,
|
|
||||||
unsigned long *recvBytes); /* Obtains bytes recv'd/trans by interface */
|
|
||||||
int WSCNTL_GetRouteTable(int numRoutes, wscntl_routeentry *routeTable); /* get the routing for the interface intf */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP/IP action codes.
|
* TCP/IP action codes.
|
||||||
|
|
Loading…
Reference in New Issue