GNUnet 0.21.1
gnunet-nat-server.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_nat_service.h"
29#include "gnunet_protocols.h"
30// FIXME can we build this without this header?
31#include "../../service/nat-auto/nat-auto.h"
32
33
38{
43
48};
49
50
54static const struct GNUNET_CONFIGURATION_Handle *cfg;
55
56
64static void
65try_anat (uint32_t dst_ipv4,
66 uint16_t dport,
67 int is_tcp)
68{
69 struct GNUNET_NAT_Handle *h;
70 struct sockaddr_in lsa;
71 struct sockaddr_in rsa;
72 const struct sockaddr *sa;
73 socklen_t sa_len;
74
76 "Asking for connection reversal with %x and code %u\n",
77 (unsigned int) dst_ipv4,
78 (unsigned int) dport);
79 memset (&lsa, 0, sizeof(lsa));
80 lsa.sin_family = AF_INET;
81#if HAVE_SOCKADDR_IN_SIN_LEN
82 lsa.sin_len = sizeof(sa);
83#endif
84 lsa.sin_addr.s_addr = 0;
85 lsa.sin_port = htons (dport);
86 memset (&rsa, 0, sizeof(rsa));
87 rsa.sin_family = AF_INET;
88#if HAVE_SOCKADDR_IN_SIN_LEN
89 rsa.sin_len = sizeof(sa);
90#endif
91 rsa.sin_addr.s_addr = dst_ipv4;
92 rsa.sin_port = htons (dport);
93 sa_len = sizeof(lsa);
94 sa = (const struct sockaddr *) &lsa;
96 "none",
97 is_tcp ? IPPROTO_TCP : IPPROTO_UDP,
98 1,
99 &sa,
100 &sa_len,
101 NULL, NULL, NULL);
103 &lsa,
104 &rsa);
106}
107
108
113{
118
122 uint16_t data;
123};
124
125
132static void
133tcp_send (void *cls)
134{
135 struct TcpContext *ctx = cls;
136 const struct GNUNET_SCHEDULER_TaskContext *tc;
137
139 if ((NULL != tc->write_ready) &&
141 {
142 if (-1 ==
143 GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof(ctx->data)))
144 {
146 }
147 GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
148 }
151}
152
153
162static void
163try_send_tcp (uint32_t dst_ipv4,
164 uint16_t dport,
165 uint16_t data)
166{
167 struct GNUNET_NETWORK_Handle *s;
168 struct sockaddr_in sa;
169 struct TcpContext *ctx;
170
172 SOCK_STREAM,
173 0);
174 if (NULL == s)
175 {
177 "socket");
178 return;
179 }
180 memset (&sa, 0, sizeof(sa));
181 sa.sin_family = AF_INET;
182#if HAVE_SOCKADDR_IN_SIN_LEN
183 sa.sin_len = sizeof(sa);
184#endif
185 sa.sin_addr.s_addr = dst_ipv4;
186 sa.sin_port = htons (dport);
188 "Sending TCP message to `%s'\n",
189 GNUNET_a2s ((struct sockaddr *) &sa,
190 sizeof(sa)));
191 if ((GNUNET_OK !=
193 (const struct sockaddr *) &sa,
194 sizeof(sa))) &&
195 (errno != EINPROGRESS))
196 {
198 "connect");
200 return;
201 }
202 ctx = GNUNET_new (struct TcpContext);
203 ctx->s = s;
204 ctx->data = data;
206 s,
207 &tcp_send,
208 ctx);
209}
210
211
220static void
221try_send_udp (uint32_t dst_ipv4,
222 uint16_t dport,
223 uint16_t data)
224{
225 struct GNUNET_NETWORK_Handle *s;
226 struct sockaddr_in sa;
227
228 s = GNUNET_NETWORK_socket_create (AF_INET,
229 SOCK_DGRAM,
230 0);
231 if (NULL == s)
232 {
234 "socket");
235 return;
236 }
237 memset (&sa, 0, sizeof(sa));
238 sa.sin_family = AF_INET;
239#if HAVE_SOCKADDR_IN_SIN_LEN
240 sa.sin_len = sizeof(sa);
241#endif
242 sa.sin_addr.s_addr = dst_ipv4;
243 sa.sin_port = htons (dport);
245 "Sending UDP packet to `%s'\n",
246 GNUNET_a2s ((struct sockaddr *) &sa,
247 sizeof(sa)));
248 if (-1 ==
250 &data,
251 sizeof(data),
252 (const struct sockaddr *) &sa,
253 sizeof(sa)))
255 "sendto");
257}
258
259
267static void
268handle_test (void *cls,
269 const struct GNUNET_NAT_AUTO_TestMessage *tm)
270{
271 struct ClientData *cd = cls;
272 uint16_t dport;
273
275 "Received test request\n");
276 dport = ntohs (tm->dport);
277 if (0 == dport)
278 try_anat (tm->dst_ipv4,
279 ntohs (tm->data),
280 (int) ntohl (tm->is_tcp));
281 else if (GNUNET_YES == ntohl (tm->is_tcp))
283 dport,
284 tm->data);
285 else
287 dport,
288 tm->data);
290}
291
292
300static void
301run (void *cls,
302 const struct GNUNET_CONFIGURATION_Handle *c,
303 struct GNUNET_SERVICE_Handle *srv)
304{
305 cfg = c;
306}
307
308
314static void
315force_timeout (void *cls)
316{
317 struct ClientData *cd = cls;
318
319 cd->tt = NULL;
321}
322
323
332static void *
334 struct GNUNET_SERVICE_Client *c,
335 struct GNUNET_MQ_Handle *mq)
336{
337 struct ClientData *cd;
338
339 cd = GNUNET_new (struct ClientData);
340 cd->client = c;
343 cd);
344 return cd;
345}
346
347
355static void
357 struct GNUNET_SERVICE_Client *c,
358 void *internal_cls)
359{
360 struct ClientData *cd = internal_cls;
361
362 if (NULL != cd->tt)
364 GNUNET_free (cd);
365}
366
367
372 ("nat-server",
374 &run,
377 NULL,
381 NULL),
383
384
385#if defined(__linux__) && defined(__GLIBC__)
386#include <malloc.h>
387
391void __attribute__ ((constructor))
392GNUNET_ARM_memory_init ()
393{
394 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
395 mallopt (M_TOP_PAD, 1 * 1024);
396 malloc_trim (0);
397}
398
399
400#endif
401
402
403/* end of gnunet-nat-server.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static char * data
The data to insert into the dht.
static struct GNUNET_FS_Handle * ctx
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *srv)
Main function that will be run.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void handle_test(void *cls, const struct GNUNET_NAT_AUTO_TestMessage *tm)
We've received a request to probe a NAT traversal.
GNUNET_SERVICE_MAIN("nat-server", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(test, GNUNET_MESSAGE_TYPE_NAT_TEST, struct GNUNET_NAT_AUTO_TestMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static void force_timeout(void *cls)
Forcefully drops client after 1s.
static void try_send_tcp(uint32_t dst_ipv4, uint16_t dport, uint16_t data)
Try to send data to the IP dst_ipv4' at port dport via TCP.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
static void try_send_udp(uint32_t dst_ipv4, uint16_t dport, uint16_t data)
Try to send data to the IP dst_ipv4 at port dport via UDP.
static void try_anat(uint32_t dst_ipv4, uint16_t dport, int is_tcp)
Try contacting the peer using autonomous NAT traversal method.
static void tcp_send(void *cls)
Task called by the scheduler once we can do the TCP send (or once we failed to connect....
struct GNUNET_PQ_ResultSpec __attribute__
Constants for network protocols.
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_YES
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
int GNUNET_NAT_request_reversal(struct GNUNET_NAT_Handle *nh, const struct sockaddr_in *local_sa, const struct sockaddr_in *remote_sa)
We learned about a peer (possibly behind NAT) so run the gnunet-nat-client to send dummy ICMP respons...
Definition: nat_api.c:699
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition: nat_api.c:727
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:832
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_connect(const struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Connect a socket to some remote address.
Definition: network.c:601
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition: network.c:737
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_shutdown(struct GNUNET_NETWORK_Handle *desc, int how)
Shut down socket operations.
Definition: network.c:860
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition: network.c:771
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition: network.c:949
#define GNUNET_MESSAGE_TYPE_NAT_TEST
Message to ask NAT server to perform traversal test.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1583
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:758
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2489
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
#define GNUNET_TIME_UNIT_SECONDS
One second.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
Information we track per client.
struct GNUNET_SCHEDULER_Task * tt
Timeout task.
struct GNUNET_SERVICE_Client * client
Client handle.
Handle to a message queue.
Definition: mq.c:87
Request to test NAT traversal, sent to the gnunet-nat-server (not the service!).
Definition: nat-auto.h:39
uint32_t dst_ipv4
IPv4 target IP address.
Definition: nat-auto.h:48
uint16_t dport
Port to use, 0 to send dummy ICMP response.
Definition: nat-auto.h:53
int32_t is_tcp
GNUNET_YES for TCP, GNUNET_NO for UDP.
Definition: nat-auto.h:63
uint16_t data
Data to send OR advertised-port (in NBO) to use for dummy ICMP.
Definition: nat-auto.h:58
Handle for active NAT registrations.
Definition: nat_api.c:72
handle to a socket
Definition: network.c:53
Context information passed to each scheduler task.
const struct GNUNET_NETWORK_FDSet * write_ready
Set of file descriptors ready for writing; note that additional bits may be set that were not in the ...
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a client that is connected to a service.
Definition: service.c:252
Handle to a service.
Definition: service.c:118
Closure for tcp_send.
struct GNUNET_NETWORK_Handle * s
TCP socket.
uint16_t data
Data to transmit.