1 /*
2  * Unit test suite for protocol functions
3  *
4  * Copyright 2004 Hans Leidekker
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winsock2.h>
26 
27 #include "wine/test.h"
28 
29 /* TCP and UDP over IP fixed set of service flags */
30 #define TCPIP_SERVICE_FLAGS (XP1_GUARANTEED_DELIVERY \
31                            | XP1_GUARANTEED_ORDER    \
32                            | XP1_GRACEFUL_CLOSE      \
33                            | XP1_EXPEDITED_DATA      \
34                            | XP1_IFS_HANDLES)
35 
36 #define UDPIP_SERVICE_FLAGS (XP1_CONNECTIONLESS      \
37                            | XP1_MESSAGE_ORIENTED    \
38                            | XP1_SUPPORT_BROADCAST   \
39                            | XP1_SUPPORT_MULTIPOINT  \
40                            | XP1_IFS_HANDLES)
41 
42 static void test_service_flags(int family, int version, int socktype, int protocol, DWORD testflags)
43 {
44     DWORD expectedflags = 0;
45     if (socktype == SOCK_STREAM && protocol == IPPROTO_TCP)
46         expectedflags = TCPIP_SERVICE_FLAGS;
47     if (socktype == SOCK_DGRAM && protocol == IPPROTO_UDP)
48         expectedflags = UDPIP_SERVICE_FLAGS;
49 
50     /* check if standard TCP and UDP protocols are offering the correct service flags */
51     if ((family == AF_INET || family == AF_INET6) && version == 2 && expectedflags)
52     {
53         /* QOS may or may not be installed */
54         testflags &= ~XP1_QOS_SUPPORTED;
55         ok(expectedflags == testflags,
56            "Incorrect flags, expected 0x%x, received 0x%x\n",
57            expectedflags, testflags);
58     }
59 }
60 
61 static void test_WSAEnumProtocolsA(void)
62 {
63     INT ret, i, j, found;
64     DWORD len = 0, error;
65     WSAPROTOCOL_INFOA info, *buffer;
66     INT ptest[] = {0xdead, IPPROTO_TCP, 0xcafe, IPPROTO_UDP, 0xbeef, 0};
67 
68     ret = WSAEnumProtocolsA( NULL, NULL, &len );
69     ok( ret == SOCKET_ERROR, "WSAEnumProtocolsA() succeeded unexpectedly\n");
70     error = WSAGetLastError();
71     ok( error == WSAENOBUFS, "Expected 10055, received %d\n", error);
72 
73     len = 0;
74 
75     ret = WSAEnumProtocolsA( NULL, &info, &len );
76     ok( ret == SOCKET_ERROR, "WSAEnumProtocolsA() succeeded unexpectedly\n");
77     error = WSAGetLastError();
78     ok( error == WSAENOBUFS, "Expected 10055, received %d\n", error);
79 
80     buffer = HeapAlloc( GetProcessHeap(), 0, len );
81 
82     if (buffer)
83     {
84         ret = WSAEnumProtocolsA( NULL, buffer, &len );
85         ok( ret != SOCKET_ERROR, "WSAEnumProtocolsA() failed unexpectedly: %d\n",
86             WSAGetLastError() );
87 
88         for (i = 0; i < ret; i++)
89         {
90             ok( strlen( buffer[i].szProtocol ), "No protocol name found\n" );
91             test_service_flags( buffer[i].iAddressFamily, buffer[i].iVersion,
92                                 buffer[i].iSocketType, buffer[i].iProtocol,
93                                 buffer[i].dwServiceFlags1);
94         }
95 
96         HeapFree( GetProcessHeap(), 0, buffer );
97     }
98 
99     /* Test invalid protocols in the list */
100     ret = WSAEnumProtocolsA( ptest, NULL, &len );
101     ok( ret == SOCKET_ERROR, "WSAEnumProtocolsA() succeeded unexpectedly\n");
102     error = WSAGetLastError();
103     ok( error == WSAENOBUFS || broken(error == WSAEFAULT) /* NT4 */,
104        "Expected 10055, received %d\n", error);
105 
106     buffer = HeapAlloc( GetProcessHeap(), 0, len );
107 
108     if (buffer)
109     {
110         ret = WSAEnumProtocolsA( ptest, buffer, &len );
111         ok( ret != SOCKET_ERROR, "WSAEnumProtocolsA() failed unexpectedly: %d\n",
112             WSAGetLastError() );
113         ok( ret >= 2, "Expected at least 2 items, received %d\n", ret);
114 
115         for (i = found = 0; i < ret; i++)
116             for (j = 0; j < sizeof(ptest) / sizeof(ptest[0]); j++)
117                 if (buffer[i].iProtocol == ptest[j])
118                 {
119                     found |= 1 << j;
120                     break;
121                 }
122         ok(found == 0x0A, "Expected 2 bits represented as 0xA, received 0x%x\n", found);
123 
124         HeapFree( GetProcessHeap(), 0, buffer );
125     }
126 }
127 
128 static void test_WSAEnumProtocolsW(void)
129 {
130     INT ret, i, j, found;
131     DWORD len = 0, error;
132     WSAPROTOCOL_INFOW info, *buffer;
133     INT ptest[] = {0xdead, IPPROTO_TCP, 0xcafe, IPPROTO_UDP, 0xbeef, 0};
134 
135     ret = WSAEnumProtocolsW( NULL, NULL, &len );
136     ok( ret == SOCKET_ERROR, "WSAEnumProtocolsW() succeeded unexpectedly\n");
137     error = WSAGetLastError();
138     ok( error == WSAENOBUFS, "Expected 10055, received %d\n", error);
139 
140     len = 0;
141 
142     ret = WSAEnumProtocolsW( NULL, &info, &len );
143     ok( ret == SOCKET_ERROR, "WSAEnumProtocolsW() succeeded unexpectedly\n");
144     error = WSAGetLastError();
145     ok( error == WSAENOBUFS, "Expected 10055, received %d\n", error);
146 
147     buffer = HeapAlloc( GetProcessHeap(), 0, len );
148 
149     if (buffer)
150     {
151         ret = WSAEnumProtocolsW( NULL, buffer, &len );
152         ok( ret != SOCKET_ERROR, "WSAEnumProtocolsW() failed unexpectedly: %d\n",
153             WSAGetLastError() );
154 
155         for (i = 0; i < ret; i++)
156         {
157             ok( lstrlenW( buffer[i].szProtocol ), "No protocol name found\n" );
158             test_service_flags( buffer[i].iAddressFamily, buffer[i].iVersion,
159                                 buffer[i].iSocketType, buffer[i].iProtocol,
160                                 buffer[i].dwServiceFlags1);
161         }
162 
163         HeapFree( GetProcessHeap(), 0, buffer );
164     }
165 
166     /* Test invalid protocols in the list */
167     ret = WSAEnumProtocolsW( ptest, NULL, &len );
168     ok( ret == SOCKET_ERROR, "WSAEnumProtocolsW() succeeded unexpectedly\n");
169     error = WSAGetLastError();
170     ok( error == WSAENOBUFS || broken(error == WSAEFAULT) /* NT4 */,
171        "Expected 10055, received %d\n", error);
172 
173     buffer = HeapAlloc( GetProcessHeap(), 0, len );
174 
175     if (buffer)
176     {
177         ret = WSAEnumProtocolsW( ptest, buffer, &len );
178         ok( ret != SOCKET_ERROR, "WSAEnumProtocolsW() failed unexpectedly: %d\n",
179             WSAGetLastError() );
180         ok( ret >= 2, "Expected at least 2 items, received %d\n", ret);
181 
182         for (i = found = 0; i < ret; i++)
183             for (j = 0; j < sizeof(ptest) / sizeof(ptest[0]); j++)
184                 if (buffer[i].iProtocol == ptest[j])
185                 {
186                     found |= 1 << j;
187                     break;
188                 }
189         ok(found == 0x0A, "Expected 2 bits represented as 0xA, received 0x%x\n", found);
190 
191         HeapFree( GetProcessHeap(), 0, buffer );
192     }
193 }
194 
195 START_TEST( protocol )
196 {
197     WSADATA data;
198     WORD version = MAKEWORD( 2, 2 );
199 
200     if (WSAStartup( version, &data )) return;
201 
202     test_WSAEnumProtocolsA();
203     test_WSAEnumProtocolsW();
204 }
205