aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-07-01 10:25:59 +0000
committerChristian Grothoff <christian@grothoff.org>2011-07-01 10:25:59 +0000
commit46ac0cea02fe1949d76b86c7a0750f9e7854fef6 (patch)
tree0aaa8d57f22e97710e540418a7a8ec29af01e653
parentf63b18531134a0385ded2cfb9a8f461a027b4130 (diff)
downloadgnunet-46ac0cea02fe1949d76b86c7a0750f9e7854fef6.tar.gz
gnunet-46ac0cea02fe1949d76b86c7a0750f9e7854fef6.zip
finishing gnunet-nat-server
-rw-r--r--doc/man/Makefile.am1
-rw-r--r--doc/man/gnunet-arm.12
-rw-r--r--src/include/gnunet_protocols.h5
-rw-r--r--src/nat/Makefile.am5
-rw-r--r--src/nat/gnunet-nat-server.c275
-rw-r--r--src/nat/nat.c8
-rw-r--r--src/nat/nat.h63
-rw-r--r--src/util/network.c1
8 files changed, 347 insertions, 13 deletions
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 4fda5b75c..20575204f 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -2,6 +2,7 @@ man_MANS = \
2 gnunet-arm.1 \ 2 gnunet-arm.1 \
3 gnunet-directory.1 \ 3 gnunet-directory.1 \
4 gnunet-download.1 \ 4 gnunet-download.1 \
5 gnunet-nat-server.1 \
5 gnunet-peerinfo.1 \ 6 gnunet-peerinfo.1 \
6 gnunet-pseudonym.1 \ 7 gnunet-pseudonym.1 \
7 gnunet-publish.1 \ 8 gnunet-publish.1 \
diff --git a/doc/man/gnunet-arm.1 b/doc/man/gnunet-arm.1
index e440479c3..30e0082ef 100644
--- a/doc/man/gnunet-arm.1
+++ b/doc/man/gnunet-arm.1
@@ -4,7 +4,7 @@
4gnunet\-arm \- control GNUnet services 4gnunet\-arm \- control GNUnet services
5 5
6.SH SYNOPSIS 6.SH SYNOPSIS
7.B gnunet-arm 7.B gnunet\-arm
8.RI [ options ] 8.RI [ options ]
9.br 9.br
10 10
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 000b71f3b..957bcd0eb 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -309,6 +309,11 @@ extern "C"
309#define GNUNET_MESSAGE_TYPE_TRANSPORT_ATS 61 309#define GNUNET_MESSAGE_TYPE_TRANSPORT_ATS 61
310 310
311/** 311/**
312 * Message to ask NAT server to perform traversal test
313 */
314#define GNUNET_MESSAGE_TYPE_NAT_TEST 63
315
316/**
312 * Initial setup message from core client to core. 317 * Initial setup message from core client to core.
313 */ 318 */
314#define GNUNET_MESSAGE_TYPE_CORE_INIT 64 319#define GNUNET_MESSAGE_TYPE_CORE_INIT 64
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index e8dadb240..75798a252 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -23,9 +23,10 @@ bin_PROGRAMS = \
23 $(NATBIN) 23 $(NATBIN)
24 24
25gnunet_nat_server_SOURCES = \ 25gnunet_nat_server_SOURCES = \
26 gnunet-nat-server.c 26 gnunet-nat-server.c nat.h
27gnunet_nat_server_LDADD = \ 27gnunet_nat_server_LDADD = \
28 $(top_builddir)/src/util/libgnunetutil.la 28 $(top_builddir)/src/nat/libgnunetnat.la \
29 $(top_builddir)/src/util/libgnunetutil.la
29 30
30gnunet_helper_nat_server_SOURCES = \ 31gnunet_helper_nat_server_SOURCES = \
31 $(NATSERVER) 32 $(NATSERVER)
diff --git a/src/nat/gnunet-nat-server.c b/src/nat/gnunet-nat-server.c
index c1f1be668..ae831db08 100644
--- a/src/nat/gnunet-nat-server.c
+++ b/src/nat/gnunet-nat-server.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors) 3 (C) 2011 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -26,11 +26,220 @@
26 */ 26 */
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29#include "gnunet_nat_lib.h"
30#include "gnunet_protocols.h"
31#include "nat.h"
29 32
30/** 33/**
31 * Should we print some debug output? 34 * Our server.
32 */ 35 */
33#define VERBOSE 0 36static struct GNUNET_SERVER_Handle *server;
37
38/**
39 * Our configuration.
40 */
41static const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43/**
44 * Try contacting the peer using autonomous
45 * NAT traveral method.
46 *
47 * @param dst_ipv4 IPv4 address to send the fake ICMP message
48 * @param dport destination port to include in ICMP message
49 * @param is_tcp mark for TCP (GNUNET_YES) or UDP (GNUNET_NO)
50 */
51static void
52try_anat (uint32_t dst_ipv4,
53 uint16_t dport,
54 int is_tcp)
55{
56 struct GNUNET_NAT_Handle *h;
57 struct sockaddr_in sa;
58
59 h = GNUNET_NAT_register (cfg,
60 is_tcp,
61 dport,
62 0, NULL, NULL,
63 NULL, NULL, NULL);
64 memset (&sa, 0, sizeof (sa));
65#if HAVE_SOCKADDR_IN_SIN_LEN
66 sa.sin_len = sizeof (sa);
67#endif
68 sa.sin_addr.s_addr = dst_ipv4;
69 GNUNET_NAT_run_client (h, &sa);
70 GNUNET_NAT_unregister (h);
71}
72
73
74/**
75 * Closure for 'tcp_send'.
76 */
77struct TcpContext
78{
79 /**
80 * TCP socket.
81 */
82 struct GNUNET_NETWORK_Handle *s;
83
84 /**
85 * Data to transmit.
86 */
87 uint16_t data;
88};
89
90
91/**
92 * Task called by the scheduler once we can do the TCP send
93 * (or once we failed to connect...).
94 *
95 * @param ctx the 'struct TcpContext'
96 * @param tc scheduler context
97 */
98static void
99tcp_send (void *cls,
100 const struct GNUNET_SCHEDULER_TaskContext *tc)
101{
102 struct TcpContext *ctx = cls;
103
104 if ( (NULL != tc->write_ready) &&
105 (GNUNET_NETWORK_fdset_isset (tc->write_ready,
106 ctx->s)) )
107 {
108 if (-1 == GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
109 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
110 GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
111 }
112 GNUNET_NETWORK_socket_close (ctx->s);
113 GNUNET_free (ctx);
114}
115
116
117/**
118 * Try to send 'data' to the
119 * IP 'dst_ipv4' at port 'dport' via TCP.
120 *
121 * @param dst_ivp4 target IP
122 * @param dport target port
123 * @param data data to send
124 */
125static void
126try_send_tcp (uint32_t dst_ipv4,
127 uint16_t dport,
128 uint16_t data)
129{
130 struct GNUNET_NETWORK_Handle *s;
131 struct sockaddr_in sa;
132 struct TcpContext *ctx;
133
134 s = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
135 if (NULL == s)
136 {
137 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
138 return;
139 }
140 memset (&sa, 0, sizeof (sa));
141#if HAVE_SOCKADDR_IN_SIN_LEN
142 sa.sin_len = sizeof (sa);
143#endif
144 sa.sin_addr.s_addr = dst_ipv4;
145 sa.sin_port = htons (dport);
146 if ( (GNUNET_OK !=
147 GNUNET_NETWORK_socket_connect (s,
148 (const struct sockaddr*) &sa, sizeof (sa))) &&
149 (errno != EINPROGRESS) )
150 {
151 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
152 GNUNET_NETWORK_socket_close (s);
153 return;
154 }
155 ctx = GNUNET_malloc (sizeof (struct TcpContext));
156 ctx->s = s;
157 ctx->data = data;
158 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
159 s,
160 &tcp_send, ctx);
161}
162
163
164/**
165 * Try to send 'data' to the
166 * IP 'dst_ipv4' at port 'dport' via UDP.
167 *
168 * @param dst_ivp4 target IP
169 * @param dport target port
170 * @param data data to send
171 */
172static void
173try_send_udp (uint32_t dst_ipv4,
174 uint16_t dport,
175 uint16_t data)
176{
177 struct GNUNET_NETWORK_Handle *s;
178 struct sockaddr_in sa;
179
180 s = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
181 if (NULL == s)
182 {
183 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
184 return;
185 }
186 memset (&sa, 0, sizeof (sa));
187#if HAVE_SOCKADDR_IN_SIN_LEN
188 sa.sin_len = sizeof (sa);
189#endif
190 sa.sin_addr.s_addr = dst_ipv4;
191 sa.sin_port = htons (dport);
192 if (-1 == GNUNET_NETWORK_socket_sendto (s, &data, sizeof(data), (const struct sockaddr*) &sa, sizeof (sa)))
193 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
194 GNUNET_NETWORK_socket_close (s);
195}
196
197
198/**
199 * We've received a request to probe a NAT
200 * traversal. Do it.
201 *
202 * @param cls unused
203 * @param client handle to client (we always close)
204 * @param msg message with details about what to test
205 */
206static void
207test (void *cls,
208 struct GNUNET_SERVER_Client *client,
209 const struct GNUNET_MessageHeader *msg)
210{
211 const struct GNUNET_NAT_TestMessage *tm;
212 uint16_t dport;
213
214 tm = (const struct GNUNET_NAT_TestMessage*) msg;
215 dport = ntohs (tm->dport);
216 if (0 == dport)
217 try_anat (tm->dst_ipv4,
218 ntohs (tm->data),
219 (int) ntohl (tm->is_tcp));
220 else if (GNUNET_YES == ntohl (tm->is_tcp))
221 try_send_tcp (tm->dst_ipv4, dport, tm->data);
222 else
223 try_send_udp (tm->dst_ipv4, dport, tm->data);
224 GNUNET_SERVER_receive_done (client,
225 GNUNET_NO);
226}
227
228
229/**
230 * Task run during shutdown.
231 *
232 * @param ctx unused
233 * @param tc scheduler context
234 */
235static void
236shutdown_task (void *cls,
237 const struct GNUNET_SCHEDULER_TaskContext *tc)
238{
239 GNUNET_SERVER_destroy (server);
240 server = NULL;
241}
242
34 243
35/** 244/**
36 * Main function that will be run. 245 * Main function that will be run.
@@ -44,11 +253,67 @@ static void
44run (void *cls, 253run (void *cls,
45 char *const *args, 254 char *const *args,
46 const char *cfgfile, 255 const char *cfgfile,
47 const struct GNUNET_CONFIGURATION_Handle * c) 256 const struct GNUNET_CONFIGURATION_Handle *c)
48{ 257{
258 static const struct GNUNET_SERVER_MessageHandler handlers[] =
259 {
260 { &test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST, sizeof (struct GNUNET_NAT_TestMessage) },
261 { NULL, NULL, 0, 0 }
262 };
263 unsigned int port;
264 struct sockaddr_in in4;
265 struct sockaddr_in6 in6;
266 socklen_t slen[] =
267 {
268 sizeof (in4),
269 sizeof (in6),
270 0
271 };
272 struct sockaddr *sa[] =
273 {
274 (struct sockaddr*) &in4,
275 (struct sockaddr*) &in6,
276 NULL
277 };
278
279 cfg = c;
280 if ( (args[0] == NULL) ||
281 (1 != SSCANF (args[0], "%u", &port)) ||
282 (0 == port) ||
283 (65536 >= port) )
284 {
285 fprintf (stderr,
286 _("Please pass valid port number as the first argument!\n"));
287 return;
288 }
289 memset (&in4, 0, sizeof (in4));
290 memset (&in6, 0, sizeof (in6));
291 in4.sin_port = htons ((uint16_t) port);
292 in6.sin6_port = htons ((uint16_t) port);
293#if HAVE_SOCKADDR_IN_SIN_LEN
294 in4.sin_len = sizeof (in);
295 in6.sin6_len = sizeof (in6);
296#endif
297 server = GNUNET_SERVER_create (NULL, NULL,
298 (struct sockaddr*const*) sa,
299 slen,
300 GNUNET_TIME_UNIT_SECONDS,
301 GNUNET_YES);
302 GNUNET_SERVER_add_handlers (server,
303 handlers);
304 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
305 &shutdown_task,
306 NULL);
49} 307}
50 308
51 309
310/**
311 * Main function of gnunet-nat-server.
312 *
313 * @param argc number of command-line arguments
314 * @param argv command line
315 * @return 0 on success, -1 on error
316 */
52int 317int
53main (int argc, char *const argv[]) 318main (int argc, char *const argv[])
54{ 319{
@@ -58,7 +323,7 @@ main (int argc, char *const argv[])
58 323
59 if (GNUNET_OK != 324 if (GNUNET_OK !=
60 GNUNET_PROGRAM_run (argc, argv, 325 GNUNET_PROGRAM_run (argc, argv,
61 "gnunet-nat-server", 326 "gnunet-nat-server [options] PORT",
62 _("GNUnet NAT traversal test helper daemon"), 327 _("GNUnet NAT traversal test helper daemon"),
63 options, 328 options,
64 &run, NULL)) 329 &run, NULL))
diff --git a/src/nat/nat.c b/src/nat/nat.c
index 418c619e3..e708cdabf 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -1323,10 +1323,10 @@ GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
1323 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop"); 1323 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
1324 return; 1324 return;
1325 } 1325 }
1326 GNUNET_snprintf(port_as_string, 1326 GNUNET_snprintf (port_as_string,
1327 sizeof (port_as_string), 1327 sizeof (port_as_string),
1328 "%d", 1328 "%d",
1329 h->adv_port); 1329 h->adv_port);
1330#if DEBUG_TCP_NAT 1330#if DEBUG_TCP_NAT
1331 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1331 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1332 "nat", 1332 "nat",
diff --git a/src/nat/nat.h b/src/nat/nat.h
new file mode 100644
index 000000000..bff444e6d
--- /dev/null
+++ b/src/nat/nat.h
@@ -0,0 +1,63 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4
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.
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 General Public License for more details.
14
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/nat/nat.h
23 * @brief Messages for interaction with gnunet-nat-server
24 * @author Christian Grothoff
25 *
26 */
27#ifndef NAT_H
28#define NAT_H
29#include "gnunet_util_lib.h"
30
31/**
32 * Request to test NAT traversal.
33 */
34struct GNUNET_NAT_TestMessage
35{
36 /**
37 * Header with type "GNUNET_MESSAGE_TYPE_NAT_TEST"
38 */
39 struct GNUNET_MessageHeader header;
40
41 /**
42 * IPv4 target IP address
43 */
44 uint32_t dst_ipv4;
45
46 /**
47 * Port to use, 0 to send dummy ICMP response.
48 */
49 uint16_t dport;
50
51 /**
52 * Data to send OR advertised-port (in NBO) to use for dummy ICMP.
53 */
54 uint16_t data;
55
56 /**
57 * GNUNET_YES for TCP, GNUNET_NO for UDP.
58 */
59 int32_t is_tcp;
60
61};
62
63#endif
diff --git a/src/util/network.c b/src/util/network.c
index b0669b5b1..e51d7fdab 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -392,7 +392,6 @@ GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
392 392
393#ifdef MINGW 393#ifdef MINGW
394 if (SOCKET_ERROR == ret) 394 if (SOCKET_ERROR == ret)
395
396 { 395 {
397 SetErrnoFromWinsockError (WSAGetLastError ()); 396 SetErrnoFromWinsockError (WSAGetLastError ());
398 if (errno == EWOULDBLOCK) 397 if (errno == EWOULDBLOCK)