GNUnet  0.11.x
gnunet-service-nat_externalip.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2015, 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  */
36 #include "platform.h"
37 #include <math.h>
38 #include "gnunet_util_lib.h"
39 #include "gnunet_protocols.h"
40 #include "gnunet_signatures.h"
43 #include "gnunet_nat_service.h"
44 #include "gnunet-service-nat.h"
49 #include "nat.h"
50 #include <gcrypt.h>
51 
52 
57 #define EXTERN_IP_RETRY_TIMEOUT GNUNET_TIME_relative_multiply ( \
58  GNUNET_TIME_UNIT_MINUTES, 15)
59 
64 #define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply ( \
65  GNUNET_TIME_UNIT_MINUTES, 30)
66 
71 #define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply ( \
72  GNUNET_TIME_UNIT_MINUTES, 5)
73 
74 
79 {
84 
89 
94 
98  void *cb_cls;
99 };
100 
101 
106 
111 
117 
122 
127 static struct in_addr mini_external_ipv4;
128 
129 
137 static void
139  const struct in_addr *v4)
140 {
141  for (struct GN_ExternalIPMonitor *mon = mon_head;
142  NULL != mon;
143  mon = mon->next)
144  mon->cb (mon->cb_cls,
145  v4,
146  add);
147 }
148 
149 
156 static void
157 run_external_ip (void *cls);
158 
159 
169 static void
171  const struct in_addr *addr,
173 {
174  char buf[INET_ADDRSTRLEN];
175 
176  probe_external_ip_op = NULL;
177  GNUNET_SCHEDULER_cancel (probe_external_ip_task);
178  probe_external_ip_task
179  = GNUNET_SCHEDULER_add_delayed ((NULL == addr)
183  NULL);
184  switch (result)
185  {
187  GNUNET_assert (NULL != addr);
188  if (addr->s_addr == mini_external_ipv4.s_addr)
189  return; /* not change */
191  "Our external IP is now %s\n",
192  inet_ntop (AF_INET,
193  addr,
194  buf,
195  sizeof(buf)));
196  if (0 != mini_external_ipv4.s_addr)
199  mini_external_ipv4 = *addr;
202  break;
203 
204  default:
205  if (0 != mini_external_ipv4.s_addr)
208  mini_external_ipv4.s_addr = 0;
209  break;
210  }
211 }
212 
213 
220 static void
221 run_external_ip (void *cls)
222 {
223  probe_external_ip_task
226  NULL);
227  if (NULL != probe_external_ip_op)
228  {
229  GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
230  probe_external_ip_op = NULL;
231  }
232  probe_external_ip_op
234  NULL);
235 }
236 
237 
244 void
245 GN_nat_status_changed (int have_nat)
246 {
247  if (GNUNET_YES != enable_upnp)
248  return;
249  if ((GNUNET_YES == have_nat) &&
250  (NULL == probe_external_ip_task) &&
251  (NULL == probe_external_ip_op))
252  {
253  probe_external_ip_task
255  NULL);
256  return;
257  }
258  if (GNUNET_NO == have_nat)
259  {
260  if (NULL != probe_external_ip_task)
261  {
262  GNUNET_SCHEDULER_cancel (probe_external_ip_task);
263  probe_external_ip_task = NULL;
264  }
265  if (NULL != probe_external_ip_op)
266  {
267  GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
268  probe_external_ip_op = NULL;
269  }
270  }
271 }
272 
273 
281 struct GN_ExternalIPMonitor *
283  void *cb_cls)
284 {
285  struct GN_ExternalIPMonitor *mon;
286 
287  mon = GNUNET_new (struct GN_ExternalIPMonitor);
288  mon->cb = cb;
289  mon->cb_cls = cb_cls;
290  GNUNET_CONTAINER_DLL_insert (mon_head,
291  mon_tail,
292  mon);
293  if (0 != mini_external_ipv4.s_addr)
294  cb (cb_cls,
296  GNUNET_YES);
297  return mon;
298 }
299 
300 
306 void
308 {
309  GNUNET_CONTAINER_DLL_remove (mon_head,
310  mon_tail,
311  mon);
312  GNUNET_free (mon);
313 }
314 
315 
316 /* end of gnunet-service-nat_externalip.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
Opaque handle to cancel "GNUNET_NAT_mini_get_external_ipv4" operation.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void(* GN_NotifyExternalIPv4Change)(void *cls, const struct in_addr *ip, int add_remove)
Function we call when we believe our external IPv4 address changed.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void run_external_ip(void *cls)
Task used to run external-ip to get our external IPv4 address and pass it to NATed clients if possibl...
void GN_external_ipv4_monitor_stop(struct GN_ExternalIPMonitor *mon)
Stop calling monitor.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define EXTERN_IP_RETRY_SUCCESS
How long do we wait until we re-try running external-ip if the command succeeded? ...
#define GNUNET_new(type)
Allocate a struct or union of the given type.
runs the gnunet-helper-nat-server
Handle to monitor for external IP changes.
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:1253
struct GN_ExternalIPMonitor * next
Kept in DLL.
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:1280
network address translation traversal service
GNUNET_NAT_StatusCode
Error Types for the NAT subsystem (which can then later be converted/resolved to a string) ...
static char buf[2048]
static int result
Global testing status.
static struct in_addr mini_external_ipv4
What is our external IP address as claimed by external-ip? 0 for unknown.
Code to figure out what our external IPv4 address(es) might be (external IPv4s are what is seen on th...
struct GNUNET_NAT_ExternalHandle * GNUNET_NAT_mini_get_external_ipv4_(GNUNET_NAT_IPCallback cb, void *cb_cls)
Try to get the external IPv4 address of this peer.
static struct GN_ExternalIPMonitor * mon_head
List of monitors, kept in DLL.
#define EXTERN_IP_RETRY_TIMEOUT
How long do we wait until we re-try running external-ip if the command failed to terminate nicely...
static int add
Desired action is to add a record.
GN_NotifyExternalIPv4Change cb
Function to call when we believe our external IPv4 address changed.
struct GN_ExternalIPMonitor * prev
Kept in DLL.
static struct GNUNET_SCHEDULER_Task * probe_external_ip_task
Task run to obtain our external IP (if enable_upnp is set and if we find we have a NATed IP address)...
int enable_upnp
Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled...
Messages for interaction with gnunet-nat-server and gnunet-nat-service.
static void handle_external_ip(void *cls, const struct in_addr *addr, enum GNUNET_NAT_StatusCode result)
We learn our current external IP address.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
static struct GNUNET_NAT_ExternalHandle * probe_external_ip_op
Handle to our operation to run external-ip.
#define GNUNET_YES
Definition: gnunet_common.h:77
This code provides some support for doing STUN transactions.
struct GN_ExternalIPMonitor * GN_external_ipv4_monitor_start(GN_NotifyExternalIPv4Change cb, void *cb_cls)
Start monitoring external IPv4 addresses.
void GN_nat_status_changed(int have_nat)
We have changed our opinion about being NATed in the first place.
#define EXTERN_IP_RETRY_FAILURE
How long do we wait until we re-try running external-ip if the command failed (but terminated)...
static struct GN_ExternalIPMonitor * mon_tail
List of monitors, kept in DLL.
void GNUNET_NAT_mini_get_external_ipv4_cancel_(struct GNUNET_NAT_ExternalHandle *eh)
Cancel operation.
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
static void notify_monitors_external_ipv4_change(int add, const struct in_addr *v4)
Tell relevant clients about a change in our external IPv4 address.