diff options
Diffstat (limited to 'src/gns/gnunet-gns-helper-service-w32.c')
-rw-r--r-- | src/gns/gnunet-gns-helper-service-w32.c | 803 |
1 files changed, 0 insertions, 803 deletions
diff --git a/src/gns/gnunet-gns-helper-service-w32.c b/src/gns/gnunet-gns-helper-service-w32.c deleted file mode 100644 index 4c4803556..000000000 --- a/src/gns/gnunet-gns-helper-service-w32.c +++ /dev/null | |||
@@ -1,803 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file gnunet-gns-helper-service-w32.c | ||
22 | * @brief an intermediary service to access distributed GNS | ||
23 | * @author Christian Grothoff | ||
24 | * @author LRN | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include <gnunet_util_lib.h> | ||
28 | #include <gnunet_identity_service.h> | ||
29 | #include <gnunet_dnsparser_lib.h> | ||
30 | #include <gnunet_namestore_service.h> | ||
31 | #include <gnunet_gns_service.h> | ||
32 | #include <initguid.h> | ||
33 | #include "gnunet_w32nsp_lib.h" | ||
34 | #include "w32resolver.h" | ||
35 | #include <nspapi.h> | ||
36 | #include <unistr.h> | ||
37 | |||
38 | #define DEFINE_DNS_GUID(a, x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) | ||
39 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001); | ||
40 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002); | ||
41 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005); | ||
42 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006); | ||
43 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c); | ||
44 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f); | ||
45 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010); | ||
46 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c); | ||
47 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021); | ||
48 | DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); | ||
49 | DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); | ||
50 | |||
51 | |||
52 | struct request { | ||
53 | /** | ||
54 | * We keep these in a doubly-linked list (for cleanup). | ||
55 | */ | ||
56 | struct request *next; | ||
57 | |||
58 | /** | ||
59 | * We keep these in a doubly-linked list (for cleanup). | ||
60 | */ | ||
61 | struct request *prev; | ||
62 | |||
63 | /** | ||
64 | * Client that issued the request | ||
65 | */ | ||
66 | struct GNUNET_SERVICE_Client *client; | ||
67 | |||
68 | GUID sc; | ||
69 | |||
70 | int af; | ||
71 | |||
72 | wchar_t *name; | ||
73 | |||
74 | char *u8name; | ||
75 | |||
76 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
77 | }; | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Head of the doubly-linked list (for cleanup). | ||
82 | */ | ||
83 | static struct request *rq_head; | ||
84 | |||
85 | /** | ||
86 | * Tail of the doubly-linked list (for cleanup). | ||
87 | */ | ||
88 | static struct request *rq_tail; | ||
89 | |||
90 | /** | ||
91 | * Handle to GNS service. | ||
92 | */ | ||
93 | static struct GNUNET_GNS_Handle *gns; | ||
94 | |||
95 | /** | ||
96 | * Active operation on identity service. | ||
97 | */ | ||
98 | static struct GNUNET_IDENTITY_Operation *id_op; | ||
99 | |||
100 | /** | ||
101 | * Handle for identity service. | ||
102 | */ | ||
103 | static struct GNUNET_IDENTITY_Handle *identity; | ||
104 | |||
105 | /** | ||
106 | * Public key of the gns-master ego | ||
107 | */ | ||
108 | static struct GNUNET_CRYPTO_EcdsaPublicKey gns_master_pubkey; | ||
109 | |||
110 | /** | ||
111 | * Set to 1 once egos are obtained. | ||
112 | */ | ||
113 | static int got_egos; | ||
114 | |||
115 | |||
116 | /** | ||
117 | * Task run on shutdown. Cleans up everything. | ||
118 | * | ||
119 | * @param cls unused | ||
120 | */ | ||
121 | static void | ||
122 | do_shutdown(void *cls) | ||
123 | { | ||
124 | struct request *rq; | ||
125 | |||
126 | if (NULL != id_op) | ||
127 | { | ||
128 | GNUNET_IDENTITY_cancel(id_op); | ||
129 | id_op = NULL; | ||
130 | } | ||
131 | if (NULL != identity) | ||
132 | { | ||
133 | GNUNET_IDENTITY_disconnect(identity); | ||
134 | identity = NULL; | ||
135 | } | ||
136 | while (NULL != (rq = rq_head)) | ||
137 | { | ||
138 | if (NULL != rq->lookup_request) | ||
139 | GNUNET_GNS_lookup_cancel(rq->lookup_request); | ||
140 | GNUNET_CONTAINER_DLL_remove(rq_head, | ||
141 | rq_tail, | ||
142 | rq); | ||
143 | GNUNET_free_non_null(rq->name); | ||
144 | if (rq->u8name) | ||
145 | free(rq->u8name); | ||
146 | GNUNET_free(rq); | ||
147 | } | ||
148 | if (NULL != gns) | ||
149 | { | ||
150 | GNUNET_GNS_disconnect(gns); | ||
151 | gns = NULL; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | |||
156 | #define MarshallPtr(ptr, base, type) \ | ||
157 | if (ptr) \ | ||
158 | ptr = (type *) ((char *)ptr - (char *)base) | ||
159 | |||
160 | |||
161 | void | ||
162 | MarshallWSAQUERYSETW(WSAQUERYSETW *qs, GUID *sc) | ||
163 | { | ||
164 | MarshallPtr(qs->lpszServiceInstanceName, qs, wchar_t); | ||
165 | MarshallPtr(qs->lpServiceClassId, qs, GUID); | ||
166 | MarshallPtr(qs->lpVersion, qs, WSAVERSION); | ||
167 | MarshallPtr(qs->lpNSProviderId, qs, GUID); | ||
168 | MarshallPtr(qs->lpszContext, qs, wchar_t); | ||
169 | MarshallPtr(qs->lpafpProtocols, qs, AFPROTOCOLS); | ||
170 | MarshallPtr(qs->lpszQueryString, qs, wchar_t); | ||
171 | for (int i = 0; i < qs->dwNumberOfCsAddrs; i++) | ||
172 | { | ||
173 | MarshallPtr(qs->lpcsaBuffer[i].LocalAddr.lpSockaddr, qs, SOCKADDR); | ||
174 | MarshallPtr(qs->lpcsaBuffer[i].RemoteAddr.lpSockaddr, qs, SOCKADDR); | ||
175 | } | ||
176 | MarshallPtr(qs->lpcsaBuffer, qs, CSADDR_INFO); | ||
177 | if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, sc) && qs->lpBlob != NULL && qs->lpBlob->pBlobData != NULL) | ||
178 | { | ||
179 | struct hostent *he; | ||
180 | |||
181 | he = (struct hostent *)qs->lpBlob->pBlobData; | ||
182 | for (int i = 0; he->h_aliases[i] != NULL; i++) | ||
183 | MarshallPtr(he->h_aliases[i], he, char); | ||
184 | MarshallPtr(he->h_aliases, he, char *); | ||
185 | MarshallPtr(he->h_name, he, char); | ||
186 | for (int i = 0; he->h_addr_list[i] != NULL; i++) | ||
187 | MarshallPtr(he->h_addr_list[i], he, void); | ||
188 | MarshallPtr(he->h_addr_list, he, char *); | ||
189 | MarshallPtr(qs->lpBlob->pBlobData, qs, void); | ||
190 | } | ||
191 | MarshallPtr(qs->lpBlob, qs, BLOB); | ||
192 | } | ||
193 | |||
194 | |||
195 | static void | ||
196 | process_lookup_result(void *cls, | ||
197 | uint32_t rd_count, | ||
198 | const struct GNUNET_GNSRECORD_Data *rd) | ||
199 | { | ||
200 | struct request *rq = cls; | ||
201 | int i, j, csanum; | ||
202 | struct GNUNET_W32RESOLVER_GetMessage *msg; | ||
203 | struct GNUNET_MQ_Envelope *msg_env; | ||
204 | struct GNUNET_MessageHeader *msgend; | ||
205 | struct GNUNET_MQ_Envelope *msgend_env; | ||
206 | WSAQUERYSETW *qs; | ||
207 | size_t size; | ||
208 | size_t size_recalc; | ||
209 | char *ptr; | ||
210 | size_t blobsize = 0; | ||
211 | size_t blobaddrcount = 0; | ||
212 | |||
213 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
214 | "Got lookup result with count %u for rq %p with client %p\n", | ||
215 | rd_count, | ||
216 | rq, | ||
217 | rq->client); | ||
218 | rq->lookup_request = NULL; | ||
219 | |||
220 | if (0 == rd_count) | ||
221 | { | ||
222 | msgend_env = GNUNET_MQ_msg(msgend, GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); | ||
223 | GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(rq->client), | ||
224 | msgend_env); | ||
225 | GNUNET_CONTAINER_DLL_remove(rq_head, | ||
226 | rq_tail, | ||
227 | rq); | ||
228 | GNUNET_free_non_null(rq->name); | ||
229 | if (rq->u8name) | ||
230 | free(rq->u8name); | ||
231 | GNUNET_free(rq); | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | size = sizeof(struct GNUNET_W32RESOLVER_GetMessage) + sizeof(WSAQUERYSETW); | ||
236 | size += (wcslen(rq->name) + 1) * sizeof(wchar_t); | ||
237 | size += sizeof(GUID); | ||
238 | /* lpszComment ? a TXT record? */ | ||
239 | size += sizeof(GUID); | ||
240 | /* lpszContext ? Not sure what it is */ | ||
241 | csanum = 0; | ||
242 | for (i = 0; i < rd_count; i++) | ||
243 | { | ||
244 | switch (rd[i].record_type) | ||
245 | { | ||
246 | case GNUNET_DNSPARSER_TYPE_A: | ||
247 | if (rd[i].data_size != sizeof(struct in_addr)) | ||
248 | continue; | ||
249 | size += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in) * 2; | ||
250 | csanum++; | ||
251 | break; | ||
252 | |||
253 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
254 | if (rd[i].data_size != sizeof(struct in6_addr)) | ||
255 | continue; | ||
256 | size += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in6) * 2; | ||
257 | csanum++; | ||
258 | break; | ||
259 | } | ||
260 | } | ||
261 | if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, &rq->sc)) | ||
262 | { | ||
263 | size += sizeof(BLOB); | ||
264 | blobsize += sizeof(struct hostent); | ||
265 | blobsize += strlen(rq->u8name) + 1; | ||
266 | blobsize += sizeof(void *); /* For aliases */ | ||
267 | blobsize += sizeof(void *); /* For addresses */ | ||
268 | for (i = 0; i < rd_count; i++) | ||
269 | { | ||
270 | if ((rq->af == AF_INET || rq->af == AF_UNSPEC) && rd[i].record_type == GNUNET_DNSPARSER_TYPE_A) | ||
271 | { | ||
272 | blobsize += sizeof(void *); | ||
273 | blobsize += sizeof(struct in_addr); | ||
274 | blobaddrcount++; | ||
275 | } | ||
276 | else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_DNSPARSER_TYPE_AAAA) | ||
277 | { | ||
278 | blobsize += sizeof(void *); | ||
279 | blobsize += sizeof(struct in6_addr); | ||
280 | blobaddrcount++; | ||
281 | } | ||
282 | } | ||
283 | size += blobsize; | ||
284 | } | ||
285 | size_recalc = sizeof(struct GNUNET_W32RESOLVER_GetMessage) + sizeof(WSAQUERYSETW); | ||
286 | msg_env = GNUNET_MQ_msg_extra(msg, | ||
287 | size - sizeof(struct GNUNET_MessageHeader), | ||
288 | GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); | ||
289 | msg->af = htonl(rq->af); | ||
290 | msg->sc_data1 = htonl(rq->sc.Data1); | ||
291 | msg->sc_data2 = htons(rq->sc.Data2); | ||
292 | msg->sc_data3 = htons(rq->sc.Data3); | ||
293 | for (i = 0; i < 8; i++) | ||
294 | msg->sc_data4[i] = rq->sc.Data4[i]; | ||
295 | qs = (WSAQUERYSETW *)&msg[1]; | ||
296 | ptr = (char *)&qs[1]; | ||
297 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
298 | qs->dwSize = sizeof(WSAQUERYSETW); | ||
299 | qs->lpszServiceInstanceName = (wchar_t *)ptr; | ||
300 | ptr += (wcslen(rq->name) + 1) * sizeof(wchar_t); | ||
301 | size_recalc += (wcslen(rq->name) + 1) * sizeof(wchar_t); | ||
302 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
303 | wcscpy(qs->lpszServiceInstanceName, rq->name); | ||
304 | qs->lpServiceClassId = (GUID *)ptr; | ||
305 | ptr += sizeof(GUID); | ||
306 | size_recalc += sizeof(GUID); | ||
307 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
308 | GNUNET_memcpy(qs->lpServiceClassId, &rq->sc, sizeof(GUID)); | ||
309 | qs->lpVersion = NULL; | ||
310 | qs->dwNameSpace = NS_DNS; | ||
311 | qs->lpNSProviderId = (GUID *)ptr; | ||
312 | ptr += sizeof(GUID); | ||
313 | size_recalc += sizeof(GUID); | ||
314 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
315 | GNUNET_memcpy(qs->lpNSProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS, sizeof(GUID)); | ||
316 | qs->lpszContext = NULL; | ||
317 | qs->dwNumberOfProtocols = 0; | ||
318 | qs->lpafpProtocols = NULL; | ||
319 | /* Don't bother with this... */ | ||
320 | qs->lpszQueryString = NULL; | ||
321 | qs->dwNumberOfCsAddrs = rd_count; | ||
322 | qs->lpcsaBuffer = (CSADDR_INFO *)ptr; | ||
323 | ptr += sizeof(CSADDR_INFO) * csanum; | ||
324 | j = 0; | ||
325 | for (i = 0; i < rd_count; i++) | ||
326 | { | ||
327 | switch (rd[i].record_type) | ||
328 | { | ||
329 | case GNUNET_DNSPARSER_TYPE_A: | ||
330 | if (rd[i].data_size != sizeof(struct in_addr)) | ||
331 | continue; | ||
332 | qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM; | ||
333 | qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP; | ||
334 | |||
335 | qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof(struct sockaddr_in); | ||
336 | qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *)ptr; | ||
337 | ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength; | ||
338 | memset(qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength); | ||
339 | ((struct sockaddr_in *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin_family = AF_INET; | ||
340 | |||
341 | qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof(struct sockaddr_in); | ||
342 | qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *)ptr; | ||
343 | ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength; | ||
344 | memset(qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength); | ||
345 | ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_family = AF_INET; | ||
346 | ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_port = htonl(53); /* Don't ask why it's 53 */ | ||
347 | ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_addr = *(struct in_addr *)rd[i].data; | ||
348 | size_recalc += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in) * 2; | ||
349 | j++; | ||
350 | break; | ||
351 | |||
352 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
353 | if (rd[i].data_size != sizeof(struct in6_addr)) | ||
354 | continue; | ||
355 | qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM; | ||
356 | qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP; | ||
357 | |||
358 | qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof(struct sockaddr_in6); | ||
359 | qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *)ptr; | ||
360 | ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength; | ||
361 | memset(qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength); | ||
362 | ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin6_family = AF_INET6; | ||
363 | |||
364 | qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof(struct sockaddr_in6); | ||
365 | qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *)ptr; | ||
366 | ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength; | ||
367 | memset(qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength); | ||
368 | ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_family = AF_INET6; | ||
369 | ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_port = htonl(53); /* Don't ask why it's 53 */ | ||
370 | ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_addr = *(struct in6_addr *)rd[i].data; | ||
371 | size_recalc += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in6) * 2; | ||
372 | j++; | ||
373 | break; | ||
374 | |||
375 | default: | ||
376 | break; | ||
377 | } | ||
378 | } | ||
379 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
380 | qs->dwOutputFlags = 0; | ||
381 | if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, &rq->sc)) | ||
382 | { | ||
383 | struct hostent *he; | ||
384 | qs->lpBlob = (BLOB *)ptr; | ||
385 | ptr += sizeof(BLOB); | ||
386 | |||
387 | size_recalc += sizeof(BLOB); | ||
388 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
389 | |||
390 | qs->lpBlob->cbSize = blobsize; | ||
391 | qs->lpBlob->pBlobData = (BYTE *)ptr; | ||
392 | ptr += sizeof(struct hostent); | ||
393 | |||
394 | size_recalc += sizeof(struct hostent); | ||
395 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
396 | |||
397 | he = (struct hostent *)qs->lpBlob->pBlobData; | ||
398 | he->h_name = (char *)ptr; | ||
399 | ptr += strlen(rq->u8name) + 1; | ||
400 | |||
401 | size_recalc += strlen(rq->u8name) + 1; | ||
402 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
403 | |||
404 | strcpy(he->h_name, rq->u8name); | ||
405 | he->h_aliases = (char **)ptr; | ||
406 | ptr += sizeof(void *); | ||
407 | |||
408 | size_recalc += sizeof(void *); /* For aliases */ | ||
409 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
410 | |||
411 | he->h_aliases[0] = NULL; | ||
412 | he->h_addrtype = rq->af; | ||
413 | he->h_length = rq->af == AF_INET || rq->af == AF_UNSPEC ? sizeof(struct in_addr) : sizeof(struct in6_addr); | ||
414 | he->h_addr_list = (char **)ptr; | ||
415 | ptr += sizeof(void *) * (blobaddrcount + 1); | ||
416 | |||
417 | size_recalc += sizeof(void *) * (blobaddrcount + 1); /* For addresses */ | ||
418 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
419 | |||
420 | j = 0; | ||
421 | for (i = 0; i < rd_count; i++) | ||
422 | { | ||
423 | if ((rq->af == AF_INET || rq->af == AF_UNSPEC) && | ||
424 | rd[i].record_type == GNUNET_DNSPARSER_TYPE_A) | ||
425 | { | ||
426 | he->h_addr_list[j] = (char *)ptr; | ||
427 | ptr += sizeof(struct in_addr); | ||
428 | |||
429 | size_recalc += sizeof(struct in_addr); | ||
430 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
431 | |||
432 | GNUNET_memcpy(he->h_addr_list[j], rd[i].data, sizeof(struct in_addr)); | ||
433 | j++; | ||
434 | } | ||
435 | else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_DNSPARSER_TYPE_AAAA) | ||
436 | { | ||
437 | he->h_addr_list[j] = (char *)ptr; | ||
438 | ptr += sizeof(struct in6_addr); | ||
439 | |||
440 | size_recalc += sizeof(struct in6_addr); | ||
441 | GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg)); | ||
442 | |||
443 | GNUNET_memcpy(he->h_addr_list[j], rd[i].data, sizeof(struct in6_addr)); | ||
444 | j++; | ||
445 | } | ||
446 | } | ||
447 | he->h_addr_list[j] = NULL; | ||
448 | } | ||
449 | msgend_env = GNUNET_MQ_msg(msgend, GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); | ||
450 | |||
451 | if ((char *)ptr - (char *)msg != size || size_recalc != size || size_recalc != ((char *)ptr - (char *)msg)) | ||
452 | { | ||
453 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
454 | "Error in WSAQUERYSETW size calc: expected %u, got %lu (recalc %u)\n", | ||
455 | size, | ||
456 | (unsigned long)((char *)ptr - (char *)msg), | ||
457 | size_recalc); | ||
458 | } | ||
459 | MarshallWSAQUERYSETW(qs, &rq->sc); | ||
460 | GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(rq->client), | ||
461 | msg_env); | ||
462 | GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(rq->client), | ||
463 | msgend_env); | ||
464 | GNUNET_CONTAINER_DLL_remove(rq_head, | ||
465 | rq_tail, | ||
466 | rq); | ||
467 | GNUNET_free_non_null(rq->name); | ||
468 | if (rq->u8name) | ||
469 | free(rq->u8name); | ||
470 | GNUNET_free(rq); | ||
471 | } | ||
472 | |||
473 | |||
474 | static void | ||
475 | get_ip_from_hostname(struct GNUNET_SERVICE_Client *client, | ||
476 | const wchar_t *name, | ||
477 | int af, | ||
478 | GUID sc) | ||
479 | { | ||
480 | struct request *rq; | ||
481 | char *hostname; | ||
482 | size_t strl; | ||
483 | size_t namelen; | ||
484 | uint32_t rtype; | ||
485 | |||
486 | if (IsEqualGUID(&SVCID_DNS_TYPE_A, &sc)) | ||
487 | rtype = GNUNET_DNSPARSER_TYPE_A; | ||
488 | else if (IsEqualGUID(&SVCID_DNS_TYPE_NS, &sc)) | ||
489 | rtype = GNUNET_DNSPARSER_TYPE_NS; | ||
490 | else if (IsEqualGUID(&SVCID_DNS_TYPE_CNAME, &sc)) | ||
491 | rtype = GNUNET_DNSPARSER_TYPE_CNAME; | ||
492 | else if (IsEqualGUID(&SVCID_DNS_TYPE_SOA, &sc)) | ||
493 | rtype = GNUNET_DNSPARSER_TYPE_SOA; | ||
494 | else if (IsEqualGUID(&SVCID_DNS_TYPE_PTR, &sc)) | ||
495 | rtype = GNUNET_DNSPARSER_TYPE_PTR; | ||
496 | else if (IsEqualGUID(&SVCID_DNS_TYPE_MX, &sc)) | ||
497 | rtype = GNUNET_DNSPARSER_TYPE_MX; | ||
498 | else if (IsEqualGUID(&SVCID_DNS_TYPE_TEXT, &sc)) | ||
499 | rtype = GNUNET_DNSPARSER_TYPE_TXT; | ||
500 | else if (IsEqualGUID(&SVCID_DNS_TYPE_AAAA, &sc)) | ||
501 | rtype = GNUNET_DNSPARSER_TYPE_AAAA; | ||
502 | else if (IsEqualGUID(&SVCID_DNS_TYPE_SRV, &sc)) | ||
503 | rtype = GNUNET_DNSPARSER_TYPE_SRV; | ||
504 | else if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, &sc)) | ||
505 | rtype = GNUNET_DNSPARSER_TYPE_A; | ||
506 | else | ||
507 | { | ||
508 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
509 | "Unknown GUID: %08lX-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", | ||
510 | sc.Data1, | ||
511 | sc.Data2, | ||
512 | sc.Data3, | ||
513 | sc.Data4[0], | ||
514 | sc.Data4[1], | ||
515 | sc.Data4[2], | ||
516 | sc.Data4[3], | ||
517 | sc.Data4[4], | ||
518 | sc.Data4[5], | ||
519 | sc.Data4[6], | ||
520 | sc.Data4[7]); | ||
521 | GNUNET_SERVICE_client_drop(client); | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | if (name) | ||
526 | namelen = wcslen(name); | ||
527 | else | ||
528 | namelen = 0; | ||
529 | if (namelen > 0) | ||
530 | hostname = (char *)u16_to_u8(name, namelen + 1, NULL, &strl); | ||
531 | else | ||
532 | hostname = NULL; | ||
533 | |||
534 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
535 | "W32 DNS resolver asked to look up %s for `%s'.\n", | ||
536 | af == AF_INET ? "IPv4" : af == AF_INET6 ? "IPv6" : "anything", | ||
537 | hostname); | ||
538 | |||
539 | rq = GNUNET_new(struct request); | ||
540 | rq->sc = sc; | ||
541 | rq->client = client; | ||
542 | rq->af = af; | ||
543 | if (rq->af != AF_INET && rq->af != AF_INET6) | ||
544 | rq->af = AF_INET; | ||
545 | if (namelen) | ||
546 | { | ||
547 | rq->name = GNUNET_malloc((namelen + 1) * sizeof(wchar_t)); | ||
548 | GNUNET_memcpy(rq->name, | ||
549 | name, | ||
550 | (namelen + 1) * sizeof(wchar_t)); | ||
551 | rq->u8name = hostname; | ||
552 | } | ||
553 | |||
554 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
555 | "Launching a lookup for client %p with rq %p\n", | ||
556 | client, | ||
557 | rq); | ||
558 | rq->lookup_request = GNUNET_GNS_lookup(gns, | ||
559 | hostname, | ||
560 | &gns_master_pubkey, | ||
561 | rtype, | ||
562 | GNUNET_NO /* Use DHT */, | ||
563 | &process_lookup_result, | ||
564 | rq); | ||
565 | if (NULL != rq->lookup_request) | ||
566 | { | ||
567 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
568 | "Lookup launched, waiting for a reply\n"); | ||
569 | GNUNET_SERVICE_client_continue(client); | ||
570 | GNUNET_CONTAINER_DLL_insert(rq_head, | ||
571 | rq_tail, | ||
572 | rq); | ||
573 | } | ||
574 | else | ||
575 | { | ||
576 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
577 | "Lookup was not launched, disconnecting the client\n"); | ||
578 | GNUNET_free_non_null(rq->name); | ||
579 | if (rq->u8name) | ||
580 | free(rq->u8name); | ||
581 | GNUNET_free(rq); | ||
582 | GNUNET_SERVICE_client_drop(client); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | |||
587 | /** | ||
588 | * Check GET-message. | ||
589 | * | ||
590 | * @param cls identification of the client | ||
591 | * @param msg the actual message | ||
592 | * @return #GNUNET_OK if @a msg is well-formed | ||
593 | */ | ||
594 | static int | ||
595 | check_get(void *cls, | ||
596 | const struct GNUNET_W32RESOLVER_GetMessage *msg) | ||
597 | { | ||
598 | uint16_t size; | ||
599 | const wchar_t *hostname; | ||
600 | |||
601 | if (!got_egos) | ||
602 | { | ||
603 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
604 | _("Not ready to process requests, lacking ego data\n")); | ||
605 | return GNUNET_SYSERR; | ||
606 | } | ||
607 | size = ntohs(msg->header.size) - sizeof(struct GNUNET_W32RESOLVER_GetMessage); | ||
608 | hostname = (const wchar_t *)&msg[1]; | ||
609 | if (hostname[size / 2 - 1] != L'\0') | ||
610 | { | ||
611 | GNUNET_break(0); | ||
612 | return GNUNET_SYSERR; | ||
613 | } | ||
614 | return GNUNET_OK; | ||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * Handle GET-message. | ||
620 | * | ||
621 | * @param cls identification of the client | ||
622 | * @param msg the actual message | ||
623 | */ | ||
624 | static void | ||
625 | handle_get(void *cls, | ||
626 | const struct GNUNET_W32RESOLVER_GetMessage *msg) | ||
627 | { | ||
628 | struct GNUNET_SERVICE_Client *client = cls; | ||
629 | GUID sc; | ||
630 | uint16_t size; | ||
631 | const wchar_t *hostname; | ||
632 | int af; | ||
633 | |||
634 | size = ntohs(msg->header.size) - sizeof(struct GNUNET_W32RESOLVER_GetMessage); | ||
635 | af = ntohl(msg->af); | ||
636 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
637 | "Got NBO GUID: %08X-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", | ||
638 | msg->sc_data1, | ||
639 | msg->sc_data2, | ||
640 | msg->sc_data3, | ||
641 | msg->sc_data4[0], | ||
642 | msg->sc_data4[1], | ||
643 | msg->sc_data4[2], | ||
644 | msg->sc_data4[3], | ||
645 | msg->sc_data4[4], | ||
646 | msg->sc_data4[5], | ||
647 | msg->sc_data4[6], | ||
648 | msg->sc_data4[7]); | ||
649 | sc.Data1 = ntohl(msg->sc_data1); | ||
650 | sc.Data2 = ntohs(msg->sc_data2); | ||
651 | sc.Data3 = ntohs(msg->sc_data3); | ||
652 | for (int i = 0; i < 8; i++) | ||
653 | sc.Data4[i] = msg->sc_data4[i]; | ||
654 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
655 | "Got GUID: %08lX-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", | ||
656 | sc.Data1, | ||
657 | sc.Data2, | ||
658 | sc.Data3, | ||
659 | sc.Data4[0], | ||
660 | sc.Data4[1], | ||
661 | sc.Data4[2], | ||
662 | sc.Data4[3], | ||
663 | sc.Data4[4], | ||
664 | sc.Data4[5], | ||
665 | sc.Data4[6], | ||
666 | sc.Data4[7]); | ||
667 | hostname = (const wchar_t *)&msg[1]; | ||
668 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
669 | "Name of %u bytes (last word is 0x%0X): %*S\n", | ||
670 | size, | ||
671 | hostname[size / 2 - 2], | ||
672 | size / 2, | ||
673 | hostname); | ||
674 | get_ip_from_hostname(client, | ||
675 | hostname, | ||
676 | af, | ||
677 | sc); | ||
678 | } | ||
679 | |||
680 | |||
681 | /** | ||
682 | * Method called to with the ego we are to use for the lookup, | ||
683 | * when the ego is the one for the default master zone. | ||
684 | * | ||
685 | * @param cls closure (NULL, unused) | ||
686 | * @param ego ego handle, NULL if not found | ||
687 | * @param ctx context for application to store data for this ego | ||
688 | * (during the lifetime of this process, initially NULL) | ||
689 | * @param name name assigned by the user for this ego, | ||
690 | * NULL if the user just deleted the ego and it | ||
691 | * must thus no longer be used | ||
692 | */ | ||
693 | static void | ||
694 | identity_master_cb(void *cls, | ||
695 | struct GNUNET_IDENTITY_Ego *ego, | ||
696 | void **ctx, | ||
697 | const char *name) | ||
698 | { | ||
699 | id_op = NULL; | ||
700 | if (NULL == ego) | ||
701 | { | ||
702 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
703 | _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); | ||
704 | GNUNET_SCHEDULER_shutdown(); | ||
705 | return; | ||
706 | } | ||
707 | GNUNET_IDENTITY_ego_get_public_key(ego, | ||
708 | &gns_master_pubkey); | ||
709 | got_egos = 1; | ||
710 | } | ||
711 | |||
712 | |||
713 | /** | ||
714 | * Start up gns-helper-w32 service. | ||
715 | * | ||
716 | * @param cls closure | ||
717 | * @param cfg configuration to use | ||
718 | * @param service the initialized service | ||
719 | */ | ||
720 | static void | ||
721 | run(void *cls, | ||
722 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
723 | struct GNUNET_SERVICE_Handle *service) | ||
724 | { | ||
725 | gns = GNUNET_GNS_connect(cfg); | ||
726 | if (NULL == gns) | ||
727 | { | ||
728 | fprintf(stderr, | ||
729 | _("Failed to connect to GNS\n")); | ||
730 | GNUNET_SCHEDULER_shutdown(); | ||
731 | return; | ||
732 | } | ||
733 | GNUNET_SCHEDULER_add_shutdown(&do_shutdown, | ||
734 | NULL); | ||
735 | identity = GNUNET_IDENTITY_connect(cfg, | ||
736 | NULL, | ||
737 | NULL); | ||
738 | if (NULL == identity) | ||
739 | { | ||
740 | fprintf(stderr, | ||
741 | _("Failed to connect to identity service\n")); | ||
742 | GNUNET_SCHEDULER_shutdown(); | ||
743 | return; | ||
744 | } | ||
745 | id_op = GNUNET_IDENTITY_get(identity, | ||
746 | "gns-master", | ||
747 | &identity_master_cb, | ||
748 | NULL); | ||
749 | GNUNET_assert(NULL != id_op); | ||
750 | } | ||
751 | |||
752 | |||
753 | /** | ||
754 | * Handle client connecting to the service. | ||
755 | * | ||
756 | * @param cls NULL | ||
757 | * @param client the new client | ||
758 | * @param mq the message queue of @a client | ||
759 | * @return @a client | ||
760 | */ | ||
761 | static void * | ||
762 | client_connect_cb(void *cls, | ||
763 | struct GNUNET_SERVICE_Client *client, | ||
764 | struct GNUNET_MQ_Handle *mq) | ||
765 | { | ||
766 | return client; | ||
767 | } | ||
768 | |||
769 | |||
770 | /** | ||
771 | * Callback called when a client disconnected from the service | ||
772 | * | ||
773 | * @param cls closure for the service | ||
774 | * @param c the client that disconnected | ||
775 | * @param internal_cls should be equal to @a c | ||
776 | */ | ||
777 | static void | ||
778 | client_disconnect_cb(void *cls, | ||
779 | struct GNUNET_SERVICE_Client *client, | ||
780 | void *internal_cls) | ||
781 | { | ||
782 | GNUNET_assert(internal_cls == client); | ||
783 | } | ||
784 | |||
785 | |||
786 | /** | ||
787 | * Define "main" method using service macro. | ||
788 | */ | ||
789 | GNUNET_SERVICE_MAIN | ||
790 | ("gns-helper-service-w32", | ||
791 | GNUNET_SERVICE_OPTION_NONE, | ||
792 | &run, | ||
793 | &client_connect_cb, | ||
794 | &client_disconnect_cb, | ||
795 | NULL, | ||
796 | GNUNET_MQ_hd_var_size(get, | ||
797 | GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST, | ||
798 | struct GNUNET_W32RESOLVER_GetMessage, | ||
799 | NULL), | ||
800 | GNUNET_MQ_handler_end()); | ||
801 | |||
802 | |||
803 | /* end of gnunet-gns-helper-service-w32.c */ | ||