GNUnet  0.11.x
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 #include "nat-auto.h"
31 
32 
36 struct ClientData
37 {
42 
47 };
48 
49 
53 static const struct GNUNET_CONFIGURATION_Handle *cfg;
54 
55 
63 static void
64 try_anat (uint32_t dst_ipv4,
65  uint16_t dport,
66  int is_tcp)
67 {
68  struct GNUNET_NAT_Handle *h;
69  struct sockaddr_in lsa;
70  struct sockaddr_in rsa;
71  const struct sockaddr *sa;
72  socklen_t sa_len;
73 
75  "Asking for connection reversal with %x and code %u\n",
76  (unsigned int) dst_ipv4,
77  (unsigned int) dport);
78  memset (&lsa, 0, sizeof(lsa));
79  lsa.sin_family = AF_INET;
80 #if HAVE_SOCKADDR_IN_SIN_LEN
81  lsa.sin_len = sizeof(sa);
82 #endif
83  lsa.sin_addr.s_addr = 0;
84  lsa.sin_port = htons (dport);
85  memset (&rsa, 0, sizeof(rsa));
86  rsa.sin_family = AF_INET;
87 #if HAVE_SOCKADDR_IN_SIN_LEN
88  rsa.sin_len = sizeof(sa);
89 #endif
90  rsa.sin_addr.s_addr = dst_ipv4;
91  rsa.sin_port = htons (dport);
92  sa_len = sizeof(lsa);
93  sa = (const struct sockaddr *) &lsa;
94  h = GNUNET_NAT_register (cfg,
95  "none",
96  is_tcp ? IPPROTO_TCP : IPPROTO_UDP,
97  1,
98  &sa,
99  &sa_len,
100  NULL, NULL, NULL);
102  &lsa,
103  &rsa);
105 }
106 
107 
112 {
117 
121  uint16_t data;
122 };
123 
124 
131 static void
132 tcp_send (void *cls)
133 {
134  struct TcpContext *ctx = cls;
135  const struct GNUNET_SCHEDULER_TaskContext *tc;
136 
138  if ((NULL != tc->write_ready) &&
140  {
141  if (-1 ==
142  GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof(ctx->data)))
143  {
145  }
146  GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
147  }
149  GNUNET_free (ctx);
150 }
151 
152 
161 static void
162 try_send_tcp (uint32_t dst_ipv4,
163  uint16_t dport,
164  uint16_t data)
165 {
166  struct GNUNET_NETWORK_Handle *s;
167  struct sockaddr_in sa;
168  struct TcpContext *ctx;
169 
170  s = GNUNET_NETWORK_socket_create (AF_INET,
171  SOCK_STREAM,
172  0);
173  if (NULL == s)
174  {
176  "socket");
177  return;
178  }
179  memset (&sa, 0, sizeof(sa));
180  sa.sin_family = AF_INET;
181 #if HAVE_SOCKADDR_IN_SIN_LEN
182  sa.sin_len = sizeof(sa);
183 #endif
184  sa.sin_addr.s_addr = dst_ipv4;
185  sa.sin_port = htons (dport);
187  "Sending TCP message to `%s'\n",
188  GNUNET_a2s ((struct sockaddr *) &sa,
189  sizeof(sa)));
190  if ((GNUNET_OK !=
192  (const struct sockaddr *) &sa,
193  sizeof(sa))) &&
194  (errno != EINPROGRESS))
195  {
197  "connect");
199  return;
200  }
201  ctx = GNUNET_new (struct TcpContext);
202  ctx->s = s;
203  ctx->data = data;
205  s,
206  &tcp_send,
207  ctx);
208 }
209 
210 
219 static void
220 try_send_udp (uint32_t dst_ipv4,
221  uint16_t dport,
222  uint16_t data)
223 {
224  struct GNUNET_NETWORK_Handle *s;
225  struct sockaddr_in sa;
226 
227  s = GNUNET_NETWORK_socket_create (AF_INET,
228  SOCK_DGRAM,
229  0);
230  if (NULL == s)
231  {
233  "socket");
234  return;
235  }
236  memset (&sa, 0, sizeof(sa));
237  sa.sin_family = AF_INET;
238 #if HAVE_SOCKADDR_IN_SIN_LEN
239  sa.sin_len = sizeof(sa);
240 #endif
241  sa.sin_addr.s_addr = dst_ipv4;
242  sa.sin_port = htons (dport);
244  "Sending UDP packet to `%s'\n",
245  GNUNET_a2s ((struct sockaddr *) &sa,
246  sizeof(sa)));
247  if (-1 ==
249  &data,
250  sizeof(data),
251  (const struct sockaddr *) &sa,
252  sizeof(sa)))
254  "sendto");
256 }
257 
258 
266 static void
267 handle_test (void *cls,
268  const struct GNUNET_NAT_AUTO_TestMessage *tm)
269 {
270  struct ClientData *cd = cls;
271  uint16_t dport;
272 
274  "Received test request\n");
275  dport = ntohs (tm->dport);
276  if (0 == dport)
277  try_anat (tm->dst_ipv4,
278  ntohs (tm->data),
279  (int) ntohl (tm->is_tcp));
280  else if (GNUNET_YES == ntohl (tm->is_tcp))
281  try_send_tcp (tm->dst_ipv4,
282  dport,
283  tm->data);
284  else
285  try_send_udp (tm->dst_ipv4,
286  dport,
287  tm->data);
289 }
290 
291 
299 static void
300 run (void *cls,
301  const struct GNUNET_CONFIGURATION_Handle *c,
302  struct GNUNET_SERVICE_Handle *srv)
303 {
304  cfg = c;
305 }
306 
307 
313 static void
314 force_timeout (void *cls)
315 {
316  struct ClientData *cd = cls;
317 
318  cd->tt = NULL;
320 }
321 
322 
331 static void *
332 client_connect_cb (void *cls,
333  struct GNUNET_SERVICE_Client *c,
334  struct GNUNET_MQ_Handle *mq)
335 {
336  struct ClientData *cd;
337 
338  cd = GNUNET_new (struct ClientData);
339  cd->client = c;
341  &force_timeout,
342  cd);
343  return cd;
344 }
345 
346 
354 static void
356  struct GNUNET_SERVICE_Client *c,
357  void *internal_cls)
358 {
359  struct ClientData *cd = internal_cls;
360 
361  if (NULL != cd->tt)
363  GNUNET_free (cd);
364 }
365 
366 
371  ("nat-server",
373  &run,
376  NULL,
380  NULL),
382 
383 
384 #if defined(LINUX) && defined(__GLIBC__)
385 #include <malloc.h>
386 
390 void __attribute__ ((constructor))
391 GNUNET_ARM_memory_init ()
392 {
393  mallopt (M_TRIM_THRESHOLD, 4 * 1024);
394  mallopt (M_TOP_PAD, 1 * 1024);
395  malloc_trim (0);
396 }
397 
398 
399 #endif
400 
401 
402 /* end of gnunet-nat-server.c */
struct GNUNET_NETWORK_Handle * s
TCP socket.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:747
static void try_anat(uint32_t dst_ipv4, uint16_t dport, int is_tcp)
Try contacting the peer using autonomous NAT traveral method.
Handle for active NAT registrations.
Definition: nat_api.c:71
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:657
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:816
Handle to a service.
Definition: service.c:116
Context information passed to each scheduler task.
#define GNUNET_TIME_UNIT_SECONDS
One second.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:418
static void handle_test(void *cls, const struct GNUNET_NAT_AUTO_TestMessage *tm)
We&#39;ve received a request to probe a NAT traversal.
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 ...
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.
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:1557
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_NAT_TEST
Message to ask NAT server to perform traversal test.
static void try_send_tcp(uint32_t dst_ipv4, uint16_t dport, uint16_t data)
Try to send data to the IP dst_ipv4&#39; at port dport via TCP.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
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.
int GNUNET_NETWORK_socket_shutdown(struct GNUNET_NETWORK_Handle *desc, int how)
Shut down socket operations.
Definition: network.c:940
static void force_timeout(void *cls)
Forcefully drops client after 1s.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
Handle to a client that is connected to a service.
Definition: service.c:250
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
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:1253
int 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:658
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:850
Closure for tcp_send.
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)...
int32_t is_tcp
GNUNET_YES for TCP, GNUNET_NO for UDP.
Definition: nat-auto.h:63
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2324
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:692
struct GNUNET_SERVICE_Client * client
Client handle.
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:378
uint32_t dst_ipv4
IPv4 target IP address.
Definition: nat-auto.h:48
Handle to a message queue.
Definition: mq.c:85
enum RadiotapType __attribute__
Messages for interaction with gnunet-nat-auto-service.
Information we track per client.
configuration data
Definition: configuration.c:85
static void tcp_send(void *cls)
Task called by the scheduler once we can do the TCP send (or once we failed to connect...).
uint16_t data
Data to transmit.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
uint16_t dport
Port to use, 0 to send dummy ICMP response.
Definition: nat-auto.h:53
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.
handle to a socket
Definition: network.c:52
#define GNUNET_YES
Definition: gnunet_common.h:77
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *srv)
Main function that will be run.
uint16_t data
Data to send OR advertised-port (in NBO) to use for dummy ICMP.
Definition: nat-auto.h:58
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:1029
uint32_t data
The data value.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
Request to test NAT traversal, sent to the gnunet-nat-server (not the service!).
Definition: nat-auto.h:38
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_SCHEDULER_Task * tt
Timeout task.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:912
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966