| /* |
| * 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 CHAR NameIpx[] = "IPX"; |
| static const CHAR NameSpx[] = "SPX"; |
| static const CHAR NameSpxII[] = "SPX II"; |
| static const CHAR NameTcp[] = "TCP/IP"; |
| static const CHAR NameUdp[] = "UDP/IP"; |
| |
| 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_PARTIAL_MESSAGE | 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_PARTIAL_MESSAGE | 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 ) |
| { |
| memset( info, 0, sizeof(WSAPROTOCOL_INFOA) ); |
| 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; |
| strcpy( info->szProtocol, NameTcp ); |
| 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; |
| strcpy( info->szProtocol, NameUdp ); |
| break; |
| |
| case NSPROTO_IPX: |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | 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; |
| strcpy( info->szProtocol, NameIpx ); |
| 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; |
| strcpy( info->szProtocol, NameSpx ); |
| 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; |
| strcpy( info->szProtocol, NameSpxII ); |
| 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; |
| } |
| |
| /***************************************************************************** |
| * WSAEnumProtocolsA [WS2_32.@] |
| * |
| * see function WSAEnumProtocolsW |
| */ |
| INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWORD len ) |
| { |
| INT i = 0; |
| DWORD size = 0; |
| INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 }; |
| |
| if (!protocols) protocols = local; |
| |
| while (protocols[i]) i++; |
| |
| size = i * sizeof(WSAPROTOCOL_INFOA); |
| |
| if (*len < size || !buffer) |
| { |
| *len = size; |
| WSASetLastError(WSAENOBUFS); |
| return SOCKET_ERROR; |
| } |
| |
| for (i = 0; protocols[i]; i++) |
| { |
| if (WINSOCK_EnterSingleProtocolA( protocols[i], &buffer[i] ) == SOCKET_ERROR) |
| return i; |
| } |
| return i; |
| } |
| |
| /***************************************************************************** |
| * 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 ) |
| { |
| INT i = 0; |
| DWORD size = 0; |
| INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 }; |
| |
| if (!protocols) protocols = local; |
| |
| while (protocols[i]) i++; |
| |
| size = i * sizeof(WSAPROTOCOL_INFOW); |
| |
| if (*len < size || !buffer) |
| { |
| *len = size; |
| WSASetLastError(WSAENOBUFS); |
| return SOCKET_ERROR; |
| } |
| |
| for (i = 0; protocols[i]; i++) |
| { |
| if (WINSOCK_EnterSingleProtocolW( protocols[i], &buffer[i] ) == SOCKET_ERROR) |
| return i; |
| } |
| return i; |
| } |
| |
| /***************************************************************************** |
| * 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; |
| } |