ws2_32: Implemented FIONBIO and FIONREAD in WSAIoctl.
[wine] / dlls / ws2_32 / protocol.c
1 /*
2  * Protocol enumeration functions
3  *
4  * Copyright (C) 2001 Stefan Leichter
5  * Copyright (C) 2004 Hans Leidekker
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * 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 /*  02/11/2004
23  *  The protocol enumeration functions were verified to match Win2k versions
24  *  for these protocols: IPX, SPX, SPXII, TCP/IP and UDP/IP.
25  */
26
27 #include "config.h"
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <sys/types.h>
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37 #ifdef HAVE_NETDB_H
38 #include <netdb.h>
39 #endif
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winnls.h"
44 #include "wtypes.h"
45 #include "nspapi.h"
46 #include "winsock2.h"
47 #include "wsipx.h"
48 #include "wshisotp.h"
49 #include "ws2spi.h"
50
51 #include "wine/unicode.h"
52 #include "wine/debug.h"
53
54 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
55
56 /* names of the protocols */
57 static const CHAR NameIpx[]   = "IPX";
58 static const CHAR NameSpx[]   = "SPX";
59 static const CHAR NameSpxII[] = "SPX II";
60 static const CHAR NameTcp[]   = "TCP/IP";
61 static const CHAR NameUdp[]   = "UDP/IP";
62
63 static const WCHAR NameIpxW[]   = {'I', 'P', 'X', '\0'};
64 static const WCHAR NameSpxW[]   = {'S', 'P', 'X', '\0'};
65 static const WCHAR NameSpxIIW[] = {'S', 'P', 'X', ' ', 'I', 'I', '\0'};
66 static const WCHAR NameTcpW[]   = {'T', 'C', 'P', '/', 'I', 'P', '\0'};
67 static const WCHAR NameUdpW[]   = {'U', 'D', 'P', '/', 'I', 'P', '\0'};
68
69 /* Taken from Win2k */
70 static const GUID ProviderIdIP = { 0xe70f1aa0, 0xab8b, 0x11cf,
71                                    { 0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
72 static const GUID ProviderIdIPX = { 0x11058240, 0xbe47, 0x11cf,
73                                     { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
74 static const GUID ProviderIdSPX = { 0x11058241, 0xbe47, 0x11cf,
75                                     { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
76
77 /*****************************************************************************
78  *          WINSOCK_EnterSingleProtocolW [internal]
79  *
80  *    enters the protocol information of one given protocol into the given
81  *    buffer.
82  *
83  * RETURNS
84  *    1 if a protocol was entered into the buffer.
85  *    SOCKET_ERROR otherwise.
86  *
87  * BUGS
88  *    - only implemented for IPX, SPX, SPXII, TCP, UDP
89  *    - there is no check that the operating system supports the returned
90  *      protocols
91  */
92 static INT WINSOCK_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
93 {
94     memset( info, 0, sizeof(WSAPROTOCOL_INFOW) );
95     info->iProtocol = protocol;
96
97     switch (protocol)
98     {
99     case WS_IPPROTO_TCP:
100         info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_EXPEDITED_DATA |
101                                 XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER |
102                                 XP1_GUARANTEED_DELIVERY;
103         memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) );
104         info->dwCatalogEntryId = 0x3e9;
105         info->ProtocolChain.ChainLen = 1;
106         info->iVersion = 2;
107         info->iAddressFamily = WS_AF_INET;
108         info->iMaxSockAddr = 0x10;
109         info->iMinSockAddr = 0x10;
110         info->iSocketType = WS_SOCK_STREAM;
111         strcpyW( info->szProtocol, NameTcpW );
112         break;
113
114     case WS_IPPROTO_UDP:
115         info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST |
116                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
117                                 XP1_CONNECTIONLESS;
118         memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) );
119         info->dwCatalogEntryId = 0x3ea;
120         info->ProtocolChain.ChainLen = 1;
121         info->iVersion = 2;
122         info->iAddressFamily = WS_AF_INET;
123         info->iMaxSockAddr = 0x10;
124         info->iMinSockAddr = 0x10;
125         info->iSocketType = WS_SOCK_DGRAM;
126         info->dwMessageSize = 0xffbb;
127         strcpyW( info->szProtocol, NameUdpW );
128         break;
129
130     case NSPROTO_IPX:
131         info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST |
132                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
133                                 XP1_CONNECTIONLESS;
134         memcpy( &info->ProviderId, &ProviderIdIPX, sizeof(GUID) );
135         info->dwCatalogEntryId = 0x406;
136         info->ProtocolChain.ChainLen = 1;
137         info->iVersion = 2;
138         info->iAddressFamily = WS_AF_IPX;
139         info->iMaxSockAddr = 0x10;
140         info->iMinSockAddr = 0x0e;
141         info->iSocketType = WS_SOCK_DGRAM;
142         info->iProtocolMaxOffset = 0xff;
143         info->dwMessageSize = 0x240;
144         strcpyW( info->szProtocol, NameIpxW );
145         break;
146
147     case NSPROTO_SPX:
148         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM |
149                                 XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER |
150                                 XP1_GUARANTEED_DELIVERY;
151         memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) );
152         info->dwCatalogEntryId = 0x407;
153         info->ProtocolChain.ChainLen = 1;
154         info->iVersion = 2;
155         info->iAddressFamily = WS_AF_IPX;
156         info->iMaxSockAddr = 0x10;
157         info->iMinSockAddr = 0x0e;
158         info->iSocketType = 5;
159         info->dwMessageSize = 0xffffffff;
160         strcpyW( info->szProtocol, NameSpxW );
161         break;
162
163     case NSPROTO_SPXII:
164         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE |
165                                 XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED |
166                                 XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY;
167         memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) );
168         info->dwCatalogEntryId = 0x409;
169         info->ProtocolChain.ChainLen = 1;
170         info->iVersion = 2;
171         info->iAddressFamily = WS_AF_IPX;
172         info->iMaxSockAddr = 0x10;
173         info->iMinSockAddr = 0x0e;
174         info->iSocketType = 5;
175         info->dwMessageSize = 0xffffffff;
176         strcpyW( info->szProtocol, NameSpxIIW );
177         break;
178
179     default:
180         if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX))
181             FIXME("Protocol <%s> not implemented\n",
182                   (protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
183         else
184             FIXME("unknown Protocol <0x%08x>\n", protocol);
185         return SOCKET_ERROR;
186     }
187     return 1;
188 }
189
190 /*****************************************************************************
191  *          WINSOCK_EnterSingleProtocolA [internal]
192  *
193  *    see function WINSOCK_EnterSingleProtocolW
194  *
195  */
196 static INT WINSOCK_EnterSingleProtocolA( INT protocol, WSAPROTOCOL_INFOA* info )
197 {
198     memset( info, 0, sizeof(WSAPROTOCOL_INFOA) );
199     info->iProtocol = protocol;
200
201     switch (protocol)
202     {
203     case WS_IPPROTO_TCP:
204         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA |
205                                 XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER |
206                                 XP1_GUARANTEED_DELIVERY;
207         memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) );
208         info->dwCatalogEntryId = 0x3e9;
209         info->ProtocolChain.ChainLen = 1;
210         info->iVersion = 2;
211         info->iAddressFamily = WS_AF_INET;
212         info->iMaxSockAddr = 0x10;
213         info->iMinSockAddr = 0x10;
214         info->iSocketType = WS_SOCK_STREAM;
215         strcpy( info->szProtocol, NameTcp );
216         break;
217
218     case WS_IPPROTO_UDP:
219         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST |
220                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
221                                 XP1_CONNECTIONLESS;
222         memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) );
223         info->dwCatalogEntryId = 0x3ea;
224         info->ProtocolChain.ChainLen = 1;
225         info->iVersion = 2;
226         info->iAddressFamily = WS_AF_INET;
227         info->iMaxSockAddr = 0x10;
228         info->iMinSockAddr = 0x10;
229         info->iSocketType = WS_SOCK_DGRAM;
230         info->dwMessageSize = 0xffbb;
231         strcpy( info->szProtocol, NameUdp );
232         break;
233
234     case NSPROTO_IPX:
235         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST |
236                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
237                                 XP1_CONNECTIONLESS;
238         memcpy( &info->ProviderId, &ProviderIdIPX, sizeof(GUID) );
239         info->dwCatalogEntryId = 0x406;
240         info->ProtocolChain.ChainLen = 1;
241         info->iVersion = 2;
242         info->iAddressFamily = WS_AF_IPX;
243         info->iMaxSockAddr = 0x10;
244         info->iMinSockAddr = 0x0e;
245         info->iSocketType = WS_SOCK_DGRAM;
246         info->iProtocolMaxOffset = 0xff;
247         info->dwMessageSize = 0x240;
248         strcpy( info->szProtocol, NameIpx );
249         break;
250
251     case NSPROTO_SPX:
252         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM |
253                                 XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER |
254                                 XP1_GUARANTEED_DELIVERY;
255         memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) );
256         info->dwCatalogEntryId = 0x407;
257         info->ProtocolChain.ChainLen = 1;
258         info->iVersion = 2;
259         info->iAddressFamily = WS_AF_IPX;
260         info->iMaxSockAddr = 0x10;
261         info->iMinSockAddr = 0x0e;
262         info->iSocketType = 5;
263         info->dwMessageSize = 0xffffffff;
264         strcpy( info->szProtocol, NameSpx );
265         break;
266
267     case NSPROTO_SPXII:
268         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE |
269                                 XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED |
270                                 XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY;
271         memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) );
272         info->dwCatalogEntryId = 0x409;
273         info->ProtocolChain.ChainLen = 1;
274         info->iVersion = 2;
275         info->iAddressFamily = WS_AF_IPX;
276         info->iMaxSockAddr = 0x10;
277         info->iMinSockAddr = 0x0e;
278         info->iSocketType = 5;
279         info->dwMessageSize = 0xffffffff;
280         strcpy( info->szProtocol, NameSpxII );
281         break;
282
283     default:
284         if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX))
285             FIXME("Protocol <%s> not implemented\n",
286                   (protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
287         else
288             FIXME("unknown Protocol <0x%08x>\n", protocol);
289         return SOCKET_ERROR;
290     }
291     return 1;
292 }
293
294 /*****************************************************************************
295  *          WSAEnumProtocolsA       [WS2_32.@]
296  *
297  *    see function WSAEnumProtocolsW
298  */
299 INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWORD len )
300 {
301     INT i = 0;
302     DWORD size = 0;
303     INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 };
304
305     if (!buffer)
306         return SOCKET_ERROR;
307
308     if (!protocols) protocols = local;
309
310     while (protocols[i]) i++;
311
312     size = i * sizeof(WSAPROTOCOL_INFOA);
313
314     if (*len < size)
315     {
316         *len = size;
317         return SOCKET_ERROR;
318     }
319
320     for (i = 0; protocols[i]; i++)
321     {
322         if (WINSOCK_EnterSingleProtocolA( protocols[i], &buffer[i] ) == SOCKET_ERROR)
323             return i;
324     }
325     return i;
326 }
327
328 /*****************************************************************************
329  *          WSAEnumProtocolsW       [WS2_32.@]
330  *
331  * Retrieves information about specified set of active network protocols.
332  *
333  * PARAMS
334  *  protocols [I]   Pointer to null-terminated array of protocol id's. NULL
335  *                  retrieves information on all available protocols.
336  *  buffer    [I]   Pointer to a buffer to be filled with WSAPROTOCOL_INFO
337  *                  structures.
338  *  len       [I/O] Pointer to a variable specifying buffer size. On output
339  *                  the variable holds the number of bytes needed when the
340  *                  specified size is too small.
341  *
342  * RETURNS
343  *  Success: number of WSAPROTOCOL_INFO structures in buffer.
344  *  Failure: SOCKET_ERROR
345  *
346  * NOTES
347  *  NT4SP5 does not return SPX if protocols == NULL
348  *
349  * BUGS
350  *  - NT4SP5 returns in addition these list of NETBIOS protocols
351  *    (address family 17), each entry two times one for socket type 2 and 5
352  *
353  *    iProtocol   szProtocol
354  *    0x80000000  \Device\NwlnkNb
355  *    0xfffffffa  \Device\NetBT_CBENT7
356  *    0xfffffffb  \Device\Nbf_CBENT7
357  *    0xfffffffc  \Device\NetBT_NdisWan5
358  *    0xfffffffd  \Device\NetBT_El9202
359  *    0xfffffffe  \Device\Nbf_El9202
360  *    0xffffffff  \Device\Nbf_NdisWan4
361  *
362  *  - there is no check that the operating system supports the returned
363  *    protocols
364  */
365 INT WINAPI WSAEnumProtocolsW( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
366 {
367     INT i = 0;
368     DWORD size = 0;
369     INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 };
370
371     if (!buffer)
372         return SOCKET_ERROR;
373
374     if (!protocols) protocols = local;
375
376     while (protocols[i]) i++;
377
378     size = i * sizeof(WSAPROTOCOL_INFOW);
379
380     if (*len < size)
381     {
382         *len = size;
383         return SOCKET_ERROR;
384     }
385
386     for (i = 0; protocols[i]; i++)
387     {
388         if (WINSOCK_EnterSingleProtocolW( protocols[i], &buffer[i] ) == SOCKET_ERROR)
389             return i;
390     }
391     return i;
392 }
393
394 /*****************************************************************************
395  *          WSCEnumProtocols        [WS2_32.@]
396  *
397  * PARAMS
398  *  protocols [I]   Null-terminated array of iProtocol values.
399  *  buffer    [O]   Buffer of WSAPROTOCOL_INFOW structures.
400  *  len       [I/O] Size of buffer on input/output.
401  *  errno     [O]   Error code.
402  *
403  * RETURNS
404  *  Success: number of protocols to be reported on.
405  *  Failure: SOCKET_ERROR. error is in errno.
406  *
407  * BUGS
408  *  Doesn't supply info on layered protocols.
409  *
410  */
411 INT WINAPI WSCEnumProtocols( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len, LPINT errno )
412 {
413     INT ret = WSAEnumProtocolsW( protocols, buffer, len );
414
415     if (ret == SOCKET_ERROR) *errno = WSAENOBUFS;
416
417     return ret;
418 }