GNUnet  0.10.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 {
41 
46 };
47 
48 
52 static const struct GNUNET_CONFIGURATION_Handle *cfg;
53 
54 
62 static void
63 try_anat(uint32_t dst_ipv4,
64  uint16_t dport,
65  int is_tcp)
66 {
67  struct GNUNET_NAT_Handle *h;
68  struct sockaddr_in lsa;
69  struct sockaddr_in rsa;
70  const struct sockaddr *sa;
71  socklen_t sa_len;
72 
74  "Asking for connection reversal with %x and code %u\n",
75  (unsigned int)dst_ipv4,
76  (unsigned int)dport);
77  memset(&lsa, 0, sizeof(lsa));
78  lsa.sin_family = AF_INET;
79 #if HAVE_SOCKADDR_IN_SIN_LEN
80  lsa.sin_len = sizeof(sa);
81 #endif
82  lsa.sin_addr.s_addr = 0;
83  lsa.sin_port = htons(dport);
84  memset(&rsa, 0, sizeof(rsa));
85  rsa.sin_family = AF_INET;
86 #if HAVE_SOCKADDR_IN_SIN_LEN
87  rsa.sin_len = sizeof(sa);
88 #endif
89  rsa.sin_addr.s_addr = dst_ipv4;
90  rsa.sin_port = htons(dport);
91  sa_len = sizeof(lsa);
92  sa = (const struct sockaddr *)&lsa;
93  h = GNUNET_NAT_register(cfg,
94  "none",
95  is_tcp ? IPPROTO_TCP : IPPROTO_UDP,
96  1,
97  &sa,
98  &sa_len,
99  NULL, NULL, NULL);
101  &lsa,
102  &rsa);
104 }
105 
106 
110 struct TcpContext {
115 
119  uint16_t data;
120 };
121 
122 
129 static void
130 tcp_send(void *cls)
131 {
132  struct TcpContext *ctx = cls;
133  const struct GNUNET_SCHEDULER_TaskContext *tc;
134 
136  if ((NULL != tc->write_ready) &&
138  {
139  if (-1 ==
140  GNUNET_NETWORK_socket_send(ctx->s, &ctx->data, sizeof(ctx->data)))
141  {
143  }
144  GNUNET_NETWORK_socket_shutdown(ctx->s, SHUT_RDWR);
145  }
147  GNUNET_free(ctx);
148 }
149 
150 
159 static void
160 try_send_tcp(uint32_t dst_ipv4,
161  uint16_t dport,
162  uint16_t data)
163 {
164  struct GNUNET_NETWORK_Handle *s;
165  struct sockaddr_in sa;
166  struct TcpContext *ctx;
167 
168  s = GNUNET_NETWORK_socket_create(AF_INET,
169  SOCK_STREAM,
170  0);
171  if (NULL == s)
172  {
174  "socket");
175  return;
176  }
177  memset(&sa, 0, sizeof(sa));
178  sa.sin_family = AF_INET;
179 #if HAVE_SOCKADDR_IN_SIN_LEN
180  sa.sin_len = sizeof(sa);
181 #endif
182  sa.sin_addr.s_addr = dst_ipv4;
183  sa.sin_port = htons(dport);
185  "Sending TCP message to `%s'\n",
186  GNUNET_a2s((struct sockaddr *)&sa,
187  sizeof(sa)));
188  if ((GNUNET_OK !=
190  (const struct sockaddr *)&sa,
191  sizeof(sa))) &&
192  (errno != EINPROGRESS))
193  {
195  "connect");
197  return;
198  }
199  ctx = GNUNET_new(struct TcpContext);
200  ctx->s = s;
201  ctx->data = data;
203  s,
204  &tcp_send,
205  ctx);
206 }
207 
208 
217 static void
218 try_send_udp(uint32_t dst_ipv4,
219  uint16_t dport,
220  uint16_t data)
221 {
222  struct GNUNET_NETWORK_Handle *s;
223  struct sockaddr_in sa;
224 
225  s = GNUNET_NETWORK_socket_create(AF_INET,
226  SOCK_DGRAM,
227  0);
228  if (NULL == s)
229  {
231  "socket");
232  return;
233  }
234  memset(&sa, 0, sizeof(sa));
235  sa.sin_family = AF_INET;
236 #if HAVE_SOCKADDR_IN_SIN_LEN
237  sa.sin_len = sizeof(sa);
238 #endif
239  sa.sin_addr.s_addr = dst_ipv4;
240  sa.sin_port = htons(dport);
242  "Sending UDP packet to `%s'\n",
243  GNUNET_a2s((struct sockaddr *)&sa,
244  sizeof(sa)));
245  if (-1 ==
247  &data,
248  sizeof(data),
249  (const struct sockaddr *)&sa,
250  sizeof(sa)))
252  "sendto");
254 }
255 
256 
264 static void
265 handle_test(void *cls,
266  const struct GNUNET_NAT_AUTO_TestMessage *tm)
267 {
268  struct ClientData *cd = cls;
269  uint16_t dport;
270 
272  "Received test request\n");
273  dport = ntohs(tm->dport);
274  if (0 == dport)
275  try_anat(tm->dst_ipv4,
276  ntohs(tm->data),
277  (int)ntohl(tm->is_tcp));
278  else if (GNUNET_YES == ntohl(tm->is_tcp))
280  dport,
281  tm->data);
282  else
284  dport,
285  tm->data);
287 }
288 
289 
297 static void
298 run(void *cls,
299  const struct GNUNET_CONFIGURATION_Handle *c,
300  struct GNUNET_SERVICE_Handle *srv)
301 {
302  cfg = c;
303 }
304 
305 
311 static void
312 force_timeout(void *cls)
313 {
314  struct ClientData *cd = cls;
315 
316  cd->tt = NULL;
318 }
319 
320 
321 
330 static void *
332  struct GNUNET_SERVICE_Client *c,
333  struct GNUNET_MQ_Handle *mq)
334 {
335  struct ClientData *cd;
336 
337  cd = GNUNET_new(struct ClientData);
338  cd->client = c;
340  &force_timeout,
341  cd);
342  return cd;
343 }
344 
345 
353 static void
355  struct GNUNET_SERVICE_Client *c,
356  void *internal_cls)
357 {
358  struct ClientData *cd = internal_cls;
359 
360  if (NULL != cd->tt)
362  GNUNET_free(cd);
363 }
364 
365 
370  ("nat-server",
372  &run,
375  NULL,
379  NULL),
381 
382 
383 #if defined(LINUX) && defined(__GLIBC__)
384 #include <malloc.h>
385 
389 void __attribute__ ((constructor))
390 GNUNET_ARM_memory_init()
391 {
392  mallopt(M_TRIM_THRESHOLD, 4 * 1024);
393  mallopt(M_TOP_PAD, 1 * 1024);
394  malloc_trim(0);
395 }
396 #endif
397 
398 
399 
400 
401 /* 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:737
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:70
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:655
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:804
Handle to a service.
Definition: service.c:114
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:410
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:1537
#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:928
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:94
Handle to a client that is connected to a service.
Definition: service.c:246
#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:1237
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:646
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:838
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:2315
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:690
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:376
uint32_t dst_ipv4
IPv4 target IP address.
Definition: nat-auto.h:48
Handle to a message queue.
Definition: mq.c:84
enum RadiotapType __attribute__
Messages for interaction with gnunet-nat-auto-service.
Information we track per client.
configuration data
Definition: configuration.c:83
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:131
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:46
#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:1017
uint32_t data
The data value.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
#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:39
#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:900
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956