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 "ws2_32.h"
9 
10 static CHAR LocalAddress[sizeof("255.255.255.255")];
11 #define PORT 58888
12 
13 static
14 VOID
15 TestBind(IN_ADDR Address)
16 {
17     const UCHAR b1 = Address.S_un.S_un_b.s_b1;
18     const UCHAR b2 = Address.S_un.S_un_b.s_b2;
19     const UCHAR b3 = Address.S_un.S_un_b.s_b3;
20     const UCHAR b4 = Address.S_un.S_un_b.s_b4;
21 
22     int Error;
23     struct
24     {
25         INT Type;
26         INT Proto;
27         struct sockaddr_in Addr;
28         INT ExpectedResult;
29         INT ExpectedWSAResult;
30         struct sockaddr_in ExpectedAddr;
31     } Tests[] =
32     {
33         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
34         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
35         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, {{{ b1, b2, b3, b4 }}} }, 0, 0, { AF_INET, PORT, {{{ b1, b2, b3, b4 }}} } },
36         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, PORT, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
37         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
38         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
39         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, {{{ b1, b2, b3, b4 }}} }, 0, 0, { AF_INET, 0, {{{ b1, b2, b3, b4 }}} } },
40         { SOCK_STREAM, IPPROTO_TCP, { AF_INET, 0, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
41         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
42         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} }, 0, 0, { AF_INET, PORT, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
43         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, {{{ b1, b2, b3, b4 }}} }, 0, 0, { AF_INET, PORT, {{{ b1, b2, b3, b4 }}} } },
44         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, PORT, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
45         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} }, 0, 0, { AF_INET, 0, {{{ 0x7f, 0x00, 0x00, 0x01 }}} } },
46         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, {{{ 0x00, 0x00, 0x00, 0x00 }}} } },
47         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, {{{ b1, b2, b3, b4 }}} }, 0, 0,{ AF_INET, 0, {{{ b1, b2, b3, b4 }}} } },
48         { SOCK_DGRAM, IPPROTO_UDP, { AF_INET, 0, {{{ 0xff, 0xff, 0xff, 0xff }}} }, SOCKET_ERROR, WSAEADDRNOTAVAIL },
49     };
50     const INT TestCount = _countof(Tests);
51     INT i, AddrSize;
52     SOCKET Socket;
53     struct sockaddr_in Addr;
54     BOOL Broadcast = TRUE;
55 
56     for (i = 0; i < TestCount; i++)
57     {
58         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);
59         Socket = socket(AF_INET, Tests[i].Type, Tests[i].Proto);
60         if (Socket == INVALID_SOCKET)
61         {
62             skip("Failed to create socket with error %d for test %d, skipping\n", WSAGetLastError(), i);
63             continue;
64         }
65         Error = bind(Socket, (const struct sockaddr *) &Tests[i].Addr, sizeof(Tests[i].Addr));
66         ok(Error == Tests[i].ExpectedResult, "Error %d differs from expected %d for test %d\n", Error, Tests[i].ExpectedResult, i);
67         if (Error)
68         {
69             ok(WSAGetLastError() == Tests[i].ExpectedWSAResult, "Error %d differs from expected %d for test %d\n", WSAGetLastError(), Tests[i].ExpectedWSAResult, i);
70         }
71         else
72         {
73             AddrSize = sizeof(Addr);
74             Error = getsockname(Socket, (struct sockaddr *) &Addr, &AddrSize);
75             ok(Error == 0, "Unexpected error %d %d on getsockname for test %d\n", Error, WSAGetLastError(), i);
76             ok(AddrSize == sizeof(Addr), "Returned size %d differs from expected %d for test %d\n", AddrSize, sizeof(Addr), i);
77             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);
78             if (Tests[i].ExpectedAddr.sin_port)
79             {
80                 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);
81             }
82             else
83             {
84                 ok(Addr.sin_port != 0, "Port remained zero for test %d\n", i);
85             }
86         }
87         Error = closesocket(Socket);
88         ok(Error == 0, "Unexpected error %d %d on closesocket for test %d\n", Error, WSAGetLastError(), i);
89     }
90     /* Check double bind */
91     Socket = socket(AF_INET, Tests[0].Type, Tests[0].Proto);
92     ok(Socket != INVALID_SOCKET, "Failed to create socket with error %d for double bind test, next tests might be wrong\n", WSAGetLastError());
93     Error = bind(Socket, (const struct sockaddr *) &Tests[0].Addr, sizeof(Tests[0].Addr));
94     ok(Error == Tests[0].ExpectedResult, "Error %d differs from expected %d for double bind test\n", Error, Tests[0].ExpectedResult);
95     if (Error)
96     {
97         ok(WSAGetLastError() == Tests[i].ExpectedWSAResult, "Error %d differs from expected %d for double bind test\n", WSAGetLastError(), Tests[0].ExpectedWSAResult);
98     }
99     else
100     {
101         AddrSize = sizeof(Addr);
102         Error = getsockname(Socket, (struct sockaddr *) &Addr, &AddrSize);
103         ok(Error == 0, "Unexpected error %d %d on getsockname for double bind test\n", Error, WSAGetLastError());
104         ok(AddrSize == sizeof(Addr), "Returned size %d differs from expected %d for double bind test\n", AddrSize, sizeof(Addr));
105         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);
106         if (Tests[0].ExpectedAddr.sin_port)
107         {
108             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);
109         }
110         else
111         {
112             ok(Addr.sin_port != 0, "Port remained zero for double bind test\n");
113         }
114         Error = bind(Socket, (const struct sockaddr *) &Tests[2].Addr, sizeof(Tests[2].Addr));
115         ok(Error == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL, "Unexpected result %d expected %d and wsa result %d expected %ld for double bind test\n", Error, SOCKET_ERROR, WSAGetLastError(), WSAEINVAL);
116     }
117     Error = closesocket(Socket);
118     ok(Error == 0, "Unexpected error %d %d on closesocket for double bind test\n", Error, WSAGetLastError());
119     /* Check SO_BROADCAST and bind to broadcast address */
120     Socket = socket(AF_INET, Tests[10].Type, Tests[10].Proto);
121     ok(Socket != INVALID_SOCKET, "Failed to create socket with error %d for broadcast test, next tests might be wrong\n", WSAGetLastError());
122     Error = setsockopt(Socket, SOL_SOCKET, SO_BROADCAST, (const char *) &Broadcast, sizeof(Broadcast));
123     ok(Error == 0, "Unexpected error %d %d on setsockopt for broadcast test\n", Error, WSAGetLastError());
124     Error = bind(Socket, (const struct sockaddr *) &Tests[10].Addr, sizeof(Tests[10].Addr));
125     ok(Error == 0, "Unexpected error %d %d on bind for broadcast test\n", Error, WSAGetLastError());
126     Error = closesocket(Socket);
127     ok(Error == 0, "Unexpected error %d %d on closesocket for broadcast test\n", Error, WSAGetLastError());
128 }
129 
130 START_TEST(bind)
131 {
132     WSADATA WsaData;
133     int Error;
134     CHAR LocalHostName[128];
135     struct hostent *Hostent;
136     IN_ADDR Address = { 0 };
137     SOCKET Socket;
138     struct sockaddr_in Addr = { AF_INET };
139 
140     /* not yet initialized */
141     StartSeh()
142         Error = bind(INVALID_SOCKET, NULL, 0);
143         ok_dec(Error, -1);
144     EndSeh(STATUS_SUCCESS);
145     StartSeh()
146         Error = bind(INVALID_SOCKET, InvalidPointer, 0);
147         ok_dec(Error, -1);
148     EndSeh(STATUS_SUCCESS);
149 
150     Error = WSAStartup(MAKEWORD(2, 2), &WsaData);
151     ok_dec(Error, 0);
152 
153     /* initialize LocalAddress for tests */
154     Error = gethostname(LocalHostName, sizeof(LocalHostName));
155     ok_dec(Error, 0);
156     ok_dec(WSAGetLastError(), 0);
157     trace("Local host name is '%s'\n", LocalHostName);
158     Hostent = gethostbyname(LocalHostName);
159     ok(Hostent != NULL, "gethostbyname failed with %d\n", WSAGetLastError());
160     if (Hostent && Hostent->h_addr_list[0] && Hostent->h_length == sizeof(IN_ADDR))
161     {
162         memcpy(&Address, Hostent->h_addr_list[0], sizeof(Address));
163         strcpy(LocalAddress, inet_ntoa(Address));
164     }
165     trace("Local address is '%s'\n", LocalAddress);
166     ok(LocalAddress[0] != '\0',
167        "Could not determine local address. Following test results may be wrong.\n");
168 
169     /* parameter tests */
170     StartSeh()
171         Error = bind(INVALID_SOCKET, NULL, 0);
172         ok_dec(Error, SOCKET_ERROR);
173         ok_dec(WSAGetLastError(), WSAENOTSOCK);
174     EndSeh(STATUS_SUCCESS);
175     StartSeh()
176         Error = bind(INVALID_SOCKET, InvalidPointer, 0);
177         ok_dec(Error, SOCKET_ERROR);
178         ok_dec(WSAGetLastError(), WSAENOTSOCK);
179     EndSeh(STATUS_SUCCESS);
180     StartSeh()
181         Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
182         Error = bind(Socket, NULL, 0);
183         ok_dec(Error, SOCKET_ERROR);
184         ok_dec(WSAGetLastError(), WSAEFAULT);
185         closesocket(Socket);
186     EndSeh(STATUS_SUCCESS);
187     StartSeh()
188         Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
189         Error = bind(Socket, InvalidPointer, 0);
190         ok_dec(Error, SOCKET_ERROR);
191         ok_dec(WSAGetLastError(), WSAEFAULT);
192         closesocket(Socket);
193     EndSeh(STATUS_SUCCESS);
194     StartSeh()
195         Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
196         Error = bind(Socket, NULL, sizeof(Addr));
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, sizeof(Addr));
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, (const struct sockaddr *) &Addr, 0);
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, (const struct sockaddr *) &Addr, sizeof(Addr)-1);
218         ok_dec(Error, SOCKET_ERROR);
219         ok_dec(WSAGetLastError(), WSAEFAULT);
220         closesocket(Socket);
221     EndSeh(STATUS_SUCCESS);
222 
223     TestBind(Address);
224     /* TODO: test IPv6 */
225 
226     Error = WSACleanup();
227     ok_dec(Error, 0);
228 }
229