1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for getaddrinfo
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "ws2_32.h"
9 
10 #define ok_addrinfo(ai, flags, family, socktype, protocol, addrlen) do  \
11 {                                                                       \
12     ok_hex((ai)->ai_flags, flags);                                      \
13     ok_dec((ai)->ai_family, family);                                    \
14     ok_dec((ai)->ai_socktype, socktype);                                \
15     ok_dec((ai)->ai_protocol, protocol);                                \
16     ok_dec((int)(ai)->ai_addrlen, addrlen);                             \
17 } while (0)
18 
19 #define ok_sockaddr_in(sockaddr, family, port, addr) do                 \
20 {                                                                       \
21     int _i;                                                             \
22     ok_dec(((SOCKADDR_IN *)(sockaddr))->sin_family, family);            \
23     ok_dec(ntohs(((SOCKADDR_IN *)(sockaddr))->sin_port), port);         \
24     ok_hex(((SOCKADDR_IN *)(sockaddr))->sin_addr.S_un.S_addr,           \
25            inet_addr(addr));                                            \
26     for (_i = 0; _i < 7; _i++)                                          \
27         ok_dec(((SOCKADDR_IN *)(sockaddr))->sin_zero[_i], 0);           \
28 } while (0)
29 
30 CHAR LocalAddress[sizeof("255.255.255.255")];
31 
32 static
33 VOID
34 TestNodeName(VOID)
35 {
36     int Error;
37     PADDRINFOA AddrInfo;
38     ADDRINFOA Hints;
39     struct
40     {
41         PCSTR NodeName;
42         PCSTR ExpectedAddress;
43         INT Flags;
44     } Tests[] =
45     {
46         { "",                               LocalAddress },
47         { " ",                              NULL },
48         { "doesntexist.example.com",        NULL },
49         { "localhost",                      "127.0.0.1" },
50         { "localhost:80",                   NULL },
51         { "7.8.9.10",                       "7.8.9.10",         AI_NUMERICHOST },
52         { "0.0.0.0",                        "0.0.0.0",          AI_NUMERICHOST },
53         { "255.255.255.255",                "255.255.255.255",  AI_NUMERICHOST },
54         { "0.0.0.0 ",                       "0.0.0.0",    /* no AI_NUMERICHOST */ },
55         { "0.0.0.0:80",                     NULL },
56         { "0.0.0.0.0",                      NULL },
57         { "1.1.1.256",                      NULL },
58         { "1.2.3",                          NULL },
59         { "1.2.3.0x4",                      "1.2.3.4",          AI_NUMERICHOST },
60         { "1.2.3.010",                      "1.2.3.8",          AI_NUMERICHOST },
61         /* let's just assume this one doesn't change any time soon ;) */
62         { "google-public-dns-a.google.com", "8.8.8.8" },
63     };
64     const INT TestCount = sizeof(Tests) / sizeof(Tests[0]);
65     INT i;
66 
67     /* make sure we don't get IPv6 responses */
68     ZeroMemory(&Hints, sizeof(Hints));
69     Hints.ai_family = AF_INET;
70 
71     trace("Nodes\n");
72     for (i = 0; i < TestCount; i++)
73     {
74         trace("%d: '%s'\n", i, Tests[i].NodeName);
75         StartSeh()
76             AddrInfo = InvalidPointer;
77             Error = getaddrinfo(Tests[i].NodeName, NULL, &Hints, &AddrInfo);
78             if (Tests[i].ExpectedAddress)
79             {
80                 ok_dec(Error, 0);
81                 ok_dec(WSAGetLastError(), 0);
82                 ok(AddrInfo != NULL && AddrInfo != InvalidPointer,
83                    "AddrInfo = %p\n", AddrInfo);
84             }
85             else
86             {
87                 ok_dec(Error, WSAHOST_NOT_FOUND);
88                 ok_dec(WSAGetLastError(), WSAHOST_NOT_FOUND);
89                 ok_ptr(AddrInfo, NULL);
90             }
91             if (!Error && AddrInfo && AddrInfo != InvalidPointer)
92             {
93                 ok_addrinfo(AddrInfo, Tests[i].Flags, AF_INET,
94                             0, 0, sizeof(SOCKADDR_IN));
95                 ok_ptr(AddrInfo->ai_canonname, NULL);
96                 ok_sockaddr_in(AddrInfo->ai_addr, AF_INET,
97                                0, Tests[i].ExpectedAddress);
98                 ok_ptr(AddrInfo->ai_next, NULL);
99                 freeaddrinfo(AddrInfo);
100             }
101         EndSeh(STATUS_SUCCESS);
102     }
103 }
104 
105 static
106 VOID
107 TestServiceName(VOID)
108 {
109     int Error;
110     PADDRINFOA AddrInfo;
111     ADDRINFOA Hints;
112     struct
113     {
114         PCSTR ServiceName;
115         INT ExpectedPort;
116         INT SockType;
117     } Tests[] =
118     {
119         { "", 0 },
120         { "0", 0 },
121         { "1", 1 },
122         { "a", -1 },
123         { "010", 10 },
124         { "0x1a", -1 },
125         { "http", 80, SOCK_STREAM },
126         { "smtp", 25, SOCK_STREAM },
127         { "mail", 25, SOCK_STREAM }, /* alias for smtp */
128         { "router", 520, SOCK_DGRAM },
129         { "domain", 53, 0 /* DNS supports both UDP and TCP */ },
130         { ":0", -1 },
131         { "123", 123 },
132         { " 123", 123 },
133         { "    123", 123 },
134         { "32767", 32767 },
135         { "32768", 32768 },
136         { "65535", 65535 },
137         { "65536", 0 },
138         { "65537", 1 },
139         { "65540", 4 },
140         { "65536", 0 },
141         { "4294967295", 65535 },
142         { "4294967296", 65535 },
143         { "9999999999", 65535 },
144         { "999999999999999999999999999999999999", 65535 },
145         { "+5", 5 },
146         { "-1", 65535 },
147         { "-4", 65532 },
148         { "-65534", 2 },
149         { "-65535", 1 },
150         { "-65536", 0 },
151         { "-65537", 65535 },
152         { "28a", -1 },
153         { "28 ", -1 },
154         { "a28", -1 },
155     };
156     const INT TestCount = sizeof(Tests) / sizeof(Tests[0]);
157     INT i;
158 
159     /* make sure we don't get IPv6 responses */
160     ZeroMemory(&Hints, sizeof(Hints));
161     Hints.ai_family = AF_INET;
162 
163     trace("Services\n");
164     for (i = 0; i < TestCount; i++)
165     {
166         trace("%d: '%s'\n", i, Tests[i].ServiceName);
167         StartSeh()
168             AddrInfo = InvalidPointer;
169             Error = getaddrinfo(NULL, Tests[i].ServiceName, &Hints, &AddrInfo);
170             if (Tests[i].ExpectedPort != -1)
171             {
172                 ok_dec(Error, 0);
173                 ok_dec(WSAGetLastError(), 0);
174                 ok(AddrInfo != NULL && AddrInfo != InvalidPointer,
175                    "AddrInfo = %p\n", AddrInfo);
176             }
177             else
178             {
179                 ok_dec(Error, WSATYPE_NOT_FOUND);
180                 ok_dec(WSAGetLastError(), WSATYPE_NOT_FOUND);
181                 ok_ptr(AddrInfo, NULL);
182             }
183             if (!Error && AddrInfo && AddrInfo != InvalidPointer)
184             {
185                 ok_addrinfo(AddrInfo, 0, AF_INET,
186                             Tests[i].SockType, 0, sizeof(SOCKADDR_IN));
187                 ok_ptr(AddrInfo->ai_canonname, NULL);
188                 ok_sockaddr_in(AddrInfo->ai_addr, AF_INET,
189                                Tests[i].ExpectedPort, "127.0.0.1");
190                 ok_ptr(AddrInfo->ai_next, NULL);
191                 freeaddrinfo(AddrInfo);
192             }
193         EndSeh(STATUS_SUCCESS);
194     }
195 }
196 
197 START_TEST(getaddrinfo)
198 {
199     WSADATA WsaData;
200     int Error;
201     PADDRINFOA AddrInfo;
202     PADDRINFOW AddrInfoW;
203     ADDRINFOA Hints;
204     ADDRINFOW HintsW;
205     CHAR LocalHostName[128];
206     struct hostent *Hostent;
207 
208     /* not yet initialized */
209     StartSeh()
210         Error = getaddrinfo(NULL, NULL, NULL, NULL);
211         ok_dec(Error, WSANOTINITIALISED);
212     EndSeh(STATUS_SUCCESS);
213     StartSeh()
214         AddrInfo = InvalidPointer;
215         Error = getaddrinfo(NULL, NULL, NULL, &AddrInfo);
216         ok_dec(Error, WSANOTINITIALISED);
217         ok_ptr(AddrInfo, InvalidPointer);
218     EndSeh(STATUS_SUCCESS);
219 
220     Error = getaddrinfo("127.0.0.1", "80", NULL, &AddrInfo);
221     ok_dec(Error, WSANOTINITIALISED);
222 
223     Error = GetAddrInfoW(L"127.0.0.1", L"80", NULL, &AddrInfoW);
224     ok_dec(Error, WSANOTINITIALISED);
225 
226     Error = WSAStartup(MAKEWORD(2, 2), &WsaData);
227     ok_dec(Error, 0);
228 
229     /* initialize LocalAddress for tests */
230     Error = gethostname(LocalHostName, sizeof(LocalHostName));
231     ok_dec(Error, 0);
232     ok_dec(WSAGetLastError(), 0);
233     trace("Local host name is '%s'\n", LocalHostName);
234     Hostent = gethostbyname(LocalHostName);
235     ok(Hostent != NULL, "gethostbyname failed with %d\n", WSAGetLastError());
236     if (Hostent && Hostent->h_addr_list[0] && Hostent->h_length == sizeof(IN_ADDR))
237     {
238         IN_ADDR Address;
239         memcpy(&Address, Hostent->h_addr_list[0], sizeof(Address));
240         strcpy(LocalAddress, inet_ntoa(Address));
241     }
242     trace("Local address is '%s'\n", LocalAddress);
243     ok(LocalAddress[0] != '\0',
244        "Could not determine local address. Following test results may be wrong.\n");
245 
246     ZeroMemory(&Hints, sizeof(Hints));
247     /* parameter tests for getaddrinfo */
248     StartSeh() getaddrinfo(NULL, NULL, NULL, NULL); EndSeh(STATUS_ACCESS_VIOLATION);
249     StartSeh() getaddrinfo("", "", &Hints, NULL);   EndSeh(STATUS_ACCESS_VIOLATION);
250     StartSeh()
251         AddrInfo = InvalidPointer;
252         Error = getaddrinfo(NULL, NULL, NULL, &AddrInfo);
253         ok_dec(Error, WSAHOST_NOT_FOUND);
254         ok_dec(WSAGetLastError(), WSAHOST_NOT_FOUND);
255         ok_ptr(AddrInfo, NULL);
256     EndSeh(STATUS_SUCCESS);
257 
258     /* parameter tests for GetAddrInfoW */
259     StartSeh() GetAddrInfoW(NULL, NULL, NULL, NULL);  EndSeh(STATUS_ACCESS_VIOLATION);
260     StartSeh() GetAddrInfoW(L"", L"", &HintsW, NULL); EndSeh(STATUS_ACCESS_VIOLATION);
261     StartSeh()
262         AddrInfo = InvalidPointer;
263         Error = GetAddrInfoW(NULL, NULL, NULL, &AddrInfoW);
264         ok_dec(Error, WSAHOST_NOT_FOUND);
265         ok_dec(WSAGetLastError(), WSAHOST_NOT_FOUND);
266         ok_ptr(AddrInfo, InvalidPointer); /* differs from getaddrinfo */
267     EndSeh(STATUS_SUCCESS);
268 
269     TestNodeName();
270     TestServiceName();
271     /* TODO: test passing both node name and service name */
272     /* TODO: test hints */
273     /* TODO: test IPv6 */
274 
275     Error = WSACleanup();
276     ok_dec(Error, 0);
277 
278     /* not initialized anymore */
279     Error = getaddrinfo("127.0.0.1", "80", NULL, &AddrInfo);
280     ok_dec(Error, WSANOTINITIALISED);
281 
282     Error = GetAddrInfoW(L"127.0.0.1", L"80", NULL, &AddrInfoW);
283     ok_dec(Error, WSANOTINITIALISED);
284 }
285