Implemented WsControl command with id 0x101.

This commit is contained in:
Michael Stefaniuc 2001-02-28 05:17:44 +00:00 committed by Alexandre Julliard
parent 2e9cd986ff
commit 7fa17d24c0
2 changed files with 288 additions and 32 deletions

View File

@ -40,6 +40,7 @@
#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif
#include <errno.h>
/* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
@ -116,7 +117,7 @@ DWORD WINAPI WsControl(DWORD protocoll,
return (WSAEOPNOTSUPP);
}
numInt = WSCNTL_GetInterfaceCount();
numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
if (numInt < 0)
{
ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
@ -263,7 +264,7 @@ DWORD WINAPI WsControl(DWORD protocoll,
else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
{
IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
int numInt;
int numInt, numRoutes;
/* This case is used to obtain general statistics about the
network */
@ -278,16 +279,23 @@ DWORD WINAPI WsControl(DWORD protocoll,
memset(infoStruc, 0, sizeof(IPSNMPInfo));
/* Get the number of interfaces */
numInt = WSCNTL_GetInterfaceCount();
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 = numInt; /* # of routes ~ FIXME - Is this right? */
infoStruc->ipsi_numroutes = numRoutes; /* # of routes */
/* FIXME: How should the below be properly calculated? ******************/
infoStruc->ipsi_forwarding = 0x0;
@ -334,7 +342,7 @@ DWORD WINAPI WsControl(DWORD protocoll,
case IP_MIB_ADDRTABLE_ENTRY_ID:
{
IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
char ifName[512];
char ifName[IFNAMSIZ+1];
struct ifreq ifInfo;
SOCKET sock;
@ -424,10 +432,82 @@ DWORD WINAPI WsControl(DWORD protocoll,
break;
}
case 0x101:
FIXME ("Command ID Unknown but used by winipcfg.exe\n");
break;
/* This call returns the routing table.
* No official documentation found, even the name of the command is unknown.
* Work is based on
* http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
* and testings done with winipcfg.exe, route.exe and ipconfig.exe.
* pcommand->toi_entity.tei_instance seems to be the interface number
* but route.exe outputs only the information for the last interface
* if only the routes for the pcommand->toi_entity.tei_instance
* interface are returned. */
case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
{
int numRoutes, foundRoutes;
wscntl_routeentry *routeTable, *routePtr; /* route table */
IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
/* 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);
}
if (*pcbResponseInfoLen < (sizeof(IPRouteEntry) * numRoutes))
{
return (STATUS_BUFFER_TOO_SMALL);
}
/* malloc space for the routeTable */
routeTable = (wscntl_routeentry *) malloc(sizeof(wscntl_routeentry) * numRoutes);
if (!routeTable)
{
ERR ("couldn't malloc space for routeTable!\n");
}
/* get the route table */
foundRoutes = WSCNTL_GetRouteTable(numRoutes, routeTable);
if (foundRoutes < 0)
{
ERR ("Unable to open /proc filesystem to parse the route entrys!\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;
}
default:
{
@ -476,35 +556,71 @@ DWORD WINAPI WsControl(DWORD protocoll,
/*
Helper function for WsControl - Get count of the number of interfaces
by parsing /proc filesystem.
or routes by parsing /proc filesystem.
*/
int WSCNTL_GetInterfaceCount(void)
int WSCNTL_GetEntryCount(const int entrytype)
{
FILE *procfs;
char buf[512]; /* Size doesn't matter, something big */
int intcnt=0;
char *filename;
int fd;
char buf[512]; /* Size optimized for a typical workstation */
char *ptr;
int count;
int chrread;
/* Open /proc filesystem file for network devices */
procfs = fopen(PROCFS_NETDEV_FILE, "r");
if (!procfs)
switch (entrytype)
{
/* 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);
case WSCNTL_COUNT_INTERFACES:
{
filename = PROCFS_NETDEV_FILE;
count = -2; /* two haeder lines */
break;
};
while (fgets(buf, sizeof buf, procfs))
{
/* Each line in the file represents a network interface */
intcnt++;
case WSCNTL_COUNT_ROUTES:
{
filename = PROCFS_ROUTE_FILE;
count = -1; /* one haeder line */
break;
};
default:
{
return -1;
};
}
fclose(procfs);
return(intcnt);
/* 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;
}
@ -711,6 +827,112 @@ int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned l
}
/* 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 entrys 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)
*

View File

@ -18,12 +18,27 @@ typedef unsigned char uchar; /* This doesn't seem to be in any standard headers
#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_GetInterfaceCount(void); /* Obtains the number of network interfaces */
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_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.
@ -119,6 +134,24 @@ typedef struct IFEntry
} IFEntry;
/* FIXME: real name and definition of this struct that contains
* an IP route table entry is unknown */
typedef struct IPRouteEntry {
unsigned long ire_addr;
unsigned long ire_index; //matches if_index in IFEntry and iae_index in IPAddrEntry
unsigned long ire_metric;
unsigned long ire_option4;
unsigned long ire_option5;
unsigned long ire_option6;
unsigned long ire_gw;
unsigned long ire_option8;
unsigned long ire_option9;
unsigned long ire_option10;
unsigned long ire_mask;
unsigned long ire_option12;
} IPRouteEntry;
/* Not sure what EXACTLY most of this stuff does.
WsControl was implemented mainly by observing
its behaviour in Win98 ************************/
@ -130,6 +163,7 @@ typedef struct IFEntry
#define IF_ENTITY 0x200
#define ENTITY_TYPE_ID 1
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101 /* FIXME: not real name */
/************************************************/
/* Valid values to get back from entity type ID query */