2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
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
27 #include "gnunet_util_lib.h"
28 #include "gnunet_nat_lib.h"
29 #include "gnunet_protocols.h"
36 static struct GNUNET_SERVER_Handle *server;
41 static const struct GNUNET_CONFIGURATION_Handle *cfg;
45 * Try contacting the peer using autonomous
46 * NAT traveral method.
48 * @param dst_ipv4 IPv4 address to send the fake ICMP message
49 * @param dport destination port to include in ICMP message
50 * @param is_tcp mark for TCP (#GNUNET_YES) or UDP (#GNUNET_NO)
53 try_anat (uint32_t dst_ipv4,
57 struct GNUNET_NAT_Handle *h;
58 struct sockaddr_in sa;
60 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
61 "Asking for connection reversal with %x and code %u\n",
62 (unsigned int) dst_ipv4,
63 (unsigned int) dport);
64 h = GNUNET_NAT_register (cfg,
68 NULL, NULL, NULL, NULL, NULL, NULL);
69 memset (&sa, 0, sizeof (sa));
70 sa.sin_family = AF_INET;
71 #if HAVE_SOCKADDR_IN_SIN_LEN
72 sa.sin_len = sizeof (sa);
74 sa.sin_addr.s_addr = dst_ipv4;
75 GNUNET_NAT_run_client (h, &sa);
76 GNUNET_NAT_unregister (h);
81 * Closure for 'tcp_send'.
88 struct GNUNET_NETWORK_Handle *s;
98 * Task called by the scheduler once we can do the TCP send
99 * (or once we failed to connect...).
101 * @param cls the 'struct TcpContext'
106 struct TcpContext *ctx = cls;
107 const struct GNUNET_SCHEDULER_TaskContext *tc;
109 tc = GNUNET_SCHEDULER_get_task_context ();
110 if ((NULL != tc->write_ready) &&
111 (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
114 GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
116 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
118 GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
120 GNUNET_NETWORK_socket_close (ctx->s);
126 * Try to send @a data to the
127 * IP @a dst_ipv4' at port @a dport via TCP.
129 * @param dst_ipv4 target IP
130 * @param dport target port
131 * @param data data to send
134 try_send_tcp (uint32_t dst_ipv4,
138 struct GNUNET_NETWORK_Handle *s;
139 struct sockaddr_in sa;
140 struct TcpContext *ctx;
142 s = GNUNET_NETWORK_socket_create (AF_INET,
147 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
151 memset (&sa, 0, sizeof (sa));
152 sa.sin_family = AF_INET;
153 #if HAVE_SOCKADDR_IN_SIN_LEN
154 sa.sin_len = sizeof (sa);
156 sa.sin_addr.s_addr = dst_ipv4;
157 sa.sin_port = htons (dport);
158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
159 "Sending TCP message to `%s'\n",
160 GNUNET_a2s ((struct sockaddr *) &sa,
163 GNUNET_NETWORK_socket_connect (s,
164 (const struct sockaddr *) &sa,
166 (errno != EINPROGRESS) )
168 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
170 GNUNET_NETWORK_socket_close (s);
173 ctx = GNUNET_new (struct TcpContext);
176 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
184 * Try to send @a data to the
185 * IP @a dst_ipv4' at port @a dport via UDP.
187 * @param dst_ipv4 target IP
188 * @param dport target port
189 * @param data data to send
192 try_send_udp (uint32_t dst_ipv4,
196 struct GNUNET_NETWORK_Handle *s;
197 struct sockaddr_in sa;
199 s = GNUNET_NETWORK_socket_create (AF_INET,
204 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
208 memset (&sa, 0, sizeof (sa));
209 sa.sin_family = AF_INET;
210 #if HAVE_SOCKADDR_IN_SIN_LEN
211 sa.sin_len = sizeof (sa);
213 sa.sin_addr.s_addr = dst_ipv4;
214 sa.sin_port = htons (dport);
215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
216 "Sending UDP packet to `%s'\n",
217 GNUNET_a2s ((struct sockaddr *) &sa,
220 GNUNET_NETWORK_socket_sendto (s,
223 (const struct sockaddr *) &sa,
225 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
227 GNUNET_NETWORK_socket_close (s);
232 * We've received a request to probe a NAT
236 * @param client handle to client (we always close)
237 * @param msg message with details about what to test
241 struct GNUNET_SERVER_Client *client,
242 const struct GNUNET_MessageHeader *msg)
244 const struct GNUNET_NAT_TestMessage *tm;
247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
248 "Received test request\n");
249 tm = (const struct GNUNET_NAT_TestMessage *) msg;
250 dport = ntohs (tm->dport);
252 try_anat (tm->dst_ipv4,
254 (int) ntohl (tm->is_tcp));
255 else if (GNUNET_YES == ntohl (tm->is_tcp))
256 try_send_tcp (tm->dst_ipv4,
260 try_send_udp (tm->dst_ipv4,
263 GNUNET_SERVER_receive_done (client,
269 * Task run during shutdown.
274 shutdown_task (void *cls)
276 GNUNET_SERVER_destroy (server);
282 * Main function that will be run.
285 * @param args remaining command-line arguments
286 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
287 * @param c configuration
293 const struct GNUNET_CONFIGURATION_Handle *c)
295 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
296 {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST,
297 sizeof (struct GNUNET_NAT_TestMessage)},
301 struct sockaddr_in in4;
302 struct sockaddr_in6 in6;
309 struct sockaddr *sa[] = {
310 (struct sockaddr *) &in4,
311 (struct sockaddr *) &in6,
316 if ((args[0] == NULL) || (1 != SSCANF (args[0], "%u", &port)) || (0 == port)
321 ("Please pass valid port number as the first argument! (got `%s')\n"),
325 memset (&in4, 0, sizeof (in4));
326 memset (&in6, 0, sizeof (in6));
327 in4.sin_family = AF_INET;
328 in4.sin_port = htons ((uint16_t) port);
329 in6.sin6_family = AF_INET6;
330 in6.sin6_port = htons ((uint16_t) port);
331 #if HAVE_SOCKADDR_IN_SIN_LEN
332 in4.sin_len = sizeof (in4);
333 in6.sin6_len = sizeof (in6);
336 GNUNET_SERVER_create (NULL, NULL, (struct sockaddr * const *) sa, slen,
337 GNUNET_TIME_UNIT_SECONDS, GNUNET_YES);
338 GNUNET_SERVER_add_handlers (server, handlers);
339 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
345 * Main function of gnunet-nat-server.
347 * @param argc number of command-line arguments
348 * @param argv command line
349 * @return 0 on success, -1 on error
352 main (int argc, char *const argv[])
354 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
355 GNUNET_GETOPT_OPTION_END
358 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
362 GNUNET_PROGRAM_run (argc, argv, "gnunet-nat-server [options] PORT",
363 _("GNUnet NAT traversal test helper daemon"), options,
366 GNUNET_free ((void*) argv);
369 GNUNET_free ((void*) argv);
374 /* end of gnunet-nat-server.c */