GNUnet  0.20.0
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. More...
 
static void try_again (struct HelperContext *h)
 Try again starting the helper later. More...
 
static void nat_server_read (void *cls)
 We have been notified that gnunet-helper-nat-server has written something to stdout. More...
 
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. More...
 
void GN_stop_gnunet_nat_server_ (struct HelperContext *h)
 Start the gnunet-helper-nat-server and process incoming requests. More...
 
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. More...
 

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 205 of file gnunet-service-nat_helper.c.

206 {
207  struct HelperContext *h = cls;
208  char *binary;
209  char ia[INET_ADDRSTRLEN];
210 
211  h->server_read_task = NULL;
212  GNUNET_assert (NULL !=
213  inet_ntop (AF_INET, &h->internal_address, ia, sizeof(ia)));
214  /* Start the server process */
215  binary = GNUNET_OS_get_suid_binary_path (h->cfg, "gnunet-helper-nat-server");
217  {
218  /* move instantly to max delay, as this is unlikely to be fixed */
219  h->server_retry_delay = GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD;
220  GNUNET_free (binary);
221  try_again (h);
222  return;
223  }
224  h->server_stdout =
226  if (NULL == h->server_stdout)
227  {
229  GNUNET_free (binary);
230  try_again (h);
231  return;
232  }
234  "Starting `%s' at `%s'\n",
235  "gnunet-helper-nat-server",
236  ia);
238  NULL,
239  h->server_stdout,
240  NULL,
241  binary,
242  "gnunet-helper-nat-server",
243  ia,
244  NULL);
245  GNUNET_free (binary);
246  if (NULL == h->server_proc)
247  {
249  _ ("Failed to start %s\n"),
250  "gnunet-helper-nat-server");
251  GNUNET_DISK_pipe_close (h->server_stdout);
252  h->server_stdout = NULL;
253  try_again (h);
254  return;
255  }
256  /* Close the write end of the read pipe */
258  h->server_stdout_handle =
260  h->server_read_task =
262  h->server_stdout_handle,
264  h);
265 }
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
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.
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1587
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:1617
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:1534
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1444
@ 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_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.
char * GNUNET_OS_get_suid_binary_path(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 ...
struct GNUNET_OS_Process * GNUNET_OS_start_process(enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename,...)
Start a process.
Definition: os_priority.c:620
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.
@ GNUNET_OS_INHERIT_STD_NONE
No standard streams should be inherited.
Definition: gnunet_os_lib.h:77
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:1656
#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:178
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_OS_check_helper_binary(), GNUNET_OS_get_suid_binary_path(), GNUNET_OS_INHERIT_STD_NONE, GNUNET_OS_start_process(), 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:1272
#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 (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG))
138  GNUNET_OS_process_wait (h->server_proc);
139  GNUNET_OS_process_destroy (h->server_proc);
140  h->server_proc = NULL;
141  GNUNET_DISK_pipe_close (h->server_stdout);
142  h->server_stdout = NULL;
143  h->server_stdout_handle = NULL;
144  try_again (h);
145  return;
146  }
147 
148  port_start = NULL;
149  for (size_t i = 0; i < sizeof(mybuf); i++)
150  {
151  if (mybuf[i] == '\n')
152  {
153  mybuf[i] = '\0';
154  break;
155  }
156  if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf)))
157  {
158  mybuf[i] = '\0';
159  port_start = &mybuf[i + 1];
160  }
161  }
162 
163  /* construct socket address of sender */
164  memset (&sin_addr, 0, sizeof(sin_addr));
165  sin_addr.sin_family = AF_INET;
166 #if HAVE_SOCKADDR_IN_SIN_LEN
167  sin_addr.sin_len = sizeof(sin_addr);
168 #endif
169  if ((NULL == port_start) || (1 != sscanf (port_start, "%d", &port)) ||
170  (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr)))
171  {
172  /* should we restart gnunet-helper-nat-server? */
174  _ (
175  "gnunet-helper-nat-server generated malformed address `%s'\n"),
176  mybuf);
177  h->server_read_task =
179  h->server_stdout_handle,
181  h);
182  return;
183  }
184  sin_addr.sin_port = htons ((uint16_t) port);
186  "gnunet-helper-nat-server read: %s:%d\n",
187  mybuf,
188  port);
189  h->cb (h->cb_cls, &sin_addr);
190  h->server_read_task =
192  h->server_stdout_handle,
194  h);
195 }
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
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:622
#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...
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:260
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:210
enum GNUNET_GenericReturnValue GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc)
Wait for a process to terminate.
Definition: os_priority.c:871
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:234

References _, GNUNET_DISK_file_read(), GNUNET_DISK_pipe_close(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_from_strerror, GNUNET_OS_process_destroy(), GNUNET_OS_process_kill(), GNUNET_OS_process_wait(), GNUNET_SCHEDULER_add_read_file(), GNUNET_TERM_SIG, GNUNET_TIME_UNIT_FOREVER_REL, h, port, and try_again().

Referenced by 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 269 of file gnunet-service-nat_helper.c.

273 {
274  struct HelperContext *h;
275 
276  h = GNUNET_new (struct HelperContext);
277  h->cb = cb;
278  h->cb_cls = cb_cls;
279  h->internal_address = *internal_address;
280  h->cfg = cfg;
282  if (NULL == h->server_stdout)
283  {
285  return NULL;
286  }
287  return h;
288 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
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 298 of file gnunet-service-nat_helper.c.

299 {
300  if (NULL != h->server_read_task)
301  {
302  GNUNET_SCHEDULER_cancel (h->server_read_task);
303  h->server_read_task = NULL;
304  }
305  if (NULL != h->server_proc)
306  {
307  if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG))
309  GNUNET_OS_process_wait (h->server_proc);
310  GNUNET_OS_process_destroy (h->server_proc);
311  h->server_proc = NULL;
312  GNUNET_DISK_pipe_close (h->server_stdout);
313  h->server_stdout = NULL;
314  h->server_stdout_handle = NULL;
315  }
316  if (NULL != h->server_stdout)
317  {
318  GNUNET_DISK_pipe_close (h->server_stdout);
319  h->server_stdout = NULL;
320  h->server_stdout_handle = NULL;
321  }
322  GNUNET_free (h);
323 }
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975

References GNUNET_DISK_pipe_close(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_strerror, GNUNET_OS_process_destroy(), GNUNET_OS_process_kill(), GNUNET_OS_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 339 of file gnunet-service-nat_helper.c.

343 {
344  char intv4[INET_ADDRSTRLEN];
345  char remv4[INET_ADDRSTRLEN];
346  char port_as_string[6];
347  struct GNUNET_OS_Process *proc;
348  char *binary;
349 
350  if (NULL == inet_ntop (AF_INET, internal_address, intv4, INET_ADDRSTRLEN))
351  {
353  return GNUNET_SYSERR;
354  }
355  if (NULL == inet_ntop (AF_INET, remote_v4, remv4, INET_ADDRSTRLEN))
356  {
358  return GNUNET_SYSERR;
359  }
360  GNUNET_snprintf (port_as_string,
361  sizeof(port_as_string),
362  "%d",
363  internal_port);
365  "Running gnunet-helper-nat-client %s %s %u\n",
366  intv4,
367  remv4,
368  internal_port);
369  binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-nat-client");
371  NULL,
372  NULL,
373  NULL,
374  binary,
375  "gnunet-helper-nat-client",
376  intv4,
377  remv4,
378  port_as_string,
379  NULL);
380  GNUNET_free (binary);
381  if (NULL == proc)
382  return GNUNET_SYSERR;
383  /* we know that the gnunet-helper-nat-client will terminate virtually
384  * instantly */
385  GNUNET_OS_process_wait (proc);
387  return GNUNET_OK;
388 }
@ GNUNET_OK
@ GNUNET_SYSERR
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.

Referenced by handle_request_connection_reversal().

Here is the caller graph for this function: