protocol.c 13.9 KB
Newer Older
1 2 3 4
/*
 * Protocol enumeration functions
 *
 * Copyright (C) 2001 Stefan Leichter
5
 * Copyright (C) 2004 Hans Leidekker
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21
 */

22 23 24 25 26
/*  02/11/2004
 *  The protocol enumeration functions were verified to match Win2k versions
 *  for these protocols: IPX, SPX, SPXII, TCP/IP and UDP/IP.
 */

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
#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"
48
#include "ws2spi.h"
49 50 51 52 53 54

#include "wine/unicode.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(winsock);

55 56 57 58 59 60 61 62 63 64 65 66 67 68
/* 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 */
69 70 71 72 73 74
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 } };
75 76

/*****************************************************************************
77
 *          WINSOCK_EnterSingleProtocolW [internal]
78
 *
79 80
 *    enters the protocol information of one given protocol into the given
 *    buffer.
81 82
 *
 * RETURNS
83 84
 *    1 if a protocol was entered into the buffer.
 *    SOCKET_ERROR otherwise.
85 86 87 88 89 90
 *
 * BUGS
 *    - only implemented for IPX, SPX, SPXII, TCP, UDP
 *    - there is no check that the operating system supports the returned
 *      protocols
 */
91
static INT WINSOCK_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
92
{
93 94 95 96 97 98 99 100 101
    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;
102
        info->ProviderId = ProviderIdIP;
103 104 105 106 107 108 109 110 111 112 113 114 115 116
        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;
117
        info->ProviderId = ProviderIdIP;
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
        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;
133
        info->ProviderId = ProviderIdIPX;
134 135 136
        info->dwCatalogEntryId = 0x406;
        info->ProtocolChain.ChainLen = 1;
        info->iVersion = 2;
137 138 139 140
        info->iAddressFamily = WS_AF_IPX;
        info->iMaxSockAddr = 0x10;
        info->iMinSockAddr = 0x0e;
        info->iSocketType = WS_SOCK_DGRAM;
141 142
        info->iProtocolMaxOffset = 0xff;
        info->dwMessageSize = 0x240;
143 144 145 146
        strcpyW( info->szProtocol, NameIpxW );
        break;

    case NSPROTO_SPX:
147 148 149
        info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM |
                                XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER |
                                XP1_GUARANTEED_DELIVERY;
150
        info->ProviderId = ProviderIdSPX;
151 152 153
        info->dwCatalogEntryId = 0x407;
        info->ProtocolChain.ChainLen = 1;
        info->iVersion = 2;
154 155 156 157
        info->iAddressFamily = WS_AF_IPX;
        info->iMaxSockAddr = 0x10;
        info->iMinSockAddr = 0x0e;
        info->iSocketType = 5;
158
        info->dwMessageSize = 0xffffffff;
159 160 161 162
        strcpyW( info->szProtocol, NameSpxW );
        break;

    case NSPROTO_SPXII:
163
        info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE |
164 165
                                XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED |
                                XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY;
166
        info->ProviderId = ProviderIdSPX;
167 168 169
        info->dwCatalogEntryId = 0x409;
        info->ProtocolChain.ChainLen = 1;
        info->iVersion = 2;
170 171 172 173
        info->iAddressFamily = WS_AF_IPX;
        info->iMaxSockAddr = 0x10;
        info->iMinSockAddr = 0x0e;
        info->iSocketType = 5;
174
        info->dwMessageSize = 0xffffffff;
175 176 177
        strcpyW( info->szProtocol, NameSpxIIW );
        break;

178
    default:
179 180 181
        if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX))
            FIXME("Protocol <%s> not implemented\n",
                  (protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
182
        else
183 184 185 186
            FIXME("unknown Protocol <0x%08x>\n", protocol);
        return SOCKET_ERROR;
    }
    return 1;
187 188 189
}

/*****************************************************************************
190
 *          WINSOCK_EnterSingleProtocolA [internal]
191
 *
192
 *    see function WINSOCK_EnterSingleProtocolW
193 194
 *
 */
195
static INT WINSOCK_EnterSingleProtocolA( INT protocol, WSAPROTOCOL_INFOA* info )
196
{
197 198 199 200 201 202 203 204 205
    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;
206
        info->ProviderId = ProviderIdIP;
207 208 209 210 211 212 213 214 215 216 217 218 219 220
        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;
221
        info->ProviderId = ProviderIdIP;
222 223 224 225 226 227 228 229 230 231 232 233
        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:
234
        info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST |
235 236
                                XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
                                XP1_CONNECTIONLESS;
237
        info->ProviderId = ProviderIdIPX;
238 239 240
        info->dwCatalogEntryId = 0x406;
        info->ProtocolChain.ChainLen = 1;
        info->iVersion = 2;
241 242 243 244
        info->iAddressFamily = WS_AF_IPX;
        info->iMaxSockAddr = 0x10;
        info->iMinSockAddr = 0x0e;
        info->iSocketType = WS_SOCK_DGRAM;
245 246
        info->iProtocolMaxOffset = 0xff;
        info->dwMessageSize = 0x240;
247 248 249 250
        strcpy( info->szProtocol, NameIpx );
        break;

    case NSPROTO_SPX:
251 252 253
        info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM |
                                XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER |
                                XP1_GUARANTEED_DELIVERY;
254
        info->ProviderId = ProviderIdSPX;
255 256 257
        info->dwCatalogEntryId = 0x407;
        info->ProtocolChain.ChainLen = 1;
        info->iVersion = 2;
258 259 260 261
        info->iAddressFamily = WS_AF_IPX;
        info->iMaxSockAddr = 0x10;
        info->iMinSockAddr = 0x0e;
        info->iSocketType = 5;
262
        info->dwMessageSize = 0xffffffff;
263 264 265 266
        strcpy( info->szProtocol, NameSpx );
        break;

    case NSPROTO_SPXII:
267
        info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE |
268 269
                                XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED |
                                XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY;
270
        info->ProviderId = ProviderIdSPX;
271 272 273
        info->dwCatalogEntryId = 0x409;
        info->ProtocolChain.ChainLen = 1;
        info->iVersion = 2;
274 275 276 277
        info->iAddressFamily = WS_AF_IPX;
        info->iMaxSockAddr = 0x10;
        info->iMinSockAddr = 0x0e;
        info->iSocketType = 5;
278
        info->dwMessageSize = 0xffffffff;
279 280 281 282 283 284 285 286 287 288
        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;
289
    }
290 291
    return 1;
}
292

293 294 295 296 297 298 299 300 301
/*****************************************************************************
 *          WSAEnumProtocolsA       [WS2_32.@]
 *
 *    see function WSAEnumProtocolsW
 */
INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWORD len )
{
    INT i = 0;
    DWORD size = 0;
302
    INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 };
303 304

    if (!protocols) protocols = local;
305

306 307 308 309
    while (protocols[i]) i++;

    size = i * sizeof(WSAPROTOCOL_INFOA);

310
    if (*len < size || !buffer)
311 312
    {
        *len = size;
313
        WSASetLastError(WSAENOBUFS);
314 315
        return SOCKET_ERROR;
    }
316

317 318 319 320 321 322
    for (i = 0; protocols[i]; i++)
    {
        if (WINSOCK_EnterSingleProtocolA( protocols[i], &buffer[i] ) == SOCKET_ERROR)
            return i;
    }
    return i;
323 324 325
}

/*****************************************************************************
326
 *          WSAEnumProtocolsW       [WS2_32.@]
327 328 329 330
 *
 * Retrieves information about specified set of active network protocols.
 *
 * PARAMS
331 332 333 334 335 336 337
 *  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.
338 339
 *
 * RETURNS
340 341
 *  Success: number of WSAPROTOCOL_INFO structures in buffer.
 *  Failure: SOCKET_ERROR
342 343
 *
 * NOTES
344
 *  NT4SP5 does not return SPX if protocols == NULL
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
 *
 * 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
361
 */
362
INT WINAPI WSAEnumProtocolsW( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
363
{
364 365
    INT i = 0;
    DWORD size = 0;
366
    INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 };
367 368 369 370 371 372 373

    if (!protocols) protocols = local;

    while (protocols[i]) i++;

    size = i * sizeof(WSAPROTOCOL_INFOW);

374
    if (*len < size || !buffer)
375 376
    {
        *len = size;
377
        WSASetLastError(WSAENOBUFS);
378 379 380 381 382 383 384 385 386
        return SOCKET_ERROR;
    }

    for (i = 0; protocols[i]; i++)
    {
        if (WINSOCK_EnterSingleProtocolW( protocols[i], &buffer[i] ) == SOCKET_ERROR)
            return i;
    }
    return i;
387 388 389
}

/*****************************************************************************
390 391 392 393 394 395 396 397 398 399 400 401 402 403
 *          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.
404 405
 *
 */
406
INT WINAPI WSCEnumProtocols( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len, LPINT err )
407
{
408 409
    INT ret = WSAEnumProtocolsW( protocols, buffer, len );

410
    if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
411 412

    return ret;
413
}