GNUnet  0.10.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(GNUNET_TIME_UNIT_MINUTES, 15)
58 
63 #define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 30)
64 
69 #define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
70 
71 
80 
85 
90 
94  void *cb_cls;
95 };
96 
97 
102 
107 
113 
118 
123 static struct in_addr mini_external_ipv4;
124 
125 
133 static void
135  const struct in_addr *v4)
136 {
137  for (struct GN_ExternalIPMonitor *mon = mon_head;
138  NULL != mon;
139  mon = mon->next)
140  mon->cb(mon->cb_cls,
141  v4,
142  add);
143 }
144 
145 
152 static void
153 run_external_ip(void *cls);
154 
155 
165 static void
167  const struct in_addr *addr,
169 {
170  char buf[INET_ADDRSTRLEN];
171 
172  probe_external_ip_op = NULL;
173  GNUNET_SCHEDULER_cancel(probe_external_ip_task);
174  probe_external_ip_task
175  = GNUNET_SCHEDULER_add_delayed((NULL == addr)
179  NULL);
180  switch (result)
181  {
183  GNUNET_assert(NULL != addr);
184  if (addr->s_addr == mini_external_ipv4.s_addr)
185  return; /* not change */
187  "Our external IP is now %s\n",
188  inet_ntop(AF_INET,
189  addr,
190  buf,
191  sizeof(buf)));
192  if (0 != mini_external_ipv4.s_addr)
195  mini_external_ipv4 = *addr;
198  break;
199 
200  default:
201  if (0 != mini_external_ipv4.s_addr)
204  mini_external_ipv4.s_addr = 0;
205  break;
206  }
207 }
208 
209 
216 static void
217 run_external_ip(void *cls)
218 {
219  probe_external_ip_task
222  NULL);
223  if (NULL != probe_external_ip_op)
224  {
225  GNUNET_NAT_mini_get_external_ipv4_cancel_(probe_external_ip_op);
226  probe_external_ip_op = NULL;
227  }
228  probe_external_ip_op
230  NULL);
231 }
232 
233 
240 void
242 {
243  if (GNUNET_YES != enable_upnp)
244  return;
245  if ((GNUNET_YES == have_nat) &&
246  (NULL == probe_external_ip_task) &&
247  (NULL == probe_external_ip_op))
248  {
249  probe_external_ip_task
251  NULL);
252  return;
253  }
254  if (GNUNET_NO == have_nat)
255  {
256  if (NULL != probe_external_ip_task)
257  {
258  GNUNET_SCHEDULER_cancel(probe_external_ip_task);
259  probe_external_ip_task = NULL;
260  }
261  if (NULL != probe_external_ip_op)
262  {
263  GNUNET_NAT_mini_get_external_ipv4_cancel_(probe_external_ip_op);
264  probe_external_ip_op = NULL;
265  }
266  }
267 }
268 
269 
277 struct GN_ExternalIPMonitor *
279  void *cb_cls)
280 {
281  struct GN_ExternalIPMonitor *mon;
282 
283  mon = GNUNET_new(struct GN_ExternalIPMonitor);
284  mon->cb = cb;
285  mon->cb_cls = cb_cls;
287  mon_tail,
288  mon);
289  if (0 != mini_external_ipv4.s_addr)
290  cb(cb_cls,
292  GNUNET_YES);
293  return mon;
294 }
295 
296 
302 void
304 {
306  mon_tail,
307  mon);
308  GNUNET_free(mon);
309 }
310 
311 /* 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:1237
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:1264
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:131
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:956
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.