Commit c9d25827 authored by James Hatheway's avatar James Hatheway Committed by Alexandre Julliard

Adds an initial WSAIoctl function with support for only the

SIO_GET_INTERFACE_LIST command. Adds initial code to WsControl function to support the WSCNTL_TCPIP_QUERY_INFO command.
parent 67247b2b
......@@ -69,6 +69,9 @@
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif
#include "wine/winbase16.h"
#include "wingdi.h"
......@@ -84,6 +87,7 @@
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(winsock)
#define DEBUG_SOCKADDR 0
......@@ -119,6 +123,10 @@ typedef struct /* WSAAsyncSelect() control struct */
#define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
#define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
#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? */
typedef struct _WSINFO
{
DWORD dwThisProcess;
......@@ -148,6 +156,9 @@ int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
int WSAIOCTL_GetInterfaceCount(void);
int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
UINT16 wsaErrno(void);
UINT16 wsaHerrno(void);
......@@ -1270,6 +1281,280 @@ SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
}
/**********************************************************************
* WSAIoctl (WS2_32)
*
*
* FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
*/
INT WINAPI WSAIoctl (SOCKET s,
DWORD dwIoControlCode,
LPVOID lpvInBuffer,
DWORD cbInBuffer,
LPVOID lpbOutBuffer,
DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
LPWSINFO pwsi = WINSOCK_GetIData();
if( _check_ws(pwsi, s) )
{
int fd = _get_sock_fd(s);
switch( dwIoControlCode )
{
case SIO_GET_INTERFACE_LIST:
{
INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
int i, numInt;
struct ifreq ifInfo;
char ifName[512];
TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
numInt = WSAIOCTL_GetInterfaceCount();
if (numInt < 0)
{
ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
close(fd);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
for (i=0; i<numInt; i++)
{
if (!WSAIOCTL_GetInterfaceName(i, ifName))
{
ERR ("Error parsing /proc filesystem!\n");
close(fd);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
ifInfo.ifr_addr.sa_family = AF_INET;
/* IP Address */
strcpy (ifInfo.ifr_name, ifName);
if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
{
ERR ("Error obtaining IP address\n");
close(fd);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
else
{
struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
intArray->iiAddress.AddressIn.sin_family = AF_INET;
intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
}
/* Broadcast Address */
strcpy (ifInfo.ifr_name, ifName);
if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
{
ERR ("Error obtaining Broadcast IP address\n");
close(fd);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
else
{
struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
}
/* Subnet Mask */
strcpy (ifInfo.ifr_name, ifName);
if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
{
ERR ("Error obtaining Subnet IP address\n");
close(fd);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
else
{
struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
intArray->iiNetmask.AddressIn.sin_family = AF_INET;
intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
}
/* Socket Status Flags */
strcpy(ifInfo.ifr_name, ifName);
if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
{
ERR ("Error obtaining status flags for socket!\n");
close(fd);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
else
{
/* FIXME - Is this the right flag to use? */
intArray->iiFlags = ifInfo.ifr_flags;
}
intArray++; /* Prepare for another interface */
}
/* Calculate the size of the array being returned */
*lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
break;
}
default:
{
WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
close(fd);
WSASetLastError(WSAEOPNOTSUPP);
return (SOCKET_ERROR);
}
}
/* Function executed with no errors */
close(fd);
return (0);
}
else
{
WSASetLastError(WSAENOTSOCK);
return (SOCKET_ERROR);
}
}
/*
Helper function for WSAIoctl - Get count of the number of interfaces
by parsing /proc filesystem.
*/
int WSAIOCTL_GetInterfaceCount(void)
{
FILE *procfs;
char buf[512]; /* Size doesn't matter, something big */
int intcnt=0;
/* 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);
while (fgets(buf, sizeof buf, procfs))
{
/* Each line in the file represents a network interface */
intcnt++;
}
fclose(procfs);
return(intcnt);
}
/*
Helper function for WSAIoctl - Get name of device from interface number
by parsing /proc filesystem.
*/
int WSAIOCTL_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);
}
/***********************************************************************
* ioctlsocket() (WSOCK32.12)
*/
......
......@@ -56,7 +56,7 @@ init WSOCK32_LibMain
47 stub WSAHtons
48 stub WSAInstallServiceClassA
49 stub WSAInstallServiceClassW
50 stub WSAIoctl
50 stdcall WSAIoctl(long long ptr long ptr long ptr ptr ptr) WSAIoctl
51 stdcall gethostbyaddr(ptr long long) WSOCK32_gethostbyaddr
52 stdcall gethostbyname(str) WSOCK32_gethostbyname
53 stdcall getprotobyname(str) WSOCK32_getprotobyname
......
/* wscontrol.h
*
* This header file includes #defines, structure and type definitions,
* and function declarations that support the implementation of the
* (undocumented) Winsock 1 call WsControl.
*
* The functionality of WsControl was created by observing its behaviour
* in Windows 98, so there are likely to be bugs with the assumptions
* that were made.
*/
#ifndef WSCONTROL_H_INCLUDED
#define WSCONTROL_H_INCLUDED
typedef unsigned char uchar; /* This doesn't seem to be in any standard headers */
#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? */
/* WsControl Helper Functions */
int WSCNTL_GetInterfaceCount(void); /* Obtains the number of network interfaces */
int WSCNTL_GetInterfaceName(int, char *); /* Obtains the name of an interface */
int WSCNTL_GetTransRecvStat(int intNumber, ulong *transBytes, ulong *recvBytes); /* Obtains bytes
recv'd/trans by interface */
/*
* TCP/IP action codes.
*/
#define WSCNTL_TCPIP_QUERY_INFO 0x00000000
#define WSCNTL_TCPIP_SET_INFO 0x00000001
#define WSCNTL_TCPIP_ICMP_ECHO 0x00000002
#define WSCNTL_TCPIP_TEST 0x00000003
/* Structure of an entity ID */
typedef struct TDIEntityID
{
ulong tei_entity;
ulong tei_instance;
} TDIEntityID;
/* Structure of an object ID */
typedef struct TDIObjectID
{
TDIEntityID toi_entity;
ulong toi_class;
ulong toi_type;
ulong toi_id;
} TDIObjectID;
typedef struct IPSNMPInfo
{
ulong ipsi_forwarding;
ulong ipsi_defaultttl;
ulong ipsi_inreceives;
ulong ipsi_inhdrerrors;
ulong ipsi_inaddrerrors;
ulong ipsi_forwdatagrams;
ulong ipsi_inunknownprotos;
ulong ipsi_indiscards;
ulong ipsi_indelivers;
ulong ipsi_outrequests;
ulong ipsi_routingdiscards;
ulong ipsi_outdiscards;
ulong ipsi_outnoroutes;
ulong ipsi_reasmtimeout;
ulong ipsi_reasmreqds;
ulong ipsi_reasmoks;
ulong ipsi_reasmfails;
ulong ipsi_fragoks;
ulong ipsi_fragfails;
ulong ipsi_fragcreates;
ulong ipsi_numif;
ulong ipsi_numaddr;
ulong ipsi_numroutes;
} IPSNMPInfo;
typedef struct IPAddrEntry
{
ulong iae_addr;
ulong iae_index;
ulong iae_mask;
ulong iae_bcastaddr;
ulong iae_reasmsize;
ushort iae_context;
ushort iae_pad;
} IPAddrEntry;
#define MAX_PHYSADDR_SIZE 8
#define MAX_IFDESCR_LEN 256
typedef struct IFEntry
{
ulong if_index;
ulong if_type;
ulong if_mtu;
ulong if_speed;
ulong if_physaddrlen;
uchar if_physaddr[MAX_PHYSADDR_SIZE];
ulong if_adminstatus;
ulong if_operstatus;
ulong if_lastchange;
ulong if_inoctets;
ulong if_inucastpkts;
ulong if_innucastpkts;
ulong if_indiscards;
ulong if_inerrors;
ulong if_inunknownprotos;
ulong if_outoctets;
ulong if_outucastpkts;
ulong if_outnucastpkts;
ulong if_outdiscards;
ulong if_outerrors;
ulong if_outqlen;
ulong if_descrlen;
uchar if_descr[1];
} IFEntry;
/* Not sure what EXACTLY most of this stuff does.
WsControl was implemented mainly by observing
its behaviour in Win98 ************************/
#define INFO_CLASS_GENERIC 0x100
#define INFO_CLASS_PROTOCOL 0x200
#define INFO_TYPE_PROVIDER 0x100
#define ENTITY_LIST_ID 0
#define CL_NL_ENTITY 0x301
#define IF_ENTITY 0x200
#define ENTITY_TYPE_ID 1
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
/************************************************/
/* Valid values to get back from entity type ID query */
#define CO_TL_NBF 0x400 /* Entity implements NBF prot. */
#define CO_TL_SPX 0x402 /* Entity implements SPX prot. */
#define CO_TL_TCP 0x404 /* Entity implements TCP prot. */
#define CO_TL_SPP 0x406 /* Entity implements SPP prot. */
#define CL_TL_NBF 0x401 /* CL NBF protocol */
#define CL_TL_UDP 0x403 /* Entity implements UDP */
#define ER_ICMP 0x380 /* The ICMP protocol */
#define CL_NL_IPX 0x301 /* Entity implements IPX */
#define CL_NL_IP 0x303 /* Entity implements IP */
#define AT_ARP 0x280 /* Entity implements ARP */
#define AT_NULL 0x282 /* Entity does no address */
#define IF_GENERIC 0x200 /* Generic interface */
#define IF_MIB 0x202 /* Supports MIB-2 interface */
#endif /* WSCONTROL_H_INCLUDED */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment