aboutsummaryrefslogtreecommitdiff
path: root/src/nat-auto/gnunet-nat-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat-auto/gnunet-nat-server.c')
-rw-r--r--src/nat-auto/gnunet-nat-server.c402
1 files changed, 0 insertions, 402 deletions
diff --git a/src/nat-auto/gnunet-nat-server.c b/src/nat-auto/gnunet-nat-server.c
deleted file mode 100644
index e091ab3b0..000000000
--- a/src/nat-auto/gnunet-nat-server.c
+++ /dev/null
@@ -1,402 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 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/**
22 * @file src/nat/gnunet-nat-server.c
23 * @brief Daemon to run on 'gnunet.org' to help test NAT traversal code
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_nat_service.h"
29#include "gnunet_protocols.h"
30#include "nat-auto.h"
31
32
33/**
34 * Information we track per client.
35 */
36struct ClientData
37{
38 /**
39 * Timeout task.
40 */
41 struct GNUNET_SCHEDULER_Task *tt;
42
43 /**
44 * Client handle.
45 */
46 struct GNUNET_SERVICE_Client *client;
47};
48
49
50/**
51 * Our configuration.
52 */
53static const struct GNUNET_CONFIGURATION_Handle *cfg;
54
55
56/**
57 * Try contacting the peer using autonomous NAT traversal method.
58 *
59 * @param dst_ipv4 IPv4 address to send the fake ICMP message
60 * @param dport destination port to include in ICMP message
61 * @param is_tcp mark for TCP (#GNUNET_YES) or UDP (#GNUNET_NO)
62 */
63static void
64try_anat (uint32_t dst_ipv4,
65 uint16_t dport,
66 int is_tcp)
67{
68 struct GNUNET_NAT_Handle *h;
69 struct sockaddr_in lsa;
70 struct sockaddr_in rsa;
71 const struct sockaddr *sa;
72 socklen_t sa_len;
73
74 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
75 "Asking for connection reversal with %x and code %u\n",
76 (unsigned int) dst_ipv4,
77 (unsigned int) dport);
78 memset (&lsa, 0, sizeof(lsa));
79 lsa.sin_family = AF_INET;
80#if HAVE_SOCKADDR_IN_SIN_LEN
81 lsa.sin_len = sizeof(sa);
82#endif
83 lsa.sin_addr.s_addr = 0;
84 lsa.sin_port = htons (dport);
85 memset (&rsa, 0, sizeof(rsa));
86 rsa.sin_family = AF_INET;
87#if HAVE_SOCKADDR_IN_SIN_LEN
88 rsa.sin_len = sizeof(sa);
89#endif
90 rsa.sin_addr.s_addr = dst_ipv4;
91 rsa.sin_port = htons (dport);
92 sa_len = sizeof(lsa);
93 sa = (const struct sockaddr *) &lsa;
94 h = GNUNET_NAT_register (cfg,
95 "none",
96 is_tcp ? IPPROTO_TCP : IPPROTO_UDP,
97 1,
98 &sa,
99 &sa_len,
100 NULL, NULL, NULL);
101 GNUNET_NAT_request_reversal (h,
102 &lsa,
103 &rsa);
104 GNUNET_NAT_unregister (h);
105}
106
107
108/**
109 * Closure for #tcp_send.
110 */
111struct TcpContext
112{
113 /**
114 * TCP socket.
115 */
116 struct GNUNET_NETWORK_Handle *s;
117
118 /**
119 * Data to transmit.
120 */
121 uint16_t data;
122};
123
124
125/**
126 * Task called by the scheduler once we can do the TCP send
127 * (or once we failed to connect...).
128 *
129 * @param cls the `struct TcpContext`
130 */
131static void
132tcp_send (void *cls)
133{
134 struct TcpContext *ctx = cls;
135 const struct GNUNET_SCHEDULER_TaskContext *tc;
136
137 tc = GNUNET_SCHEDULER_get_task_context ();
138 if ((NULL != tc->write_ready) &&
139 (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
140 {
141 if (-1 ==
142 GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof(ctx->data)))
143 {
144 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
145 }
146 GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
147 }
148 GNUNET_NETWORK_socket_close (ctx->s);
149 GNUNET_free (ctx);
150}
151
152
153/**
154 * Try to send @a data to the
155 * IP @a dst_ipv4' at port @a dport via TCP.
156 *
157 * @param dst_ipv4 target IP
158 * @param dport target port
159 * @param data data to send
160 */
161static void
162try_send_tcp (uint32_t dst_ipv4,
163 uint16_t dport,
164 uint16_t data)
165{
166 struct GNUNET_NETWORK_Handle *s;
167 struct sockaddr_in sa;
168 struct TcpContext *ctx;
169
170 s = GNUNET_NETWORK_socket_create (AF_INET,
171 SOCK_STREAM,
172 0);
173 if (NULL == s)
174 {
175 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
176 "socket");
177 return;
178 }
179 memset (&sa, 0, sizeof(sa));
180 sa.sin_family = AF_INET;
181#if HAVE_SOCKADDR_IN_SIN_LEN
182 sa.sin_len = sizeof(sa);
183#endif
184 sa.sin_addr.s_addr = dst_ipv4;
185 sa.sin_port = htons (dport);
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "Sending TCP message to `%s'\n",
188 GNUNET_a2s ((struct sockaddr *) &sa,
189 sizeof(sa)));
190 if ((GNUNET_OK !=
191 GNUNET_NETWORK_socket_connect (s,
192 (const struct sockaddr *) &sa,
193 sizeof(sa))) &&
194 (errno != EINPROGRESS))
195 {
196 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
197 "connect");
198 GNUNET_NETWORK_socket_close (s);
199 return;
200 }
201 ctx = GNUNET_new (struct TcpContext);
202 ctx->s = s;
203 ctx->data = data;
204 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
205 s,
206 &tcp_send,
207 ctx);
208}
209
210
211/**
212 * Try to send @a data to the
213 * IP @a dst_ipv4 at port @a dport via UDP.
214 *
215 * @param dst_ipv4 target IP
216 * @param dport target port
217 * @param data data to send
218 */
219static void
220try_send_udp (uint32_t dst_ipv4,
221 uint16_t dport,
222 uint16_t data)
223{
224 struct GNUNET_NETWORK_Handle *s;
225 struct sockaddr_in sa;
226
227 s = GNUNET_NETWORK_socket_create (AF_INET,
228 SOCK_DGRAM,
229 0);
230 if (NULL == s)
231 {
232 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
233 "socket");
234 return;
235 }
236 memset (&sa, 0, sizeof(sa));
237 sa.sin_family = AF_INET;
238#if HAVE_SOCKADDR_IN_SIN_LEN
239 sa.sin_len = sizeof(sa);
240#endif
241 sa.sin_addr.s_addr = dst_ipv4;
242 sa.sin_port = htons (dport);
243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
244 "Sending UDP packet to `%s'\n",
245 GNUNET_a2s ((struct sockaddr *) &sa,
246 sizeof(sa)));
247 if (-1 ==
248 GNUNET_NETWORK_socket_sendto (s,
249 &data,
250 sizeof(data),
251 (const struct sockaddr *) &sa,
252 sizeof(sa)))
253 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
254 "sendto");
255 GNUNET_NETWORK_socket_close (s);
256}
257
258
259/**
260 * We've received a request to probe a NAT
261 * traversal. Do it.
262 *
263 * @param cls handle to client (we always close)
264 * @param msg message with details about what to test
265 */
266static void
267handle_test (void *cls,
268 const struct GNUNET_NAT_AUTO_TestMessage *tm)
269{
270 struct ClientData *cd = cls;
271 uint16_t dport;
272
273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
274 "Received test request\n");
275 dport = ntohs (tm->dport);
276 if (0 == dport)
277 try_anat (tm->dst_ipv4,
278 ntohs (tm->data),
279 (int) ntohl (tm->is_tcp));
280 else if (GNUNET_YES == ntohl (tm->is_tcp))
281 try_send_tcp (tm->dst_ipv4,
282 dport,
283 tm->data);
284 else
285 try_send_udp (tm->dst_ipv4,
286 dport,
287 tm->data);
288 GNUNET_SERVICE_client_drop (cd->client);
289}
290
291
292/**
293 * Main function that will be run.
294 *
295 * @param cls closure
296 * @param c configuration
297 * @param srv service handle
298 */
299static void
300run (void *cls,
301 const struct GNUNET_CONFIGURATION_Handle *c,
302 struct GNUNET_SERVICE_Handle *srv)
303{
304 cfg = c;
305}
306
307
308/**
309 * Forcefully drops client after 1s.
310 *
311 * @param cls our `struct ClientData` of a client to drop
312 */
313static void
314force_timeout (void *cls)
315{
316 struct ClientData *cd = cls;
317
318 cd->tt = NULL;
319 GNUNET_SERVICE_client_drop (cd->client);
320}
321
322
323/**
324 * Callback called when a client connects to the service.
325 *
326 * @param cls closure for the service
327 * @param c the new client that connected to the service
328 * @param mq the message queue used to send messages to the client
329 * @return our `struct ClientData`
330 */
331static void *
332client_connect_cb (void *cls,
333 struct GNUNET_SERVICE_Client *c,
334 struct GNUNET_MQ_Handle *mq)
335{
336 struct ClientData *cd;
337
338 cd = GNUNET_new (struct ClientData);
339 cd->client = c;
340 cd->tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
341 &force_timeout,
342 cd);
343 return cd;
344}
345
346
347/**
348 * Callback called when a client disconnected from the service
349 *
350 * @param cls closure for the service
351 * @param c the client that disconnected
352 * @param internal_cls our `struct ClientData`
353 */
354static void
355client_disconnect_cb (void *cls,
356 struct GNUNET_SERVICE_Client *c,
357 void *internal_cls)
358{
359 struct ClientData *cd = internal_cls;
360
361 if (NULL != cd->tt)
362 GNUNET_SCHEDULER_cancel (cd->tt);
363 GNUNET_free (cd);
364}
365
366
367/**
368 * Define "main" method using service macro.
369 */
370GNUNET_SERVICE_MAIN
371 ("nat-server",
372 GNUNET_SERVICE_OPTION_NONE,
373 &run,
374 &client_connect_cb,
375 &client_disconnect_cb,
376 NULL,
377 GNUNET_MQ_hd_fixed_size (test,
378 GNUNET_MESSAGE_TYPE_NAT_TEST,
379 struct GNUNET_NAT_AUTO_TestMessage,
380 NULL),
381 GNUNET_MQ_handler_end ());
382
383
384#if defined(__linux__) && defined(__GLIBC__)
385#include <malloc.h>
386
387/**
388 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
389 */
390void __attribute__ ((constructor))
391GNUNET_ARM_memory_init ()
392{
393 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
394 mallopt (M_TOP_PAD, 1 * 1024);
395 malloc_trim (0);
396}
397
398
399#endif
400
401
402/* end of gnunet-nat-server.c */