[WS2_32_APITESTS] Add rebind and bind to broadcast tests ROSTESTS-278
[reactos.git] / rostests / apitests / ws2_32 / bind.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for bind
5 * PROGRAMMER: Peter Hater
6 */
7
8 #include <apitest.h>
9
10 #define WIN32_NO_STATUS
11 #define _INC_WINDOWS
12 #define COM_NO_WINDOWS_H
13 #include <stdarg.h>
14 #include <windef.h>
15 #include <winbase.h>
16 #include <ws2tcpip.h>
17 #include <ndk/umtypes.h>
18
19 CHAR LocalAddress[sizeof("255.255.255.255")];
20 #define PORT 58888
21
22 static
23 VOID
24 TestBind(IN_ADDR Address)
25 {
26 int Error;
27 struct
28 {
29 INT Type;
30 INT Proto;
31 struct sockaddr_in Addr;
32 INT ExpectedResult;
33 INT ExpectedWSAResult;
34 struct sockaddr_in ExpectedAddr;
35 } Tests[] =
36 {
37 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
38 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
39 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, Address }, 0, 0, { AF_INET, PORT, Address } },
40 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
41 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
42 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
43 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, Address }, 0, 0, { AF_INET, 0, Address } },
44 { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
45 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
46 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
47 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, Address }, 0, 0, { AF_INET, PORT, Address } },
48 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
49 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
50 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
51 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, Address }, 0, 0,{ AF_INET, 0, Address } },
52 { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
53 };
54 const INT TestCount = _countof(Tests);
55 INT i, AddrSize;
56 SOCKET Socket;
57 struct sockaddr_in Addr;
58 BOOL Broadcast = TRUE;
59
60 for (i = 0; i < TestCount; i++)
61 {
62 trace("%d: %s %d.%d.%d.%d:%d\n", i, Tests[i].Type == SOCK_STREAM ? "TCP" : "UDP", Tests[i].Addr.sin_addr.S_un.S_un_b.s_b1, Tests[i].Addr.sin_addr.S_un.S_un_b.s_b2, Tests[i].Addr.sin_addr.S_un.S_un_b.s_b3, Tests[i].Addr.sin_addr.S_un.S_un_b.s_b4, Tests[i].ExpectedAddr.sin_port);
63 Socket = socket(AF_INET, Tests[i].Type, Tests[i].Proto);
64 if (Socket == INVALID_SOCKET)
65 {
66 skip("Failed to create socket with error %d for test %d, skipping\n", WSAGetLastError(), i);
67 continue;
68 }
69 Error = bind(Socket, (const struct sockaddr *) &Tests[i].Addr, sizeof(Tests[i].Addr));
70 ok(Error == Tests[i].ExpectedResult, "Error %d differs from expected %d for test %d\n", Error, Tests[i].ExpectedResult, i);
71 if (Error)
72 {
73 ok(WSAGetLastError() == Tests[i].ExpectedWSAResult, "Error %d differs from expected %d for test %d\n", WSAGetLastError(), Tests[i].ExpectedWSAResult, i);
74 }
75 else
76 {
77 ok(WSAGetLastError() == 0, "Unexpected error %d on bind for test %d\n", WSAGetLastError(), i);
78 AddrSize = sizeof(Addr);
79 Error = getsockname(Socket, (struct sockaddr *) &Addr, &AddrSize);
80 ok(Error == 0, "Unexpected error %d on getsockname for test %d\n", Error, i);
81 ok(WSAGetLastError() == 0, "Unexpected error %d on getsockname for test %d\n", WSAGetLastError(), i);
82 ok(AddrSize == sizeof(Addr), "Returned size %d differs from expected %d for test %d\n", AddrSize, sizeof(Addr), i);
83 ok(Addr.sin_addr.s_addr == Tests[i].ExpectedAddr.sin_addr.s_addr, "Expected address %lx differs from returned address %lx for test %d\n", Tests[i].ExpectedAddr.sin_addr.s_addr, Addr.sin_addr.s_addr, i);
84 if (Tests[i].ExpectedAddr.sin_port)
85 {
86 ok(Addr.sin_port == Tests[i].ExpectedAddr.sin_port, "Returned port %d differs from expected %d for test %d\n", Addr.sin_port, Tests[i].ExpectedAddr.sin_port, i);
87 }
88 else
89 {
90 ok(Addr.sin_port != 0, "Port remained zero for test %d\n", i);
91 }
92 }
93 Error = closesocket(Socket);
94 ok(Error == 0, "Unexpected error %d on closesocket for test %d\n", Error, i);
95 ok(WSAGetLastError() == 0, "Unexpected wsa error %d on closesocket for test %d\n", WSAGetLastError(), i);
96 }
97 /* Check double bind */
98 Socket = socket(AF_INET, Tests[0].Type, Tests[0].Proto);
99 ok(Socket != INVALID_SOCKET, "Failed to create socket with error %d for double bind test, next tests might be wrong\n", WSAGetLastError());
100 Error = bind(Socket, (const struct sockaddr *) &Tests[0].Addr, sizeof(Tests[0].Addr));
101 ok(Error == Tests[0].ExpectedResult, "Error %d differs from expected %d for double bind test\n", Error, Tests[0].ExpectedResult);
102 if (Error)
103 {
104 ok(WSAGetLastError() == Tests[i].ExpectedWSAResult, "Error %d differs from expected %d for double bind test\n", WSAGetLastError(), Tests[0].ExpectedWSAResult);
105 }
106 else
107 {
108 ok(WSAGetLastError() == 0, "Unexpected error %d on bind for double bind test\n", WSAGetLastError());
109 AddrSize = sizeof(Addr);
110 Error = getsockname(Socket, (struct sockaddr *) &Addr, &AddrSize);
111 ok(Error == 0, "Unexpected error %d on getsockname for double bind test\n", Error);
112 ok(WSAGetLastError() == 0, "Unexpected error %d on getsockname for double bind test\n", WSAGetLastError());
113 ok(AddrSize == sizeof(Addr), "Returned size %d differs from expected %d for double bind test\n", AddrSize, sizeof(Addr));
114 ok(Addr.sin_addr.s_addr == Tests[0].ExpectedAddr.sin_addr.s_addr, "Expected address %lx differs from returned address %lx for double bind test\n", Tests[0].ExpectedAddr.sin_addr.s_addr, Addr.sin_addr.s_addr);
115 if (Tests[0].ExpectedAddr.sin_port)
116 {
117 ok(Addr.sin_port == Tests[0].ExpectedAddr.sin_port, "Returned port %d differs from expected %d for double bind test\n", Addr.sin_port, Tests[0].ExpectedAddr.sin_port);
118 }
119 else
120 {
121 ok(Addr.sin_port != 0, "Port remained zero for double bind test\n");
122 }
123 Error = bind(Socket, (const struct sockaddr *) &Tests[2].Addr, sizeof(Tests[2].Addr));
124 ok(Error == SOCKET_ERROR, "Unexpected result %d expected %d for double bind test\n", Error, SOCKET_ERROR);
125 ok(WSAGetLastError() == WSAEINVAL, "Unexpected wsa result %d expected %ld for double bind test\n", WSAGetLastError(), WSAEINVAL);
126 }
127 Error = closesocket(Socket);
128 ok(Error == 0, "Unexpected error %d on closesocket for double bind test\n", Error);
129 ok(WSAGetLastError() == 0, "Unexpected wsa error %d on closesocket for double bind test\n", WSAGetLastError());
130 /* Check SO_BROADCAST and bind to broadcast address */
131 Socket = socket(AF_INET, Tests[10].Type, Tests[10].Proto);
132 ok(Socket != INVALID_SOCKET, "Failed to create socket with error %d for broadcast test, next tests might be wrong\n", WSAGetLastError());
133 Error = setsockopt(Socket, SOL_SOCKET, SO_BROADCAST, (const char *) &Broadcast, sizeof(Broadcast));
134 ok(Error == 0, "Unexpected error %d on setsockopt for broadcast test\n", Error);
135 ok(WSAGetLastError() == 0, "Unexpected wsa error %d on setsockopt for broadcast test\n", WSAGetLastError());
136 Error = bind(Socket, (const struct sockaddr *) &Tests[10].Addr, sizeof(Tests[10].Addr));
137 ok(Error == 0, "Unexpected error %d on bind for broadcast test\n", Error);
138 ok(WSAGetLastError() == 0, "Unexpected wsa error %d on bind for broadcast test\n", WSAGetLastError());
139 Error = closesocket(Socket);
140 ok(Error == 0, "Unexpected error %d on closesocket for broadcast test\n", Error);
141 ok(WSAGetLastError() == 0, "Unexpected wsa error %d on closesocket for broadcast test\n", WSAGetLastError());
142 }
143
144 START_TEST(bind)
145 {
146 WSADATA WsaData;
147 int Error;
148 CHAR LocalHostName[128];
149 struct hostent *Hostent;
150 IN_ADDR Address;
151 SOCKET Socket;
152 struct sockaddr_in Addr = { AF_INET };
153
154 /* not yet initialized */
155 StartSeh()
156 Error = bind(INVALID_SOCKET, NULL, 0);
157 ok_dec(Error, -1);
158 EndSeh(STATUS_SUCCESS);
159 StartSeh()
160 Error = bind(INVALID_SOCKET, InvalidPointer, 0);
161 ok_dec(Error, -1);
162 EndSeh(STATUS_SUCCESS);
163
164 Error = WSAStartup(MAKEWORD(2, 2), &WsaData);
165 ok_dec(Error, 0);
166
167 /* initialize LocalAddress for tests */
168 Error = gethostname(LocalHostName, sizeof(LocalHostName));
169 ok_dec(Error, 0);
170 ok_dec(WSAGetLastError(), 0);
171 trace("Local host name is '%s'\n", LocalHostName);
172 Hostent = gethostbyname(LocalHostName);
173 ok(Hostent != NULL, "gethostbyname failed with %d\n", WSAGetLastError());
174 if (Hostent && Hostent->h_addr_list[0] && Hostent->h_length == sizeof(IN_ADDR))
175 {
176 memcpy(&Address, Hostent->h_addr_list[0], sizeof(Address));
177 strcpy(LocalAddress, inet_ntoa(Address));
178 }
179 trace("Local address is '%s'\n", LocalAddress);
180 ok(LocalAddress[0] != '\0',
181 "Could not determine local address. Following test results may be wrong.\n");
182
183 /* parameter tests */
184 StartSeh()
185 Error = bind(INVALID_SOCKET, NULL, 0);
186 ok_dec(Error, SOCKET_ERROR);
187 ok_dec(WSAGetLastError(), WSAENOTSOCK);
188 EndSeh(STATUS_SUCCESS);
189 StartSeh()
190 Error = bind(INVALID_SOCKET, InvalidPointer, 0);
191 ok_dec(Error, SOCKET_ERROR);
192 ok_dec(WSAGetLastError(), WSAENOTSOCK);
193 EndSeh(STATUS_SUCCESS);
194 StartSeh()
195 Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
196 Error = bind(Socket, NULL, 0);
197 ok_dec(Error, SOCKET_ERROR);
198 ok_dec(WSAGetLastError(), WSAEFAULT);
199 closesocket(Socket);
200 EndSeh(STATUS_SUCCESS);
201 StartSeh()
202 Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
203 Error = bind(Socket, InvalidPointer, 0);
204 ok_dec(Error, SOCKET_ERROR);
205 ok_dec(WSAGetLastError(), WSAEFAULT);
206 closesocket(Socket);
207 EndSeh(STATUS_SUCCESS);
208 StartSeh()
209 Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
210 Error = bind(Socket, NULL, sizeof(Addr));
211 ok_dec(Error, SOCKET_ERROR);
212 ok_dec(WSAGetLastError(), WSAEFAULT);
213 closesocket(Socket);
214 EndSeh(STATUS_SUCCESS);
215 StartSeh()
216 Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
217 Error = bind(Socket, InvalidPointer, sizeof(Addr));
218 ok_dec(Error, SOCKET_ERROR);
219 ok_dec(WSAGetLastError(), WSAEFAULT);
220 closesocket(Socket);
221 EndSeh(STATUS_ACCESS_VIOLATION);
222 StartSeh()
223 Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
224 Error = bind(Socket, (const struct sockaddr *) &Addr, 0);
225 ok_dec(Error, SOCKET_ERROR);
226 ok_dec(WSAGetLastError(), WSAEFAULT);
227 closesocket(Socket);
228 EndSeh(STATUS_SUCCESS);
229 StartSeh()
230 Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
231 Error = bind(Socket, (const struct sockaddr *) &Addr, sizeof(Addr)-1);
232 ok_dec(Error, SOCKET_ERROR);
233 ok_dec(WSAGetLastError(), WSAEFAULT);
234 closesocket(Socket);
235 EndSeh(STATUS_SUCCESS);
236
237 TestBind(Address);
238 /* TODO: test IPv6 */
239
240 Error = WSACleanup();
241 ok_dec(Error, 0);
242 }