GNUnet 0.22.2
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 "gnunet_util_lib.h"
35#include "gnunet_protocols.h"
36#include "gnunet_nat_service.h"
38#include "nat-auto.h"
39#include <gcrypt.h>
40
41
45#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply ( \
46 GNUNET_TIME_UNIT_SECONDS, 5)
47
48
52struct ClientHandle
53{
58
63
68
72 struct GNUNET_MQ_Handle *mq;
73};
74
75
80{
85
90
95
100
105
110
117
122
127};
128
129
133static struct ClientHandle *ch_head;
134
138static struct ClientHandle *ch_tail;
139
144
149
153static const struct GNUNET_CONFIGURATION_Handle *cfg;
154
159
160
169static int
171 const struct
173{
174 return GNUNET_OK; /* checked later */
175}
176
177
183static void
185{
186 if (NULL != ac->timeout_task)
187 {
189 ac->timeout_task = NULL;
190 }
191}
192
193
200static void
202{
203 struct AutoconfigContext *ac = cls;
204 struct ClientHandle *ch = ac->ch;
206 struct GNUNET_MQ_Envelope *env;
207 size_t c_size;
208 char *buf;
209 struct GNUNET_CONFIGURATION_Handle *diff;
210
211 ac->timeout_task = NULL;
213
214 /* Send back response */
216 ac->c);
218 &c_size);
221 c_size,
223 arm->status_code = htonl ((uint32_t) ac->status_code);
224 arm->type = htonl ((uint32_t) ac->type);
225 GNUNET_memcpy (&arm[1],
226 buf,
227 c_size);
228 GNUNET_free (buf);
230 env);
231
232 /* clean up */
236 ac_tail,
237 ac);
238 GNUNET_free (ac);
240}
241
242
249static void
251{
253 ac->timeout_task
255 ac);
256}
257
258
264static void
266{
267 switch (ac->enable_upnpc)
268 {
269 case GNUNET_YES:
271 "NAT",
272 "ENABLE_UPNP",
273 "YES");
274 break;
275
276 case GNUNET_NO:
278 "NAT",
279 "ENABLE_UPNP",
280 "NO");
281 break;
282
283 case GNUNET_SYSERR:
284 /* We are unsure, do not change option */
285 break;
286 }
287}
288
289
297static void
299 const struct
301{
302 struct ClientHandle *ch = cls;
303 size_t left = ntohs (message->header.size) - sizeof(*message);
304 struct AutoconfigContext *ac;
305
306 ac = GNUNET_new (struct AutoconfigContext);
308 ac->ch = ch;
310 if (GNUNET_OK !=
312 (const char *) &message[1],
313 left,
314 NULL))
315 {
316 GNUNET_break (0);
319 GNUNET_free (ac);
320 return;
321 }
323 "Received REQUEST_AUTO_CONFIG message from client\n");
324
326 ac_tail,
327 ac);
328 ac->orig
330 ac->timeout_task
333 ac);
334 ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
335
336 /* Probe for upnpc */
337 if (GNUNET_SYSERR ==
339 GNUNET_NO,
340 NULL))
341 {
343 _ ("UPnP client `upnpc` command not found, disabling UPnP\n"));
345 }
346 else
347 {
348 /* We might at some point be behind NAT, try upnpc */
350 }
352
353 /* Finally, check if we are already done */
355}
356
357
363static void
364shutdown_task (void *cls)
365{
366 struct AutoconfigContext *ac;
367
368 while (NULL != (ac = ac_head))
369 {
371 ac_tail,
372 ac);
374 GNUNET_free (ac);
375 }
376 if (NULL != stats)
377 {
379 GNUNET_NO);
380 stats = NULL;
381 }
382}
383
384
392static void
393run (void *cls,
394 const struct GNUNET_CONFIGURATION_Handle *c,
396{
397 cfg = c;
399 NULL);
400 stats = GNUNET_STATISTICS_create ("nat-auto",
401 cfg);
402}
403
404
413static void *
415 struct GNUNET_SERVICE_Client *c,
416 struct GNUNET_MQ_Handle *mq)
417{
418 struct ClientHandle *ch;
419
420 ch = GNUNET_new (struct ClientHandle);
421 ch->mq = mq;
422 ch->client = c;
424 ch_tail,
425 ch);
426 return ch;
427}
428
429
437static void
439 struct GNUNET_SERVICE_Client *c,
440 void *internal_cls)
441{
442 struct ClientHandle *ch = internal_cls;
443
445 ch_tail,
446 ch);
447 GNUNET_free (ch);
448}
449
450
456 "nat-auto",
458 &run,
461 NULL,
462 GNUNET_MQ_hd_var_size (autoconfig_request,
465 NULL),
467
468
469#if defined(__linux__) && defined(__GLIBC__)
470#include <malloc.h>
471
472void __attribute__((constructor)) GNUNET_NAT_memory_init (void);
473
477void __attribute__ ((constructor))
478GNUNET_NAT_memory_init ()
479{
480 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
481 mallopt (M_TOP_PAD, 1 * 1024);
482 malloc_trim (0);
483}
484
485
486#endif
487
488/* end of gnunet-service-nat.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct AutoconfigContext * ac_tail
DLL of our autoconfiguration operations.
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.
static void conclude_autoconfig_request(void *cls)
Finish handling the autoconfiguration request and send the response to the client.
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 struct ClientHandle * ch_head
Head of client DLL.
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "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.
static struct AutoconfigContext * ac_head
DLL of our autoconfiguration operations.
static void update_enable_upnpc_option(struct AutoconfigContext *ac)
Update ENABLE_UPNPC configuration option.
#define AUTOCONFIG_TIMEOUT
How long do we wait until we forcefully terminate autoconfiguration?
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
static struct ClientHandle * ch_tail
Tail of client DLL.
static void shutdown_task(void *cls)
Task run during shutdown.
static void terminate_ac_activities(struct AutoconfigContext *ac)
Stop all pending activities with respect to the ac.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Setup NAT service.
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...
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.
struct GNUNET_PQ_ResultSpec __attribute__
Constants for network protocols.
API to create, modify and access statistics.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(const struct GNUNET_OS_ProjectData *pd)
Create a new configuration object.
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_deserialize(struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *source_filename)
De-serializes configuration.
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
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_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
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:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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:61
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
GNUNET_NAT_StatusCode
Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
GNUNET_NAT_Type
What the situation of the NAT connectivity.
@ GNUNET_NAT_ERROR_SUCCESS
Just the default.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
#define GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
Message from NAT service with the autoconfiguration result.
#define GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG
Message to ask NAT service to request autoconfiguration.
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,...
Definition: scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
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:1304
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:1277
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2418
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Context for autoconfiguration operations.
struct AutoconfigContext * prev
Kept in a DLL.
struct AutoconfigContext * next
Kept in a DLL.
int enable_upnpc
GNUNET_YES if upnpc should be used, GNUNET_NO if upnpc should not be used, GNUNET_SYSERR if we should...
struct GNUNET_CONFIGURATION_Handle * c
Configuration we are creating.
enum GNUNET_NAT_Type type
NAT type to return to the client.
struct GNUNET_CONFIGURATION_Handle * orig
Original configuration (for diffing).
enum GNUNET_NAT_StatusCode status_code
Status code to return to the client.
struct ClientHandle * ch
Which client asked the question.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task to force termination.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct ClientHandle * prev
Kept in a DLL.
struct ClientHandle * next
Kept in a DLL.
struct GNUNET_SERVICE_Client * client
The handle to this client.
struct GNUNET_MQ_Handle * mq
The message queue to this client.
struct GNUNET_MQ_Handle * mq
Message Queue for the channel (which we are implementing).
Definition: cadet.h:142
Handle to a message queue.
Definition: mq.c:87
Client requesting automatic configuration.
Definition: nat-auto.h:71
struct GNUNET_MessageHeader header
Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG.
Definition: nat-auto.h:75
Service responding with proposed configuration.
Definition: nat-auto.h:85
int32_t type
An enum GNUNET_NAT_Type in NBO.
Definition: nat-auto.h:99
int32_t status_code
An enum GNUNET_NAT_StatusCode in NBO.
Definition: nat-auto.h:94
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a client that is connected to a service.
Definition: service.c:249
Handle to a service.
Definition: service.c:116
Handle for the service.