325 lines
11 KiB
C
325 lines
11 KiB
C
/*
|
|
* Protocol enumeration functions
|
|
*
|
|
* Copyright (C) 2001 Stefan Leichter
|
|
* Copyright (C) 2004 Hans Leidekker
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
/* 02/11/2004
|
|
* The protocol enumeration functions were verified to match Win2k versions
|
|
* for these protocols: IPX, SPX, SPXII, TCP/IP and UDP/IP.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
#ifdef HAVE_ARPA_INET_H
|
|
#include <arpa/inet.h>
|
|
#endif
|
|
#ifdef HAVE_NETDB_H
|
|
#include <netdb.h>
|
|
#endif
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "wtypes.h"
|
|
#include "nspapi.h"
|
|
#include "winsock2.h"
|
|
#include "wsipx.h"
|
|
#include "wshisotp.h"
|
|
#include "ws2spi.h"
|
|
|
|
#include "wine/unicode.h"
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(winsock);
|
|
|
|
/* names of the protocols */
|
|
static const WCHAR NameIpxW[] = {'I', 'P', 'X', '\0'};
|
|
static const WCHAR NameSpxW[] = {'S', 'P', 'X', '\0'};
|
|
static const WCHAR NameSpxIIW[] = {'S', 'P', 'X', ' ', 'I', 'I', '\0'};
|
|
static const WCHAR NameTcpW[] = {'T', 'C', 'P', '/', 'I', 'P', '\0'};
|
|
static const WCHAR NameUdpW[] = {'U', 'D', 'P', '/', 'I', 'P', '\0'};
|
|
|
|
/* Taken from Win2k */
|
|
static const GUID ProviderIdIP = { 0xe70f1aa0, 0xab8b, 0x11cf,
|
|
{ 0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
|
|
static const GUID ProviderIdIPX = { 0x11058240, 0xbe47, 0x11cf,
|
|
{ 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
|
|
static const GUID ProviderIdSPX = { 0x11058241, 0xbe47, 0x11cf,
|
|
{ 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
|
|
|
|
/*****************************************************************************
|
|
* WINSOCK_EnterSingleProtocolW [internal]
|
|
*
|
|
* enters the protocol information of one given protocol into the given
|
|
* buffer.
|
|
*
|
|
* RETURNS
|
|
* 1 if a protocol was entered into the buffer.
|
|
* SOCKET_ERROR otherwise.
|
|
*
|
|
* BUGS
|
|
* - only implemented for IPX, SPX, SPXII, TCP, UDP
|
|
* - there is no check that the operating system supports the returned
|
|
* protocols
|
|
*/
|
|
static INT WINSOCK_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
|
|
{
|
|
memset( info, 0, sizeof(WSAPROTOCOL_INFOW) );
|
|
info->iProtocol = protocol;
|
|
|
|
switch (protocol)
|
|
{
|
|
case WS_IPPROTO_TCP:
|
|
info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA |
|
|
XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER |
|
|
XP1_GUARANTEED_DELIVERY;
|
|
info->ProviderId = ProviderIdIP;
|
|
info->dwCatalogEntryId = 0x3e9;
|
|
info->ProtocolChain.ChainLen = 1;
|
|
info->iVersion = 2;
|
|
info->iAddressFamily = WS_AF_INET;
|
|
info->iMaxSockAddr = 0x10;
|
|
info->iMinSockAddr = 0x10;
|
|
info->iSocketType = WS_SOCK_STREAM;
|
|
strcpyW( info->szProtocol, NameTcpW );
|
|
break;
|
|
|
|
case WS_IPPROTO_UDP:
|
|
info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST |
|
|
XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
|
|
XP1_CONNECTIONLESS;
|
|
info->ProviderId = ProviderIdIP;
|
|
info->dwCatalogEntryId = 0x3ea;
|
|
info->ProtocolChain.ChainLen = 1;
|
|
info->iVersion = 2;
|
|
info->iAddressFamily = WS_AF_INET;
|
|
info->iMaxSockAddr = 0x10;
|
|
info->iMinSockAddr = 0x10;
|
|
info->iSocketType = WS_SOCK_DGRAM;
|
|
info->dwMessageSize = 0xffbb;
|
|
strcpyW( info->szProtocol, NameUdpW );
|
|
break;
|
|
|
|
case NSPROTO_IPX:
|
|
info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST |
|
|
XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
|
|
XP1_CONNECTIONLESS;
|
|
info->ProviderId = ProviderIdIPX;
|
|
info->dwCatalogEntryId = 0x406;
|
|
info->ProtocolChain.ChainLen = 1;
|
|
info->iVersion = 2;
|
|
info->iAddressFamily = WS_AF_IPX;
|
|
info->iMaxSockAddr = 0x10;
|
|
info->iMinSockAddr = 0x0e;
|
|
info->iSocketType = WS_SOCK_DGRAM;
|
|
info->iProtocolMaxOffset = 0xff;
|
|
info->dwMessageSize = 0x240;
|
|
strcpyW( info->szProtocol, NameIpxW );
|
|
break;
|
|
|
|
case NSPROTO_SPX:
|
|
info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM |
|
|
XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER |
|
|
XP1_GUARANTEED_DELIVERY;
|
|
info->ProviderId = ProviderIdSPX;
|
|
info->dwCatalogEntryId = 0x407;
|
|
info->ProtocolChain.ChainLen = 1;
|
|
info->iVersion = 2;
|
|
info->iAddressFamily = WS_AF_IPX;
|
|
info->iMaxSockAddr = 0x10;
|
|
info->iMinSockAddr = 0x0e;
|
|
info->iSocketType = 5;
|
|
info->dwMessageSize = 0xffffffff;
|
|
strcpyW( info->szProtocol, NameSpxW );
|
|
break;
|
|
|
|
case NSPROTO_SPXII:
|
|
info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE |
|
|
XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED |
|
|
XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY;
|
|
info->ProviderId = ProviderIdSPX;
|
|
info->dwCatalogEntryId = 0x409;
|
|
info->ProtocolChain.ChainLen = 1;
|
|
info->iVersion = 2;
|
|
info->iAddressFamily = WS_AF_IPX;
|
|
info->iMaxSockAddr = 0x10;
|
|
info->iMinSockAddr = 0x0e;
|
|
info->iSocketType = 5;
|
|
info->dwMessageSize = 0xffffffff;
|
|
strcpyW( info->szProtocol, NameSpxIIW );
|
|
break;
|
|
|
|
default:
|
|
if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX))
|
|
FIXME("Protocol <%s> not implemented\n",
|
|
(protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
|
|
else
|
|
FIXME("unknown Protocol <0x%08x>\n", protocol);
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* WINSOCK_EnterSingleProtocolA [internal]
|
|
*
|
|
* see function WINSOCK_EnterSingleProtocolW
|
|
*
|
|
*/
|
|
static INT WINSOCK_EnterSingleProtocolA( INT protocol, WSAPROTOCOL_INFOA* info )
|
|
{
|
|
WSAPROTOCOL_INFOW infow;
|
|
INT ret;
|
|
memset( info, 0, sizeof(WSAPROTOCOL_INFOA) );
|
|
|
|
ret = WINSOCK_EnterSingleProtocolW( protocol, &infow );
|
|
if (ret != SOCKET_ERROR)
|
|
{
|
|
/* convert the structure from W to A */
|
|
memcpy( info, &infow, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
|
|
WideCharToMultiByte( CP_ACP, 0, infow.szProtocol, -1,
|
|
info->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static INT WINSOCK_EnumProtocols( BOOL unicode, LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
|
|
{
|
|
INT i = 0;
|
|
DWORD size = 0;
|
|
INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 };
|
|
union _info
|
|
{
|
|
LPWSAPROTOCOL_INFOA a;
|
|
LPWSAPROTOCOL_INFOW w;
|
|
} info;
|
|
info.w = buffer;
|
|
|
|
if (!protocols) protocols = local;
|
|
|
|
while (protocols[i]) i++;
|
|
|
|
size = i * (unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA));
|
|
|
|
if (*len < size || !buffer)
|
|
{
|
|
*len = size;
|
|
WSASetLastError(WSAENOBUFS);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
for (i = 0; protocols[i]; i++)
|
|
{
|
|
if (unicode)
|
|
{
|
|
if (WINSOCK_EnterSingleProtocolW( protocols[i], &info.w[i] ) == SOCKET_ERROR)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (WINSOCK_EnterSingleProtocolA( protocols[i], &info.a[i] ) == SOCKET_ERROR)
|
|
break;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* WSAEnumProtocolsA [WS2_32.@]
|
|
*
|
|
* see function WSAEnumProtocolsW
|
|
*/
|
|
INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWORD len )
|
|
{
|
|
return WINSOCK_EnumProtocols( FALSE, protocols, (LPWSAPROTOCOL_INFOW) buffer, len);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* WSAEnumProtocolsW [WS2_32.@]
|
|
*
|
|
* Retrieves information about specified set of active network protocols.
|
|
*
|
|
* PARAMS
|
|
* protocols [I] Pointer to null-terminated array of protocol id's. NULL
|
|
* retrieves information on all available protocols.
|
|
* buffer [I] Pointer to a buffer to be filled with WSAPROTOCOL_INFO
|
|
* structures.
|
|
* len [I/O] Pointer to a variable specifying buffer size. On output
|
|
* the variable holds the number of bytes needed when the
|
|
* specified size is too small.
|
|
*
|
|
* RETURNS
|
|
* Success: number of WSAPROTOCOL_INFO structures in buffer.
|
|
* Failure: SOCKET_ERROR
|
|
*
|
|
* NOTES
|
|
* NT4SP5 does not return SPX if protocols == NULL
|
|
*
|
|
* BUGS
|
|
* - NT4SP5 returns in addition these list of NETBIOS protocols
|
|
* (address family 17), each entry two times one for socket type 2 and 5
|
|
*
|
|
* iProtocol szProtocol
|
|
* 0x80000000 \Device\NwlnkNb
|
|
* 0xfffffffa \Device\NetBT_CBENT7
|
|
* 0xfffffffb \Device\Nbf_CBENT7
|
|
* 0xfffffffc \Device\NetBT_NdisWan5
|
|
* 0xfffffffd \Device\NetBT_El9202
|
|
* 0xfffffffe \Device\Nbf_El9202
|
|
* 0xffffffff \Device\Nbf_NdisWan4
|
|
*
|
|
* - there is no check that the operating system supports the returned
|
|
* protocols
|
|
*/
|
|
INT WINAPI WSAEnumProtocolsW( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
|
|
{
|
|
return WINSOCK_EnumProtocols( TRUE, protocols, buffer, len);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* WSCEnumProtocols [WS2_32.@]
|
|
*
|
|
* PARAMS
|
|
* protocols [I] Null-terminated array of iProtocol values.
|
|
* buffer [O] Buffer of WSAPROTOCOL_INFOW structures.
|
|
* len [I/O] Size of buffer on input/output.
|
|
* errno [O] Error code.
|
|
*
|
|
* RETURNS
|
|
* Success: number of protocols to be reported on.
|
|
* Failure: SOCKET_ERROR. error is in errno.
|
|
*
|
|
* BUGS
|
|
* Doesn't supply info on layered protocols.
|
|
*
|
|
*/
|
|
INT WINAPI WSCEnumProtocols( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len, LPINT err )
|
|
{
|
|
INT ret = WSAEnumProtocolsW( protocols, buffer, len );
|
|
|
|
if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
|
|
|
|
return ret;
|
|
}
|