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 
76 {
81 
86 
91 
95  void *cb_cls;
96 
97 };
98 
99 
104 
109 
115 
120 
125 static struct in_addr mini_external_ipv4;
126 
127 
135 static void
137  const struct in_addr *v4)
138 {
139  for (struct GN_ExternalIPMonitor *mon = mon_head;
140  NULL != mon;
141  mon = mon->next)
142  mon->cb (mon->cb_cls,
143  v4,
144  add);
145 }
146 
147 
154 static void
155 run_external_ip (void *cls);
156 
157 
167 static void
169  const struct in_addr *addr,
171 {
172  char buf[INET_ADDRSTRLEN];
173 
174  probe_external_ip_op = NULL;
175  GNUNET_SCHEDULER_cancel (probe_external_ip_task);
176  probe_external_ip_task
177  = GNUNET_SCHEDULER_add_delayed ((NULL == addr)
181  NULL);
182  switch (result)
183  {
185  GNUNET_assert (NULL != addr);
186  if (addr->s_addr == mini_external_ipv4.s_addr)
187  return; /* not change */
189  "Our external IP is now %s\n",
190  inet_ntop (AF_INET,
191  addr,
192  buf,
193  sizeof (buf)));
194  if (0 != mini_external_ipv4.s_addr)
197  mini_external_ipv4 = *addr;
200  break;
201  default:
202  if (0 != mini_external_ipv4.s_addr)
205  mini_external_ipv4.s_addr = 0;
206  break;
207  }
208 }
209 
210 
217 static void
218 run_external_ip (void *cls)
219 {
220  probe_external_ip_task
223  NULL);
224  if (NULL != probe_external_ip_op)
225  {
226  GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
227  probe_external_ip_op = NULL;
228  }
229  probe_external_ip_op
231  NULL);
232 }
233 
234 
241 void
242 GN_nat_status_changed (int have_nat)
243 {
244  if (GNUNET_YES != enable_upnp)
245  return;
246  if ( (GNUNET_YES == have_nat) &&
247  (NULL == probe_external_ip_task) &&
248  (NULL == probe_external_ip_op) )
249  {
250  probe_external_ip_task
252  NULL);
253  return;
254  }
255  if (GNUNET_NO == have_nat)
256  {
257  if (NULL != probe_external_ip_task)
258  {
259  GNUNET_SCHEDULER_cancel (probe_external_ip_task);
260  probe_external_ip_task = NULL;
261  }
262  if (NULL != probe_external_ip_op)
263  {
264  GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
265  probe_external_ip_op = NULL;
266  }
267  }
268 }
269 
270 
278 struct GN_ExternalIPMonitor *
280  void *cb_cls)
281 {
282  struct GN_ExternalIPMonitor *mon;
283 
284  mon = GNUNET_new (struct GN_ExternalIPMonitor);
285  mon->cb = cb;
286  mon->cb_cls = cb_cls;
287  GNUNET_CONTAINER_DLL_insert (mon_head,
288  mon_tail,
289  mon);
290  if (0 != mini_external_ipv4.s_addr)
291  cb (cb_cls,
293  GNUNET_YES);
294  return mon;
295 }
296 
297 
303 void
305 {
306  GNUNET_CONTAINER_DLL_remove (mon_head,
307  mon_tail,
308  mon);
309  GNUNET_free (mon);
310 }
311 
312 /* 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:81
#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:1246
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:1273
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:80
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:965
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.