gnunet-gns-helper-service-w32.c 25 KB

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