aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transport/Makefile.am19
-rw-r--r--src/transport/gnunet-nat-server.c1
-rw-r--r--src/transport/plugin_transport_udp.c1604
-rw-r--r--src/transport/plugin_transport_udp_nat.c1676
-rw-r--r--src/transport/test_transport_api_udp_nat_peer1.conf7
-rw-r--r--src/transport/test_transport_api_udp_nat_peer2.conf6
-rw-r--r--src/transport/test_transport_api_udp_peer2.conf10
7 files changed, 1167 insertions, 2156 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index da925bc0d..42952fa6c 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -72,7 +72,6 @@ gnunet_service_transport_LDADD = \
72plugin_LTLIBRARIES = \ 72plugin_LTLIBRARIES = \
73 libgnunet_plugin_transport_tcp.la \ 73 libgnunet_plugin_transport_tcp.la \
74 libgnunet_plugin_transport_udp.la \ 74 libgnunet_plugin_transport_udp.la \
75 libgnunet_plugin_transport_udp_nat.la \
76 $(HTTP_PLUGIN_LA) \ 75 $(HTTP_PLUGIN_LA) \
77 libgnunet_plugin_transport_template.la 76 libgnunet_plugin_transport_template.la
78# TODO: add http, nat, etc. 77# TODO: add http, nat, etc.
@@ -104,15 +103,15 @@ libgnunet_plugin_transport_udp_la_LIBADD = \
104libgnunet_plugin_transport_udp_la_LDFLAGS = \ 103libgnunet_plugin_transport_udp_la_LDFLAGS = \
105 $(GN_PLUGIN_LDFLAGS) 104 $(GN_PLUGIN_LDFLAGS)
106 105
107libgnunet_plugin_transport_udp_nat_la_SOURCES = \ 106#libgnunet_plugin_transport_udp_nat_la_SOURCES = \
108 plugin_transport_udp_nat.c 107# plugin_transport_udp_nat.c
109libgnunet_plugin_transport_udp_nat_la_LIBADD = \ 108#libgnunet_plugin_transport_udp_nat_la_LIBADD = \
110 $(top_builddir)/src/hello/libgnunethello.la \ 109# $(top_builddir)/src/hello/libgnunethello.la \
111 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 110# $(top_builddir)/src/statistics/libgnunetstatistics.la \
112 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 111# $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
113 $(top_builddir)/src/util/libgnunetutil.la 112# $(top_builddir)/src/util/libgnunetutil.la
114libgnunet_plugin_transport_udp_nat_la_LDFLAGS = \ 113#libgnunet_plugin_transport_udp_nat_la_LDFLAGS = \
115 $(GN_PLUGIN_LDFLAGS) 114# $(GN_PLUGIN_LDFLAGS)
116 115
117if HAVE_MHD 116if HAVE_MHD
118libgnunet_plugin_transport_http_la_SOURCES = \ 117libgnunet_plugin_transport_http_la_SOURCES = \
diff --git a/src/transport/gnunet-nat-server.c b/src/transport/gnunet-nat-server.c
index 8f39ab374..9bef4dbc8 100644
--- a/src/transport/gnunet-nat-server.c
+++ b/src/transport/gnunet-nat-server.c
@@ -248,6 +248,7 @@ process_icmp_response ()
248 memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt)); 248 memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt));
249 off += sizeof (ip_pkt); 249 off += sizeof (ip_pkt);
250 250
251 have_udp = 0;
251 if (ip_pkt.proto == IPPROTO_UDP) 252 if (ip_pkt.proto == IPPROTO_UDP)
252 { 253 {
253 have_udp = 1; 254 have_udp = 1;
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 4de3f2c44..d66725957 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -20,9 +20,21 @@
20 20
21/** 21/**
22 * @file transport/plugin_transport_udp.c 22 * @file transport/plugin_transport_udp.c
23 * @brief Implementation of the UDP transport service 23 * @brief Implementation of the UDP NAT punching
24 * transport service
24 * @author Christian Grothoff 25 * @author Christian Grothoff
25 * @author Nathan Evans 26 * @author Nathan Evans
27 *
28 * The idea with this transport is to connect gnunet peers to each other
29 * when ONE is behind a NAT. This is based on pwnat (http://samy.pl/pwnat)
30 * created by Samy Kamkar. When configured with the PWNAT options, this
31 * transport will start a server daemon which sends dummy ICMP and UDP
32 * messages out to a predefined address (typically 1.2.3.4).
33 *
34 * When a non-NAT'd peer (the client) learns of the NAT'd peer (the server)
35 * address, it will send ICMP RESPONSES to the NAT'd peers external address.
36 * The NAT box should forward these faked responses to the server, which
37 * can then connect directly to the non-NAT'd peer.
26 */ 38 */
27 39
28#include "platform.h" 40#include "platform.h"
@@ -40,26 +52,37 @@
40#include "plugin_transport.h" 52#include "plugin_transport.h"
41#include "transport.h" 53#include "transport.h"
42 54
43#define DEBUG_UDP GNUNET_NO 55#define DEBUG_UDP GNUNET_YES
44 56
45/** 57#define MAX_PROBES 20
58
59/*
46 * Transport cost to peer, always 1 for UDP (direct connection) 60 * Transport cost to peer, always 1 for UDP (direct connection)
47 */ 61 */
48#define UDP_DIRECT_DISTANCE 1 62#define UDP_DIRECT_DISTANCE 1
49 63
50/** 64/**
65 * Handle for request of hostname resolution, non-NULL if pending.
66 */
67static struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
68
69/**
51 * How long until we give up on transmitting the welcome message? 70 * How long until we give up on transmitting the welcome message?
52 */ 71 */
53#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 72#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
54 73
74/**
75 * Starting port for listening and sending, eventually a config value
76 */
77#define UDP_NAT_DEFAULT_PORT 22086
55 78
56/** 79/**
57 * Message-Packet header. 80 * UDP Message-Packet header.
58 */ 81 */
59struct UDPMessage 82struct UDPMessage
60{ 83{
61 /** 84 /**
62 * size of the message, in bytes, including this header. 85 * Message header.
63 */ 86 */
64 struct GNUNET_MessageHeader header; 87 struct GNUNET_MessageHeader header;
65 88
@@ -71,61 +94,188 @@ struct UDPMessage
71}; 94};
72 95
73 96
74/** 97/* Forward definition */
75 * Network format for IPv4 addresses. 98struct Plugin;
76 */ 99
77struct IPv4UdpAddress 100struct PrettyPrinterContext
101{
102 GNUNET_TRANSPORT_AddressStringCallback asc;
103 void *asc_cls;
104 uint16_t port;
105};
106
107struct MessageQueue
78{ 108{
79 /** 109 /**
80 * IPv4 address, in network byte order. 110 * Linked List
111 */
112 struct MessageQueue *next;
113
114 /**
115 * Session this message belongs to
116 */
117 struct PeerSession *session;
118
119 /**
120 * Actual message to be sent
121 */
122 char *msgbuf;
123
124 /**
125 * Size of message buffer to be sent
81 */ 126 */
82 uint32_t ipv4_addr; 127 size_t msgbuf_size;
83 128
84 /** 129 /**
85 * Port number, in network byte order. 130 * When to discard this message
86 */ 131 */
87 uint16_t u_port; 132 struct GNUNET_TIME_Absolute timeout;
133
134 /**
135 * Continuation to call when this message goes out
136 */
137 GNUNET_TRANSPORT_TransmitContinuation cont;
138
139 /**
140 * closure for continuation
141 */
142 void *cont_cls;
88 143
89}; 144};
90 145
146/**
147 * UDP NAT Probe message definition
148 */
149struct UDP_NAT_ProbeMessage
150{
151 /**
152 * Message header
153 */
154 struct GNUNET_MessageHeader header;
155
156};
91 157
92/** 158/**
93 * Network format for IPv6 addresses. 159 * UDP NAT Probe message reply definition
94 */ 160 */
95struct IPv6UdpAddress 161struct UDP_NAT_ProbeMessageReply
96{ 162{
97 /** 163 /**
98 * IPv6 address. 164 * Message header
99 */ 165 */
100 struct in6_addr ipv6_addr; 166 struct GNUNET_MessageHeader header;
167
168};
169
101 170
171/**
172 * UDP NAT Probe message confirm definition
173 */
174struct UDP_NAT_ProbeMessageConfirmation
175{
102 /** 176 /**
103 * Port number, in network byte order. 177 * Message header
104 */ 178 */
105 uint16_t u6_port; 179 struct GNUNET_MessageHeader header;
106 180
107}; 181};
108 182
109 183
184
110/** 185/**
111 * 186 * UDP NAT "Session"
112 */ 187 */
113struct PrettyPrinterContext 188struct PeerSession
114{ 189{
190
115 /** 191 /**
116 * 192 * Stored in a linked list.
117 */ 193 */
118 GNUNET_TRANSPORT_AddressStringCallback asc; 194 struct PeerSession *next;
119 195
120 /** 196 /**
121 * Closure for 'asc'. 197 * Pointer to the global plugin struct.
122 */ 198 */
123 void *asc_cls; 199 struct Plugin *plugin;
124 200
125 /** 201 /**
126 * 202 * To whom are we talking to (set to our identity
203 * if we are still waiting for the welcome message)
127 */ 204 */
128 uint16_t port; 205 struct GNUNET_PeerIdentity target;
206
207 /**
208 * Address of the other peer (either based on our 'connect'
209 * call or on our 'accept' call).
210 */
211 void *connect_addr;
212
213 /**
214 * Length of connect_addr.
215 */
216 size_t connect_alen;
217
218 /**
219 * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO)
220 */
221 int expecting_welcome;
222
223 /**
224 * From which socket do we need to send to this peer?
225 */
226 struct GNUNET_NETWORK_Handle *sock;
227
228 /*
229 * Queue of messages for this peer, in the case that
230 * we have to await a connection...
231 */
232 struct MessageQueue *messages;
233
234};
235
236struct UDP_NAT_Probes
237{
238
239 /**
240 * Linked list
241 */
242 struct UDP_NAT_Probes *next;
243
244 /**
245 * Address string that the server process returned to us
246 */
247 char *address_string;
248
249 /**
250 * Timeout for this set of probes
251 */
252 struct GNUNET_TIME_Absolute timeout;
253
254 /**
255 * Count of how many probes we've attempted
256 */
257 int count;
258
259 /**
260 * The plugin this probe belongs to
261 */
262 struct Plugin *plugin;
263
264 /**
265 * The task used to send these probes
266 */
267 GNUNET_SCHEDULER_TaskIdentifier task;
268
269 /**
270 * Network address (always ipv4)
271 */
272 struct sockaddr_in sock_addr;
273
274 /**
275 * The port to send this probe to, 0 to choose randomly
276 */
277 int port;
278
129}; 279};
130 280
131 281
@@ -144,218 +294,428 @@ struct Plugin
144 */ 294 */
145 struct GNUNET_SERVICE_Context *service; 295 struct GNUNET_SERVICE_Context *service;
146 296
297 /*
298 * Session of peers with whom we are currently connected
299 */
300 struct PeerSession *sessions;
301
147 /** 302 /**
148 * Handle for request of hostname resolution, non-NULL if pending. 303 * Handle for request of hostname resolution, non-NULL if pending.
149 */ 304 */
150 struct GNUNET_RESOLVER_RequestHandle *hostname_dns; 305 struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
151 306
152 /** 307 /**
308 * ID of task used to update our addresses when one expires.
309 */
310 GNUNET_SCHEDULER_TaskIdentifier address_update_task;
311
312 /**
313 * ID of select task
314 */
315 GNUNET_SCHEDULER_TaskIdentifier select_task;
316
317 /**
318 * Port to listen on.
319 */
320 uint16_t port;
321
322 /**
323 * The external address given to us by the user. Must be actual
324 * outside visible address for NAT punching to work.
325 */
326 char *external_address;
327
328 /**
329 * The internal address given to us by the user (or discovered).
330 */
331 char *internal_address;
332
333 /*
153 * FD Read set 334 * FD Read set
154 */ 335 */
155 struct GNUNET_NETWORK_FDSet *rs; 336 struct GNUNET_NETWORK_FDSet *rs;
156 337
338 /*
339 * stdout pipe handle for the gnunet-nat-server process
340 */
341 struct GNUNET_DISK_PipeHandle *server_stdout;
342
343 /*
344 * stdout file handle (for reading) for the gnunet-nat-server process
345 */
346 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
347
157 /** 348 /**
158 * ID of task used to update our addresses when one expires. 349 * ID of select gnunet-nat-server stdout read task
159 */ 350 */
160 GNUNET_SCHEDULER_TaskIdentifier address_update_task; 351 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
161 352
162 /** 353 /**
163 * ID of select task 354 * Is this transport configured to be behind a NAT?
164 */ 355 */
165 GNUNET_SCHEDULER_TaskIdentifier select_task; 356 int behind_nat;
166 357
167 /** 358 /**
168 * Port that we are actually listening on. 359 * The process id of the server process (if behind NAT)
169 */ 360 */
170 uint16_t open_port; 361 pid_t server_pid;
171 362
172 /** 363 /**
173 * Port that the user said we would have visible to the 364 * Probes in flight
174 * rest of the world.
175 */ 365 */
176 uint16_t adv_port; 366 struct UDP_NAT_Probes *probes;
367
368};
369
177 370
371struct UDP_Sock_Info
372{
373 /* The network handle */
374 struct GNUNET_NETWORK_Handle *desc;
375
376 /* The port we bound to */
377 int port;
178}; 378};
179 379
180/* *********** globals ************* */ 380/* *********** globals ************* */
181 381
182/** 382/**
183 * The socket that we transmit all data with 383 * the socket that we transmit all data with
384 */
385static struct UDP_Sock_Info udp_sock;
386
387
388/**
389 * Forward declaration.
184 */ 390 */
185static struct GNUNET_NETWORK_Handle *udp_sock; 391void
392udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result);
393
186 394
187/** 395/**
188 * Disconnect from a remote node. 396 * Disconnect from a remote node. Clean up session if we have one for this peer
189 * 397 *
190 * @param cls closure ('struct Plugin'), unused 398 * @param cls closure for this call (should be handle to Plugin)
191 * @param target peer do disconnect 399 * @param target the peeridentity of the peer to disconnect
192 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed 400 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
193 */ 401 */
194void 402void
195udp_disconnect (void *cls, 403udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
196 const struct GNUNET_PeerIdentity *target)
197{ 404{
198 /* nothing to do, UDP is stateless */ 405 /** TODO: Implement! */
406 return;
199} 407}
200 408
201/** 409/**
202 * Shutdown the server process (stop receiving inbound traffic). Maybe 410 * Shutdown the server process (stop receiving inbound traffic). Maybe
203 * restarted later! 411 * restarted later!
204 * 412 *
205 * @param cls closure, the 'struct Plugin*' 413 * @param cls Handle to the plugin for this transport
414 *
415 * @return returns the number of sockets successfully closed,
416 * should equal the number of sockets successfully opened
206 */ 417 */
207static int 418static int
208udp_transport_server_stop (void *cls) 419udp_transport_server_stop (void *cls)
209{ 420{
210 struct Plugin *plugin = cls; 421 struct Plugin *plugin = cls;
211 int ret; 422 int ret;
423 int ok;
212 424
213 GNUNET_assert (udp_sock != NULL); 425 ret = 0;
214 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK) 426 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
215 { 427 {
216 GNUNET_SCHEDULER_cancel (plugin->env->sched, plugin->select_task); 428 GNUNET_SCHEDULER_cancel (plugin->env->sched, plugin->select_task);
217 plugin->select_task = GNUNET_SCHEDULER_NO_TASK; 429 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
218 } 430 }
219 431
220 ret = GNUNET_NETWORK_socket_close (udp_sock); 432
221 if (ret != GNUNET_SYSERR) 433 ok = GNUNET_NETWORK_socket_close (udp_sock.desc);
222 udp_sock = NULL; 434 if (ok == GNUNET_OK)
435 udp_sock.desc = NULL;
436 ret += ok;
437
438
439 if (plugin->behind_nat == GNUNET_YES)
440 {
441 if (0 != PLIBC_KILL (plugin->server_pid, SIGTERM))
442 {
443 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
444 }
445 GNUNET_OS_process_wait (plugin->server_pid);
446 }
447
448 if (ret != GNUNET_OK)
449 return GNUNET_SYSERR;
223 return ret; 450 return ret;
224} 451}
225 452
453
454struct PeerSession *
455find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer)
456{
457 struct PeerSession *pos;
458
459 pos = plugin->sessions;
460 while (pos != NULL)
461 {
462 if (memcmp(&pos->target, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
463 return pos;
464 pos = pos->next;
465 }
466
467 return pos;
468}
469
470
226/** 471/**
227 * Function that can be used by the transport service to transmit 472 * Actually send out the message, assume we've got the address and
228 * a message using the plugin. 473 * send_handle squared away!
229 * 474 *
230 * @param cls closure, the 'struct Plugin*' 475 * @param cls closure
476 * @param send_handle which handle to send message on
231 * @param target who should receive this message (ignored by UDP) 477 * @param target who should receive this message (ignored by UDP)
232 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together 478 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
233 * @param msgbuf_size the size of the msgbuf to send 479 * @param msgbuf_size the size of the msgbuf to send
234 * @param priority how important is the message (ignored by UDP) 480 * @param priority how important is the message (ignored by UDP)
235 * @param timeout when should we time out (give up) if we can not transmit? 481 * @param timeout when should we time out (give up) if we can not transmit?
236 * @param session which session must be used (always NULL for UDP)
237 * @param addr the addr to send the message to, needs to be a sockaddr for us 482 * @param addr the addr to send the message to, needs to be a sockaddr for us
238 * @param addrlen the len of addr 483 * @param addrlen the len of addr
239 * @param force_address GNUNET_YES if the plugin MUST use the given address,
240 * GNUNET_NO means the plugin may use any other address and
241 * GNUNET_SYSERR means that only reliable existing
242 * bi-directional connections should be used (regardless
243 * of address)
244 * @param cont continuation to call once the message has 484 * @param cont continuation to call once the message has
245 * been transmitted (or if the transport is ready 485 * been transmitted (or if the transport is ready
246 * for the next transmission call; or if the 486 * for the next transmission call; or if the
247 * peer disconnected...) 487 * peer disconnected...)
248 * @param cont_cls closure for cont 488 * @param cont_cls closure for cont
249 * 489 * @return the number of bytes written
250 * @return the number of bytes written, -1 on error (in this case, cont is not called)
251 */ 490 */
252static ssize_t 491static ssize_t
253udp_plugin_send (void *cls, 492udp_real_send (void *cls,
254 const struct GNUNET_PeerIdentity *target, 493 struct GNUNET_NETWORK_Handle *send_handle,
255 const char *msgbuf, 494 const struct GNUNET_PeerIdentity *target,
256 size_t msgbuf_size, 495 const char *msgbuf,
257 unsigned int priority, 496 size_t msgbuf_size,
258 struct GNUNET_TIME_Relative timeout, 497 unsigned int priority,
259 struct Session *session, 498 struct GNUNET_TIME_Relative timeout,
260 const void *addr, 499 const void *addr,
261 size_t addrlen, 500 size_t addrlen,
262 int force_address, 501 GNUNET_TRANSPORT_TransmitContinuation cont,
263 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) 502 void *cont_cls)
264{ 503{
265 struct Plugin *plugin = cls; 504 struct Plugin *plugin = cls;
266 struct UDPMessage *message; 505 struct UDPMessage *message;
267 int ssize; 506 int ssize;
268 ssize_t sent; 507 ssize_t sent;
269 const void *sb;
270 size_t sbs;
271 struct sockaddr_in a4;
272 struct sockaddr_in6 a6;
273 const struct IPv4UdpAddress *t4;
274 const struct IPv6UdpAddress *t6;
275 508
276 GNUNET_assert (NULL == session); 509 if ((addr == NULL) || (addrlen == 0))
277 GNUNET_assert(udp_sock != NULL);
278 if ( (addr == NULL) || (addrlen == 0) )
279 { 510 {
280#if DEBUG_UDP 511#if DEBUG_UDP_NAT
281 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 512 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
282 ("udp_plugin_send called without address, returning!\n")); 513 ("udp_plugin_send called without address, returning!\n"));
283#endif 514#endif
284 return -1; /* Can never send if we don't have an address!! */ 515 cont (cont_cls, target, GNUNET_SYSERR);
285 } 516 return 0; /* Can never send if we don't have an address!! */
286 if (force_address == GNUNET_SYSERR)
287 return -1; /* never reliable */
288
289 if (addrlen == sizeof (struct IPv6UdpAddress))
290 {
291 t6 = addr;
292 memset (&a6, 0, sizeof (a6));
293#if HAVE_SOCKADDR_IN_SIN_LEN
294 a6.sin6_len = sizeof (a6);
295#endif
296 a6.sin6_family = AF_INET6;
297 a6.sin6_port = t6->u6_port;
298 memcpy (&a6.sin6_addr,
299 &t6->ipv6_addr,
300 sizeof (struct in6_addr));
301 sb = &a6;
302 sbs = sizeof (a6);
303 }
304 else if (addrlen == sizeof (struct IPv4UdpAddress))
305 {
306 t4 = addr;
307 memset (&a4, 0, sizeof (a4));
308#if HAVE_SOCKADDR_IN_SIN_LEN
309 a4.sin_len = sizeof (a4);
310#endif
311 a4.sin_family = AF_INET;
312 a4.sin_port = t4->u_port;
313 a4.sin_addr.s_addr = t4->ipv4_addr;
314 sb = &a4;
315 sbs = sizeof (a4);
316 }
317 else
318 {
319 GNUNET_break_op (0);
320 return -1;
321 } 517 }
322 518
323 /* Build the message to be sent */ 519 /* Build the message to be sent */
324 message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size); 520 message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size);
325 ssize = sizeof (struct UDPMessage) + msgbuf_size; 521 ssize = sizeof (struct UDPMessage) + msgbuf_size;
326 522
327#if DEBUG_UDP
328 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
329 "In udp_send, ssize is %d, sending message to `%s'\n",
330 ssize,
331 GNUNET_a2s(sb, sbs));
332#endif
333 message->header.size = htons (ssize); 523 message->header.size = htons (ssize);
334 message->header.type = htons (0); 524 message->header.type = htons (0);
335 memcpy (&message->sender, plugin->env->my_identity, 525 memcpy (&message->sender, plugin->env->my_identity,
336 sizeof (struct GNUNET_PeerIdentity)); 526 sizeof (struct GNUNET_PeerIdentity));
337 memcpy (&message[1], msgbuf, msgbuf_size); 527 memcpy (&message[1], msgbuf, msgbuf_size);
528
529 /* Actually send the message */
338 sent = 530 sent =
339 GNUNET_NETWORK_socket_sendto (udp_sock, message, ssize, 531 GNUNET_NETWORK_socket_sendto (send_handle, message, ssize,
340 sb, sbs); 532 addr,
341 if ( (cont != NULL) && 533 addrlen);
342 (sent != -1) ) 534
343 cont (cont_cls, target, GNUNET_OK); 535 if (cont != NULL)
536 {
537 if (sent == GNUNET_SYSERR)
538 cont (cont_cls, target, GNUNET_SYSERR);
539 else
540 {
541 cont (cont_cls, target, GNUNET_OK);
542 }
543 }
544
344 GNUNET_free (message); 545 GNUNET_free (message);
345 return sent; 546 return sent;
346} 547}
347 548
549/**
550 * We learned about a peer (possibly behind NAT) so run the
551 * gnunet-nat-client to send dummy ICMP responses
552 *
553 * @param plugin the plugin for this transport
554 * @param addr the address of the peer
555 * @param addrlen the length of the address
556 */
557void
558run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen)
559{
560 char inet4[INET_ADDRSTRLEN];
561 char *address_as_string;
562 char *port_as_string;
563 pid_t pid;
564 const struct sockaddr *sa = (const struct sockaddr *)addr;
565
566 if (addrlen < sizeof (struct sockaddr))
567 return;
568 switch (sa->sa_family)
569 {
570 case AF_INET:
571 if (addrlen != sizeof (struct sockaddr_in))
572 return;
573 inet_ntop (AF_INET,
574 &((struct sockaddr_in *) sa)->sin_addr,
575 inet4, INET_ADDRSTRLEN);
576 address_as_string = GNUNET_strdup (inet4);
577 break;
578 case AF_INET6:
579 default:
580 return;
581 }
582
583 GNUNET_asprintf(&port_as_string, "%d", plugin->port);
584#if DEBUG_UDP_NAT
585 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
586 _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->port);
587#endif
588 /* Start the server process */
589 pid = GNUNET_OS_start_process(NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL);
590 GNUNET_free(address_as_string);
591 GNUNET_free(port_as_string);
592 GNUNET_OS_process_wait (pid);
593}
594
595/**
596 * Function that can be used by the transport service to transmit
597 * a message using the plugin.
598 *
599 * @param cls closure
600 * @param target who should receive this message (ignored by UDP)
601 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
602 * @param msgbuf_size the size of the msgbuf to send
603 * @param priority how important is the message (ignored by UDP)
604 * @param timeout when should we time out (give up) if we can not transmit?
605 * @param session identifier used for this session (can be NULL)
606 * @param addr the addr to send the message to, needs to be a sockaddr for us
607 * @param addrlen the len of addr
608 * @param force_address not used, we had better have an address to send to
609 * because we are stateless!!
610 * @param cont continuation to call once the message has
611 * been transmitted (or if the transport is ready
612 * for the next transmission call; or if the
613 * peer disconnected...)
614 * @param cont_cls closure for cont
615 *
616 * @return the number of bytes written (may return 0 and the message can
617 * still be transmitted later!)
618 */
619static ssize_t
620udp_plugin_send (void *cls,
621 const struct GNUNET_PeerIdentity *target,
622 const char *msgbuf,
623 size_t msgbuf_size,
624 unsigned int priority,
625 struct GNUNET_TIME_Relative timeout,
626 struct Session *session,
627 const void *addr,
628 size_t addrlen,
629 int force_address,
630 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
631{
632 struct Plugin *plugin = cls;
633 ssize_t sent;
634 struct MessageQueue *temp_message;
635 struct PeerSession *peer_session;
636 struct sockaddr_in *sockaddr = (struct sockaddr_in *)addr;
637 int other_peer_natd;
638
639 GNUNET_assert (NULL == session);
640 other_peer_natd = GNUNET_NO;
641 if ((sockaddr->sin_family == AF_INET) && (ntohs(sockaddr->sin_port) == 0))
642 {
643 other_peer_natd = GNUNET_YES;
644 }
645
646 sent = 0;
647
648 if (other_peer_natd == GNUNET_YES)
649 {
650 peer_session = find_session(plugin, target);
651 if (peer_session == NULL) /* We have a new peer to add */
652 {
653 /*
654 * The first time, we can assume we have no knowledge of a
655 * working port for this peer, call the ICMP/UDP message sender
656 * and wait...
657 */
658 peer_session = GNUNET_malloc(sizeof(struct PeerSession));
659 peer_session->connect_addr = GNUNET_malloc(addrlen);
660 memcpy(peer_session->connect_addr, addr, addrlen);
661 peer_session->connect_alen = addrlen;
662 peer_session->plugin = plugin;
663 peer_session->sock = NULL;
664 memcpy(&peer_session->target, target, sizeof(struct GNUNET_PeerIdentity));
665 peer_session->expecting_welcome = GNUNET_YES;
666
667 peer_session->next = plugin->sessions;
668 plugin->sessions = peer_session;
669
670 peer_session->messages = GNUNET_malloc(sizeof(struct MessageQueue));
671 peer_session->messages->msgbuf = GNUNET_malloc(msgbuf_size);
672 memcpy(peer_session->messages->msgbuf, msgbuf, msgbuf_size);
673 peer_session->messages->msgbuf_size = msgbuf_size;
674 peer_session->messages->next = NULL;
675 peer_session->messages->timeout = GNUNET_TIME_relative_to_absolute(timeout);
676 peer_session->messages->cont = cont;
677 peer_session->messages->cont_cls = cont_cls;
678#if DEBUG_UDP_NAT
679 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
680 _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target));
681#endif
682 run_gnunet_nat_client(plugin, addr, addrlen);
683 }
684 else
685 {
686 if (peer_session->expecting_welcome == GNUNET_NO) /* We are "connected" */
687 {
688 sent = udp_real_send(cls, peer_session->sock, target, msgbuf, msgbuf_size, priority, timeout, peer_session->connect_addr, peer_session->connect_alen, cont, cont_cls);
689 }
690 else /* Haven't gotten a response from this peer, queue message */
691 {
692 temp_message = GNUNET_malloc(sizeof(struct MessageQueue));
693 temp_message->msgbuf = GNUNET_malloc(msgbuf_size);
694 memcpy(temp_message->msgbuf, msgbuf, msgbuf_size);
695 temp_message->msgbuf_size = msgbuf_size;
696 temp_message->timeout = GNUNET_TIME_relative_to_absolute(timeout);
697 temp_message->cont = cont;
698 temp_message->cont_cls = cont_cls;
699 temp_message->next = peer_session->messages;
700 peer_session->messages = temp_message;
701 }
702 }
703 }
704 else /* Other peer not behind a NAT, so we can just send the message as is */
705 {
706 sent = udp_real_send(cls, udp_sock.desc, target, msgbuf, msgbuf_size, priority, timeout, addr, addrlen, cont, cont_cls);
707 }
708
709 if (sent == GNUNET_SYSERR)
710 return 0;
711
712 return sent;
713}
714
348 715
349/** 716/**
350 * Add the IP of our network interface to the list of 717 * Add the IP of our network interface to the list of
351 * our external IP addresses. 718 * our external IP addresses.
352 *
353 * @param cls closure (the 'struct Plugin*')
354 * @param name name of the interface (can be NULL for unknown)
355 * @param isDefault is this presumably the default interface
356 * @param addr address of this interface (can be NULL for unknown or unassigned)
357 * @param addrlen length of the address
358 * @return GNUNET_OK to continue iterating
359 */ 719 */
360static int 720static int
361process_interfaces (void *cls, 721process_interfaces (void *cls,
@@ -365,47 +725,39 @@ process_interfaces (void *cls,
365{ 725{
366 struct Plugin *plugin = cls; 726 struct Plugin *plugin = cls;
367 int af; 727 int af;
368 struct IPv4UdpAddress t4; 728 struct sockaddr_in *v4;
369 struct IPv6UdpAddress t6; 729 struct sockaddr_in6 *v6;
370 void *arg;
371 uint16_t args;
372 730
373 af = addr->sa_family; 731 af = addr->sa_family;
374 if (af == AF_INET) 732 if (af == AF_INET)
375 { 733 {
376 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; 734 v4 = (struct sockaddr_in *) addr;
377 t4.u_port = htons (plugin->adv_port); 735 if (plugin->behind_nat == GNUNET_YES)
378 arg = &t4; 736 {
379 args = sizeof (t4); 737 GNUNET_assert(inet_pton(AF_INET, plugin->external_address, &v4->sin_addr) == GNUNET_OK);
380 } 738 v4->sin_port = htons (0); /* Indicates to receiver we are behind NAT */
381 else if (af == AF_INET6) 739 }
382 { 740 else
383 if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr)) 741 v4->sin_port = htons (plugin->port);
384 {
385 /* skip link local addresses */
386 return GNUNET_OK;
387 }
388 memcpy (&t6.ipv6_addr,
389 &((struct sockaddr_in6 *) addr)->sin6_addr,
390 sizeof (struct in6_addr));
391 t6.u6_port = htons (plugin->adv_port);
392 arg = &t6;
393 args = sizeof (t6);
394 } 742 }
395 else 743 else
396 { 744 {
397 GNUNET_break (0); 745 GNUNET_assert (af == AF_INET6);
398 return GNUNET_OK; 746 v6 = (struct sockaddr_in6 *) addr;
399 } 747 if (plugin->behind_nat == GNUNET_YES)
400 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | 748 v6->sin6_port = htons (0);
401 GNUNET_ERROR_TYPE_BULK, 749 else
402 "udp", 750 v6->sin6_port = htons (plugin->port);
403 _("Found address `%s' (%s)\n"), 751 }
404 GNUNET_a2s (addr, addrlen), 752
405 name); 753 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
406 plugin->env->notify_address (plugin->env->cls, 754 GNUNET_ERROR_TYPE_BULK,
407 "udp", 755 "udp", _("Found address `%s' (%s)\n"),
408 arg, args, GNUNET_TIME_UNIT_FOREVER_REL); 756 GNUNET_a2s (addr, addrlen), name);
757 plugin->env->notify_address (plugin->env->cls,
758 "udp",
759 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL);
760
409 return GNUNET_OK; 761 return GNUNET_OK;
410} 762}
411 763
@@ -434,15 +786,363 @@ process_hostname_ips (void *cls,
434} 786}
435 787
436 788
789/**
790 * Send UDP probe messages or UDP keepalive messages, depending on the
791 * state of the connection.
792 *
793 * @param cls closure for this call (should be the main Plugin)
794 * @param tc task context for running this
795 */
796static void
797send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
798{
799 struct UDP_NAT_Probes *probe = cls;
800 struct UDP_NAT_ProbeMessage *message;
801 struct Plugin *plugin = probe->plugin;
802
803 message = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessage));
804 message->header.size = htons(sizeof(struct UDP_NAT_ProbeMessage));
805 message->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE);
806 /* If they gave us a port, use that. If not, try our port. */
807 if (probe->port != 0)
808 probe->sock_addr.sin_port = htons(probe->port);
809 else
810 probe->sock_addr.sin_port = htons(plugin->port);
811
812#if DEBUG_UDP_NAT
813 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
814 _("Sending a probe to port %d\n"), ntohs(probe->sock_addr.sin_port));
815#endif
816
817 probe->count++;
818
819 udp_real_send(plugin, udp_sock.desc, NULL,
820 (char *)message, ntohs(message->header.size), 0,
821 GNUNET_TIME_relative_get_unit(),
822 &probe->sock_addr, sizeof(probe->sock_addr),
823 &udp_probe_continuation, probe);
824
825 GNUNET_free(message);
826}
827
828
829/**
830 * Continuation for probe sends. If the last probe was sent
831 * "successfully", schedule sending of another one. If not,
832 *
833 */
834void
835udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result)
836{
837 struct UDP_NAT_Probes *probe = cls;
838 struct Plugin *plugin = probe->plugin;
839
840 if ((result == GNUNET_OK) && (probe->count < MAX_PROBES))
841 {
842#if DEBUG_UDP_NAT
843 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
844 _("Scheduling next probe for 10000 milliseconds\n"));
845#endif
846 probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 10000), &send_udp_probe_message, probe);
847 }
848 else /* Destroy the probe context. */
849 {
850#if DEBUG_UDP_NAT
851 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
852 _("Sending probe didn't go well...\n"));
853#endif
854 }
855}
856
857/**
858 * Find probe message by address
859 *
860 * @param plugin the plugin for this transport
861 * @param address_string the ip address as a string
862 */
863struct UDP_NAT_Probes *
864find_probe(struct Plugin *plugin, char * address_string)
865{
866 struct UDP_NAT_Probes *pos;
867
868 pos = plugin->probes;
869 while (pos != NULL)
870 if (strcmp(pos->address_string, address_string) == 0)
871 return pos;
872
873 return pos;
874}
875
876
437/* 877/*
438 * @param cls the plugin handle 878 * @param cls the plugin handle
439 * @param tc the scheduling context (for rescheduling this function again) 879 * @param tc the scheduling context (for rescheduling this function again)
440 * 880 *
441 * We have been notified that our writeset has something to read. Presumably 881 * We have been notified that gnunet-nat-server has written something to stdout.
442 * select has been called already, so we can go ahead and start reading from 882 * Handle the output, then reschedule this function to be called again once
443 * the socket immediately. Then we check if there is more to be read by 883 * more is available.
444 * calling select ourselves while there is stuff on the wire. Then reschedule 884 *
445 * this function to be called again once more is available. 885 */
886static void
887udp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
888{
889 struct Plugin *plugin = cls;
890 char mybuf[40];
891 ssize_t bytes;
892 memset(&mybuf, 0, sizeof(mybuf));
893 int i;
894 struct UDP_NAT_Probes *temp_probe;
895 int port;
896 char *port_start;
897 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, &mybuf, sizeof(mybuf));
898
899 if (bytes < 1)
900 {
901#if DEBUG_UDP_NAT
902 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
903 _("Finished reading from server stdout with code: %d\n"), bytes);
904#endif
905 return;
906 }
907
908 port = 0;
909 port_start = NULL;
910 for (i = 0; i < sizeof(mybuf); i++)
911 {
912 if (mybuf[i] == '\n')
913 mybuf[i] = '\0';
914
915 if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf)))
916 {
917 mybuf[i] = '\0';
918 port_start = &mybuf[i + 1];
919 }
920 }
921
922 if (port_start != NULL)
923 port = atoi(port_start);
924
925#if DEBUG_UDP_NAT
926 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
927 _("nat-server-read read: %s port %d\n"), &mybuf, port);
928#endif
929
930 /** We have received an ICMP response, ostensibly from a non-NAT'd peer
931 * that wants to connect to us! Send a message to establish a connection.
932 */
933 temp_probe = find_probe(plugin, &mybuf[0]);
934
935 if (temp_probe == NULL)
936 {
937 temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes));
938 temp_probe->address_string = strdup(&mybuf[0]);
939 temp_probe->sock_addr.sin_family = AF_INET;
940 GNUNET_assert(inet_pton(AF_INET, &mybuf[0], &temp_probe->sock_addr.sin_addr) == 1);
941 temp_probe->port = port;
942 temp_probe->next = plugin->probes;
943 temp_probe->plugin = plugin;
944 temp_probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), &send_udp_probe_message, temp_probe);
945 plugin->probes = temp_probe;
946 }
947
948 plugin->server_read_task =
949 GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
950 GNUNET_TIME_UNIT_FOREVER_REL,
951 plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
952
953}
954
955
956/**
957 * Demultiplexer for UDP NAT messages
958 *
959 * @param plugin the main plugin for this transport
960 * @param sender from which peer the message was received
961 * @param currhdr pointer to the header of the message
962 * @param sender_addr the address from which the message was received
963 * @param fromlen the length of the address
964 * @param sockinfo which socket did we receive the message on
965 */
966static void
967udp_demultiplexer(struct Plugin *plugin, struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *currhdr, struct sockaddr_storage *sender_addr, socklen_t fromlen, struct UDP_Sock_Info *sockinfo)
968{
969 struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply;
970 struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation;
971
972 char addr_buf[INET_ADDRSTRLEN];
973 struct UDP_NAT_Probes *outgoing_probe;
974 struct PeerSession *peer_session;
975 struct MessageQueue *pending_message;
976 struct MessageQueue *pending_message_temp;
977
978 if (memcmp(sender, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
979 {
980#if DEBUG_UDP_NAT
981 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
982 _("Received a message from myself, dropping!!!\n"));
983#endif
984 return;
985 }
986
987 switch (ntohs(currhdr->type))
988 {
989 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE:
990 /* Send probe reply */
991 outgoing_probe_reply = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageReply));
992 outgoing_probe_reply->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageReply));
993 outgoing_probe_reply->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY);
994
995#if DEBUG_UDP_NAT
996 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
997 _("Received a probe on listen port %d, sent_from port %d\n"), sockinfo->port, ntohs(((struct sockaddr_in *)sender_addr)->sin_port));
998#endif
999
1000 udp_real_send(plugin, sockinfo->desc, NULL,
1001 (char *)outgoing_probe_reply,
1002 ntohs(outgoing_probe_reply->header.size), 0,
1003 GNUNET_TIME_relative_get_unit(),
1004 sender_addr, fromlen,
1005 NULL, NULL);
1006
1007#if DEBUG_UDP_NAT
1008 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
1009 _("Sent PROBE REPLY to port %d on outgoing port %d\n"), ntohs(((struct sockaddr_in *)sender_addr)->sin_port), sockinfo->port);
1010#endif
1011 GNUNET_free(outgoing_probe_reply);
1012 break;
1013 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY:
1014 /* Check for existing probe, check ports returned, send confirmation if all is well */
1015#if DEBUG_UDP_NAT
1016 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
1017 _("Received PROBE REPLY from port %d on incoming port %d\n"), ntohs(((struct sockaddr_in *)sender_addr)->sin_port), sockinfo->port);
1018#endif
1019 /* FIXME: use nonce, then IPv6 replies could work I think... */
1020 if (sender_addr->ss_family == AF_INET)
1021 {
1022 memset(&addr_buf, 0, sizeof(addr_buf));
1023 inet_ntop(AF_INET, &((struct sockaddr_in *) sender_addr)->sin_addr, addr_buf, INET_ADDRSTRLEN);
1024 outgoing_probe = find_probe(plugin, &addr_buf[0]);
1025 if (outgoing_probe != NULL)
1026 {
1027#if DEBUG_UDP_NAT
1028 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
1029 _("Sending confirmation that we were reached!\n"));
1030#endif
1031 outgoing_probe_confirmation = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
1032 outgoing_probe_confirmation->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
1033 outgoing_probe_confirmation->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM);
1034
1035 udp_real_send(plugin, sockinfo->desc, NULL, (char *)outgoing_probe_confirmation, ntohs(outgoing_probe_confirmation->header.size), 0, GNUNET_TIME_relative_get_unit(), sender_addr, fromlen, NULL, NULL);
1036
1037 if (outgoing_probe->task != GNUNET_SCHEDULER_NO_TASK)
1038 {
1039 GNUNET_SCHEDULER_cancel(plugin->env->sched, outgoing_probe->task);
1040 outgoing_probe->task = GNUNET_SCHEDULER_NO_TASK;
1041 /* Schedule task to timeout and remove probe if confirmation not received */
1042 }
1043 GNUNET_free(outgoing_probe_confirmation);
1044 }
1045 else
1046 {
1047#if DEBUG_UDP_NAT
1048 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
1049 _("Received a probe reply, but have no record of a sent probe!\n"));
1050#endif
1051 }
1052 }
1053 break;
1054 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM:
1055 peer_session = find_session(plugin, sender);
1056#if DEBUG_UDP_NAT
1057 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
1058 _("Looking up peer session for peer %s\n"), GNUNET_i2s(sender));
1059#endif
1060 if (peer_session == NULL) /* Shouldn't this NOT happen? */
1061 {
1062#if DEBUG_UDP_NAT
1063 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
1064 _("Peer not in list, adding (THIS MAY BE A MISTAKE) %s\n"), GNUNET_i2s(sender));
1065#endif
1066 peer_session = GNUNET_malloc(sizeof(struct PeerSession));
1067 peer_session->connect_addr = GNUNET_malloc(fromlen);
1068 memcpy(peer_session->connect_addr, sender_addr, fromlen);
1069 peer_session->connect_alen = fromlen;
1070 peer_session->plugin = plugin;
1071 peer_session->sock = sockinfo->desc;
1072 memcpy(&peer_session->target, sender, sizeof(struct GNUNET_PeerIdentity));
1073 peer_session->expecting_welcome = GNUNET_NO;
1074
1075 peer_session->next = plugin->sessions;
1076 plugin->sessions = peer_session;
1077
1078 peer_session->messages = NULL;
1079 }
1080 else if (peer_session->expecting_welcome == GNUNET_YES)
1081 {
1082 peer_session->expecting_welcome = GNUNET_NO;
1083 /* FIXME: There is no way to find this based on receiving port at the moment! */
1084 peer_session->sock = sockinfo->desc; /* This may matter, not sure right now... */
1085 ((struct sockaddr_in *)peer_session->connect_addr)->sin_port = ((struct sockaddr_in *) sender_addr)->sin_port;
1086#if DEBUG_UDP_NAT
1087 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
1088 _("Received a probe confirmation, will send to peer on port %d\n"), ntohs(((struct sockaddr_in *)peer_session->connect_addr)->sin_port));
1089#endif
1090 if (peer_session->messages != NULL)
1091 {
1092#if DEBUG_UDP_NAT
1093 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
1094 _("Received a probe confirmation, sending queued messages.\n"));
1095#endif
1096 pending_message = peer_session->messages;
1097 int count = 0;
1098 while (pending_message != NULL)
1099 {
1100#if DEBUG_UDP_NAT
1101 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
1102 _("sending queued message %d\n"), count);
1103#endif
1104 udp_real_send(plugin, peer_session->sock, &peer_session->target, pending_message->msgbuf, pending_message->msgbuf_size, 0, GNUNET_TIME_relative_get_unit(), peer_session->connect_addr, peer_session->connect_alen, pending_message->cont, pending_message->cont_cls);
1105 pending_message_temp = pending_message;
1106 pending_message = pending_message->next;
1107 GNUNET_free(pending_message_temp->msgbuf);
1108 GNUNET_free(pending_message_temp);
1109#if DEBUG_UDP_NAT
1110 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
1111 _("finished sending queued message %d\n"), count);
1112#endif
1113 count++;
1114 }
1115 }
1116
1117 }
1118 else
1119 {
1120#if DEBUG_UDP_NAT
1121 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
1122 _("Received probe confirmation for already confirmed peer!\n"));
1123#endif
1124 }
1125 /* Received confirmation, add peer with address/port specified */
1126 break;
1127 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_KEEPALIVE:
1128 /* Once we've sent NAT_PROBE_CONFIRM change to sending keepalives */
1129 /* If we receive these just ignore! */
1130 break;
1131 default:
1132 plugin->env->receive (plugin->env->cls, sender, currhdr, UDP_DIRECT_DISTANCE,
1133 NULL, (char *)sender_addr, fromlen);
1134 }
1135
1136}
1137
1138
1139/*
1140 * @param cls the plugin handle
1141 * @param tc the scheduling context (for rescheduling this function again)
1142 *
1143 * We have been notified that our writeset has something to read. We don't
1144 * know which socket needs to be read, so we have to check each one
1145 * Then reschedule this function to be called again once more is available.
446 * 1146 *
447 */ 1147 */
448static void 1148static void
@@ -459,126 +1159,77 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
459 int offset; 1159 int offset;
460 int count; 1160 int count;
461 int tsize; 1161 int tsize;
1162
462 char *msgbuf; 1163 char *msgbuf;
463 const struct GNUNET_MessageHeader *currhdr; 1164 const struct GNUNET_MessageHeader *currhdr;
464 struct IPv4UdpAddress t4;
465 struct IPv6UdpAddress t6;
466 const struct sockaddr_in *s4;
467 const struct sockaddr_in6 *s6;
468 const void *ca;
469 size_t calen;
470
471#if DEBUG_UDP
472 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
473 ("entered select...\n"));
474#endif
475 1165
476 buflen = GNUNET_NETWORK_socket_recvfrom_amount (udp_sock); 1166 buf = NULL;
1167 sender = NULL;
477 1168
478#if DEBUG_UDP 1169 buflen = GNUNET_NETWORK_socket_recvfrom_amount (udp_sock.desc);
479 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
480 ("we expect to read %u bytes\n"), buflen);
481#endif
482 1170
483 if (buflen == GNUNET_NO) 1171 if (buflen == GNUNET_NO)
484 return; 1172 return;
1173
1174 buf = GNUNET_malloc (buflen);
1175 fromlen = sizeof (addr);
1176 memset (&addr, 0, fromlen);
1177 ret =
1178 GNUNET_NETWORK_socket_recvfrom (udp_sock.desc, buf, buflen,
1179 (struct sockaddr *) &addr, &fromlen);
485 1180
486 buf = GNUNET_malloc (buflen); 1181#if DEBUG_UDP_NAT
487 fromlen = sizeof (addr); 1182 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1183 ("socket_recv returned %u, src_addr_len is %u\n"), ret,
1184 fromlen);
1185#endif
488 1186
489 memset (&addr, 0, fromlen); 1187 if (ret <= 0)
490 ret = 1188 {
491 GNUNET_NETWORK_socket_recvfrom (udp_sock, buf, buflen, 1189 GNUNET_free (buf);
492 (struct sockaddr *) &addr, &fromlen); 1190 return;
1191 }
1192 msg = (struct UDPMessage *) buf;
493 1193
494#if DEBUG_UDP 1194#if DEBUG_UDP_NAT
495 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 1195 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
496 ("socket_recv returned %u, src_addr_len is %u\n"), ret, 1196 ("header reports message size of %d, type %d\n"),
497 fromlen); 1197 ntohs (msg->header.size), ntohs (msg->header.type));
498#endif 1198#endif
1199 if (ntohs (msg->header.size) < sizeof (struct UDPMessage))
1200 {
1201 GNUNET_free (buf);
1202 return;
1203 }
499 1204
500 if (ret <= 0) 1205 msgbuf = (char *)&msg[1];
501 { 1206 sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
502 GNUNET_free (buf); 1207 memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
503 return;
504 }
505 msg = (struct UDPMessage *) buf;
506 1208
507#if DEBUG_UDP 1209 offset = 0;
508 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 1210 count = 0;
509 ("header reports message size of %d\n"), 1211 tsize = ntohs (msg->header.size) - sizeof(struct UDPMessage);
510 ntohs (msg->header.size));
511 1212
512 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 1213 while (offset < tsize)
513 ("header reports message type of %d\n"), 1214 {
514 ntohs (msg->header.type)); 1215 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
1216#if DEBUG_UDP_NAT
1217 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1218 ("processing msg %d: type %d, size %d at offset %d\n"),
1219 count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
515#endif 1220#endif
516 if (ntohs (msg->header.size) < sizeof (struct UDPMessage)) 1221 udp_demultiplexer(plugin, sender, currhdr, &addr, fromlen, &udp_sock);
517 { 1222#if DEBUG_UDP_NAT
518 GNUNET_free (buf); 1223 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
519 GNUNET_NETWORK_fdset_zero (plugin->rs); 1224 ("processing done msg %d: type %d, size %d at offset %d\n"),
520 GNUNET_NETWORK_fdset_set (plugin->rs, udp_sock); 1225 count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
521 return;
522 }
523 msgbuf = (char *)&msg[1];
524 sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
525 memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
526
527 offset = 0;
528 count = 0;
529 tsize = ntohs (msg->header.size) - sizeof(struct UDPMessage);
530#if DEBUG_UDP
531 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "UDP", _
532 ("offset is %d, tsize is %d (UDPMessage size is %d)\n"),
533 offset, tsize, sizeof(struct UDPMessage));
534#endif 1226#endif
1227 offset += ntohs(currhdr->size);
1228 count++;
1229 }
1230 GNUNET_free_non_null (buf);
1231 GNUNET_free_non_null (sender);
535 1232
536 if (fromlen == sizeof (struct sockaddr_in))
537 {
538 s4 = (const struct sockaddr_in*) &addr;
539 t4.u_port = s4->sin_port;
540 t4.ipv4_addr = s4->sin_addr.s_addr;
541 ca = &t4;
542 calen = sizeof (struct IPv4UdpAddress);
543 }
544 else if (fromlen == sizeof (struct sockaddr_in6))
545 {
546 s6 = (const struct sockaddr_in6*) &addr;
547 t6.u6_port = s6->sin6_port;
548 memcpy (&t6.ipv6_addr,
549 &s6->sin6_addr,
550 sizeof (struct in6_addr));
551 ca = &t6;
552 calen = sizeof (struct IPv6UdpAddress);
553 }
554 else
555 {
556 GNUNET_break (0);
557 ca = NULL;
558 calen = 0;
559 }
560 while (offset < tsize)
561 {
562 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
563#if DEBUG_UDP
564 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
565 ("processing msg %d: type %d, size %d at offset %d\n"),
566 count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
567#endif
568 plugin->env->receive (plugin->env->cls,
569 sender, currhdr, UDP_DIRECT_DISTANCE,
570 NULL, ca, calen);
571 offset += ntohs(currhdr->size);
572#if DEBUG_UDP
573 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
574 ("offset now %d, tsize %d\n"),
575 offset, tsize);
576#endif
577 count++;
578 }
579
580 GNUNET_free (sender);
581 GNUNET_free (buf);
582 1233
583 plugin->select_task = 1234 plugin->select_task =
584 GNUNET_SCHEDULER_add_select (plugin->env->sched, 1235 GNUNET_SCHEDULER_add_select (plugin->env->sched,
@@ -590,27 +1241,104 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
590} 1241}
591 1242
592/** 1243/**
593 * Create a UDP socket. If possible, use IPv6, otherwise 1244 * Create a slew of UDP sockets. If possible, use IPv6, otherwise
594 * try IPv4. 1245 * try IPv4.
595 * @param cls closure, the 'struct Plugin*' 1246 *
1247 * @param cls closure for server start, should be a struct Plugin *
1248 *
1249 * @return number of sockets created or GNUNET_SYSERR on error
596 */ 1250 */
597static struct GNUNET_NETWORK_Handle * 1251static int
598udp_transport_server_start (void *cls) 1252udp_transport_server_start (void *cls)
599{ 1253{
600 struct Plugin *plugin = cls; 1254 struct Plugin *plugin = cls;
601 struct GNUNET_NETWORK_Handle *desc;
602 struct sockaddr_in serverAddrv4; 1255 struct sockaddr_in serverAddrv4;
603 struct sockaddr_in6 serverAddrv6; 1256 struct sockaddr_in6 serverAddrv6;
604 struct sockaddr *serverAddr; 1257 struct sockaddr *serverAddr;
605 socklen_t addrlen; 1258 socklen_t addrlen;
1259 int sockets_created;
1260
1261 /* Pipe to read from started processes stdout (on read end) */
1262 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES);
1263
1264 sockets_created = 0;
1265 if (plugin->server_stdout == NULL)
1266 return sockets_created;
1267
1268 if (plugin->behind_nat == GNUNET_YES)
1269 {
1270#if DEBUG_UDP_NAT
1271 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1272 "udp",
1273 "Starting gnunet-nat-server process\n");
1274#endif
1275 /* Start the server process */
1276 plugin->server_pid = GNUNET_OS_start_process(NULL, plugin->server_stdout, "gnunet-nat-server", "gnunet-nat-server", plugin->internal_address, NULL);
1277 if (plugin->server_pid == GNUNET_SYSERR)
1278 {
1279#if DEBUG_UDP_NAT
1280 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1281 "udp",
1282 "Failed to start gnunet-nat-server process\n");
1283#endif
1284 return GNUNET_SYSERR;
1285 }
1286 /* Close the write end of the read pipe */
1287 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1288
1289 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1290 plugin->server_read_task =
1291 GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
1292 GNUNET_TIME_UNIT_FOREVER_REL,
1293 plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1294 }
1295
1296 udp_sock.desc = NULL;
606 1297
607 desc = NULL; 1298
608 if (GNUNET_YES != 1299 udp_sock.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17);
1300 if (NULL == udp_sock.desc)
1301 {
1302 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket");
1303 return sockets_created;
1304 }
1305 else
1306 {
1307 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1308#if HAVE_SOCKADDR_IN_SIN_LEN
1309 serverAddrv4.sin_len = sizeof (serverAddrv4);
1310#endif
1311 serverAddrv4.sin_family = AF_INET;
1312 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1313 serverAddrv4.sin_port = htons (plugin->port);
1314 addrlen = sizeof (serverAddrv4);
1315 serverAddr = (struct sockaddr *) &serverAddrv4;
1316#if DEBUG_UDP_NAT
1317 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1318 "udp",
1319 "Binding to port %d\n", ntohs(serverAddrv4.sin_port));
1320#endif
1321 while (GNUNET_NETWORK_socket_bind (udp_sock.desc, serverAddr, addrlen) !=
1322 GNUNET_OK)
1323 {
1324 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1325#if DEBUG_UDP_NAT
1326 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1327 "udp",
1328 "Binding failed, trying new port %d\n", ntohs(serverAddrv4.sin_port));
1329#endif
1330 }
1331 udp_sock.port = ntohs(serverAddrv4.sin_port);
1332 sockets_created++;
1333 }
1334
1335
1336 if ((udp_sock.desc == NULL) && (GNUNET_YES !=
609 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD", 1337 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD",
610 "DISABLE-IPV6")) 1338 "DISABLE-IPV6")))
611 { 1339 {
612 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17); 1340 udp_sock.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17);
613 if (desc != NULL) 1341 if (udp_sock.desc != NULL)
614 { 1342 {
615 memset (&serverAddrv6, 0, sizeof (serverAddrv6)); 1343 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
616#if HAVE_SOCKADDR_IN_SIN_LEN 1344#if HAVE_SOCKADDR_IN_SIN_LEN
@@ -618,43 +1346,19 @@ udp_transport_server_start (void *cls)
618#endif 1346#endif
619 serverAddrv6.sin6_family = AF_INET6; 1347 serverAddrv6.sin6_family = AF_INET6;
620 serverAddrv6.sin6_addr = in6addr_any; 1348 serverAddrv6.sin6_addr = in6addr_any;
621 serverAddrv6.sin6_port = htons (plugin->open_port); 1349 serverAddrv6.sin6_port = htons (plugin->port);
622 addrlen = sizeof (serverAddrv6); 1350 addrlen = sizeof (serverAddrv6);
623 serverAddr = (struct sockaddr *) &serverAddrv6; 1351 serverAddr = (struct sockaddr *) &serverAddrv6;
1352 sockets_created++;
624 } 1353 }
625 } 1354 }
626 if (NULL == desc)
627 {
628 desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17);
629 if (NULL == desc)
630 {
631 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket");
632 return NULL;
633 }
634 else
635 {
636 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
637#if HAVE_SOCKADDR_IN_SIN_LEN
638 serverAddrv4.sin_len = sizeof (serverAddrv4);
639#endif
640 serverAddrv4.sin_family = AF_INET;
641 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
642 serverAddrv4.sin_port = htons (plugin->open_port);
643 addrlen = sizeof (serverAddrv4);
644 serverAddr = (struct sockaddr *) &serverAddrv4;
645 }
646 }
647
648 if (desc != NULL)
649 {
650 GNUNET_assert (GNUNET_NETWORK_socket_bind (desc, serverAddr, addrlen) ==
651 GNUNET_OK);
652 }
653 1355
654 plugin->rs = GNUNET_NETWORK_fdset_create (); 1356 plugin->rs = GNUNET_NETWORK_fdset_create ();
655 1357
656 GNUNET_NETWORK_fdset_zero (plugin->rs); 1358 GNUNET_NETWORK_fdset_zero (plugin->rs);
657 GNUNET_NETWORK_fdset_set (plugin->rs, desc); 1359
1360
1361 GNUNET_NETWORK_fdset_set (plugin->rs, udp_sock.desc);
658 1362
659 plugin->select_task = 1363 plugin->select_task =
660 GNUNET_SCHEDULER_add_select (plugin->env->sched, 1364 GNUNET_SCHEDULER_add_select (plugin->env->sched,
@@ -663,7 +1367,7 @@ udp_transport_server_start (void *cls)
663 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, 1367 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
664 NULL, &udp_plugin_select, plugin); 1368 NULL, &udp_plugin_select, plugin);
665 1369
666 return desc; 1370 return sockets_created;
667} 1371}
668 1372
669 1373
@@ -677,11 +1381,19 @@ udp_transport_server_start (void *cls)
677static uint16_t 1381static uint16_t
678check_port (struct Plugin *plugin, uint16_t in_port) 1382check_port (struct Plugin *plugin, uint16_t in_port)
679{ 1383{
680 if ((in_port == plugin->adv_port) || (in_port == plugin->open_port)) 1384
681 return in_port; 1385 /* FIXME: remember what ports we are using to better respond to this */
682 return (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1386 return in_port;
683 2) == 0) 1387 /*
684 ? plugin->open_port : plugin->adv_port; 1388 for (i = plugin->starting_port; i < plugin->num_ports + plugin->starting_port; i++)
1389 {
1390 if (in_port == i)
1391 return in_port;
1392 }
1393
1394 return GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1395 plugin->num_ports) + plugin->starting_port;
1396 */
685} 1397}
686 1398
687 1399
@@ -692,40 +1404,46 @@ check_port (struct Plugin *plugin, uint16_t in_port)
692 * connect to it but simply to see if the binary format is technically 1404 * connect to it but simply to see if the binary format is technically
693 * legal for establishing a connection. 1405 * legal for establishing a connection.
694 * 1406 *
695 * @param cls handle to Plugin 1407 * @param cls closure, should be our handle to the Plugin
696 * @param addr address to check 1408 * @param addr pointer to the address, may be modified (slightly)
697 * @param addrlen length of addr 1409 * @param addrlen length of addr
698 * @return GNUNET_OK if this is a plausible address for this peer 1410 * @return GNUNET_OK if this is a plausible address for this peer
699 * and transport, GNUNET_SYSERR if not 1411 * and transport, GNUNET_SYSERR if not
1412 *
700 */ 1413 */
701static int 1414static int
702udp_check_address (void *cls, void *addr, size_t addrlen) 1415udp_check_address (void *cls, void *addr, size_t addrlen)
703{ 1416{
704 struct Plugin *plugin = cls; 1417 struct Plugin *plugin = cls;
705 struct IPv4UdpAddress *v4; 1418 char buf[sizeof (struct sockaddr_in6)];
706 struct IPv6UdpAddress *v6;
707 1419
708 if ((addrlen != sizeof (struct IPv4UdpAddress)) && 1420 struct sockaddr_in *v4;
709 (addrlen != sizeof (struct IPv6UdpAddress))) 1421 struct sockaddr_in6 *v6;
1422
1423 if ((addrlen != sizeof (struct sockaddr_in)) &&
1424 (addrlen != sizeof (struct sockaddr_in6)))
710 { 1425 {
711 GNUNET_break_op (0); 1426 GNUNET_break_op (0);
712 return GNUNET_SYSERR; 1427 return GNUNET_SYSERR;
713 } 1428 }
714 if (addrlen == sizeof (struct IPv4UdpAddress)) 1429 memcpy (buf, addr, sizeof (struct sockaddr_in6));
1430 if (addrlen == sizeof (struct sockaddr_in))
715 { 1431 {
716 v4 = (struct IPv4UdpAddress *) addr; 1432 v4 = (struct sockaddr_in *) buf;
717 v4->u_port = htons (check_port (plugin, ntohs (v4->u_port))); 1433 v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port)));
718 } 1434 }
719 else 1435 else
720 { 1436 {
721 v6 = (struct IPv6UdpAddress *) addr; 1437 v6 = (struct sockaddr_in6 *) buf;
722 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) 1438 v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port)));
723 {
724 GNUNET_break_op (0);
725 return GNUNET_SYSERR;
726 }
727 v6->u6_port = htons (check_port (plugin, ntohs (v6->u6_port)));
728 } 1439 }
1440
1441#if DEBUG_UDP_NAT
1442 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1443 "udp",
1444 "Informing transport service about my address `%s'.\n",
1445 GNUNET_a2s (addr, addrlen));
1446#endif
729 return GNUNET_OK; 1447 return GNUNET_OK;
730} 1448}
731 1449
@@ -776,40 +1494,12 @@ udp_plugin_address_pretty_printer (void *cls,
776 void *asc_cls) 1494 void *asc_cls)
777{ 1495{
778 struct Plugin *plugin = cls; 1496 struct Plugin *plugin = cls;
1497 const struct sockaddr_in *v4;
1498 const struct sockaddr_in6 *v6;
779 struct PrettyPrinterContext *ppc; 1499 struct PrettyPrinterContext *ppc;
780 const void *sb;
781 struct sockaddr_in a4;
782 struct sockaddr_in6 a6;
783 const struct IPv4UdpAddress *t4;
784 const struct IPv6UdpAddress *t6;
785 size_t sbs;
786 uint16_t port;
787 1500
788 if (addrlen == sizeof (struct IPv6UdpAddress)) 1501 if ((addrlen != sizeof (struct sockaddr_in)) &&
789 { 1502 (addrlen != sizeof (struct sockaddr_in6)))
790 t6 = addr;
791 memset (&a6, 0, sizeof (a6));
792 a6.sin6_family = AF_INET6;
793 a6.sin6_port = t6->u6_port;
794 port = ntohs (t6->u6_port);
795 memcpy (&a6.sin6_addr,
796 &t6->ipv6_addr,
797 sizeof (struct in6_addr));
798 sb = &a6;
799 sbs = sizeof (a6);
800 }
801 else if (addrlen == sizeof (struct IPv4UdpAddress))
802 {
803 t4 = addr;
804 memset (&a4, 0, sizeof (a4));
805 a4.sin_family = AF_INET;
806 a4.sin_port = t4->u_port;
807 a4.sin_addr.s_addr = t4->ipv4_addr;
808 port = ntohs (t4->u_port);
809 sb = &a4;
810 sbs = sizeof (a4);
811 }
812 else
813 { 1503 {
814 /* invalid address */ 1504 /* invalid address */
815 GNUNET_break_op (0); 1505 GNUNET_break_op (0);
@@ -819,87 +1509,42 @@ udp_plugin_address_pretty_printer (void *cls,
819 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext)); 1509 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
820 ppc->asc = asc; 1510 ppc->asc = asc;
821 ppc->asc_cls = asc_cls; 1511 ppc->asc_cls = asc_cls;
822 ppc->port = port; 1512 if (addrlen == sizeof (struct sockaddr_in))
823 GNUNET_RESOLVER_hostname_get (plugin->env->sched,
824 plugin->env->cfg,
825 sb,
826 sbs,
827 !numeric, timeout, &append_port, ppc);
828}
829
830
831
832/**
833 * Function called for a quick conversion of the binary address to
834 * a numeric address. Note that the caller must not free the
835 * address and that the next call to this function is allowed
836 * to override the address again.
837 *
838 * @param cls closure
839 * @param addr binary address
840 * @param addrlen length of the address
841 * @return string representing the same address
842 */
843static const char*
844udp_address_to_string (void *cls,
845 const void *addr,
846 size_t addrlen)
847{
848 static char rbuf[INET6_ADDRSTRLEN + 10];
849 char buf[INET6_ADDRSTRLEN];
850 const void *sb;
851 struct in_addr a4;
852 struct in6_addr a6;
853 const struct IPv4UdpAddress *t4;
854 const struct IPv6UdpAddress *t6;
855 int af;
856 uint16_t port;
857
858 if (addrlen == sizeof (struct IPv6UdpAddress))
859 { 1513 {
860 t6 = addr; 1514 v4 = (const struct sockaddr_in *) addr;
861 af = AF_INET6; 1515 ppc->port = ntohs (v4->sin_port);
862 port = ntohs (t6->u6_port);
863 memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
864 sb = &a6;
865 } 1516 }
866 else if (addrlen == sizeof (struct IPv4UdpAddress)) 1517 else
867 { 1518 {
868 t4 = addr; 1519 v6 = (const struct sockaddr_in6 *) addr;
869 af = AF_INET; 1520 ppc->port = ntohs (v6->sin6_port);
870 port = ntohs (t4->u_port); 1521
871 memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
872 sb = &a4;
873 } 1522 }
874 else 1523 GNUNET_RESOLVER_hostname_get (plugin->env->sched,
875 return NULL; 1524 plugin->env->cfg,
876 inet_ntop (af, sb, buf, INET6_ADDRSTRLEN); 1525 addr,
877 GNUNET_snprintf (rbuf, 1526 addrlen,
878 sizeof (rbuf), 1527 !numeric, timeout, &append_port, ppc);
879 "%s:%u",
880 buf,
881 port);
882 return rbuf;
883} 1528}
884 1529
885 1530
886/** 1531/**
887 * The exported method. Makes the core api available via a global and 1532 * The exported method. Makes the core api available via a global and
888 * returns the udp transport API. 1533 * returns the udp transport API.
889 *
890 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
891 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
892 */ 1534 */
893void * 1535void *
894libgnunet_plugin_transport_udp_init (void *cls) 1536libgnunet_plugin_transport_udp_init (void *cls)
895{ 1537{
896 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; 1538 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1539 unsigned long long mtu;
1540 unsigned long long port;
897 struct GNUNET_TRANSPORT_PluginFunctions *api; 1541 struct GNUNET_TRANSPORT_PluginFunctions *api;
898 struct Plugin *plugin; 1542 struct Plugin *plugin;
899 struct GNUNET_SERVICE_Context *service; 1543 struct GNUNET_SERVICE_Context *service;
900 unsigned long long aport; 1544 int sockets_created;
901 unsigned long long bport; 1545 int behind_nat;
902 unsigned long long mtu; 1546 char *internal_address;
1547 char *external_address;
903 1548
904 service = GNUNET_SERVICE_start ("transport-udp", env->sched, env->cfg); 1549 service = GNUNET_SERVICE_start ("transport-udp", env->sched, env->cfg);
905 if (service == NULL) 1550 if (service == NULL)
@@ -909,29 +1554,66 @@ libgnunet_plugin_transport_udp_init (void *cls)
909 "udp"); 1554 "udp");
910 return NULL; 1555 return NULL;
911 } 1556 }
912 aport = 0; 1557
913 if ((GNUNET_OK != 1558 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
914 GNUNET_CONFIGURATION_get_value_number (env->cfg, 1559 "transport-udp",
915 "transport-udp", 1560 "BEHIND_NAT"))
916 "PORT", 1561 behind_nat = GNUNET_YES; /* We are behind nat (according to the user) */
917 &bport)) || 1562 else
918 (bport > 65535) || 1563 behind_nat = GNUNET_NO; /* We are not behind nat! */
919 ((GNUNET_OK == 1564
920 GNUNET_CONFIGURATION_get_value_number (env->cfg, 1565 external_address = NULL;
921 "transport-udp", 1566 if ((GNUNET_YES == behind_nat) && (GNUNET_OK !=
922 "ADVERTISED-PORT", 1567 GNUNET_CONFIGURATION_get_value_string (env->cfg,
923 &aport)) && (aport > 65535))) 1568 "transport-udp",
1569 "EXTERNAL_ADDRESS",
1570 &external_address)))
924 { 1571 {
925 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, 1572 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
926 "udp", 1573 "udp",
927 _ 1574 _
928 ("Require valid port number for service `%s' in configuration!\n"), 1575 ("Require EXTERNAL_ADDRESS for service `%s' in configuration!\n"),
929 "transport-udp"); 1576 "transport-udp");
930 GNUNET_SERVICE_stop (service); 1577 GNUNET_SERVICE_stop (service);
931 return NULL; 1578 return NULL;
932 } 1579 }
933 if (aport == 0) 1580
934 aport = bport; 1581 internal_address = NULL;
1582 if ((GNUNET_YES == behind_nat) && (GNUNET_OK !=
1583 GNUNET_CONFIGURATION_get_value_string (env->cfg,
1584 "transport-udp",
1585 "INTERNAL_ADDRESS",
1586 &internal_address)))
1587 {
1588 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
1589 "udp",
1590 _
1591 ("Require INTERNAL_ADDRESS for service `%s' in configuration!\n"),
1592 "transport-udp");
1593 GNUNET_SERVICE_stop (service);
1594 GNUNET_free_non_null(external_address);
1595 return NULL;
1596 }
1597
1598 if (GNUNET_OK !=
1599 GNUNET_CONFIGURATION_get_value_number (env->cfg,
1600 "transport-udp",
1601 "PORT",
1602 &port))
1603 port = UDP_NAT_DEFAULT_PORT;
1604 else if (port > 65535)
1605 {
1606 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
1607 "udp",
1608 _("Given `%s' option is out of range: %llu > %u\n"),
1609 "PORT",
1610 port,
1611 65535);
1612 GNUNET_SERVICE_stop (service);
1613 GNUNET_free_non_null(external_address);
1614 GNUNET_free_non_null(internal_address);
1615 return NULL;
1616 }
935 1617
936 mtu = 1240; 1618 mtu = 1240;
937 if (mtu < 1200) 1619 if (mtu < 1200)
@@ -941,9 +1623,12 @@ libgnunet_plugin_transport_udp_init (void *cls)
941 "UDP"); 1623 "UDP");
942 1624
943 plugin = GNUNET_malloc (sizeof (struct Plugin)); 1625 plugin = GNUNET_malloc (sizeof (struct Plugin));
944 plugin->open_port = bport; 1626 plugin->external_address = external_address;
945 plugin->adv_port = aport; 1627 plugin->internal_address = internal_address;
1628 plugin->port = port;
1629 plugin->behind_nat = behind_nat;
946 plugin->env = env; 1630 plugin->env = env;
1631
947 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 1632 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
948 api->cls = plugin; 1633 api->cls = plugin;
949 1634
@@ -951,11 +1636,9 @@ libgnunet_plugin_transport_udp_init (void *cls)
951 api->disconnect = &udp_disconnect; 1636 api->disconnect = &udp_disconnect;
952 api->address_pretty_printer = &udp_plugin_address_pretty_printer; 1637 api->address_pretty_printer = &udp_plugin_address_pretty_printer;
953 api->check_address = &udp_check_address; 1638 api->check_address = &udp_check_address;
954 api->address_to_string = &udp_address_to_string; 1639
955 plugin->service = service; 1640 plugin->service = service;
956 1641
957 /* FIXME: do the two calls below periodically again and
958 not just once (since the info we get might change...) */
959 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin); 1642 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
960 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->sched, 1643 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->sched,
961 env->cfg, 1644 env->cfg,
@@ -964,13 +1647,14 @@ libgnunet_plugin_transport_udp_init (void *cls)
964 &process_hostname_ips, 1647 &process_hostname_ips,
965 plugin); 1648 plugin);
966 1649
967 udp_sock = udp_transport_server_start (plugin); 1650 sockets_created = udp_transport_server_start (plugin);
968 1651
969 GNUNET_assert (udp_sock != NULL); 1652 GNUNET_assert (sockets_created == 1);
970 1653
971 return api; 1654 return api;
972} 1655}
973 1656
1657
974void * 1658void *
975libgnunet_plugin_transport_udp_done (void *cls) 1659libgnunet_plugin_transport_udp_done (void *cls)
976{ 1660{
@@ -978,10 +1662,10 @@ libgnunet_plugin_transport_udp_done (void *cls)
978 struct Plugin *plugin = api->cls; 1662 struct Plugin *plugin = api->cls;
979 1663
980 udp_transport_server_stop (plugin); 1664 udp_transport_server_stop (plugin);
981 if (NULL != plugin->hostname_dns) 1665 if (NULL != hostname_dns)
982 { 1666 {
983 GNUNET_RESOLVER_request_cancel (plugin->hostname_dns); 1667 GNUNET_RESOLVER_request_cancel (hostname_dns);
984 plugin->hostname_dns = NULL; 1668 hostname_dns = NULL;
985 } 1669 }
986 GNUNET_SERVICE_stop (plugin->service); 1670 GNUNET_SERVICE_stop (plugin->service);
987 1671
diff --git a/src/transport/plugin_transport_udp_nat.c b/src/transport/plugin_transport_udp_nat.c
deleted file mode 100644
index 5f225a91c..000000000
--- a/src/transport/plugin_transport_udp_nat.c
+++ /dev/null
@@ -1,1676 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2010 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 2, 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 transport/plugin_transport_udp.c
23 * @brief Implementation of the UDP NAT punching
24 * transport service
25 * @author Christian Grothoff
26 * @author Nathan Evans
27 *
28 * The idea with this transport is to connect gnunet peers to each other
29 * when ONE is behind a NAT. This is based on pwnat (http://samy.pl/pwnat)
30 * created by Samy Kamkar. When configured with the PWNAT options, this
31 * transport will start a server daemon which sends dummy ICMP and UDP
32 * messages out to a predefined address (typically 1.2.3.4).
33 *
34 * When a non-NAT'd peer (the client) learns of the NAT'd peer (the server)
35 * address, it will send ICMP RESPONSES to the NAT'd peers external address.
36 * The NAT box should forward these faked responses to the server, which
37 * can then connect directly to the non-NAT'd peer.
38 */
39
40#include "platform.h"
41#include "gnunet_hello_lib.h"
42#include "gnunet_connection_lib.h"
43#include "gnunet_os_lib.h"
44#include "gnunet_peerinfo_service.h"
45#include "gnunet_protocols.h"
46#include "gnunet_resolver_service.h"
47#include "gnunet_server_lib.h"
48#include "gnunet_service_lib.h"
49#include "gnunet_signatures.h"
50#include "gnunet_statistics_service.h"
51#include "gnunet_transport_service.h"
52#include "plugin_transport.h"
53#include "transport.h"
54
55#define DEBUG_UDP_NAT GNUNET_YES
56
57#define MAX_PROBES 20
58
59/*
60 * Transport cost to peer, always 1 for UDP (direct connection)
61 */
62#define UDP_DIRECT_DISTANCE 1
63
64/**
65 * Handle for request of hostname resolution, non-NULL if pending.
66 */
67static struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
68
69/**
70 * How long until we give up on transmitting the welcome message?
71 */
72#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
73
74/**
75 * Starting port for listening and sending, eventually a config value
76 */
77#define UDP_NAT_DEFAULT_PORT 22086
78
79/**
80 * UDP Message-Packet header.
81 */
82struct UDPMessage
83{
84 /**
85 * Message header.
86 */
87 struct GNUNET_MessageHeader header;
88
89 /**
90 * What is the identity of the sender (GNUNET_hash of public key)
91 */
92 struct GNUNET_PeerIdentity sender;
93
94};
95
96
97/* Forward definition */
98struct Plugin;
99
100struct PrettyPrinterContext
101{
102 GNUNET_TRANSPORT_AddressStringCallback asc;
103 void *asc_cls;
104 uint16_t port;
105};
106
107struct MessageQueue
108{
109 /**
110 * Linked List
111 */
112 struct MessageQueue *next;
113
114 /**
115 * Session this message belongs to
116 */
117 struct PeerSession *session;
118
119 /**
120 * Actual message to be sent
121 */
122 char *msgbuf;
123
124 /**
125 * Size of message buffer to be sent
126 */
127 size_t msgbuf_size;
128
129 /**
130 * When to discard this message
131 */
132 struct GNUNET_TIME_Absolute timeout;
133
134 /**
135 * Continuation to call when this message goes out
136 */
137 GNUNET_TRANSPORT_TransmitContinuation cont;
138
139 /**
140 * closure for continuation
141 */
142 void *cont_cls;
143
144};
145
146/**
147 * UDP NAT Probe message definition
148 */
149struct UDP_NAT_ProbeMessage
150{
151 /**
152 * Message header
153 */
154 struct GNUNET_MessageHeader header;
155
156};
157
158/**
159 * UDP NAT Probe message reply definition
160 */
161struct UDP_NAT_ProbeMessageReply
162{
163 /**
164 * Message header
165 */
166 struct GNUNET_MessageHeader header;
167
168};
169
170
171/**
172 * UDP NAT Probe message confirm definition
173 */
174struct UDP_NAT_ProbeMessageConfirmation
175{
176 /**
177 * Message header
178 */
179 struct GNUNET_MessageHeader header;
180
181};
182
183
184
185/**
186 * UDP NAT "Session"
187 */
188struct PeerSession
189{
190
191 /**
192 * Stored in a linked list.
193 */
194 struct PeerSession *next;
195
196 /**
197 * Pointer to the global plugin struct.
198 */
199 struct Plugin *plugin;
200
201 /**
202 * To whom are we talking to (set to our identity
203 * if we are still waiting for the welcome message)
204 */
205 struct GNUNET_PeerIdentity target;
206
207 /**
208 * Address of the other peer (either based on our 'connect'
209 * call or on our 'accept' call).
210 */
211 void *connect_addr;
212
213 /**
214 * Length of connect_addr.
215 */
216 size_t connect_alen;
217
218 /**
219 * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO)
220 */
221 int expecting_welcome;
222
223 /**
224 * From which socket do we need to send to this peer?
225 */
226 struct GNUNET_NETWORK_Handle *sock;
227
228 /*
229 * Queue of messages for this peer, in the case that
230 * we have to await a connection...
231 */
232 struct MessageQueue *messages;
233
234};
235
236struct UDP_NAT_Probes
237{
238
239 /**
240 * Linked list
241 */
242 struct UDP_NAT_Probes *next;
243
244 /**
245 * Address string that the server process returned to us
246 */
247 char *address_string;
248
249 /**
250 * Timeout for this set of probes
251 */
252 struct GNUNET_TIME_Absolute timeout;
253
254 /**
255 * Count of how many probes we've attempted
256 */
257 int count;
258
259 /**
260 * The plugin this probe belongs to
261 */
262 struct Plugin *plugin;
263
264 /**
265 * The task used to send these probes
266 */
267 GNUNET_SCHEDULER_TaskIdentifier task;
268
269 /**
270 * Network address (always ipv4)
271 */
272 struct sockaddr_in sock_addr;
273
274 /**
275 * The port to send this probe to, 0 to choose randomly
276 */
277 int port;
278
279};
280
281
282/**
283 * Encapsulation of all of the state of the plugin.
284 */
285struct Plugin
286{
287 /**
288 * Our environment.
289 */
290 struct GNUNET_TRANSPORT_PluginEnvironment *env;
291
292 /**
293 * Handle to the network service.
294 */
295 struct GNUNET_SERVICE_Context *service;
296
297 /*
298 * Session of peers with whom we are currently connected
299 */
300 struct PeerSession *sessions;
301
302 /**
303 * Handle for request of hostname resolution, non-NULL if pending.
304 */
305 struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
306
307 /**
308 * ID of task used to update our addresses when one expires.
309 */
310 GNUNET_SCHEDULER_TaskIdentifier address_update_task;
311
312 /**
313 * ID of select task
314 */
315 GNUNET_SCHEDULER_TaskIdentifier select_task;
316
317 /**
318 * Port to listen on.
319 */
320 uint16_t port;
321
322 /**
323 * The external address given to us by the user. Must be actual
324 * outside visible address for NAT punching to work.
325 */
326 char *external_address;
327
328 /**
329 * The internal address given to us by the user (or discovered).
330 */
331 char *internal_address;
332
333 /*
334 * FD Read set
335 */
336 struct GNUNET_NETWORK_FDSet *rs;
337
338 /*
339 * stdout pipe handle for the gnunet-nat-server process
340 */
341 struct GNUNET_DISK_PipeHandle *server_stdout;
342
343 /*
344 * stdout file handle (for reading) for the gnunet-nat-server process
345 */
346 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
347
348 /**
349 * ID of select gnunet-nat-server stdout read task
350 */
351 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
352
353 /**
354 * Is this transport configured to be behind a NAT?
355 */
356 int behind_nat;
357
358 /**
359 * The process id of the server process (if behind NAT)
360 */
361 pid_t server_pid;
362
363 /**
364 * Probes in flight
365 */
366 struct UDP_NAT_Probes *probes;
367
368};
369
370
371struct UDP_Sock_Info
372{
373 /* The network handle */
374 struct GNUNET_NETWORK_Handle *desc;
375
376 /* The port we bound to */
377 int port;
378};
379
380/* *********** globals ************* */
381
382/**
383 * the socket that we transmit all data with
384 */
385static struct UDP_Sock_Info udp_nat_sock;
386
387
388/**
389 * Forward declaration.
390 */
391void
392udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result);
393
394
395/**
396 * Disconnect from a remote node. Clean up session if we have one for this peer
397 *
398 * @param cls closure for this call (should be handle to Plugin)
399 * @param target the peeridentity of the peer to disconnect
400 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
401 */
402void
403udp_nat_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
404{
405 /** TODO: Implement! */
406 return;
407}
408
409/**
410 * Shutdown the server process (stop receiving inbound traffic). Maybe
411 * restarted later!
412 *
413 * @param cls Handle to the plugin for this transport
414 *
415 * @return returns the number of sockets successfully closed,
416 * should equal the number of sockets successfully opened
417 */
418static int
419udp_nat_transport_server_stop (void *cls)
420{
421 struct Plugin *plugin = cls;
422 int ret;
423 int ok;
424
425 ret = 0;
426 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
427 {
428 GNUNET_SCHEDULER_cancel (plugin->env->sched, plugin->select_task);
429 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
430 }
431
432
433 ok = GNUNET_NETWORK_socket_close (udp_nat_sock.desc);
434 if (ok == GNUNET_OK)
435 udp_nat_sock.desc = NULL;
436 ret += ok;
437
438
439 if (plugin->behind_nat == GNUNET_YES)
440 {
441 if (0 != PLIBC_KILL (plugin->server_pid, SIGTERM))
442 {
443 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
444 }
445 GNUNET_OS_process_wait (plugin->server_pid);
446 }
447
448 if (ret != GNUNET_OK)
449 return GNUNET_SYSERR;
450 return ret;
451}
452
453
454struct PeerSession *
455find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer)
456{
457 struct PeerSession *pos;
458
459 pos = plugin->sessions;
460 while (pos != NULL)
461 {
462 if (memcmp(&pos->target, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
463 return pos;
464 pos = pos->next;
465 }
466
467 return pos;
468}
469
470
471/**
472 * Actually send out the message, assume we've got the address and
473 * send_handle squared away!
474 *
475 * @param cls closure
476 * @param send_handle which handle to send message on
477 * @param target who should receive this message (ignored by UDP)
478 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
479 * @param msgbuf_size the size of the msgbuf to send
480 * @param priority how important is the message (ignored by UDP)
481 * @param timeout when should we time out (give up) if we can not transmit?
482 * @param addr the addr to send the message to, needs to be a sockaddr for us
483 * @param addrlen the len of addr
484 * @param cont continuation to call once the message has
485 * been transmitted (or if the transport is ready
486 * for the next transmission call; or if the
487 * peer disconnected...)
488 * @param cont_cls closure for cont
489 * @return the number of bytes written
490 */
491static ssize_t
492udp_nat_real_send (void *cls,
493 struct GNUNET_NETWORK_Handle *send_handle,
494 const struct GNUNET_PeerIdentity *target,
495 const char *msgbuf,
496 size_t msgbuf_size,
497 unsigned int priority,
498 struct GNUNET_TIME_Relative timeout,
499 const void *addr,
500 size_t addrlen,
501 GNUNET_TRANSPORT_TransmitContinuation cont,
502 void *cont_cls)
503{
504 struct Plugin *plugin = cls;
505 struct UDPMessage *message;
506 int ssize;
507 ssize_t sent;
508
509 if ((addr == NULL) || (addrlen == 0))
510 {
511#if DEBUG_UDP_NAT
512 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
513 ("udp_nat_plugin_send called without address, returning!\n"));
514#endif
515 cont (cont_cls, target, GNUNET_SYSERR);
516 return 0; /* Can never send if we don't have an address!! */
517 }
518
519 /* Build the message to be sent */
520 message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size);
521 ssize = sizeof (struct UDPMessage) + msgbuf_size;
522
523 message->header.size = htons (ssize);
524 message->header.type = htons (0);
525 memcpy (&message->sender, plugin->env->my_identity,
526 sizeof (struct GNUNET_PeerIdentity));
527 memcpy (&message[1], msgbuf, msgbuf_size);
528
529 /* Actually send the message */
530 sent =
531 GNUNET_NETWORK_socket_sendto (send_handle, message, ssize,
532 addr,
533 addrlen);
534
535 if (cont != NULL)
536 {
537 if (sent == GNUNET_SYSERR)
538 cont (cont_cls, target, GNUNET_SYSERR);
539 else
540 {
541 cont (cont_cls, target, GNUNET_OK);
542 }
543 }
544
545 GNUNET_free (message);
546 return sent;
547}
548
549/**
550 * We learned about a peer (possibly behind NAT) so run the
551 * gnunet-nat-client to send dummy ICMP responses
552 *
553 * @param plugin the plugin for this transport
554 * @param addr the address of the peer
555 * @param addrlen the length of the address
556 */
557void
558run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen)
559{
560 char inet4[INET_ADDRSTRLEN];
561 char *address_as_string;
562 char *port_as_string;
563 pid_t pid;
564 const struct sockaddr *sa = (const struct sockaddr *)addr;
565
566 if (addrlen < sizeof (struct sockaddr))
567 return;
568 switch (sa->sa_family)
569 {
570 case AF_INET:
571 if (addrlen != sizeof (struct sockaddr_in))
572 return;
573 inet_ntop (AF_INET,
574 &((struct sockaddr_in *) sa)->sin_addr,
575 inet4, INET_ADDRSTRLEN);
576 address_as_string = GNUNET_strdup (inet4);
577 break;
578 case AF_INET6:
579 default:
580 return;
581 }
582
583 GNUNET_asprintf(&port_as_string, "%d", plugin->port);
584#if DEBUG_UDP_NAT
585 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
586 _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->port);
587#endif
588 /* Start the server process */
589 pid = GNUNET_OS_start_process(NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL);
590 GNUNET_free(address_as_string);
591 GNUNET_free(port_as_string);
592 GNUNET_OS_process_wait (pid);
593}
594
595/**
596 * Function that can be used by the transport service to transmit
597 * a message using the plugin.
598 *
599 * @param cls closure
600 * @param target who should receive this message (ignored by UDP)
601 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
602 * @param msgbuf_size the size of the msgbuf to send
603 * @param priority how important is the message (ignored by UDP)
604 * @param timeout when should we time out (give up) if we can not transmit?
605 * @param session identifier used for this session (can be NULL)
606 * @param addr the addr to send the message to, needs to be a sockaddr for us
607 * @param addrlen the len of addr
608 * @param force_address not used, we had better have an address to send to
609 * because we are stateless!!
610 * @param cont continuation to call once the message has
611 * been transmitted (or if the transport is ready
612 * for the next transmission call; or if the
613 * peer disconnected...)
614 * @param cont_cls closure for cont
615 *
616 * @return the number of bytes written (may return 0 and the message can
617 * still be transmitted later!)
618 */
619static ssize_t
620udp_nat_plugin_send (void *cls,
621 const struct GNUNET_PeerIdentity *target,
622 const char *msgbuf,
623 size_t msgbuf_size,
624 unsigned int priority,
625 struct GNUNET_TIME_Relative timeout,
626 struct Session *session,
627 const void *addr,
628 size_t addrlen,
629 int force_address,
630 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
631{
632 struct Plugin *plugin = cls;
633 ssize_t sent;
634 struct MessageQueue *temp_message;
635 struct PeerSession *peer_session;
636 struct sockaddr_in *sockaddr = (struct sockaddr_in *)addr;
637 int other_peer_natd;
638
639 GNUNET_assert (NULL == session);
640 other_peer_natd = GNUNET_NO;
641 if ((sockaddr->sin_family == AF_INET) && (ntohs(sockaddr->sin_port) == 0))
642 {
643 other_peer_natd = GNUNET_YES;
644 }
645
646 sent = 0;
647
648 if (other_peer_natd == GNUNET_YES)
649 {
650 peer_session = find_session(plugin, target);
651 if (peer_session == NULL) /* We have a new peer to add */
652 {
653 /*
654 * The first time, we can assume we have no knowledge of a
655 * working port for this peer, call the ICMP/UDP message sender
656 * and wait...
657 */
658 peer_session = GNUNET_malloc(sizeof(struct PeerSession));
659 peer_session->connect_addr = GNUNET_malloc(addrlen);
660 memcpy(peer_session->connect_addr, addr, addrlen);
661 peer_session->connect_alen = addrlen;
662 peer_session->plugin = plugin;
663 peer_session->sock = NULL;
664 memcpy(&peer_session->target, target, sizeof(struct GNUNET_PeerIdentity));
665 peer_session->expecting_welcome = GNUNET_YES;
666
667 peer_session->next = plugin->sessions;
668 plugin->sessions = peer_session;
669
670 peer_session->messages = GNUNET_malloc(sizeof(struct MessageQueue));
671 peer_session->messages->msgbuf = GNUNET_malloc(msgbuf_size);
672 memcpy(peer_session->messages->msgbuf, msgbuf, msgbuf_size);
673 peer_session->messages->msgbuf_size = msgbuf_size;
674 peer_session->messages->next = NULL;
675 peer_session->messages->timeout = GNUNET_TIME_relative_to_absolute(timeout);
676 peer_session->messages->cont = cont;
677 peer_session->messages->cont_cls = cont_cls;
678#if DEBUG_UDP_NAT
679 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
680 _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target));
681#endif
682 run_gnunet_nat_client(plugin, addr, addrlen);
683 }
684 else
685 {
686 if (peer_session->expecting_welcome == GNUNET_NO) /* We are "connected" */
687 {
688 sent = udp_nat_real_send(cls, peer_session->sock, target, msgbuf, msgbuf_size, priority, timeout, peer_session->connect_addr, peer_session->connect_alen, cont, cont_cls);
689 }
690 else /* Haven't gotten a response from this peer, queue message */
691 {
692 temp_message = GNUNET_malloc(sizeof(struct MessageQueue));
693 temp_message->msgbuf = GNUNET_malloc(msgbuf_size);
694 memcpy(temp_message->msgbuf, msgbuf, msgbuf_size);
695 temp_message->msgbuf_size = msgbuf_size;
696 temp_message->timeout = GNUNET_TIME_relative_to_absolute(timeout);
697 temp_message->cont = cont;
698 temp_message->cont_cls = cont_cls;
699 temp_message->next = peer_session->messages;
700 peer_session->messages = temp_message;
701 }
702 }
703 }
704 else /* Other peer not behind a NAT, so we can just send the message as is */
705 {
706 sent = udp_nat_real_send(cls, udp_nat_sock.desc, target, msgbuf, msgbuf_size, priority, timeout, addr, addrlen, cont, cont_cls);
707 }
708
709 if (sent == GNUNET_SYSERR)
710 return 0;
711
712 return sent;
713}
714
715
716/**
717 * Add the IP of our network interface to the list of
718 * our external IP addresses.
719 */
720static int
721process_interfaces (void *cls,
722 const char *name,
723 int isDefault,
724 const struct sockaddr *addr, socklen_t addrlen)
725{
726 struct Plugin *plugin = cls;
727 int af;
728 struct sockaddr_in *v4;
729 struct sockaddr_in6 *v6;
730
731 af = addr->sa_family;
732 if (af == AF_INET)
733 {
734 v4 = (struct sockaddr_in *) addr;
735 if (plugin->behind_nat == GNUNET_YES)
736 {
737 GNUNET_assert(inet_pton(AF_INET, plugin->external_address, &v4->sin_addr) == GNUNET_OK);
738 v4->sin_port = htons (0); /* Indicates to receiver we are behind NAT */
739 }
740 else
741 v4->sin_port = htons (plugin->port);
742 }
743 else
744 {
745 GNUNET_assert (af == AF_INET6);
746 v6 = (struct sockaddr_in6 *) addr;
747 if (plugin->behind_nat == GNUNET_YES)
748 v6->sin6_port = htons (0);
749 else
750 v6->sin6_port = htons (plugin->port);
751 }
752
753 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
754 GNUNET_ERROR_TYPE_BULK,
755 "udp-nat", _("Found address `%s' (%s)\n"),
756 GNUNET_a2s (addr, addrlen), name);
757 plugin->env->notify_address (plugin->env->cls,
758 "udp_nat",
759 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL);
760
761 return GNUNET_OK;
762}
763
764
765/**
766 * Function called by the resolver for each address obtained from DNS
767 * for our own hostname. Add the addresses to the list of our
768 * external IP addresses.
769 *
770 * @param cls closure
771 * @param addr one of the addresses of the host, NULL for the last address
772 * @param addrlen length of the address
773 */
774static void
775process_hostname_ips (void *cls,
776 const struct sockaddr *addr, socklen_t addrlen)
777{
778 struct Plugin *plugin = cls;
779
780 if (addr == NULL)
781 {
782 plugin->hostname_dns = NULL;
783 return;
784 }
785 process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen);
786}
787
788
789/**
790 * Send UDP probe messages or UDP keepalive messages, depending on the
791 * state of the connection.
792 *
793 * @param cls closure for this call (should be the main Plugin)
794 * @param tc task context for running this
795 */
796static void
797send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
798{
799 struct UDP_NAT_Probes *probe = cls;
800 struct UDP_NAT_ProbeMessage *message;
801 struct Plugin *plugin = probe->plugin;
802
803 message = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessage));
804 message->header.size = htons(sizeof(struct UDP_NAT_ProbeMessage));
805 message->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE);
806 /* If they gave us a port, use that. If not, try our port. */
807 if (probe->port != 0)
808 probe->sock_addr.sin_port = htons(probe->port);
809 else
810 probe->sock_addr.sin_port = htons(plugin->port);
811
812#if DEBUG_UDP_NAT
813 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
814 _("Sending a probe to port %d\n"), ntohs(probe->sock_addr.sin_port));
815#endif
816
817 probe->count++;
818
819 udp_nat_real_send(plugin, udp_nat_sock.desc, NULL,
820 (char *)message, ntohs(message->header.size), 0,
821 GNUNET_TIME_relative_get_unit(),
822 &probe->sock_addr, sizeof(probe->sock_addr),
823 &udp_probe_continuation, probe);
824
825 GNUNET_free(message);
826}
827
828
829/**
830 * Continuation for probe sends. If the last probe was sent
831 * "successfully", schedule sending of another one. If not,
832 *
833 */
834void
835udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result)
836{
837 struct UDP_NAT_Probes *probe = cls;
838 struct Plugin *plugin = probe->plugin;
839
840 if ((result == GNUNET_OK) && (probe->count < MAX_PROBES))
841 {
842#if DEBUG_UDP_NAT
843 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
844 _("Scheduling next probe for 10000 milliseconds\n"));
845#endif
846 probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 10000), &send_udp_probe_message, probe);
847 }
848 else /* Destroy the probe context. */
849 {
850#if DEBUG_UDP_NAT
851 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
852 _("Sending probe didn't go well...\n"));
853#endif
854 }
855}
856
857/**
858 * Find probe message by address
859 *
860 * @param plugin the plugin for this transport
861 * @param address_string the ip address as a string
862 */
863struct UDP_NAT_Probes *
864find_probe(struct Plugin *plugin, char * address_string)
865{
866 struct UDP_NAT_Probes *pos;
867
868 pos = plugin->probes;
869 while (pos != NULL)
870 if (strcmp(pos->address_string, address_string) == 0)
871 return pos;
872
873 return pos;
874}
875
876
877/*
878 * @param cls the plugin handle
879 * @param tc the scheduling context (for rescheduling this function again)
880 *
881 * We have been notified that gnunet-nat-server has written something to stdout.
882 * Handle the output, then reschedule this function to be called again once
883 * more is available.
884 *
885 */
886static void
887udp_nat_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
888{
889 struct Plugin *plugin = cls;
890 char mybuf[40];
891 ssize_t bytes;
892 memset(&mybuf, 0, sizeof(mybuf));
893 int i;
894 struct UDP_NAT_Probes *temp_probe;
895 int port;
896 char *port_start;
897 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, &mybuf, sizeof(mybuf));
898
899 if (bytes < 1)
900 {
901#if DEBUG_UDP_NAT
902 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
903 _("Finished reading from server stdout with code: %d\n"), bytes);
904#endif
905 return;
906 }
907
908 port = 0;
909 port_start = NULL;
910 for (i = 0; i < sizeof(mybuf); i++)
911 {
912 if (mybuf[i] == '\n')
913 mybuf[i] = '\0';
914
915 if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf)))
916 {
917 mybuf[i] = '\0';
918 port_start = &mybuf[i + 1];
919 }
920 }
921
922 if (port_start != NULL)
923 port = atoi(port_start);
924
925#if DEBUG_UDP_NAT
926 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
927 _("nat-server-read read: %s port %d\n"), &mybuf, port);
928#endif
929
930 /** We have received an ICMP response, ostensibly from a non-NAT'd peer
931 * that wants to connect to us! Send a message to establish a connection.
932 */
933 temp_probe = find_probe(plugin, &mybuf[0]);
934
935 if (temp_probe == NULL)
936 {
937 temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes));
938 temp_probe->address_string = strdup(&mybuf[0]);
939 temp_probe->sock_addr.sin_family = AF_INET;
940 GNUNET_assert(inet_pton(AF_INET, &mybuf[0], &temp_probe->sock_addr.sin_addr) == 1);
941 temp_probe->port = port;
942 temp_probe->next = plugin->probes;
943 temp_probe->plugin = plugin;
944 temp_probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), &send_udp_probe_message, temp_probe);
945 plugin->probes = temp_probe;
946 }
947
948 plugin->server_read_task =
949 GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
950 GNUNET_TIME_UNIT_FOREVER_REL,
951 plugin->server_stdout_handle, &udp_nat_plugin_server_read, plugin);
952
953}
954
955
956/**
957 * Demultiplexer for UDP NAT messages
958 *
959 * @param plugin the main plugin for this transport
960 * @param sender from which peer the message was received
961 * @param currhdr pointer to the header of the message
962 * @param sender_addr the address from which the message was received
963 * @param fromlen the length of the address
964 * @param sockinfo which socket did we receive the message on
965 */
966static void
967udp_nat_demultiplexer(struct Plugin *plugin, struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *currhdr, struct sockaddr_storage *sender_addr, socklen_t fromlen, struct UDP_Sock_Info *sockinfo)
968{
969 struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply;
970 struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation;
971
972 char addr_buf[INET_ADDRSTRLEN];
973 struct UDP_NAT_Probes *outgoing_probe;
974 struct PeerSession *peer_session;
975 struct MessageQueue *pending_message;
976 struct MessageQueue *pending_message_temp;
977
978 if (memcmp(sender, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
979 {
980#if DEBUG_UDP_NAT
981 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
982 _("Received a message from myself, dropping!!!\n"));
983#endif
984 return;
985 }
986
987 switch (ntohs(currhdr->type))
988 {
989 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE:
990 /* Send probe reply */
991 outgoing_probe_reply = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageReply));
992 outgoing_probe_reply->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageReply));
993 outgoing_probe_reply->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY);
994
995#if DEBUG_UDP_NAT
996 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
997 _("Received a probe on listen port %d, sent_from port %d\n"), sockinfo->port, ntohs(((struct sockaddr_in *)sender_addr)->sin_port));
998#endif
999
1000 udp_nat_real_send(plugin, sockinfo->desc, NULL,
1001 (char *)outgoing_probe_reply,
1002 ntohs(outgoing_probe_reply->header.size), 0,
1003 GNUNET_TIME_relative_get_unit(),
1004 sender_addr, fromlen,
1005 NULL, NULL);
1006
1007#if DEBUG_UDP_NAT
1008 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
1009 _("Sent PROBE REPLY to port %d on outgoing port %d\n"), ntohs(((struct sockaddr_in *)sender_addr)->sin_port), sockinfo->port);
1010#endif
1011 GNUNET_free(outgoing_probe_reply);
1012 break;
1013 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY:
1014 /* Check for existing probe, check ports returned, send confirmation if all is well */
1015#if DEBUG_UDP_NAT
1016 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
1017 _("Received PROBE REPLY from port %d on incoming port %d\n"), ntohs(((struct sockaddr_in *)sender_addr)->sin_port), sockinfo->port);
1018#endif
1019 /* FIXME: use nonce, then IPv6 replies could work I think... */
1020 if (sender_addr->ss_family == AF_INET)
1021 {
1022 memset(&addr_buf, 0, sizeof(addr_buf));
1023 inet_ntop(AF_INET, &((struct sockaddr_in *) sender_addr)->sin_addr, addr_buf, INET_ADDRSTRLEN);
1024 outgoing_probe = find_probe(plugin, &addr_buf[0]);
1025 if (outgoing_probe != NULL)
1026 {
1027#if DEBUG_UDP_NAT
1028 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
1029 _("Sending confirmation that we were reached!\n"));
1030#endif
1031 outgoing_probe_confirmation = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
1032 outgoing_probe_confirmation->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
1033 outgoing_probe_confirmation->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM);
1034
1035 udp_nat_real_send(plugin, sockinfo->desc, NULL, (char *)outgoing_probe_confirmation, ntohs(outgoing_probe_confirmation->header.size), 0, GNUNET_TIME_relative_get_unit(), sender_addr, fromlen, NULL, NULL);
1036
1037 if (outgoing_probe->task != GNUNET_SCHEDULER_NO_TASK)
1038 {
1039 GNUNET_SCHEDULER_cancel(plugin->env->sched, outgoing_probe->task);
1040 outgoing_probe->task = GNUNET_SCHEDULER_NO_TASK;
1041 /* Schedule task to timeout and remove probe if confirmation not received */
1042 }
1043 GNUNET_free(outgoing_probe_confirmation);
1044 }
1045 else
1046 {
1047#if DEBUG_UDP_NAT
1048 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat",
1049 _("Received a probe reply, but have no record of a sent probe!\n"));
1050#endif
1051 }
1052 }
1053 break;
1054 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM:
1055 peer_session = find_session(plugin, sender);
1056#if DEBUG_UDP_NAT
1057 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
1058 _("Looking up peer session for peer %s\n"), GNUNET_i2s(sender));
1059#endif
1060 if (peer_session == NULL) /* Shouldn't this NOT happen? */
1061 {
1062#if DEBUG_UDP_NAT
1063 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
1064 _("Peer not in list, adding (THIS MAY BE A MISTAKE) %s\n"), GNUNET_i2s(sender));
1065#endif
1066 peer_session = GNUNET_malloc(sizeof(struct PeerSession));
1067 peer_session->connect_addr = GNUNET_malloc(fromlen);
1068 memcpy(peer_session->connect_addr, sender_addr, fromlen);
1069 peer_session->connect_alen = fromlen;
1070 peer_session->plugin = plugin;
1071 peer_session->sock = sockinfo->desc;
1072 memcpy(&peer_session->target, sender, sizeof(struct GNUNET_PeerIdentity));
1073 peer_session->expecting_welcome = GNUNET_NO;
1074
1075 peer_session->next = plugin->sessions;
1076 plugin->sessions = peer_session;
1077
1078 peer_session->messages = NULL;
1079 }
1080 else if (peer_session->expecting_welcome == GNUNET_YES)
1081 {
1082 peer_session->expecting_welcome = GNUNET_NO;
1083 /* FIXME: There is no way to find this based on receiving port at the moment! */
1084 peer_session->sock = sockinfo->desc; /* This may matter, not sure right now... */
1085 ((struct sockaddr_in *)peer_session->connect_addr)->sin_port = ((struct sockaddr_in *) sender_addr)->sin_port;
1086#if DEBUG_UDP_NAT
1087 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat",
1088 _("Received a probe confirmation, will send to peer on port %d\n"), ntohs(((struct sockaddr_in *)peer_session->connect_addr)->sin_port));
1089#endif
1090 if (peer_session->messages != NULL)
1091 {
1092#if DEBUG_UDP_NAT
1093 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat",
1094 _("Received a probe confirmation, sending queued messages.\n"));
1095#endif
1096 pending_message = peer_session->messages;
1097 int count = 0;
1098 while (pending_message != NULL)
1099 {
1100#if DEBUG_UDP_NAT
1101 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat",
1102 _("sending queued message %d\n"), count);
1103#endif
1104 udp_nat_real_send(plugin, peer_session->sock, &peer_session->target, pending_message->msgbuf, pending_message->msgbuf_size, 0, GNUNET_TIME_relative_get_unit(), peer_session->connect_addr, peer_session->connect_alen, pending_message->cont, pending_message->cont_cls);
1105 pending_message_temp = pending_message;
1106 pending_message = pending_message->next;
1107 GNUNET_free(pending_message_temp->msgbuf);
1108 GNUNET_free(pending_message_temp);
1109#if DEBUG_UDP_NAT
1110 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat",
1111 _("finished sending queued message %d\n"), count);
1112#endif
1113 count++;
1114 }
1115 }
1116
1117 }
1118 else
1119 {
1120#if DEBUG_UDP_NAT
1121 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat",
1122 _("Received probe confirmation for already confirmed peer!\n"));
1123#endif
1124 }
1125 /* Received confirmation, add peer with address/port specified */
1126 break;
1127 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_KEEPALIVE:
1128 /* Once we've sent NAT_PROBE_CONFIRM change to sending keepalives */
1129 /* If we receive these just ignore! */
1130 break;
1131 default:
1132 plugin->env->receive (plugin->env->cls, sender, currhdr, UDP_DIRECT_DISTANCE,
1133 NULL, (char *)sender_addr, fromlen);
1134 }
1135
1136}
1137
1138
1139/*
1140 * @param cls the plugin handle
1141 * @param tc the scheduling context (for rescheduling this function again)
1142 *
1143 * We have been notified that our writeset has something to read. We don't
1144 * know which socket needs to be read, so we have to check each one
1145 * Then reschedule this function to be called again once more is available.
1146 *
1147 */
1148static void
1149udp_nat_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1150{
1151 struct Plugin *plugin = cls;
1152 char *buf;
1153 struct UDPMessage *msg;
1154 struct GNUNET_PeerIdentity *sender;
1155 unsigned int buflen;
1156 socklen_t fromlen;
1157 struct sockaddr_storage addr;
1158 ssize_t ret;
1159 int offset;
1160 int count;
1161 int tsize;
1162
1163 char *msgbuf;
1164 const struct GNUNET_MessageHeader *currhdr;
1165
1166 buf = NULL;
1167 sender = NULL;
1168
1169 buflen = GNUNET_NETWORK_socket_recvfrom_amount (udp_nat_sock.desc);
1170
1171 if (buflen == GNUNET_NO)
1172 return;
1173
1174 buf = GNUNET_malloc (buflen);
1175 fromlen = sizeof (addr);
1176 memset (&addr, 0, fromlen);
1177 ret =
1178 GNUNET_NETWORK_socket_recvfrom (udp_nat_sock.desc, buf, buflen,
1179 (struct sockaddr *) &addr, &fromlen);
1180
1181#if DEBUG_UDP_NAT
1182 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", _
1183 ("socket_recv returned %u, src_addr_len is %u\n"), ret,
1184 fromlen);
1185#endif
1186
1187 if (ret <= 0)
1188 {
1189 GNUNET_free (buf);
1190 return;
1191 }
1192 msg = (struct UDPMessage *) buf;
1193
1194#if DEBUG_UDP_NAT
1195 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1196 ("header reports message size of %d, type %d\n"),
1197 ntohs (msg->header.size), ntohs (msg->header.type));
1198#endif
1199 if (ntohs (msg->header.size) < sizeof (struct UDPMessage))
1200 {
1201 GNUNET_free (buf);
1202 return;
1203 }
1204
1205 msgbuf = (char *)&msg[1];
1206 sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1207 memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
1208
1209 offset = 0;
1210 count = 0;
1211 tsize = ntohs (msg->header.size) - sizeof(struct UDPMessage);
1212
1213 while (offset < tsize)
1214 {
1215 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
1216#if DEBUG_UDP_NAT
1217 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1218 ("processing msg %d: type %d, size %d at offset %d\n"),
1219 count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
1220#endif
1221 udp_nat_demultiplexer(plugin, sender, currhdr, &addr, fromlen, &udp_nat_sock);
1222#if DEBUG_UDP_NAT
1223 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1224 ("processing done msg %d: type %d, size %d at offset %d\n"),
1225 count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
1226#endif
1227 offset += ntohs(currhdr->size);
1228 count++;
1229 }
1230 GNUNET_free_non_null (buf);
1231 GNUNET_free_non_null (sender);
1232
1233
1234 plugin->select_task =
1235 GNUNET_SCHEDULER_add_select (plugin->env->sched,
1236 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1237 GNUNET_SCHEDULER_NO_TASK,
1238 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1239 NULL, &udp_nat_plugin_select, plugin);
1240
1241}
1242
1243/**
1244 * Create a slew of UDP sockets. If possible, use IPv6, otherwise
1245 * try IPv4.
1246 *
1247 * @param cls closure for server start, should be a struct Plugin *
1248 *
1249 * @return number of sockets created or GNUNET_SYSERR on error
1250 */
1251static int
1252udp_nat_transport_server_start (void *cls)
1253{
1254 struct Plugin *plugin = cls;
1255 struct sockaddr_in serverAddrv4;
1256 struct sockaddr_in6 serverAddrv6;
1257 struct sockaddr *serverAddr;
1258 socklen_t addrlen;
1259 int sockets_created;
1260
1261 /* Pipe to read from started processes stdout (on read end) */
1262 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES);
1263
1264 sockets_created = 0;
1265 if (plugin->server_stdout == NULL)
1266 return sockets_created;
1267
1268 if (plugin->behind_nat == GNUNET_YES)
1269 {
1270#if DEBUG_UDP_NAT
1271 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1272 "udp_nat",
1273 "Starting gnunet-nat-server process\n");
1274#endif
1275 /* Start the server process */
1276 plugin->server_pid = GNUNET_OS_start_process(NULL, plugin->server_stdout, "gnunet-nat-server", "gnunet-nat-server", plugin->internal_address, NULL);
1277 if (plugin->server_pid == GNUNET_SYSERR)
1278 {
1279#if DEBUG_UDP_NAT
1280 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1281 "udp_nat",
1282 "Failed to start gnunet-nat-server process\n");
1283#endif
1284 return GNUNET_SYSERR;
1285 }
1286 /* Close the write end of the read pipe */
1287 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1288
1289 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1290 plugin->server_read_task =
1291 GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
1292 GNUNET_TIME_UNIT_FOREVER_REL,
1293 plugin->server_stdout_handle, &udp_nat_plugin_server_read, plugin);
1294 }
1295
1296 udp_nat_sock.desc = NULL;
1297
1298
1299 udp_nat_sock.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17);
1300 if (NULL == udp_nat_sock.desc)
1301 {
1302 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", "socket");
1303 return sockets_created;
1304 }
1305 else
1306 {
1307 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1308#if HAVE_SOCKADDR_IN_SIN_LEN
1309 serverAddrv4.sin_len = sizeof (serverAddrv4);
1310#endif
1311 serverAddrv4.sin_family = AF_INET;
1312 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1313 serverAddrv4.sin_port = htons (plugin->port);
1314 addrlen = sizeof (serverAddrv4);
1315 serverAddr = (struct sockaddr *) &serverAddrv4;
1316#if DEBUG_UDP_NAT
1317 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1318 "udp_nat",
1319 "Binding to port %d\n", ntohs(serverAddrv4.sin_port));
1320#endif
1321 while (GNUNET_NETWORK_socket_bind (udp_nat_sock.desc, serverAddr, addrlen) !=
1322 GNUNET_OK)
1323 {
1324 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1325#if DEBUG_UDP_NAT
1326 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1327 "udp_nat",
1328 "Binding failed, trying new port %d\n", ntohs(serverAddrv4.sin_port));
1329#endif
1330 }
1331 udp_nat_sock.port = ntohs(serverAddrv4.sin_port);
1332 sockets_created++;
1333 }
1334
1335
1336 if ((udp_nat_sock.desc == NULL) && (GNUNET_YES !=
1337 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD",
1338 "DISABLE-IPV6")))
1339 {
1340 udp_nat_sock.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17);
1341 if (udp_nat_sock.desc != NULL)
1342 {
1343 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1344#if HAVE_SOCKADDR_IN_SIN_LEN
1345 serverAddrv6.sin6_len = sizeof (serverAddrv6);
1346#endif
1347 serverAddrv6.sin6_family = AF_INET6;
1348 serverAddrv6.sin6_addr = in6addr_any;
1349 serverAddrv6.sin6_port = htons (plugin->port);
1350 addrlen = sizeof (serverAddrv6);
1351 serverAddr = (struct sockaddr *) &serverAddrv6;
1352 sockets_created++;
1353 }
1354 }
1355
1356 plugin->rs = GNUNET_NETWORK_fdset_create ();
1357
1358 GNUNET_NETWORK_fdset_zero (plugin->rs);
1359
1360
1361 GNUNET_NETWORK_fdset_set (plugin->rs, udp_nat_sock.desc);
1362
1363 plugin->select_task =
1364 GNUNET_SCHEDULER_add_select (plugin->env->sched,
1365 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1366 GNUNET_SCHEDULER_NO_TASK,
1367 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1368 NULL, &udp_nat_plugin_select, plugin);
1369
1370 return sockets_created;
1371}
1372
1373
1374/**
1375 * Check if the given port is plausible (must be either
1376 * our listen port or our advertised port). If it is
1377 * neither, we return one of these two ports at random.
1378 *
1379 * @return either in_port or a more plausible port
1380 */
1381static uint16_t
1382check_port (struct Plugin *plugin, uint16_t in_port)
1383{
1384
1385 /* FIXME: remember what ports we are using to better respond to this */
1386 return in_port;
1387 /*
1388 for (i = plugin->starting_port; i < plugin->num_ports + plugin->starting_port; i++)
1389 {
1390 if (in_port == i)
1391 return in_port;
1392 }
1393
1394 return GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1395 plugin->num_ports) + plugin->starting_port;
1396 */
1397}
1398
1399
1400/**
1401 * Another peer has suggested an address for this peer and transport
1402 * plugin. Check that this could be a valid address. This function
1403 * is not expected to 'validate' the address in the sense of trying to
1404 * connect to it but simply to see if the binary format is technically
1405 * legal for establishing a connection.
1406 *
1407 * @param cls closure, should be our handle to the Plugin
1408 * @param addr pointer to the address, may be modified (slightly)
1409 * @param addrlen length of addr
1410 * @return GNUNET_OK if this is a plausible address for this peer
1411 * and transport, GNUNET_SYSERR if not
1412 *
1413 */
1414static int
1415udp_nat_check_address (void *cls, void *addr, size_t addrlen)
1416{
1417 struct Plugin *plugin = cls;
1418 char buf[sizeof (struct sockaddr_in6)];
1419
1420 struct sockaddr_in *v4;
1421 struct sockaddr_in6 *v6;
1422
1423 if ((addrlen != sizeof (struct sockaddr_in)) &&
1424 (addrlen != sizeof (struct sockaddr_in6)))
1425 {
1426 GNUNET_break_op (0);
1427 return GNUNET_SYSERR;
1428 }
1429 memcpy (buf, addr, sizeof (struct sockaddr_in6));
1430 if (addrlen == sizeof (struct sockaddr_in))
1431 {
1432 v4 = (struct sockaddr_in *) buf;
1433 v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port)));
1434 }
1435 else
1436 {
1437 v6 = (struct sockaddr_in6 *) buf;
1438 v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port)));
1439 }
1440
1441#if DEBUG_UDP_NAT
1442 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1443 "udp_nat",
1444 "Informing transport service about my address `%s'.\n",
1445 GNUNET_a2s (addr, addrlen));
1446#endif
1447 return GNUNET_OK;
1448}
1449
1450
1451/**
1452 * Append our port and forward the result.
1453 */
1454static void
1455append_port (void *cls, const char *hostname)
1456{
1457 struct PrettyPrinterContext *ppc = cls;
1458 char *ret;
1459
1460 if (hostname == NULL)
1461 {
1462 ppc->asc (ppc->asc_cls, NULL);
1463 GNUNET_free (ppc);
1464 return;
1465 }
1466 GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
1467 ppc->asc (ppc->asc_cls, ret);
1468 GNUNET_free (ret);
1469}
1470
1471
1472/**
1473 * Convert the transports address to a nice, human-readable
1474 * format.
1475 *
1476 * @param cls closure
1477 * @param type name of the transport that generated the address
1478 * @param addr one of the addresses of the host, NULL for the last address
1479 * the specific address format depends on the transport
1480 * @param addrlen length of the address
1481 * @param numeric should (IP) addresses be displayed in numeric form?
1482 * @param timeout after how long should we give up?
1483 * @param asc function to call on each string
1484 * @param asc_cls closure for asc
1485 */
1486static void
1487udp_nat_plugin_address_pretty_printer (void *cls,
1488 const char *type,
1489 const void *addr,
1490 size_t addrlen,
1491 int numeric,
1492 struct GNUNET_TIME_Relative timeout,
1493 GNUNET_TRANSPORT_AddressStringCallback asc,
1494 void *asc_cls)
1495{
1496 struct Plugin *plugin = cls;
1497 const struct sockaddr_in *v4;
1498 const struct sockaddr_in6 *v6;
1499 struct PrettyPrinterContext *ppc;
1500
1501 if ((addrlen != sizeof (struct sockaddr_in)) &&
1502 (addrlen != sizeof (struct sockaddr_in6)))
1503 {
1504 /* invalid address */
1505 GNUNET_break_op (0);
1506 asc (asc_cls, NULL);
1507 return;
1508 }
1509 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
1510 ppc->asc = asc;
1511 ppc->asc_cls = asc_cls;
1512 if (addrlen == sizeof (struct sockaddr_in))
1513 {
1514 v4 = (const struct sockaddr_in *) addr;
1515 ppc->port = ntohs (v4->sin_port);
1516 }
1517 else
1518 {
1519 v6 = (const struct sockaddr_in6 *) addr;
1520 ppc->port = ntohs (v6->sin6_port);
1521
1522 }
1523 GNUNET_RESOLVER_hostname_get (plugin->env->sched,
1524 plugin->env->cfg,
1525 addr,
1526 addrlen,
1527 !numeric, timeout, &append_port, ppc);
1528}
1529
1530
1531/**
1532 * The exported method. Makes the core api available via a global and
1533 * returns the udp transport API.
1534 */
1535void *
1536libgnunet_plugin_transport_udp_nat_init (void *cls)
1537{
1538 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1539 unsigned long long mtu;
1540 unsigned long long port;
1541 struct GNUNET_TRANSPORT_PluginFunctions *api;
1542 struct Plugin *plugin;
1543 struct GNUNET_SERVICE_Context *service;
1544 int sockets_created;
1545 int behind_nat;
1546 char *internal_address;
1547 char *external_address;
1548
1549 service = GNUNET_SERVICE_start ("transport-udp-nat", env->sched, env->cfg);
1550 if (service == NULL)
1551 {
1552 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "udp_nat", _
1553 ("Failed to start service for `%s' transport plugin.\n"),
1554 "udp-nat");
1555 return NULL;
1556 }
1557
1558 if (GNUNET_OK !=
1559 GNUNET_CONFIGURATION_get_value_string (env->cfg,
1560 "transport-udp-nat",
1561 "EXTERNAL_ADDRESS",
1562 &external_address))
1563 {
1564 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
1565 "udp_nat",
1566 _
1567 ("Require EXTERNAL_ADDRESS for service `%s' in configuration!\n"),
1568 "transport-udp");
1569 GNUNET_SERVICE_stop (service);
1570 return NULL;
1571 }
1572
1573 if (GNUNET_OK !=
1574 GNUNET_CONFIGURATION_get_value_string (env->cfg,
1575 "transport-udp-nat",
1576 "INTERNAL_ADDRESS",
1577 &internal_address))
1578 {
1579 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
1580 "udp_nat",
1581 _
1582 ("Require INTERNAL_ADDRESS for service `%s' in configuration!\n"),
1583 "transport-udp");
1584 GNUNET_SERVICE_stop (service);
1585 GNUNET_free_non_null(external_address);
1586 return NULL;
1587 }
1588
1589 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
1590 "transport-udp-nat",
1591 "BEHIND_NAT"))
1592 behind_nat = GNUNET_YES; /* We are behind nat (according to the user) */
1593 else
1594 behind_nat = GNUNET_NO; /* We are not behind nat! */
1595
1596 if (GNUNET_OK !=
1597 GNUNET_CONFIGURATION_get_value_number (env->cfg,
1598 "transport-udp-nat",
1599 "PORT",
1600 &port))
1601 port = UDP_NAT_DEFAULT_PORT;
1602 else if (port > 65535)
1603 {
1604 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
1605 "udp_nat",
1606 _("Given `%s' option is out of range: %llu > %u\n"),
1607 "PORT",
1608 port,
1609 65535);
1610 GNUNET_SERVICE_stop (service);
1611 GNUNET_free_non_null(external_address);
1612 GNUNET_free_non_null(internal_address);
1613 return NULL;
1614 }
1615
1616 mtu = 1240;
1617 if (mtu < 1200)
1618 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
1619 "udp_nat",
1620 _("MTU %llu for `%s' is probably too low!\n"), mtu,
1621 "UDP");
1622
1623 plugin = GNUNET_malloc (sizeof (struct Plugin));
1624 plugin->external_address = external_address;
1625 plugin->internal_address = internal_address;
1626 plugin->port = port;
1627 plugin->behind_nat = behind_nat;
1628 plugin->env = env;
1629
1630 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1631 api->cls = plugin;
1632
1633 api->send = &udp_nat_plugin_send;
1634 api->disconnect = &udp_nat_disconnect;
1635 api->address_pretty_printer = &udp_nat_plugin_address_pretty_printer;
1636 api->check_address = &udp_nat_check_address;
1637
1638 plugin->service = service;
1639
1640 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
1641 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->sched,
1642 env->cfg,
1643 AF_UNSPEC,
1644 HOSTNAME_RESOLVE_TIMEOUT,
1645 &process_hostname_ips,
1646 plugin);
1647
1648 sockets_created = udp_nat_transport_server_start (plugin);
1649
1650 GNUNET_assert (sockets_created == 1);
1651
1652 return api;
1653}
1654
1655
1656void *
1657libgnunet_plugin_transport_udp_nat_done (void *cls)
1658{
1659 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1660 struct Plugin *plugin = api->cls;
1661
1662 udp_nat_transport_server_stop (plugin);
1663 if (NULL != hostname_dns)
1664 {
1665 GNUNET_RESOLVER_request_cancel (hostname_dns);
1666 hostname_dns = NULL;
1667 }
1668 GNUNET_SERVICE_stop (plugin->service);
1669
1670 GNUNET_NETWORK_fdset_destroy (plugin->rs);
1671 GNUNET_free (plugin);
1672 GNUNET_free (api);
1673 return NULL;
1674}
1675
1676/* end of plugin_transport_udp.c */
diff --git a/src/transport/test_transport_api_udp_nat_peer1.conf b/src/transport/test_transport_api_udp_nat_peer1.conf
index 0956c83eb..7c52dcd78 100644
--- a/src/transport/test_transport_api_udp_nat_peer1.conf
+++ b/src/transport/test_transport_api_udp_nat_peer1.conf
@@ -1,6 +1,6 @@
1[transport-udp-nat] 1[transport-udp]
2PORT = 12368 2PORT = 12368
3BEHIND_NAT = YES 3BEHIND_NAT = NO
4INTERNAL_ADDRESS = 127.0.0.1 4INTERNAL_ADDRESS = 127.0.0.1
5EXTERNAL_ADDRESS = 127.0.0.1 5EXTERNAL_ADDRESS = 127.0.0.1
6 6
@@ -36,11 +36,12 @@ MINIMUM-FRIENDS = 0
36AUTOSTART = NO 36AUTOSTART = NO
37 37
38[transport] 38[transport]
39PLUGINS = udp_nat 39PLUGINS = udp
40DEBUG = NO 40DEBUG = NO
41ACCEPT_FROM6 = ::1; 41ACCEPT_FROM6 = ::1;
42ACCEPT_FROM = 127.0.0.1; 42ACCEPT_FROM = 127.0.0.1;
43NEIGHBOUR_LIMIT = 50 43NEIGHBOUR_LIMIT = 50
44#BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport
44BINARY = gnunet-service-transport 45BINARY = gnunet-service-transport
45CONFIG = $DEFAULTCONFIG 46CONFIG = $DEFAULTCONFIG
46HOME = $SERVICEHOME 47HOME = $SERVICEHOME
diff --git a/src/transport/test_transport_api_udp_nat_peer2.conf b/src/transport/test_transport_api_udp_nat_peer2.conf
index 3dc4d672b..23cae9e9c 100644
--- a/src/transport/test_transport_api_udp_nat_peer2.conf
+++ b/src/transport/test_transport_api_udp_nat_peer2.conf
@@ -1,4 +1,4 @@
1[transport-udp-nat] 1[transport-udp]
2PORT = 22368 2PORT = 22368
3BEHIND_NAT = NO 3BEHIND_NAT = NO
4EXTERNAL_ADDRESS = 127.0.0.1 4EXTERNAL_ADDRESS = 127.0.0.1
@@ -33,19 +33,21 @@ MINIMUM-FRIENDS = 0
33AUTOSTART = NO 33AUTOSTART = NO
34 34
35[transport] 35[transport]
36PLUGINS = udp_nat 36PLUGINS = udp
37DEBUG = NO 37DEBUG = NO
38PREFIX = 38PREFIX =
39ACCEPT_FROM6 = ::1; 39ACCEPT_FROM6 = ::1;
40ACCEPT_FROM = 127.0.0.1; 40ACCEPT_FROM = 127.0.0.1;
41NEIGHBOUR_LIMIT = 50 41NEIGHBOUR_LIMIT = 50
42BINARY = gnunet-service-transport 42BINARY = gnunet-service-transport
43#BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport
43CONFIG = $DEFAULTCONFIG 44CONFIG = $DEFAULTCONFIG
44HOME = $SERVICEHOME 45HOME = $SERVICEHOME
45HOSTNAME = localhost 46HOSTNAME = localhost
46PORT = 22365 47PORT = 22365
47UNIXPATH = /tmp/gnunet-p2-service-transport.sock 48UNIXPATH = /tmp/gnunet-p2-service-transport.sock
48#PREFIX = xterm -e xterm -T transport -e gdb --args 49#PREFIX = xterm -e xterm -T transport -e gdb --args
50#PREFIX = valgrind --track-origins=yes --leak-check=full --log-file=valgrind_udp_peer2.log
49 51
50[peerinfo] 52[peerinfo]
51TRUST = $SERVICEHOME/data/credit/ 53TRUST = $SERVICEHOME/data/credit/
diff --git a/src/transport/test_transport_api_udp_peer2.conf b/src/transport/test_transport_api_udp_peer2.conf
index 2259e23f7..284f09b21 100644
--- a/src/transport/test_transport_api_udp_peer2.conf
+++ b/src/transport/test_transport_api_udp_peer2.conf
@@ -41,7 +41,7 @@ CONFIG = $DEFAULTCONFIG
41HOME = $SERVICEHOME 41HOME = $SERVICEHOME
42HOSTNAME = localhost 42HOSTNAME = localhost
43PORT = 22365 43PORT = 22365
44UNIXPATH = /tmp/gnunet-p1-service-transport.sock 44UNIXPATH = /tmp/gnunet-p2-service-transport.sock
45#PREFIX = valgrind --track-origins=yes --leak-check=full --log-file=valgrind_udp_peer2.log 45#PREFIX = valgrind --track-origins=yes --leak-check=full --log-file=valgrind_udp_peer2.log
46 46
47[peerinfo] 47[peerinfo]
@@ -54,7 +54,7 @@ CONFIG = $DEFAULTCONFIG
54HOME = $SERVICEHOME 54HOME = $SERVICEHOME
55HOSTNAME = localhost 55HOSTNAME = localhost
56PORT = 22369 56PORT = 22369
57UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock 57UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
58 58
59[resolver] 59[resolver]
60ACCEPT_FROM6 = ::1; 60ACCEPT_FROM6 = ::1;
@@ -64,7 +64,7 @@ CONFIG = $DEFAULTCONFIG
64HOME = $SERVICEHOME 64HOME = $SERVICEHOME
65HOSTNAME = localhost 65HOSTNAME = localhost
66PORT = 22364 66PORT = 22364
67UNIXPATH = /tmp/gnunet-p1-service-resolver.sock 67UNIXPATH = /tmp/gnunet-p2-service-resolver.sock
68 68
69[statistics] 69[statistics]
70ACCEPT_FROM6 = ::1; 70ACCEPT_FROM6 = ::1;
@@ -74,7 +74,7 @@ CONFIG = $DEFAULTCONFIG
74HOME = $SERVICEHOME 74HOME = $SERVICEHOME
75HOSTNAME = localhost 75HOSTNAME = localhost
76PORT = 22367 76PORT = 22367
77UNIXPATH = /tmp/gnunet-p1-service-statistics.sock 77UNIXPATH = /tmp/gnunet-p2-service-statistics.sock
78 78
79[arm] 79[arm]
80DEFAULTSERVICES = 80DEFAULTSERVICES =
@@ -85,7 +85,7 @@ CONFIG = $DEFAULTCONFIG
85HOME = $SERVICEHOME 85HOME = $SERVICEHOME
86HOSTNAME = localhost 86HOSTNAME = localhost
87PORT = 22366 87PORT = 22366
88UNIXPATH = /tmp/gnunet-p1-service-arm.sock 88UNIXPATH = /tmp/gnunet-p2-service-arm.sock
89 89
90[transport-tcp] 90[transport-tcp]
91TIMEOUT = 300000 91TIMEOUT = 300000