summaryrefslogtreecommitdiff
path: root/src/gns
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns')
-rw-r--r--src/gns/Makefile.am60
-rw-r--r--src/gns/gns-helper-service-w32.conf4
-rw-r--r--src/gns/gnunet-gns-helper-service-w32.c803
-rw-r--r--src/gns/nss/Makefile.am5
-rw-r--r--src/gns/w32nsp-install.c143
-rw-r--r--src/gns/w32nsp-resolve.c464
-rw-r--r--src/gns/w32nsp-uninstall.c31
-rw-r--r--src/gns/w32nsp.c711
-rw-r--r--src/gns/w32nsp.def2
9 files changed, 10 insertions, 2213 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 0d38cb51e..4a152a6df 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -15,7 +15,6 @@ EXTRA_DIST = \
15 test_gns_lookup.conf \ 15 test_gns_lookup.conf \
16 test_gns_proxy.conf \ 16 test_gns_proxy.conf \
17 test_gns_simple_lookup.conf \ 17 test_gns_simple_lookup.conf \
18 gns-helper-service-w32.conf \
19 w32nsp.def \ 18 w32nsp.def \
20 openssl.cnf \ 19 openssl.cnf \
21 gnunet-gns-proxy-setup-ca.in \ 20 gnunet-gns-proxy-setup-ca.in \
@@ -25,14 +24,6 @@ EXTRA_DIST = \
25 $(check_SCRIPTS) \ 24 $(check_SCRIPTS) \
26 $(pkgdata_DATA) 25 $(pkgdata_DATA)
27 26
28if MINGW
29 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
30 DO_W32_HELPER = gnunet-gns-helper-service-w32
31 DO_W32_NSP = libw32nsp.la
32 DO_W32_NSPTOOLS = w32nsp-install w32nsp-uninstall w32nsp-resolve
33 DO_W32_HS_CONF = gns-helper-service-w32.conf
34 DO_NONPOSIX_GNSIMPORT = gnunet-gns-import
35endif
36USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la 27USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la
37 28
38if USE_COVERAGE 29if USE_COVERAGE
@@ -46,11 +37,9 @@ libexecdir= $(pkglibdir)/libexec/
46plugindir = $(libdir)/gnunet 37plugindir = $(libdir)/gnunet
47 38
48pkgcfg_DATA = \ 39pkgcfg_DATA = \
49 gns.conf \ 40 gns.conf
50 $(DO_W32_HS_CONF)
51 41
52lib_LTLIBRARIES = \ 42lib_LTLIBRARIES = \
53 $(DO_W32_NSP) \
54 libgnunetgns.la 43 libgnunetgns.la
55 44
56 45
@@ -73,12 +62,9 @@ endif
73libexec_PROGRAMS = \ 62libexec_PROGRAMS = \
74 gnunet-service-gns \ 63 gnunet-service-gns \
75 gnunet-dns2gns \ 64 gnunet-dns2gns \
76 $(DO_W32_HELPER) \
77 $(DO_PROXY) 65 $(DO_PROXY)
78 66
79bin_PROGRAMS = \ 67bin_PROGRAMS = \
80 $(DO_W32_NSPTOOLS) \
81 $(DO_NONPOSIX_GNSIMPORT) \
82 gnunet-gns 68 gnunet-gns
83 69
84noinst_PROGRAMS = \ 70noinst_PROGRAMS = \
@@ -199,35 +185,15 @@ test_gns_proxy_LDADD = $(MHD_LIBS) $(LIB_GNURL) -lgnutls \
199 $(GN_LIBINTL) 185 $(GN_LIBINTL)
200test_gns_proxy_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) 186test_gns_proxy_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS)
201 187
202gnunet_gns_helper_service_w32_SOURCES = \ 188#gnunet_gns_import_SOURCES = \
203 gnunet-gns-helper-service-w32.c 189# gnunet-gns-import.c
204gnunet_gns_helper_service_w32_LDADD = \ 190#gnunet_gns_import_LDADD = \
205 libgnunetgns.la \ 191# $(top_builddir)/src/identity/libgnunetidentity.la \
206 $(top_builddir)/src/identity/libgnunetidentity.la \ 192# $(top_builddir)/src/namestore/libgnunetnamestore.la \
207 $(top_builddir)/src/util/libgnunetutil.la \ 193# $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
208 $(GN_LIBINTL) 194# $(top_builddir)/src/util/libgnunetutil.la \
209 195# $(GN_LIBINTL)
210gnunet_gns_import_SOURCES = \
211 gnunet-gns-import.c
212gnunet_gns_import_LDADD = \
213 $(top_builddir)/src/identity/libgnunetidentity.la \
214 $(top_builddir)/src/namestore/libgnunetnamestore.la \
215 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
216 $(top_builddir)/src/util/libgnunetutil.la \
217 $(GN_LIBINTL)
218
219 196
220w32nsp_install_SOURCES = \
221 w32nsp-install.c
222w32nsp_install_LDADD = -lws2_32
223
224w32nsp_uninstall_SOURCES = \
225 w32nsp-uninstall.c
226w32nsp_uninstall_LDADD = -lws2_32
227
228w32nsp_resolve_SOURCES = \
229 w32nsp-resolve.c
230w32nsp_resolve_LDADD = -lws2_32
231 197
232gnunet_service_gns_SOURCES = \ 198gnunet_service_gns_SOURCES = \
233 gnunet-service-gns.c gnunet-service-gns.h \ 199 gnunet-service-gns.c gnunet-service-gns.h \
@@ -247,14 +213,6 @@ gnunet_service_gns_LDADD = \
247 $(GN_LIBINTL) 213 $(GN_LIBINTL)
248 214
249 215
250libw32nsp_la_SOURCES = \
251 w32nsp.c
252libw32nsp_la_LIBADD = \
253 -lole32 -lws2_32
254libw32nsp_la_LDFLAGS = \
255 -export-symbols $(top_srcdir)/src/gns/w32nsp.def \
256 -no-undefined -static-libgcc
257
258libgnunetgns_la_SOURCES = \ 216libgnunetgns_la_SOURCES = \
259 gns_api.c gns_api.h \ 217 gns_api.c gns_api.h \
260 gns_tld_api.c gns.h 218 gns_tld_api.c gns.h
diff --git a/src/gns/gns-helper-service-w32.conf b/src/gns/gns-helper-service-w32.conf
deleted file mode 100644
index a7b9fdd70..000000000
--- a/src/gns/gns-helper-service-w32.conf
+++ /dev/null
@@ -1,4 +0,0 @@
1[gns-helper-service-w32]
2START_ON_DEMAND = YES
3BINARY = gnunet-gns-helper-service-w32
4PORT = 5353
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)
39DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
40DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
41DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005);
42DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006);
43DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c);
44DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f);
45DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010);
46DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
47DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
48DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
49DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
50
51
52struct 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 */
83static struct request *rq_head;
84
85/**
86 * Tail of the doubly-linked list (for cleanup).
87 */
88static struct request *rq_tail;
89
90/**
91 * Handle to GNS service.
92 */
93static struct GNUNET_GNS_Handle *gns;
94
95/**
96 * Active operation on identity service.
97 */
98static struct GNUNET_IDENTITY_Operation *id_op;
99
100/**
101 * Handle for identity service.
102 */
103static struct GNUNET_IDENTITY_Handle *identity;
104
105/**
106 * Public key of the gns-master ego
107 */
108static struct GNUNET_CRYPTO_EcdsaPublicKey gns_master_pubkey;
109
110/**
111 * Set to 1 once egos are obtained.
112 */
113static int got_egos;
114
115
116/**
117 * Task run on shutdown. Cleans up everything.
118 *
119 * @param cls unused
120 */
121static void
122do_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
161void
162MarshallWSAQUERYSETW(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
195static void
196process_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
474static void
475get_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 */
594static int
595check_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 */
624static void
625handle_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 */
693static void
694identity_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 */
720static void
721run(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 */
761static void *
762client_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 */
777static void
778client_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 */
789GNUNET_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 */
diff --git a/src/gns/nss/Makefile.am b/src/gns/nss/Makefile.am
index 5d42f777f..f4a12ddee 100644
--- a/src/gns/nss/Makefile.am
+++ b/src/gns/nss/Makefile.am
@@ -18,18 +18,16 @@
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19# USA. 19# USA.
20 20
21EXTRA_DIST = map-file 21EXTRA_DIST = map-file
22 22
23AM_LDFLAGS=-avoid-version -module -export-dynamic 23AM_LDFLAGS=-avoid-version -module -export-dynamic
24 24
25nssdir = $(libdir)/gnunet/nss 25nssdir = $(libdir)/gnunet/nss
26 26
27if !MINGW
28nss_LTLIBRARIES = \ 27nss_LTLIBRARIES = \
29 libnss_gns.la \ 28 libnss_gns.la \
30 libnss_gns4.la \ 29 libnss_gns4.la \
31 libnss_gns6.la 30 libnss_gns6.la
32endif
33 31
34sources = nss_gns_query.h nss_gns_query.c 32sources = nss_gns_query.h nss_gns_query.c
35 33
@@ -45,4 +43,3 @@ libnss_gns4_la_LDFLAGS=$(libnss_gns_la_LDFLAGS)
45libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES) 43libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES)
46libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1 44libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1
47libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS) 45libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS)
48
diff --git a/src/gns/w32nsp-install.c b/src/gns/w32nsp-install.c
deleted file mode 100644
index 2674359fb..000000000
--- a/src/gns/w32nsp-install.c
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 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 gns/w32nsp-install.c
22 * @brief W32 integration installer for GNS
23 * @author LRN
24 */
25
26#include <ws2spi.h>
27#include <windows.h>
28#include <nspapi.h>
29#include <initguid.h>
30#include "gnunet_w32nsp_lib.h"
31#include <stdio.h>
32
33int
34main(int argc, char **argv)
35{
36 int ret;
37 int r = 1;
38 WSADATA wsd;
39 GUID id = GNUNET_NAMESPACE_PROVIDER_DNS;
40 wchar_t *cmdl;
41 int wargc;
42 wchar_t **wargv;
43 /* Allocate a 4K buffer to retrieve all the namespace providers */
44 DWORD dwInitialBufferLen = 4096;
45 DWORD dwBufferLen;
46 WSANAMESPACE_INFO *pi;
47 int p_count;
48 int i;
49
50 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
51 {
52 fprintf(stderr, "WSAStartup () failed: %lu\n", GetLastError());
53 return 5;
54 }
55
56 dwBufferLen = dwInitialBufferLen;
57 pi = malloc(dwBufferLen);
58 if (NULL == pi)
59 {
60 fprintf(stderr, "malloc (%lu) failed: %d\n", dwBufferLen, errno);
61 WSACleanup();
62 return 6;
63 }
64 p_count = WSAEnumNameSpaceProviders(&dwBufferLen, pi);
65 if (SOCKET_ERROR == p_count)
66 {
67 DWORD err = GetLastError();
68 if (WSAEFAULT == err && dwBufferLen != dwInitialBufferLen)
69 {
70 free(pi);
71
72 pi = malloc(dwBufferLen);
73 if (pi == NULL)
74 {
75 fprintf(stderr, "malloc (%lu) failed: %d\n", dwBufferLen, errno);
76 WSACleanup();
77 return 6;
78 }
79
80 p_count = WSAEnumNameSpaceProviders(&dwBufferLen, pi);
81 if (SOCKET_ERROR == p_count)
82 {
83 fprintf(stderr, "WSAEnumNameSpaceProviders (&%lu, %p) failed: %lu\n", dwBufferLen, pi, GetLastError());
84 free(pi);
85 WSACleanup();
86 return 7;
87 }
88 }
89 else
90 {
91 fprintf(stderr, "WSAEnumNameSpaceProviders (&%lu, %p) failed: %lu\n", dwBufferLen, pi, GetLastError());
92 free(pi);
93 WSACleanup();
94 return 8;
95 }
96 }
97 for (i = 0; i < p_count; i++)
98 {
99 if (IsEqualGUID(&pi[i].NSProviderId, &id))
100 {
101 fprintf(stderr, "GNUnet DNS provider is already installed\n");
102 free(pi);
103 WSACleanup();
104 return 0;
105 }
106 }
107 free(pi);
108
109 cmdl = GetCommandLineW();
110 if (cmdl == NULL)
111 {
112 WSACleanup();
113 return 2;
114 }
115 wargv = CommandLineToArgvW(cmdl, &wargc);
116 if (wargv == NULL)
117 {
118 WSACleanup();
119 return 3;
120 }
121 r = 4;
122
123 if (wargc == 2)
124 {
125 ret = WSCInstallNameSpace(L"GNUnet DNS provider", wargv[1], NS_DNS, 0, &id);
126 if (ret == NO_ERROR)
127 {
128 fprintf(stderr, "Installed GNUnet DNS provider\n");
129 r = 0;
130 }
131 else
132 {
133 r = 1;
134 fprintf(stderr,
135 "WSCInstallNameSpace (L\"GNUnet DNS provider\", \"%S\", %d, 0, %p) failed: %lu\n",
136 wargv[1], NS_DNS, &id, GetLastError());
137 }
138 }
139 else
140 fprintf(stderr, "Usage: %S <path-to-libw32nsp>\n", wargv[0]);
141 WSACleanup();
142 return r;
143}
diff --git a/src/gns/w32nsp-resolve.c b/src/gns/w32nsp-resolve.c
deleted file mode 100644
index ad0fd3586..000000000
--- a/src/gns/w32nsp-resolve.c
+++ /dev/null
@@ -1,464 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 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 gns/w32nsp-resolve.c
22 * @brief W32 integration for GNS
23 * @author LRN
24 */
25/* Instead of including gnunet_common.h */
26#define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0)
27
28#include <ws2tcpip.h>
29#include <windows.h>
30#include <nspapi.h>
31#include <ws2spi.h>
32#include <nspapi.h>
33#include <initguid.h>
34#include "gnunet_w32nsp_lib.h"
35#include <stdio.h>
36
37typedef int (WSPAPI *LPNSPSTARTUP)(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);
38
39GUID host = { 0x0002a800, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
40GUID ip4 = { 0x00090035, 0, 1, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } };
41GUID ip6 = { 0x00090035, 0, 0x001c, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } };
42
43DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);
44
45#define DEFINE_DNS_GUID(a, x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
46DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
47DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
48DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005);
49DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006);
50DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c);
51DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f);
52DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010);
53DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
54DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
55DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
56DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
57
58//
59// Utility to turn a list of offsets into a list of addresses. Used
60// to convert structures returned as BLOBs.
61//
62
63VOID
64FixList(PCHAR ** List, PCHAR Base)
65{
66 if (*List)
67 {
68 PCHAR * Addr;
69
70 Addr = *List = (PCHAR *)(((DWORD)*List + Base));
71 while (*Addr)
72 {
73 *Addr = (PCHAR)(((DWORD)*Addr + Base));
74 Addr++;
75 }
76 }
77}
78
79
80//
81// Routine to convert a hostent returned in a BLOB to one with
82// usable pointers. The structure is converted in-place.
83//
84VOID
85UnpackHostEnt(struct hostent * hostent)
86{
87 PCHAR pch;
88
89 pch = (PCHAR)hostent;
90
91 if (hostent->h_name)
92 {
93 hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
94 }
95 FixList(&hostent->h_aliases, pch);
96 FixList(&hostent->h_addr_list, pch);
97}
98
99
100static void
101print_hostent(struct hostent *he)
102{
103 int i;
104 char **pAlias;
105
106 printf("\tOfficial name: %s\n", he->h_name);
107 for (i = 0, pAlias = he->h_aliases; *pAlias != 0; pAlias++)
108 {
109 printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
110 }
111 printf("\tAddress type: ");
112 switch (he->h_addrtype)
113 {
114 case AF_INET:
115 printf("AF_INET\n");
116 break;
117
118 case AF_INET6:
119 printf("AF_INET6\n");
120 break;
121
122 case AF_NETBIOS:
123 printf("AF_NETBIOS\n");
124 break;
125
126 default:
127 printf(" %d\n", he->h_addrtype);
128 break;
129 }
130 printf("\tAddress length: %d\n", he->h_length);
131
132 if (he->h_addrtype == AF_INET)
133 {
134 struct sockaddr_in addr;
135 memset(&addr, 0, sizeof(addr));
136 addr.sin_family = AF_INET;
137 addr.sin_port = 0;
138 i = 0;
139 while (he->h_addr_list[i] != 0)
140 {
141 char buf[1024];
142 DWORD buflen = 1024;
143 addr.sin_addr = *(struct in_addr *)he->h_addr_list[i++];
144 if (NO_ERROR == WSAAddressToStringA((LPSOCKADDR)&addr, sizeof(addr), NULL, buf, &buflen))
145 printf("\tIPv4 Address #%d: %s\n", i, buf);
146 else
147 printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError());
148 }
149 }
150 else if (he->h_addrtype == AF_INET6)
151 {
152 struct sockaddr_in6 addr;
153 memset(&addr, 0, sizeof(addr));
154 addr.sin6_family = AF_INET6;
155 addr.sin6_port = 0;
156 i = 0;
157 while (he->h_addr_list[i] != 0)
158 {
159 char buf[1024];
160 DWORD buflen = 1024;
161 addr.sin6_addr = *(struct in6_addr *)he->h_addr_list[i++];
162 if (NO_ERROR == WSAAddressToStringA((LPSOCKADDR)&addr, sizeof(addr), NULL, buf, &buflen))
163 printf("\tIPv6 Address #%d: %s\n", i, buf);
164 else
165 printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError());
166 }
167 }
168}
169
170
171int
172main(int argc, char **argv)
173{
174 int ret;
175 int r = 1;
176 WSADATA wsd;
177 GUID prov;
178 GUID sc;
179 wchar_t *cmdl;
180 int wargc;
181 wchar_t **wargv;
182
183 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
184 {
185 fprintf(stderr, "WSAStartup() failed: %lu\n", GetLastError());
186 return 5;
187 }
188
189 cmdl = GetCommandLineW();
190 if (cmdl == NULL)
191 {
192 WSACleanup();
193 return 2;
194 }
195 wargv = CommandLineToArgvW(cmdl, &wargc);
196 if (wargv == NULL)
197 {
198 WSACleanup();
199 return 3;
200 }
201 r = 4;
202
203 if (wargc == 5)
204 {
205 if (wcscmp(wargv[1], L"A") == 0)
206 sc = SVCID_DNS_TYPE_A;
207 else if (wcscmp(wargv[1], L"AAAA") == 0)
208 sc = SVCID_DNS_TYPE_AAAA;
209 else if (wcscmp(wargv[1], L"name") == 0)
210 sc = SVCID_HOSTNAME;
211 else if (wcscmp(wargv[1], L"addr") == 0)
212 sc = SVCID_INET_HOSTADDRBYNAME;
213 else
214 wargc -= 1;
215 if (wcscmp(wargv[4], L"mswdns") == 0)
216 prov = W32_DNS;
217 else if (wcscmp(wargv[4], L"gnunetdns") == 0)
218 prov = GNUNET_NAMESPACE_PROVIDER_DNS;
219 else
220 wargc -= 1;
221 }
222 else if (wargc == 3)
223 {
224 }
225 else
226 {
227 fprintf(stderr, "Usage: %S <record type> <service name> <NSP library path> <NSP id>\n"
228 "record type - one of the following: A | AAAA | name | addr\n"
229 "service name - a string to resolve; \" \" (a space) means 'blank'\n"
230 "NSP library path - path to libw32nsp\n"
231 "NSP id - one of the following: mswdns | gnunetdns\n",
232 wargv[0]);
233 }
234
235 if (wargc == 5)
236 {
237 HMODULE nsp;
238
239 nsp = LoadLibraryW(wargv[3]);
240 if (nsp == NULL)
241 {
242 fprintf(stderr, "Failed to load library `%S'\n", wargv[3]);
243 }
244 else
245 {
246 LPNSPSTARTUP startup = (LPNSPSTARTUP)GetProcAddress(nsp, "NSPStartup");
247 if (startup == NULL)
248 startup = (LPNSPSTARTUP)GetProcAddress(nsp, "NSPStartup@8");
249 if (startup != NULL)
250 {
251 NSP_ROUTINE api;
252 api.cbSize = sizeof(api);
253 ret = startup(&prov, &api);
254 if (NO_ERROR != ret)
255 fprintf(stderr, "startup failed: %lu\n", GetLastError());
256 else
257 {
258 HANDLE lookup;
259 WSAQUERYSETW search;
260 char buf[4096];
261 WSAQUERYSETW *result = (WSAQUERYSETW *)buf;
262 DWORD resultsize;
263 DWORD err;
264 memset(&search, 0, sizeof(search));
265 search.dwSize = sizeof(search);
266 search.lpszServiceInstanceName = (wcscmp(wargv[2], L" ") == 0) ? NULL : wargv[2];
267 search.lpServiceClassId = &sc;
268 search.lpNSProviderId = &prov;
269 search.dwNameSpace = NS_ALL;
270 ret = api.NSPLookupServiceBegin(&prov, &search, NULL, LUP_RETURN_ALL, &lookup);
271 if (ret != NO_ERROR)
272 {
273 fprintf(stderr, "lookup start failed\n");
274 }
275 else
276 {
277 resultsize = 4096;
278 ret = api.NSPLookupServiceNext(lookup, LUP_RETURN_ALL, &resultsize, result);
279 err = GetLastError();
280 if (ret != NO_ERROR)
281 {
282 fprintf(stderr, "lookup next failed: %lu\n", err);
283 }
284 else
285 {
286 int i;
287 printf("Got result:\n");
288 printf(" lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");
289 if (result->lpServiceClassId)
290 printf(" lpServiceClassId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
291 result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],
292 result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],
293 result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);
294 else
295 printf(" lpServiceClassId: NULL\n");
296 if (result->lpVersion)
297 printf(" lpVersion: 0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);
298 else
299 printf(" lpVersion: NULL\n");
300 printf(" lpszComment: %S\n", result->lpszComment ? result->lpszComment : L"NULL");
301 printf(" dwNameSpace: %lu\n", result->dwNameSpace);
302 if (result->lpNSProviderId)
303 printf(" lpNSProviderId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
304 result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],
305 result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],
306 result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);
307 else
308 printf(" lpNSProviderId: NULL\n");
309 printf(" lpszContext: %S\n", result->lpszContext ? result->lpszContext : L"NULL");
310 printf(" dwNumberOfProtocols: %lu\n", result->dwNumberOfProtocols);
311 printf(" lpszQueryString: %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");
312 printf(" dwNumberOfCsAddrs: %lu\n", result->dwNumberOfCsAddrs);
313 for (i = 0; i < result->dwNumberOfCsAddrs; i++)
314 {
315 switch (result->lpcsaBuffer[i].iSocketType)
316 {
317 case SOCK_STREAM:
318 printf(" %d: iSocketType = SOCK_STREAM\n", i);
319 break;
320
321 case SOCK_DGRAM:
322 printf(" %d: iSocketType = SOCK_DGRAM\n", i);
323 break;
324
325 default:
326 printf(" %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);
327 }
328 switch (result->lpcsaBuffer[i].iProtocol)
329 {
330 case IPPROTO_TCP:
331 printf(" %d: iProtocol = IPPROTO_TCP\n", i);
332 break;
333
334 case IPPROTO_UDP:
335 printf(" %d: iProtocol = IPPROTO_UDP\n", i);
336 break;
337
338 default:
339 printf(" %d: iProtocol = %d\n", i, result->lpcsaBuffer[i].iProtocol);
340 }
341 switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)
342 {
343 case AF_INET:
344 printf(" %d: loc family = AF_INET\n", i);
345 break;
346
347 case AF_INET6:
348 printf(" %d: loc family = AF_INET6\n", i);
349 break;
350
351 default:
352 printf(" %d: loc family = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);
353 }
354 switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)
355 {
356 case AF_INET:
357 printf(" %d: rem family = AF_INET\n", i);
358 break;
359
360 case AF_INET6:
361 printf(" %d: rem family = AF_INET6\n", i);
362 break;
363
364 default:
365 printf(" %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);
366 }
367 char buf[1024];
368 DWORD buflen = 1024;
369 if (NO_ERROR == WSAAddressToStringA(result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))
370 printf("\tLocal Address #%d: %s\n", i, buf);
371 else
372 printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError());
373 buflen = 1024;
374 if (NO_ERROR == WSAAddressToStringA(result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))
375 printf("\tRemote Address #%d: %s\n", i, buf);
376 else
377 printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError());
378 }
379 printf(" dwOutputFlags: 0x%08lX\n", result->dwOutputFlags);
380 printf(" lpBlob: 0x%p\n", result->lpBlob);
381 if (result->lpBlob)
382 {
383 struct hostent *he = malloc(result->lpBlob->cbSize);
384 if (he != NULL)
385 {
386 GNUNET_memcpy(he, result->lpBlob->pBlobData, result->lpBlob->cbSize);
387 UnpackHostEnt(he);
388 print_hostent(he);
389 free(he);
390 }
391 }
392 }
393 ret = api.NSPLookupServiceEnd(lookup);
394 if (ret != NO_ERROR)
395 printf("NSPLookupServiceEnd() failed: %lu\n", GetLastError());
396 }
397 api.NSPCleanup(&prov);
398 }
399 }
400 FreeLibrary(nsp);
401 }
402 }
403 else if (wargc == 3)
404 {
405 int s;
406 ADDRINFOW hints;
407 ADDRINFOW *result;
408 ADDRINFOW *pos;
409
410 memset(&hints, 0, sizeof(struct addrinfo));
411 hints.ai_family = AF_UNSPEC;
412 hints.ai_socktype = SOCK_STREAM;
413
414 if (0 != (s = GetAddrInfoW(wargv[2], NULL, &hints, &result)))
415 {
416 fprintf(stderr, "Cound not resolve `%S' using GetAddrInfoW: %lu\n",
417 wargv[2], GetLastError());
418 }
419 else
420 {
421 for (pos = result; pos != NULL; pos = pos->ai_next)
422 {
423 wchar_t tmpbuf[1024];
424 DWORD buflen = 1024;
425 if (0 == WSAAddressToStringW(pos->ai_addr, pos->ai_addrlen, NULL, tmpbuf, &buflen))
426 fprintf(stderr, "Result:\n"
427 " flags: 0x%X\n"
428 " family: 0x%X\n"
429 " socktype: 0x%X\n"
430 " protocol: 0x%X\n"
431 " addrlen: %u\n"
432 " addr: %S\n"
433 " canonname: %S\n",
434 pos->ai_flags,
435 pos->ai_family,
436 pos->ai_socktype,
437 pos->ai_protocol,
438 pos->ai_addrlen,
439 tmpbuf,
440 pos->ai_canonname);
441 else
442 fprintf(stderr, "Result:\n"
443 " flags: 0x%X\n"
444 " family: 0x%X\n"
445 " socktype: 0x%X\n"
446 " protocol: 0x%X\n"
447 " addrlen: %u\n"
448 " addr: %S\n"
449 " canonname: %S\n",
450 pos->ai_flags,
451 pos->ai_family,
452 pos->ai_socktype,
453 pos->ai_protocol,
454 pos->ai_addrlen,
455 L"<can't stringify>",
456 pos->ai_canonname);
457 }
458 if (NULL != result)
459 FreeAddrInfoW(result);
460 }
461 }
462 WSACleanup();
463 return r;
464}
diff --git a/src/gns/w32nsp-uninstall.c b/src/gns/w32nsp-uninstall.c
deleted file mode 100644
index f5031f341..000000000
--- a/src/gns/w32nsp-uninstall.c
+++ /dev/null
@@ -1,31 +0,0 @@
1#include <ws2spi.h>
2#include <windows.h>
3#include <nspapi.h>
4#include <initguid.h>
5#include "gnunet_w32nsp_lib.h"
6#include <stdio.h>
7
8int
9main(int argc, char **argv)
10{
11 int ret;
12 GUID id = GNUNET_NAMESPACE_PROVIDER_DNS;
13 WSADATA wsd;
14
15 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
16 {
17 fprintf(stderr, "WSAStartup () failed: %lu\n", GetLastError());
18 return 5;
19 }
20
21 ret = WSCUnInstallNameSpace(&id);
22 if (ret == NO_ERROR)
23 {
24 fprintf(stderr, "Uninstalled GNUnet DNS provider\n");
25 WSACleanup();
26 return 0;
27 }
28 fprintf(stderr, "WSCUnInstallNameSpace () failed: %lu\n", GetLastError());
29 WSACleanup();
30 return 1;
31} \ No newline at end of file
diff --git a/src/gns/w32nsp.c b/src/gns/w32nsp.c
deleted file mode 100644
index 3de4452f0..000000000
--- a/src/gns/w32nsp.c
+++ /dev/null
@@ -1,711 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 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 gns/w32nsp.c
22 * @brief W32 integration for GNS
23 * @author LRN
24 */
25/* This code is partially based upon samples from the book
26 * "Network Programming For Microsoft Windows, 2Nd Edition".
27 */
28
29#define VERBOSE 0
30#if !VERBOSE
31# define DEBUGLOG(s, ...)
32#endif
33#if VERBOSE
34# define __printf__ printf
35# define DEBUGLOG(s, ...) printf(s, ## __VA_ARGS__)
36#endif
37
38#include <stdint.h>
39#include <ws2tcpip.h>
40#include <ws2spi.h>
41#include <windows.h>
42#include <nspapi.h>
43
44#define WINDOWS 1
45#define MINGW 1
46#ifndef __BYTE_ORDER
47#ifdef _BYTE_ORDER
48#define __BYTE_ORDER _BYTE_ORDER
49#else
50#ifdef BYTE_ORDER
51#define __BYTE_ORDER BYTE_ORDER
52#endif
53#endif
54#endif
55#ifndef __BIG_ENDIAN
56#ifdef _BIG_ENDIAN
57#define __BIG_ENDIAN _BIG_ENDIAN
58#else
59#ifdef BIG_ENDIAN
60#define __BIG_ENDIAN BIG_ENDIAN
61#endif
62#endif
63#endif
64#ifndef __LITTLE_ENDIAN
65#ifdef _LITTLE_ENDIAN
66#define __LITTLE_ENDIAN _LITTLE_ENDIAN
67#else
68#ifdef LITTLE_ENDIAN
69#define __LITTLE_ENDIAN LITTLE_ENDIAN
70#endif
71#endif
72#endif
73#include "w32resolver.h"
74#include <initguid.h>
75#include "gnunet_w32nsp_lib.h"
76#undef INITGUID
77
78#define NSPAPI_VERSION_MAJOR 4
79#define NSPAPI_VERSION_MINOR 4
80
81static CRITICAL_SECTION records_cs;
82
83struct record {
84 _win_socket s;
85 DWORD flags;
86 uint8_t state;
87 char *buf;
88 wchar_t *name;
89};
90
91static struct record *records = NULL;
92static size_t records_len = 0;
93static size_t records_size = 0;
94
95static int
96resize_records()
97{
98 size_t new_size = records_len > 0 ? records_len * 2 : 5;
99 struct record *new_records = malloc(new_size * sizeof(struct record));
100
101 if (new_records == NULL)
102 {
103 SetLastError(WSA_NOT_ENOUGH_MEMORY);
104 return 0;
105 }
106 GNUNET_memcpy(new_records, records, records_len * sizeof(struct record));
107 memset(&new_records[records_len], 0, sizeof(struct record) * (new_size - records_len));
108 records_size = new_size;
109 free(records);
110 records = new_records;
111 return 1;
112}
113
114static int
115add_record(_win_socket s, const wchar_t *name, DWORD flags)
116{
117 int res = 1;
118 int i;
119 int empty = -1;
120
121 //EnterCriticalSection (&records_cs);
122 for (i = 0; i < records_len; i++)
123 if (records[i].state == 0)
124 break;
125 empty = i;
126 if (i == records_len)
127 {
128 res = resize_records();
129 if (res)
130 empty = records_len++;
131 }
132 if (res)
133 {
134 struct record r;
135 r.s = s;
136 r.flags = flags;
137 r.name = (wchar_t *)name;
138 r.state = 1;
139 r.buf = NULL;
140 if (name)
141 r.name = wcsdup(name);
142 records[empty] = r;
143 }
144 //LeaveCriticalSection (&records_cs);
145 return res;
146}
147
148/* These are not defined by mingw.org headers at the moment*/
149typedef INT (WSPAPI *LPNSPIOCTL)(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPWSACOMPLETION, LPWSATHREADID);
150typedef struct _NSP_ROUTINE_XP {
151 DWORD cbSize;
152 DWORD dwMajorVersion;
153 DWORD dwMinorVersion;
154 LPNSPCLEANUP NSPCleanup;
155 LPNSPLOOKUPSERVICEBEGIN NSPLookupServiceBegin;
156 LPNSPLOOKUPSERVICENEXT NSPLookupServiceNext;
157 LPNSPLOOKUPSERVICEEND NSPLookupServiceEnd;
158 LPNSPSETSERVICE NSPSetService;
159 LPNSPINSTALLSERVICECLASS NSPInstallServiceClass;
160 LPNSPREMOVESERVICECLASS NSPRemoveServiceClass;
161 LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo;
162 LPNSPIOCTL NSPIoctl;
163} NSP_ROUTINE_XP;
164
165static _win_socket
166connect_to_dns_resolver()
167{
168 struct sockaddr_in addr;
169 _win_socket r;
170 int ret;
171
172 r = _win_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
173 if (INVALID_SOCKET == r)
174 {
175 SetLastError(16004);
176 return r;
177 }
178
179 addr.sin_family = AF_INET;
180 addr.sin_port = htons(5353); /* TCP 5353 is not registered; UDP 5353 is */
181 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
182
183 ret = _win_connect(r, (struct sockaddr *)&addr, sizeof(addr));
184 if (SOCKET_ERROR == ret)
185 {
186 DWORD err = GetLastError();
187 closesocket(r);
188 SetLastError(err);
189 SetLastError(16005);
190 r = INVALID_SOCKET;
191 }
192 return r;
193}
194
195static int
196send_name_to_ip_request(LPWSAQUERYSETW lpqsRestrictions,
197 LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags,
198 _win_socket *resolver)
199{
200 struct GNUNET_W32RESOLVER_GetMessage *msg;
201 int af4 = 0;
202 int af6 = 0;
203 char *buf;
204 int ret = 1;
205 int i;
206 size_t size = sizeof(struct GNUNET_W32RESOLVER_GetMessage);
207 size_t namelen = 0;
208
209 if (lpqsRestrictions->lpszServiceInstanceName)
210 namelen = sizeof(wchar_t) * (wcslen(lpqsRestrictions->lpszServiceInstanceName) + 1);
211 size += namelen;
212 buf = malloc(size);
213 msg = (struct GNUNET_W32RESOLVER_GetMessage *)buf;
214 msg->header.size = htons(size);
215 msg->header.type = htons(GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST);
216 if (lpqsRestrictions->dwNumberOfProtocols > 0)
217 {
218 int i;
219 for (i = 0; i < lpqsRestrictions->dwNumberOfProtocols; i++)
220 {
221 if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET)
222 af4 = 1;
223 if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET6)
224 af6 = 1;
225 }
226 }
227 if (af4 && !af6)
228 msg->af = htonl(AF_INET);
229 else if (af6 && !af4)
230 msg->af = htonl(AF_INET6);
231 else
232 msg->af = htonl(AF_UNSPEC);
233 if (lpqsRestrictions->lpszServiceInstanceName)
234 GNUNET_memcpy(&msg[1], lpqsRestrictions->lpszServiceInstanceName, namelen);
235 msg->sc_data1 = htonl(lpqsRestrictions->lpServiceClassId->Data1);
236 msg->sc_data2 = htons(lpqsRestrictions->lpServiceClassId->Data2);
237 msg->sc_data3 = htons(lpqsRestrictions->lpServiceClassId->Data3);
238 for (i = 0; i < 8; i++)
239 msg->sc_data4[i] = lpqsRestrictions->lpServiceClassId->Data4[i];
240 *resolver = connect_to_dns_resolver();
241 if (*resolver != INVALID_SOCKET)
242 {
243 if (size != send(*resolver, buf, size, 0))
244 {
245#if VERBOSE
246 DWORD err = GetLastError();
247#endif
248 closesocket(*resolver);
249 *resolver = INVALID_SOCKET;
250 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: failed to send request: %lu\n", err);
251 SetLastError(WSATRY_AGAIN);
252 ret = 0;
253 }
254 }
255 else
256 ret = 0;
257 free(buf);
258 return ret;
259}
260
261static int WSPAPI
262NSPCleanup(LPGUID lpProviderId)
263{
264 DEBUGLOG("NSPCleanup\n");
265 if (IsEqualGUID(lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
266 {
267 return NO_ERROR;
268 }
269 SetLastError(WSAEINVALIDPROVIDER);
270 return SOCKET_ERROR;
271}
272
273BOOL WINAPI
274DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
275{
276 switch (fdwReason)
277 {
278 case DLL_PROCESS_ATTACH:
279 if (!InitializeCriticalSectionAndSpinCount(&records_cs, 0x00000400))
280 {
281 return FALSE;
282 }
283 break;
284
285 case DLL_THREAD_ATTACH:
286 break;
287
288 case DLL_THREAD_DETACH:
289 break;
290
291 case DLL_PROCESS_DETACH:
292 DeleteCriticalSection(&records_cs);
293 break;
294 }
295 return TRUE;
296}
297
298
299
300
301static int WSPAPI
302GNUNET_W32NSP_LookupServiceBegin(LPGUID lpProviderId, LPWSAQUERYSETW lpqsRestrictions,
303 LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags,
304 LPHANDLE lphLookup)
305{
306 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin\n");
307 if (IsEqualGUID(lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
308 {
309 SOCKET s;
310 if (lpqsRestrictions->dwNameSpace != NS_DNS && lpqsRestrictions->dwNameSpace != NS_ALL)
311 {
312 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: wrong namespace\n");
313 SetLastError(WSAEINVAL);
314 return SOCKET_ERROR;
315 }
316 if (lpqsRestrictions->lpszServiceInstanceName != NULL)
317 {
318 wchar_t *s = lpqsRestrictions->lpszServiceInstanceName;
319 size_t len = wcslen(s);
320 if (len >= 5 && wcscmp(&s[len - 5], L".zkey") == 0)
321 {
322 }
323 else if (len >= 4 && wcscmp(&s[len - 4], L".gnu") == 0)
324 {
325 }
326 else
327 {
328 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: unsupported TLD\n");
329 SetLastError(WSAEINVAL);
330 return SOCKET_ERROR;
331 }
332 }
333
334 if (send_name_to_ip_request(lpqsRestrictions,
335 lpServiceClassInfo, dwControlFlags, &s))
336 {
337 if (!(add_record(s, lpqsRestrictions->lpszServiceInstanceName, dwControlFlags)))
338 {
339 DWORD err = GetLastError();
340 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: failed to add a record\n");
341 closesocket(s);
342 SetLastError(err);
343 return SOCKET_ERROR;
344 }
345 *lphLookup = (HANDLE)s;
346 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: OK (%lu)\n", GetLastError());
347 return NO_ERROR;
348 }
349 return SOCKET_ERROR;
350 }
351 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: wrong provider\n");
352 SetLastError(WSAEINVALIDPROVIDER);
353 return SOCKET_ERROR;
354}
355
356#define UnmarshallPtr(ptr, ptrtype, base) \
357 if (ptr) \
358 ptr = (ptrtype *) (base + (uintptr_t)ptr)
359
360static void
361UnmarshallWSAQUERYSETW(LPWSAQUERYSETW req)
362{
363 int i;
364 char *base = (char *)req;
365
366 UnmarshallPtr(req->lpszServiceInstanceName, wchar_t, base);
367 UnmarshallPtr(req->lpServiceClassId, GUID, base);
368 UnmarshallPtr(req->lpVersion, WSAVERSION, base);
369 UnmarshallPtr(req->lpszComment, wchar_t, base);
370 UnmarshallPtr(req->lpNSProviderId, GUID, base);
371 UnmarshallPtr(req->lpszContext, wchar_t, base);
372 UnmarshallPtr(req->lpafpProtocols, AFPROTOCOLS, base);
373 UnmarshallPtr(req->lpszQueryString, wchar_t, base);
374 UnmarshallPtr(req->lpcsaBuffer, CSADDR_INFO, base);
375 for (i = 0; i < req->dwNumberOfCsAddrs; i++)
376 {
377 UnmarshallPtr(req->lpcsaBuffer[i].LocalAddr.lpSockaddr, SOCKADDR, base);
378 UnmarshallPtr(req->lpcsaBuffer[i].RemoteAddr.lpSockaddr, SOCKADDR, base);
379 }
380 UnmarshallPtr(req->lpBlob, BLOB, base);
381 if (req->lpBlob)
382 UnmarshallPtr(req->lpBlob->pBlobData, BYTE, base);
383}
384
385static int WSAAPI
386GNUNET_W32NSP_LookupServiceNext(HANDLE hLookup, DWORD dwControlFlags,
387 LPDWORD lpdwBufferLength, LPWSAQUERYSETW lpqsResults)
388{
389 /*DWORD effective_flags;*/
390 int i;
391 struct GNUNET_MessageHeader header = { 0, 0 };
392 int rec = -1;
393 int rc;
394 int to_receive;
395 int t;
396 char *buf;
397
398 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext\n");
399 //EnterCriticalSection (&records_cs);
400 for (i = 0; i < records_len; i++)
401 {
402 if (records[i].s == (_win_socket)hLookup)
403 {
404 rec = i;
405 break;
406 }
407 }
408 if (rec == -1)
409 {
410 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: invalid handle\n");
411 SetLastError(WSA_INVALID_HANDLE);
412 //LeaveCriticalSection (&records_cs);
413 return SOCKET_ERROR;
414 }
415 if (records[rec].state & 4)
416 {
417 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: session is closed\n");
418 SetLastError(WSA_E_NO_MORE);
419 //LeaveCriticalSection (&records_cs);
420 return SOCKET_ERROR;
421 }
422 /*effective_flags = dwControlFlags & records[rec].flags;*/
423 if (records[rec].buf)
424 {
425 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: checking buffer\n");
426 header = *((struct GNUNET_MessageHeader *)records[rec].buf);
427 if (*lpdwBufferLength < header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage))
428 {
429 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
430 SetLastError(WSAEFAULT);
431 //LeaveCriticalSection (&records_cs);
432 return SOCKET_ERROR;
433 }
434 GNUNET_memcpy(lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)records[rec].buf)[1], header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage));
435 free(records[rec].buf);
436 records[rec].buf = NULL;
437 //LeaveCriticalSection (&records_cs);
438 UnmarshallWSAQUERYSETW((LPWSAQUERYSETW)lpqsResults);
439 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: OK (from buffer)\n");
440 return NO_ERROR;
441 }
442 records[rec].state |= 8;
443 //LeaveCriticalSection (&records_cs);
444 to_receive = sizeof(header);
445 rc = 0;
446#if VERBOSE
447 {
448 unsigned long have;
449 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
450 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a header from %p, %lu bytes available\n", to_receive, hLookup, have);
451 }
452#endif
453 while (to_receive > 0)
454 {
455 t = recv((_win_socket)hLookup, &((char *)&header)[rc], to_receive, 0);
456 if (t > 0)
457 {
458 rc += t;
459 to_receive -= t;
460 }
461 else
462 break;
463 }
464#if VERBOSE
465 {
466 unsigned long have;
467 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
468 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a header from %p, %lu bytes available\n", rc, hLookup, have);
469 }
470#endif
471 //EnterCriticalSection (&records_cs);
472 records[rec].state &= ~8;
473 if (rc != sizeof(header))
474 {
475 if (records[rec].state & 2)
476 {
477 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
478 SetLastError(WSA_E_CANCELLED);
479 }
480 else
481 {
482 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for a header (rc %d != %u, state is 0x%0X)\n", rc, sizeof(header), records[rec].state);
483 SetLastError(WSA_E_NO_MORE);
484 }
485 records[rec].state |= 4;
486 //LeaveCriticalSection (&records_cs);
487 return SOCKET_ERROR;
488 }
489 records[rec].state &= ~8;
490 header.type = ntohs(header.type);
491 header.size = ntohs(header.size);
492 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: header type %d, header size %u\n", header.type, header.size);
493 if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE ||
494 (header.type == GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE &&
495 header.size == sizeof(header)))
496 {
497 records[rec].state |= 4;
498 if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE)
499 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: header type is wrong\n");
500 else
501 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: empty header - no data\n");
502 //LeaveCriticalSection (&records_cs);
503 SetLastError(WSA_E_NO_MORE);
504 return SOCKET_ERROR;
505 }
506 buf = malloc(header.size);
507 if (buf == NULL)
508 {
509 records[rec].state |= 4;
510 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: malloc() failed\n");
511 //LeaveCriticalSection (&records_cs);
512 SetLastError(WSA_E_NO_MORE);
513 return SOCKET_ERROR;
514 }
515 records[rec].state |= 8;
516 //LeaveCriticalSection (&records_cs);
517 GNUNET_memcpy(buf, &header, sizeof(header));
518 to_receive = header.size - sizeof(header);
519 rc = 0;
520#if VERBOSE
521 {
522 unsigned long have;
523 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
524 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a body from %p, %lu bytes available\n", to_receive, hLookup, have);
525 }
526#endif
527 while (to_receive > 0)
528 {
529 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: recv (%d)\n", to_receive);
530 t = recv((_win_socket)hLookup, &((char *)&((struct GNUNET_MessageHeader *)buf)[1])[rc], to_receive, 0);
531 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: recv returned %d\n", t);
532 if (t > 0)
533 {
534 rc += t;
535 to_receive -= t;
536 }
537 else
538 break;
539 }
540#if VERBOSE
541 {
542 unsigned long have;
543 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
544 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a body from %p, %lu bytes available\n", rc, hLookup, have);
545 }
546#endif
547 //EnterCriticalSection (&records_cs);
548 records[rec].state &= ~8;
549 if (rc != header.size - sizeof(header))
550 {
551 free(buf);
552 if (records[rec].state & 2)
553 {
554 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
555 SetLastError(WSA_E_CANCELLED);
556 }
557 else
558 {
559 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for the rest (rc %d != %d, state is 0x%0X)\n", rc, header.size - sizeof(header), records[rec].state);
560 SetLastError(WSA_E_NO_MORE);
561 }
562 records[rec].state |= 4;
563 //LeaveCriticalSection (&records_cs);
564 return SOCKET_ERROR;
565 }
566 if (*lpdwBufferLength < header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage))
567 {
568 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
569 SetLastError(WSAEFAULT);
570 records[rec].buf = buf;
571 //LeaveCriticalSection (&records_cs);
572 return SOCKET_ERROR;
573 }
574 //LeaveCriticalSection (&records_cs);
575 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: writing %d bytes into result buffer\n", header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage));
576 GNUNET_memcpy(lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)buf)[1], header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage));
577 free(buf);
578 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: OK\n");
579 UnmarshallWSAQUERYSETW((LPWSAQUERYSETW)lpqsResults);
580 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: returning (%lu)\n", GetLastError());
581 return NO_ERROR;
582}
583
584static int WSPAPI
585GNUNET_W32NSP_LookupServiceEnd(HANDLE hLookup)
586{
587 int i;
588 int rec = -1;
589
590 DEBUGLOG("GNUNET_W32NSP_LookupServiceEnd\n");
591 //EnterCriticalSection (&records_cs);
592 for (i = 0; i < records_len; i++)
593 {
594 if (records[i].s == (_win_socket)hLookup)
595 {
596 rec = i;
597 break;
598 }
599 }
600 if (rec == -1)
601 {
602 SetLastError(WSA_INVALID_HANDLE);
603 //LeaveCriticalSection (&records_cs);
604 DEBUGLOG("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n");
605 return SOCKET_ERROR;
606 }
607 records[rec].state |= 2;
608 closesocket(records[rec].s);
609 while (records[rec].state & 8)
610 {
611 //LeaveCriticalSection (&records_cs);
612 Sleep(10);
613 //EnterCriticalSection (&records_cs);
614 }
615 if (records[rec].buf)
616 free(records[rec].buf);
617 records[rec].buf = NULL;
618 records[rec].state = 0;
619 if (records[rec].name)
620 free(records[rec].name);
621 //LeaveCriticalSection (&records_cs);
622 DEBUGLOG("GNUNET_W32NSP_LookupServiceEnd: OK\n");
623 return NO_ERROR;
624}
625
626static int WSAAPI
627GNUNET_W32NSP_SetService(LPGUID lpProviderId,
628 LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo,
629 WSAESETSERVICEOP essOperation, DWORD dwControlFlags)
630{
631 DEBUGLOG("GNUNET_W32NSP_SetService\n");
632 SetLastError(WSAEOPNOTSUPP);
633 return SOCKET_ERROR;
634}
635
636static int WSAAPI
637GNUNET_W32NSP_InstallServiceClass(LPGUID lpProviderId,
638 LPWSASERVICECLASSINFOW lpServiceClassInfo)
639{
640 DEBUGLOG("GNUNET_W32NSP_InstallServiceClass\n");
641 SetLastError(WSAEOPNOTSUPP);
642 return SOCKET_ERROR;
643}
644
645
646static int WSAAPI
647GNUNET_W32NSP_RemoveServiceClass(LPGUID lpProviderId, LPGUID lpServiceClassId)
648{
649 DEBUGLOG("GNUNET_W32NSP_RemoveServiceClass\n");
650 SetLastError(WSAEOPNOTSUPP);
651 return SOCKET_ERROR;
652}
653
654static int WSAAPI
655GNUNET_W32NSP_GetServiceClassInfo(LPGUID lpProviderId, LPDWORD lpdwBufSize,
656 LPWSASERVICECLASSINFOW lpServiceClassInfo)
657{
658 DEBUGLOG("GNUNET_W32NSP_GetServiceClassInfo\n");
659 SetLastError(WSAEOPNOTSUPP);
660 return SOCKET_ERROR;
661}
662
663static int WSAAPI
664GNUNET_W32NSP_Ioctl(HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
665 DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
666 LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion,
667 LPWSATHREADID lpThreadId)
668{
669 DEBUGLOG("GNUNET_W32NSP_Ioctl\n");
670 SetLastError(WSAEOPNOTSUPP);
671 return SOCKET_ERROR;
672}
673
674/**
675 * This function is called by Winsock to hook up our provider.
676 * It is the only function that [should be/is] exported by the
677 * provider. All other routines are passed as pointers in lpnspRoutines.
678 */
679int WSAAPI
680GNUNET_W32NSP_NSPStartup(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines)
681{
682 if (IsEqualGUID(lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
683 {
684 if (!connect_to_dns_resolver())
685 {
686 return SOCKET_ERROR;
687 }
688 /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member.
689 * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl
690 * and use that offset as cbSize.
691 */
692 lpnspRoutines->cbSize = sizeof(NSP_ROUTINE);
693
694 lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR;
695 lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR;
696 lpnspRoutines->NSPCleanup = NSPCleanup;
697 lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin;
698 lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext;
699 lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd;
700 lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService;
701 lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass;
702 lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass;
703 lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo;
704 /*((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl;*/
705 lpnspRoutines->NSPIoctl = GNUNET_W32NSP_Ioctl;
706 return NO_ERROR;
707 }
708 SetLastError(WSAEINVALIDPROVIDER);
709 return SOCKET_ERROR;
710}
711
diff --git a/src/gns/w32nsp.def b/src/gns/w32nsp.def
deleted file mode 100644
index 6bd28b283..000000000
--- a/src/gns/w32nsp.def
+++ /dev/null
@@ -1,2 +0,0 @@
1EXPORTS
2NSPStartup=GNUNET_W32NSP_NSPStartup