GNUnet 0.27.0
 
Loading...
Searching...
No Matches
gnunet-service-nat_helper.c File Reference

runs the gnunet-helper-nat-server More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet-service-nat_helper.h"
Include dependency graph for gnunet-service-nat_helper.c:

Go to the source code of this file.

Data Structures

struct  HelperContext
 Information we keep per NAT helper process. More...
 

Functions

static void restart_nat_server (void *cls)
 Task that restarts the gnunet-helper-nat-server process after a crash after a certain delay.
 
static void try_again (struct HelperContext *h)
 Try again starting the helper later.
 
static void nat_server_read (void *cls)
 We have been notified that gnunet-helper-nat-server has written something to stdout.
 
struct HelperContextGN_start_gnunet_nat_server_ (const struct in_addr *internal_address, GN_ReversalCallback cb, void *cb_cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
 Start the gnunet-helper-nat-server and process incoming requests.
 
void GN_stop_gnunet_nat_server_ (struct HelperContext *h)
 Start the gnunet-helper-nat-server and process incoming requests.
 
int GN_request_connection_reversal (const struct in_addr *internal_address, uint16_t internal_port, const struct in_addr *remote_v4, const struct GNUNET_CONFIGURATION_Handle *cfg)
 We want to connect to a peer that is behind NAT.
 

Detailed Description

runs the gnunet-helper-nat-server

Author
Milan Bouchet-Valat
Christian Grothoff

Definition in file gnunet-service-nat_helper.c.

Function Documentation

◆ restart_nat_server()

static void restart_nat_server ( void *  cls)
static

Task that restarts the gnunet-helper-nat-server process after a crash after a certain delay.

Parameters
clsa struct HelperContext

Definition at line 213 of file gnunet-service-nat_helper.c.

214{
215 struct HelperContext *h = cls;
216 char *binary;
217 char ia[INET_ADDRSTRLEN];
218
219 h->server_read_task = NULL;
220 GNUNET_assert (NULL !=
221 inet_ntop (AF_INET, &h->internal_address, ia, sizeof(ia)));
222 /* Start the server process */
224 h->cfg,
225 "gnunet-helper-nat-server");
226 if (GNUNET_YES !=
229 ia))
230 {
231 /* move instantly to max delay, as this is unlikely to be fixed */
233 GNUNET_free (binary);
234 try_again (h);
235 return;
236 }
237 h->server_stdout =
239 if (NULL == h->server_stdout)
240 {
242 GNUNET_free (binary);
243 try_again (h);
244 return;
245 }
247 "Starting `%s' at `%s'\n",
248 "gnunet-helper-nat-server",
249 ia);
253 h->server_proc,
255 STDOUT_FILENO)));
256 if (GNUNET_OK !=
257 GNUNET_process_run_command_va (h->server_proc,
258 binary,
259 "gnunet-helper-nat-server",
260 ia,
261 NULL))
262 {
263 GNUNET_process_destroy (h->server_proc);
264 h->server_proc = NULL;
265 GNUNET_free (binary);
267 _ ("Failed to start %s\n"),
268 "gnunet-helper-nat-server");
269 GNUNET_DISK_pipe_close (h->server_stdout);
270 h->server_stdout = NULL;
271 try_again (h);
272 return;
273 }
274 GNUNET_free (binary);
275 /* Close the write end of the read pipe */
276 GNUNET_DISK_pipe_close_end (h->server_stdout,
278 h->server_stdout_handle =
279 GNUNET_DISK_pipe_handle (h->server_stdout,
281 h->server_read_task =
283 h->server_stdout_handle,
285 h);
286}
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition gnunet-arm.c:98
static void nat_server_read(void *cls)
We have been notified that gnunet-helper-nat-server has written something to stdout.
static void try_again(struct HelperContext *h)
Try again starting the helper later.
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition disk.c:1703
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition disk.c:1524
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition disk.c:1671
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Closes one half of an interprocess channel.
Definition disk.c:1618
@ GNUNET_DISK_PF_BLOCKING_RW
Configure both pipe ends for blocking operations if set.
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_YES
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#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_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_free(ptr)
Wrapper around free.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_process_run_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command and start a process.
Definition os_process.c:903
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition os_process.c:363
#define GNUNET_process_set_options(proc,...)
Set the requested options for the process.
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.
char * GNUNET_OS_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
#define GNUNET_process_option_inherit_wpipe(wpipe, child_fd)
Have child process inherit a pipe for writing.
struct GNUNET_Process * GNUNET_process_create(enum GNUNET_OS_InheritStdioFlags std_inheritance)
Create a process handle.
Definition os_process.c:462
@ GNUNET_OS_INHERIT_STD_NONE
No standard streams should be inherited.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, 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:1667
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD
Threshold after which exponential backoff should not increase (15 m).
#define _(String)
GNU gettext support macro.
Definition platform.h:179
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration that we are using.
Definition arm_api.c:112
Information we keep per NAT helper process.

References _, GNUNET_ARM_Handle::cfg, GNUNET_assert, GNUNET_DISK_PF_BLOCKING_RW, GNUNET_DISK_pipe(), GNUNET_DISK_pipe_close(), GNUNET_DISK_pipe_close_end(), GNUNET_DISK_PIPE_END_READ, GNUNET_DISK_PIPE_END_WRITE, GNUNET_DISK_pipe_handle(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_OK, GNUNET_OS_check_helper_binary(), GNUNET_OS_get_suid_binary_path(), GNUNET_OS_INHERIT_STD_NONE, GNUNET_OS_project_data_gnunet(), GNUNET_process_create(), GNUNET_process_destroy(), GNUNET_process_option_inherit_wpipe, GNUNET_process_run_command_va(), GNUNET_process_set_options, GNUNET_SCHEDULER_add_read_file(), GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, h, nat_server_read(), and try_again().

Referenced by GN_start_gnunet_nat_server_(), and try_again().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_again()

static void try_again ( struct HelperContext h)
static

Try again starting the helper later.

Parameters
hcontext of the helper

Definition at line 100 of file gnunet-service-nat_helper.c.

101{
102 GNUNET_assert (NULL == h->server_read_task);
103 h->server_retry_delay = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay);
104 h->server_read_task = GNUNET_SCHEDULER_add_delayed (h->server_retry_delay,
106 h);
107}
static void restart_nat_server(void *cls)
Task that restarts the gnunet-helper-nat-server process after a crash after a certain delay.
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:1283
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...

References GNUNET_assert, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_STD_BACKOFF, h, and restart_nat_server().

Referenced by nat_server_read(), and restart_nat_server().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nat_server_read()

static void nat_server_read ( void *  cls)
static

We have been notified that gnunet-helper-nat-server has written something to stdout.

Handle the output, then reschedule this function to be called again once more is available.

Parameters
clsthe struct HelperContext

Definition at line 118 of file gnunet-service-nat_helper.c.

119{
120 struct HelperContext *h = cls;
121 char mybuf[40];
122 ssize_t bytes;
123 int port;
124 const char *port_start;
125 struct sockaddr_in sin_addr;
126
127 h->server_read_task = NULL;
128 memset (mybuf, 0, sizeof(mybuf));
129 bytes =
130 GNUNET_DISK_file_read (h->server_stdout_handle, mybuf, sizeof(mybuf));
131 if (bytes < 1)
132 {
134 "Finished reading from server stdout with code: %d\n",
135 (int) bytes);
136 if (GNUNET_OK !=
137 GNUNET_process_kill (h->server_proc,
140 "nat",
141 "kill");
142 GNUNET_process_wait (h->server_proc,
143 true,
144 NULL,
145 NULL);
146 GNUNET_process_destroy (h->server_proc);
147 h->server_proc = NULL;
148 GNUNET_DISK_pipe_close (h->server_stdout);
149 h->server_stdout = NULL;
150 h->server_stdout_handle = NULL;
151 try_again (h);
152 return;
153 }
154
155 port_start = NULL;
156 for (size_t i = 0; i < sizeof(mybuf); i++)
157 {
158 if (mybuf[i] == '\n')
159 {
160 mybuf[i] = '\0';
161 break;
162 }
163 if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf)))
164 {
165 mybuf[i] = '\0';
166 port_start = &mybuf[i + 1];
167 }
168 }
169
170 /* construct socket address of sender */
171 memset (&sin_addr, 0, sizeof(sin_addr));
172 sin_addr.sin_family = AF_INET;
173#if HAVE_SOCKADDR_IN_SIN_LEN
174 sin_addr.sin_len = sizeof(sin_addr);
175#endif
176 if ((NULL == port_start) || (1 != sscanf (port_start, "%d", &port)) ||
177 (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr)))
178 {
179 /* should we restart gnunet-helper-nat-server? */
181 _ (
182 "gnunet-helper-nat-server generated malformed address `%s'\n")
183 ,
184 mybuf);
185 h->server_read_task =
187 h->server_stdout_handle,
189 h);
190 return;
191 }
192 sin_addr.sin_port = htons ((uint16_t) port);
194 "gnunet-helper-nat-server read: %s:%d\n",
195 mybuf,
196 port);
197 h->cb (h->cb_cls, &sin_addr);
198 h->server_read_task =
200 h->server_stdout_handle,
202 h);
203}
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition disk.c:704
#define GNUNET_log_from_strerror(level, component, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
enum GNUNET_GenericReturnValue GNUNET_process_wait(struct GNUNET_Process *proc, bool blocking, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Wait for a process to terminate.
enum GNUNET_GenericReturnValue GNUNET_process_kill(struct GNUNET_Process *proc, int sig)
Sends a signal to the process.
Definition os_process.c:307
#define GNUNET_TERM_SIG
The termination signal.
Definition platform.h:235

References _, GNUNET_DISK_file_read(), GNUNET_DISK_pipe_close(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_from_strerror, GNUNET_OK, GNUNET_process_destroy(), GNUNET_process_kill(), GNUNET_process_wait(), GNUNET_SCHEDULER_add_read_file(), GNUNET_TERM_SIG, GNUNET_TIME_UNIT_FOREVER_REL, h, nat_server_read(), port, and try_again().

Referenced by nat_server_read(), and restart_nat_server().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GN_start_gnunet_nat_server_()

struct HelperContext * GN_start_gnunet_nat_server_ ( const struct in_addr *  internal_address,
GN_ReversalCallback  cb,
void *  cb_cls,
const struct GNUNET_CONFIGURATION_Handle cfg 
)

Start the gnunet-helper-nat-server and process incoming requests.

Parameters
internal_address
cbfunction to call if we receive a request
cb_clsclosure for cb
cfghandle to the GNUnet configuration
Returns
NULL on error

Definition at line 290 of file gnunet-service-nat_helper.c.

294{
295 struct HelperContext *h;
296
297 h = GNUNET_new (struct HelperContext);
298 h->cb = cb;
299 h->cb_cls = cb_cls;
300 h->internal_address = *internal_address;
301 h->cfg = cfg;
303 if (NULL == h->server_stdout)
304 {
306 return NULL;
307 }
308 return h;
309}
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition gnunet-arm.c:108
void GN_stop_gnunet_nat_server_(struct HelperContext *h)
Start the gnunet-helper-nat-server and process incoming requests.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct in_addr internal_address
IP address we pass to the NAT helper.
GN_ReversalCallback cb
Function to call if we receive a reversal request.
void * cb_cls
Closure for cb.

References HelperContext::cb, HelperContext::cb_cls, cfg, GNUNET_ARM_Handle::cfg, GN_stop_gnunet_nat_server_(), GNUNET_new, h, HelperContext::internal_address, and restart_nat_server().

Referenced by run_scan().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GN_stop_gnunet_nat_server_()

void GN_stop_gnunet_nat_server_ ( struct HelperContext h)

Start the gnunet-helper-nat-server and process incoming requests.

Parameters
hhelper context to stop

Definition at line 319 of file gnunet-service-nat_helper.c.

320{
321 if (NULL != h->server_read_task)
322 {
323 GNUNET_SCHEDULER_cancel (h->server_read_task);
324 h->server_read_task = NULL;
325 }
326 if (NULL != h->server_proc)
327 {
328 if (GNUNET_OK !=
329 GNUNET_process_kill (h->server_proc,
332 "kill");
334 GNUNET_process_wait (h->server_proc,
335 true,
336 NULL,
337 NULL));
338 GNUNET_process_destroy (h->server_proc);
339 h->server_proc = NULL;
340 GNUNET_DISK_pipe_close (h->server_stdout);
341 h->server_stdout = NULL;
342 h->server_stdout_handle = NULL;
343 }
344 if (NULL != h->server_stdout)
345 {
346 GNUNET_DISK_pipe_close (h->server_stdout);
347 h->server_stdout = NULL;
348 h->server_stdout_handle = NULL;
349 }
350 GNUNET_free (h);
351}
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986

References GNUNET_assert, GNUNET_DISK_pipe_close(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_strerror, GNUNET_OK, GNUNET_process_destroy(), GNUNET_process_kill(), GNUNET_process_wait(), GNUNET_SCHEDULER_cancel(), GNUNET_TERM_SIG, and h.

Referenced by free_lal(), and GN_start_gnunet_nat_server_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GN_request_connection_reversal()

int GN_request_connection_reversal ( const struct in_addr *  internal_address,
uint16_t  internal_port,
const struct in_addr *  remote_v4,
const struct GNUNET_CONFIGURATION_Handle cfg 
)

We want to connect to a peer that is behind NAT.

Run the gnunet-helper-nat-client to send dummy ICMP responses to cause that peer to connect to us (connection reversal).

Parameters
internal_addressout internal address to use
internal_portport to use
remote_v4the address of the peer (IPv4-only)
cfghandle to the GNUnet configuration
Returns
GNUNET_SYSERR on error, GNUNET_OK otherwise

Definition at line 367 of file gnunet-service-nat_helper.c.

371{
372 char intv4[INET_ADDRSTRLEN];
373 char remv4[INET_ADDRSTRLEN];
374 char port_as_string[6];
375 struct GNUNET_Process *proc;
376 char *binary;
377
378 if (NULL == inet_ntop (AF_INET,
379 internal_address,
380 intv4,
381 INET_ADDRSTRLEN))
382 {
384 "inet_ntop");
385 return GNUNET_SYSERR;
386 }
387 if (NULL == inet_ntop (AF_INET,
388 remote_v4,
389 remv4,
390 INET_ADDRSTRLEN))
391 {
393 "inet_ntop");
394 return GNUNET_SYSERR;
395 }
396 GNUNET_snprintf (port_as_string,
397 sizeof(port_as_string),
398 "%d",
399 internal_port);
401 "Running gnunet-helper-nat-client %s %s %u\n",
402 intv4,
403 remv4,
404 internal_port);
406 cfg,
407 "gnunet-helper-nat-client");
409 if (GNUNET_OK !=
411 proc,
412 binary,
413 "gnunet-helper-nat-client",
414 intv4,
415 remv4,
416 port_as_string,
417 NULL))
418 {
420 GNUNET_free (binary);
421 return GNUNET_SYSERR;
422 }
423 GNUNET_free (binary);
424 /* we know that the gnunet-helper-nat-client will terminate virtually
425 * instantly */
428 true,
429 NULL,
430 NULL));
432 return GNUNET_OK;
433}
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.

References cfg, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_OK, GNUNET_OS_get_suid_binary_path(), GNUNET_OS_INHERIT_STD_NONE, GNUNET_OS_project_data_gnunet(), GNUNET_process_create(), GNUNET_process_destroy(), GNUNET_process_run_command_va(), GNUNET_process_wait(), GNUNET_snprintf(), and GNUNET_SYSERR.

Referenced by handle_request_connection_reversal().

Here is the call graph for this function:
Here is the caller graph for this function: