GNUnet  0.10.x
gnunet-service-nat-auto.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2016, 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 
33 #include "platform.h"
34 #include <math.h>
35 #include "gnunet_util_lib.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_signatures.h"
38 #include "gnunet_nat_service.h"
41 #include "nat-auto.h"
42 #include <gcrypt.h>
43 
44 
48 #define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
49 
50 
54 struct ClientHandle
55 {
56 
60  struct ClientHandle *next;
61 
65  struct ClientHandle *prev;
66 
71 
75  struct GNUNET_MQ_Handle *mq;
76 };
77 
78 
83 {
88 
93 
97  struct ClientHandle *ch;
98 
103 
108 
113 
120 
124  enum GNUNET_NAT_StatusCode status_code;
125 
130 };
131 
132 
136 static struct ClientHandle *ch_head;
137 
141 static struct ClientHandle *ch_tail;
142 
146 static struct AutoconfigContext *ac_head;
147 
151 static struct AutoconfigContext *ac_tail;
152 
156 static const struct GNUNET_CONFIGURATION_Handle *cfg;
157 
162 
163 
172 static int
174  const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
175 {
176  return GNUNET_OK; /* checked later */
177 }
178 
179 
185 static void
187 {
188  if (NULL != ac->timeout_task)
189  {
191  ac->timeout_task = NULL;
192  }
193 }
194 
195 
202 static void
204 {
205  struct AutoconfigContext *ac = cls;
206  struct ClientHandle *ch = ac->ch;
208  struct GNUNET_MQ_Envelope *env;
209  size_t c_size;
210  char *buf;
211  struct GNUNET_CONFIGURATION_Handle *diff;
212 
213  ac->timeout_task = NULL;
215 
216  /* Send back response */
218  ac->c);
219  buf = GNUNET_CONFIGURATION_serialize (diff,
220  &c_size);
222  env = GNUNET_MQ_msg_extra (arm,
223  c_size,
225  arm->status_code = htonl ((uint32_t) ac->status_code);
226  arm->type = htonl ((uint32_t) ac->type);
227  GNUNET_memcpy (&arm[1],
228  buf,
229  c_size);
230  GNUNET_free (buf);
231  GNUNET_MQ_send (ch->mq,
232  env);
233 
234  /* clean up */
238  ac_tail,
239  ac);
240  GNUNET_free (ac);
242 }
243 
244 
251 static void
253 {
255  ac->timeout_task
257  ac);
258 }
259 
260 
266 static void
268 {
269  switch (ac->enable_upnpc)
270  {
271  case GNUNET_YES:
273  "NAT",
274  "ENABLE_UPNP",
275  "YES");
276  break;
277  case GNUNET_NO:
279  "NAT",
280  "ENABLE_UPNP",
281  "NO");
282  break;
283  case GNUNET_SYSERR:
284  /* We are unsure, do not change option */
285  break;
286  }
287 }
288 
289 
297 static void
299  const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
300 {
301  struct ClientHandle *ch = cls;
302  size_t left = ntohs (message->header.size) - sizeof (*message);
303  struct AutoconfigContext *ac;
304 
305  ac = GNUNET_new (struct AutoconfigContext);
307  ac->ch = ch;
309  if (GNUNET_OK !=
311  (const char *) &message[1],
312  left,
313  NULL))
314  {
315  GNUNET_break (0);
318  GNUNET_free (ac);
319  return;
320  }
322  "Received REQUEST_AUTO_CONFIG message from client\n");
323 
325  ac_tail,
326  ac);
327  ac->orig
328  = GNUNET_CONFIGURATION_dup (ac->c);
329  ac->timeout_task
332  ac);
333  ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
334 
335  /* Probe for upnpc */
336  if (GNUNET_SYSERR ==
338  GNUNET_NO,
339  NULL))
340  {
342  _("UPnP client `upnpc` command not found, disabling UPnP\n"));
343  ac->enable_upnpc = GNUNET_NO;
344  }
345  else
346  {
347  /* We might at some point be behind NAT, try upnpc */
348  ac->enable_upnpc = GNUNET_YES;
349  }
351 
352  /* Finally, check if we are already done */
354 }
355 
356 
362 static void
363 shutdown_task (void *cls)
364 {
365  struct AutoconfigContext *ac;
366 
367  while (NULL != (ac = ac_head))
368  {
370  ac_tail,
371  ac);
373  GNUNET_free (ac);
374  }
375  if (NULL != stats)
376  {
378  GNUNET_NO);
379  stats = NULL;
380  }
381 }
382 
383 
391 static void
392 run (void *cls,
393  const struct GNUNET_CONFIGURATION_Handle *c,
395 {
396  cfg = c;
398  NULL);
399  stats = GNUNET_STATISTICS_create ("nat-auto",
400  cfg);
401 }
402 
403 
412 static void *
413 client_connect_cb (void *cls,
414  struct GNUNET_SERVICE_Client *c,
415  struct GNUNET_MQ_Handle *mq)
416 {
417  struct ClientHandle *ch;
418 
419  ch = GNUNET_new (struct ClientHandle);
420  ch->mq = mq;
421  ch->client = c;
423  ch_tail,
424  ch);
425  return ch;
426 }
427 
428 
436 static void
438  struct GNUNET_SERVICE_Client *c,
439  void *internal_cls)
440 {
441  struct ClientHandle *ch = internal_cls;
442 
444  ch_tail,
445  ch);
446  GNUNET_free (ch);
447 }
448 
449 
454 ("nat-auto",
456  &run,
459  NULL,
460  GNUNET_MQ_hd_var_size (autoconfig_request,
463  NULL),
465 
466 
467 #if defined(LINUX) && defined(__GLIBC__)
468 #include <malloc.h>
469 
473 void __attribute__ ((constructor))
474 GNUNET_ARM_memory_init ()
475 {
476  mallopt (M_TRIM_THRESHOLD, 4 * 1024);
477  mallopt (M_TOP_PAD, 1 * 1024);
478  malloc_trim (0);
479 }
480 #endif
481 
482 /* end of gnunet-service-nat.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
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 struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
#define GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
Message from NAT service with the autoconfiguration result.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
struct GNUNET_CONFIGURATION_Handle * c
Configuration we are creating.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct ClientHandle * prev
Kept in a DLL.
Handle to a service.
Definition: service.c:116
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
Client requesting automatic configuration.
Definition: nat-auto.h:72
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Setup NAT service.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
Service responding with proposed configuration.
Definition: nat-auto.h:87
static void conclude_autoconfig_request(void *cls)
Finish handling the autoconfiguration request and send the response to the client.
static void handle_autoconfig_request(void *cls, const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from client.
int enable_upnpc
GNUNET_YES if upnpc should be used, GNUNET_NO if upnpc should not be used, GNUNET_SYSERR if we should...
#define GNUNET_NO
Definition: gnunet_common.h:81
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task to force termination.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
int GNUNET_OS_check_helper_binary(const char *binary, int check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
Handle for the service.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
int32_t status_code
An enum GNUNET_NAT_StatusCode in NBO.
Definition: nat-auto.h:97
struct AutoconfigContext * prev
Kept in a DLL.
static void shutdown_task(void *cls)
Task run during shutdown.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static void check_autoconfig_finished(struct AutoconfigContext *ac)
Check if all autoconfiguration operations have concluded, and if they have, send the result back to t...
Handle to a client that is connected to a service.
Definition: service.c:249
static struct ClientHandle * ch_tail
Tail of client DLL.
static struct AutoconfigContext * ac_head
DLL of our autoconfiguration operations.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
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:1246
enum GNUNET_NAT_Type type
NAT type to return to the client.
#define GNUNET_memcpy(dst, src, n)
int32_t type
An enum GNUNET_NAT_Type in NBO.
Definition: nat-auto.h:102
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_get_diff(const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new)
Compute configuration with only entries that have been changed.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1273
Context for autoconfiguration operations.
GNUNET_NAT_StatusCode
Error Types for the NAT subsystem (which can then later be converted/resolved to a string) ...
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
static char buf[2048]
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2618
GNUNET_SERVICE_MAIN("nat-auto", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(autoconfig_request, GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG, struct GNUNET_NAT_AUTO_AutoconfigRequestMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
struct GNUNET_SERVICE_Client * client
The handle to this client.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
static void terminate_ac_activities(struct AutoconfigContext *ac)
Stop all pending activities with respect to the ac.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct GNUNET_MQ_Handle * mq
The message queue to this client.
struct AutoconfigContext * next
Kept in a DLL.
#define GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG
Message to ask NAT service to request autoconfiguration.
static int check_autoconfig_request(void *cls, const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from client.
static void update_enable_upnpc_option(struct AutoconfigContext *ac)
Update ENABLE_UPNPC configuration option.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
Handle to a message queue.
Definition: mq.c:85
enum RadiotapType __attribute__
Messages for interaction with gnunet-nat-auto-service.
configuration data
Definition: configuration.c:85
struct ClientHandle * ch
Which client asked the question.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
struct GNUNET_CONFIGURATION_Handle * orig
Original configuration (for diffing).
struct GNUNET_MessageHeader header
Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG.
Definition: nat-auto.h:77
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
#define GNUNET_YES
Definition: gnunet_common.h:80
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
GNUNET_NAT_Type
What the situation of the NAT connectivity.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
int GNUNET_CONFIGURATION_deserialize(struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *basedir)
De-serializes configuration.
enum GNUNET_NAT_StatusCode status_code
Status code to return to the client.
struct ClientHandle * next
Kept in a DLL.
#define AUTOCONFIG_TIMEOUT
How long do we wait until we forcefully terminate autoconfiguration?
static struct AutoconfigContext * ac_tail
DLL of our autoconfiguration operations.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2533
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static struct ClientHandle * ch_head
Head of client DLL.
#define GNUNET_free(ptr)
Wrapper around free.
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.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965