aboutsummaryrefslogtreecommitdiff
path: root/src/cli/nat-auto
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/nat-auto')
-rw-r--r--src/cli/nat-auto/.gitignore2
-rw-r--r--src/cli/nat-auto/Makefile.am26
-rw-r--r--src/cli/nat-auto/gnunet-nat-auto.c367
-rw-r--r--src/cli/nat-auto/gnunet-nat-server.c403
-rw-r--r--src/cli/nat-auto/meson.build14
5 files changed, 812 insertions, 0 deletions
diff --git a/src/cli/nat-auto/.gitignore b/src/cli/nat-auto/.gitignore
new file mode 100644
index 000000000..c750bf612
--- /dev/null
+++ b/src/cli/nat-auto/.gitignore
@@ -0,0 +1,2 @@
1gnunet-nat-auto
2gnunet-nat-server
diff --git a/src/cli/nat-auto/Makefile.am b/src/cli/nat-auto/Makefile.am
new file mode 100644
index 000000000..4b2d74280
--- /dev/null
+++ b/src/cli/nat-auto/Makefile.am
@@ -0,0 +1,26 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4libexecdir= $(pkglibdir)/libexec/
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8bin_PROGRAMS = \
9 gnunet-nat-auto \
10 gnunet-nat-server
11
12gnunet_nat_server_SOURCES = \
13 gnunet-nat-server.c
14gnunet_nat_server_LDADD = \
15 $(top_builddir)/src/service/nat/libgnunetnatnew.la \
16 $(top_builddir)/src/lib/util/libgnunetutil.la
17gnunet_nat_server_LDFLAGS = \
18 $(GN_LIBINTL)
19
20gnunet_nat_auto_SOURCES = \
21 gnunet-nat-auto.c
22gnunet_nat_auto_LDADD = \
23 $(top_builddir)/src/service/nat-auto/libgnunetnatauto.la \
24 $(top_builddir)/src/lib/util/libgnunetutil.la
25gnunet_nat_auto_LDFLAGS = \
26 $(GN_LIBINTL)
diff --git a/src/cli/nat-auto/gnunet-nat-auto.c b/src/cli/nat-auto/gnunet-nat-auto.c
new file mode 100644
index 000000000..055a949bd
--- /dev/null
+++ b/src/cli/nat-auto/gnunet-nat-auto.c
@@ -0,0 +1,367 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2015, 2016, 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-auto.c
23 * @brief Command-line tool for testing and autoconfiguration of NAT traversal
24 * @author Christian Grothoff
25 * @author Bruno Cabral
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_nat_service.h"
30#include "gnunet_nat_auto_service.h"
31
32/**
33 * Value to return from #main().
34 */
35static int global_ret;
36
37/**
38 * Handle to ongoing autoconfiguration.
39 */
40static struct GNUNET_NAT_AUTO_AutoHandle *ah;
41
42/**
43 * If we do auto-configuration, should we write the result
44 * to a file?
45 */
46static int write_cfg;
47
48/**
49 * Configuration filename.
50 */
51static const char *cfg_file;
52
53/**
54 * Original configuration.
55 */
56static const struct GNUNET_CONFIGURATION_Handle *cfg;
57
58/**
59 * Adapter we are supposed to test.
60 */
61static char *section_name;
62
63/**
64 * Should we run autoconfiguration?
65 */
66static int do_auto;
67
68/**
69 * Handle to a NAT test operation.
70 */
71static struct GNUNET_NAT_AUTO_Test *nt;
72
73/**
74 * Flag set to 1 if we use IPPROTO_UDP.
75 */
76static int use_udp;
77
78/**
79 * Flag set to 1 if we use IPPROTO_TCP.
80 */
81static int use_tcp;
82
83/**
84 * Protocol to use.
85 */
86static uint8_t proto;
87
88/**
89 * Test if all activities have finished, and if so,
90 * terminate.
91 */
92static void
93test_finished ()
94{
95 if (NULL != ah)
96 return;
97 if (NULL != nt)
98 return;
99 GNUNET_SCHEDULER_shutdown ();
100}
101
102
103/**
104 * Function to iterate over suggested changes options
105 *
106 * @param cls closure
107 * @param section name of the section
108 * @param option name of the option
109 * @param value value of the option
110 */
111static void
112auto_conf_iter (void *cls,
113 const char *section,
114 const char *option,
115 const char *value)
116{
117 struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
118
119 printf ("%s: %s\n", option, value);
120 if (NULL != new_cfg)
121 GNUNET_CONFIGURATION_set_value_string (new_cfg, section, option, value);
122}
123
124
125/**
126 * Function called with the result from the autoconfiguration.
127 *
128 * @param cls closure
129 * @param diff minimal suggested changes to the original configuration
130 * to make it work (as best as we can)
131 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
132 * @param type what the situation of the NAT
133 */
134static void
135auto_config_cb (void *cls,
136 const struct GNUNET_CONFIGURATION_Handle *diff,
137 enum GNUNET_NAT_StatusCode result,
138 enum GNUNET_NAT_Type type)
139{
140 const char *nat_type;
141 char unknown_type[64];
142 struct GNUNET_CONFIGURATION_Handle *new_cfg;
143
144 ah = NULL;
145 switch (type)
146 {
147 case GNUNET_NAT_TYPE_NO_NAT:
148 nat_type = "NO NAT";
149 break;
150
151 case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
152 nat_type = "NAT but we can traverse";
153 break;
154
155 case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
156 nat_type = "NAT but STUN is able to identify the correct information";
157 break;
158
159 case GNUNET_NAT_TYPE_UPNP_NAT:
160 nat_type = "NAT but UPNP opened the ports";
161 break;
162
163 default:
164 sprintf (unknown_type, "NAT unknown, type %u", type);
165 nat_type = unknown_type;
166 break;
167 }
168
169 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
170 "NAT status: %s/%s\n",
171 GNUNET_NAT_AUTO_status2string (result),
172 nat_type);
173
174 if (NULL == diff)
175 return;
176
177 /* Shortcut: if there are no changes suggested, bail out early. */
178 if (GNUNET_NO == GNUNET_CONFIGURATION_is_dirty (diff))
179 {
180 test_finished ();
181 return;
182 }
183
184 /* Apply diff to original configuration and show changes
185 to the user */
186 new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
187
188 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
189 _ ("Suggested configuration changes:\n"));
190 GNUNET_CONFIGURATION_iterate_section_values (diff,
191 "nat",
192 &auto_conf_iter,
193 new_cfg);
194
195 /* If desired, write configuration to file; we write only the
196 changes to the defaults to keep things compact. */
197 if (write_cfg)
198 {
199 struct GNUNET_CONFIGURATION_Handle *def_cfg;
200
201 GNUNET_CONFIGURATION_set_value_string (new_cfg, "ARM", "CONFIG", NULL);
202 def_cfg = GNUNET_CONFIGURATION_create ();
203 GNUNET_break (GNUNET_OK == GNUNET_CONFIGURATION_load (def_cfg, NULL));
204 if (GNUNET_OK !=
205 GNUNET_CONFIGURATION_write_diffs (def_cfg, new_cfg, cfg_file))
206 {
207 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
208 _ ("Failed to write configuration to `%s'\n"),
209 cfg_file);
210 global_ret = 1;
211 }
212 else
213 {
214 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
215 _ ("Wrote updated configuration to `%s'\n"),
216 cfg_file);
217 }
218 GNUNET_CONFIGURATION_destroy (def_cfg);
219 }
220
221 if (NULL != new_cfg)
222 GNUNET_CONFIGURATION_destroy (new_cfg);
223 test_finished ();
224}
225
226
227/**
228 * Function called to report success or failure for
229 * NAT configuration test.
230 *
231 * @param cls closure
232 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
233 */
234static void
235test_report_cb (void *cls, enum GNUNET_NAT_StatusCode result)
236{
237 nt = NULL;
238 printf ("NAT test result: %s\n", GNUNET_NAT_AUTO_status2string (result));
239 test_finished ();
240}
241
242
243/**
244 * Task run on shutdown.
245 *
246 * @param cls NULL
247 */
248static void
249do_shutdown (void *cls)
250{
251 if (NULL != ah)
252 {
253 GNUNET_NAT_AUTO_autoconfig_cancel (ah);
254 ah = NULL;
255 }
256 if (NULL != nt)
257 {
258 GNUNET_NAT_AUTO_test_stop (nt);
259 nt = NULL;
260 }
261}
262
263
264/**
265 * Main function that will be run.
266 *
267 * @param cls closure
268 * @param args remaining command-line arguments
269 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
270 * @param c configuration
271 */
272static void
273run (void *cls,
274 char *const *args,
275 const char *cfgfile,
276 const struct GNUNET_CONFIGURATION_Handle *c)
277{
278 cfg_file = cfgfile;
279 cfg = c;
280
281 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
282
283 if (do_auto)
284 {
285 ah = GNUNET_NAT_AUTO_autoconfig_start (c, &auto_config_cb, NULL);
286 }
287
288 if (use_tcp && use_udp)
289 {
290 if (do_auto)
291 return;
292 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Cannot use TCP and UDP\n");
293 global_ret = 1;
294 return;
295 }
296 proto = 0;
297 if (use_tcp)
298 proto = IPPROTO_TCP;
299 if (use_udp)
300 proto = IPPROTO_UDP;
301
302 if (NULL != section_name)
303 {
304 nt = GNUNET_NAT_AUTO_test_start (c,
305 proto,
306 section_name,
307 &test_report_cb,
308 NULL);
309 }
310 test_finished ();
311}
312
313
314/**
315 * Main function of gnunet-nat-auto
316 *
317 * @param argc number of command-line arguments
318 * @param argv command line
319 * @return 0 on success, -1 on error
320 */
321int
322main (int argc, char *const argv[])
323{
324 struct GNUNET_GETOPT_CommandLineOption options[] =
325 { GNUNET_GETOPT_option_flag ('a',
326 "auto",
327 gettext_noop ("run autoconfiguration"),
328 &do_auto),
329
330 GNUNET_GETOPT_option_string (
331 'S',
332 "section",
333 "NAME",
334 gettext_noop (
335 "section name providing the configuration for the adapter"),
336 &section_name),
337
338 GNUNET_GETOPT_option_flag ('t', "tcp", gettext_noop ("use TCP"), &use_tcp),
339
340 GNUNET_GETOPT_option_flag ('u', "udp", gettext_noop ("use UDP"), &use_udp),
341
342 GNUNET_GETOPT_option_flag (
343 'w',
344 "write",
345 gettext_noop ("write configuration file (for autoconfiguration)"),
346 &write_cfg),
347 GNUNET_GETOPT_OPTION_END };
348
349 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
350 return 2;
351 if (GNUNET_OK !=
352 GNUNET_PROGRAM_run (argc,
353 argv,
354 "gnunet-nat-auto [options]",
355 _ ("GNUnet NAT traversal autoconfiguration"),
356 options,
357 &run,
358 NULL))
359 {
360 global_ret = 1;
361 }
362 GNUNET_free_nz ((void *) argv);
363 return global_ret;
364}
365
366
367/* end of gnunet-nat-auto.c */
diff --git a/src/cli/nat-auto/gnunet-nat-server.c b/src/cli/nat-auto/gnunet-nat-server.c
new file mode 100644
index 000000000..baa610e8f
--- /dev/null
+++ b/src/cli/nat-auto/gnunet-nat-server.c
@@ -0,0 +1,403 @@
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// FIXME can we build this without this header?
31#include "../../service/nat-auto/nat-auto.h"
32
33
34/**
35 * Information we track per client.
36 */
37struct ClientData
38{
39 /**
40 * Timeout task.
41 */
42 struct GNUNET_SCHEDULER_Task *tt;
43
44 /**
45 * Client handle.
46 */
47 struct GNUNET_SERVICE_Client *client;
48};
49
50
51/**
52 * Our configuration.
53 */
54static const struct GNUNET_CONFIGURATION_Handle *cfg;
55
56
57/**
58 * Try contacting the peer using autonomous NAT traversal method.
59 *
60 * @param dst_ipv4 IPv4 address to send the fake ICMP message
61 * @param dport destination port to include in ICMP message
62 * @param is_tcp mark for TCP (#GNUNET_YES) or UDP (#GNUNET_NO)
63 */
64static void
65try_anat (uint32_t dst_ipv4,
66 uint16_t dport,
67 int is_tcp)
68{
69 struct GNUNET_NAT_Handle *h;
70 struct sockaddr_in lsa;
71 struct sockaddr_in rsa;
72 const struct sockaddr *sa;
73 socklen_t sa_len;
74
75 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
76 "Asking for connection reversal with %x and code %u\n",
77 (unsigned int) dst_ipv4,
78 (unsigned int) dport);
79 memset (&lsa, 0, sizeof(lsa));
80 lsa.sin_family = AF_INET;
81#if HAVE_SOCKADDR_IN_SIN_LEN
82 lsa.sin_len = sizeof(sa);
83#endif
84 lsa.sin_addr.s_addr = 0;
85 lsa.sin_port = htons (dport);
86 memset (&rsa, 0, sizeof(rsa));
87 rsa.sin_family = AF_INET;
88#if HAVE_SOCKADDR_IN_SIN_LEN
89 rsa.sin_len = sizeof(sa);
90#endif
91 rsa.sin_addr.s_addr = dst_ipv4;
92 rsa.sin_port = htons (dport);
93 sa_len = sizeof(lsa);
94 sa = (const struct sockaddr *) &lsa;
95 h = GNUNET_NAT_register (cfg,
96 "none",
97 is_tcp ? IPPROTO_TCP : IPPROTO_UDP,
98 1,
99 &sa,
100 &sa_len,
101 NULL, NULL, NULL);
102 GNUNET_NAT_request_reversal (h,
103 &lsa,
104 &rsa);
105 GNUNET_NAT_unregister (h);
106}
107
108
109/**
110 * Closure for #tcp_send.
111 */
112struct TcpContext
113{
114 /**
115 * TCP socket.
116 */
117 struct GNUNET_NETWORK_Handle *s;
118
119 /**
120 * Data to transmit.
121 */
122 uint16_t data;
123};
124
125
126/**
127 * Task called by the scheduler once we can do the TCP send
128 * (or once we failed to connect...).
129 *
130 * @param cls the `struct TcpContext`
131 */
132static void
133tcp_send (void *cls)
134{
135 struct TcpContext *ctx = cls;
136 const struct GNUNET_SCHEDULER_TaskContext *tc;
137
138 tc = GNUNET_SCHEDULER_get_task_context ();
139 if ((NULL != tc->write_ready) &&
140 (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
141 {
142 if (-1 ==
143 GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof(ctx->data)))
144 {
145 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
146 }
147 GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
148 }
149 GNUNET_NETWORK_socket_close (ctx->s);
150 GNUNET_free (ctx);
151}
152
153
154/**
155 * Try to send @a data to the
156 * IP @a dst_ipv4' at port @a dport via TCP.
157 *
158 * @param dst_ipv4 target IP
159 * @param dport target port
160 * @param data data to send
161 */
162static void
163try_send_tcp (uint32_t dst_ipv4,
164 uint16_t dport,
165 uint16_t data)
166{
167 struct GNUNET_NETWORK_Handle *s;
168 struct sockaddr_in sa;
169 struct TcpContext *ctx;
170
171 s = GNUNET_NETWORK_socket_create (AF_INET,
172 SOCK_STREAM,
173 0);
174 if (NULL == s)
175 {
176 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
177 "socket");
178 return;
179 }
180 memset (&sa, 0, sizeof(sa));
181 sa.sin_family = AF_INET;
182#if HAVE_SOCKADDR_IN_SIN_LEN
183 sa.sin_len = sizeof(sa);
184#endif
185 sa.sin_addr.s_addr = dst_ipv4;
186 sa.sin_port = htons (dport);
187 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
188 "Sending TCP message to `%s'\n",
189 GNUNET_a2s ((struct sockaddr *) &sa,
190 sizeof(sa)));
191 if ((GNUNET_OK !=
192 GNUNET_NETWORK_socket_connect (s,
193 (const struct sockaddr *) &sa,
194 sizeof(sa))) &&
195 (errno != EINPROGRESS))
196 {
197 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
198 "connect");
199 GNUNET_NETWORK_socket_close (s);
200 return;
201 }
202 ctx = GNUNET_new (struct TcpContext);
203 ctx->s = s;
204 ctx->data = data;
205 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
206 s,
207 &tcp_send,
208 ctx);
209}
210
211
212/**
213 * Try to send @a data to the
214 * IP @a dst_ipv4 at port @a dport via UDP.
215 *
216 * @param dst_ipv4 target IP
217 * @param dport target port
218 * @param data data to send
219 */
220static void
221try_send_udp (uint32_t dst_ipv4,
222 uint16_t dport,
223 uint16_t data)
224{
225 struct GNUNET_NETWORK_Handle *s;
226 struct sockaddr_in sa;
227
228 s = GNUNET_NETWORK_socket_create (AF_INET,
229 SOCK_DGRAM,
230 0);
231 if (NULL == s)
232 {
233 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
234 "socket");
235 return;
236 }
237 memset (&sa, 0, sizeof(sa));
238 sa.sin_family = AF_INET;
239#if HAVE_SOCKADDR_IN_SIN_LEN
240 sa.sin_len = sizeof(sa);
241#endif
242 sa.sin_addr.s_addr = dst_ipv4;
243 sa.sin_port = htons (dport);
244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
245 "Sending UDP packet to `%s'\n",
246 GNUNET_a2s ((struct sockaddr *) &sa,
247 sizeof(sa)));
248 if (-1 ==
249 GNUNET_NETWORK_socket_sendto (s,
250 &data,
251 sizeof(data),
252 (const struct sockaddr *) &sa,
253 sizeof(sa)))
254 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
255 "sendto");
256 GNUNET_NETWORK_socket_close (s);
257}
258
259
260/**
261 * We've received a request to probe a NAT
262 * traversal. Do it.
263 *
264 * @param cls handle to client (we always close)
265 * @param tm message with details about what to test
266 */
267static void
268handle_test (void *cls,
269 const struct GNUNET_NAT_AUTO_TestMessage *tm)
270{
271 struct ClientData *cd = cls;
272 uint16_t dport;
273
274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
275 "Received test request\n");
276 dport = ntohs (tm->dport);
277 if (0 == dport)
278 try_anat (tm->dst_ipv4,
279 ntohs (tm->data),
280 (int) ntohl (tm->is_tcp));
281 else if (GNUNET_YES == ntohl (tm->is_tcp))
282 try_send_tcp (tm->dst_ipv4,
283 dport,
284 tm->data);
285 else
286 try_send_udp (tm->dst_ipv4,
287 dport,
288 tm->data);
289 GNUNET_SERVICE_client_drop (cd->client);
290}
291
292
293/**
294 * Main function that will be run.
295 *
296 * @param cls closure
297 * @param c configuration
298 * @param srv service handle
299 */
300static void
301run (void *cls,
302 const struct GNUNET_CONFIGURATION_Handle *c,
303 struct GNUNET_SERVICE_Handle *srv)
304{
305 cfg = c;
306}
307
308
309/**
310 * Forcefully drops client after 1s.
311 *
312 * @param cls our `struct ClientData` of a client to drop
313 */
314static void
315force_timeout (void *cls)
316{
317 struct ClientData *cd = cls;
318
319 cd->tt = NULL;
320 GNUNET_SERVICE_client_drop (cd->client);
321}
322
323
324/**
325 * Callback called when a client connects to the service.
326 *
327 * @param cls closure for the service
328 * @param c the new client that connected to the service
329 * @param mq the message queue used to send messages to the client
330 * @return our `struct ClientData`
331 */
332static void *
333client_connect_cb (void *cls,
334 struct GNUNET_SERVICE_Client *c,
335 struct GNUNET_MQ_Handle *mq)
336{
337 struct ClientData *cd;
338
339 cd = GNUNET_new (struct ClientData);
340 cd->client = c;
341 cd->tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
342 &force_timeout,
343 cd);
344 return cd;
345}
346
347
348/**
349 * Callback called when a client disconnected from the service
350 *
351 * @param cls closure for the service
352 * @param c the client that disconnected
353 * @param internal_cls our `struct ClientData`
354 */
355static void
356client_disconnect_cb (void *cls,
357 struct GNUNET_SERVICE_Client *c,
358 void *internal_cls)
359{
360 struct ClientData *cd = internal_cls;
361
362 if (NULL != cd->tt)
363 GNUNET_SCHEDULER_cancel (cd->tt);
364 GNUNET_free (cd);
365}
366
367
368/**
369 * Define "main" method using service macro.
370 */
371GNUNET_SERVICE_MAIN
372 ("nat-server",
373 GNUNET_SERVICE_OPTION_NONE,
374 &run,
375 &client_connect_cb,
376 &client_disconnect_cb,
377 NULL,
378 GNUNET_MQ_hd_fixed_size (test,
379 GNUNET_MESSAGE_TYPE_NAT_TEST,
380 struct GNUNET_NAT_AUTO_TestMessage,
381 NULL),
382 GNUNET_MQ_handler_end ());
383
384
385#if defined(__linux__) && defined(__GLIBC__)
386#include <malloc.h>
387
388/**
389 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
390 */
391void __attribute__ ((constructor))
392GNUNET_ARM_memory_init ()
393{
394 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
395 mallopt (M_TOP_PAD, 1 * 1024);
396 malloc_trim (0);
397}
398
399
400#endif
401
402
403/* end of gnunet-nat-server.c */
diff --git a/src/cli/nat-auto/meson.build b/src/cli/nat-auto/meson.build
new file mode 100644
index 000000000..69e719126
--- /dev/null
+++ b/src/cli/nat-auto/meson.build
@@ -0,0 +1,14 @@
1executable ('gnunet-nat-auto',
2 ['gnunet-nat-auto.c'],
3 dependencies: [libgnunetnatauto_dep, libgnunetutil_dep,
4 libgnunetnat_dep],
5 include_directories: [incdir, configuration_inc],
6 install: true,
7 install_dir: get_option('bindir'))
8executable ('gnunet-nat-server',
9 ['gnunet-nat-server.c'],
10 dependencies: [libgnunetnatauto_dep, libgnunetutil_dep, libgnunetnat_dep],
11 include_directories: [incdir, configuration_inc],
12 install: true,
13 install_dir: get_option('bindir'))
14