- merge; service API change
[oweals/gnunet.git] / src / nat / gnunet-service-nat.c
1 /*
2   This file is part of GNUnet.
3   Copyright (C) 2016, 2017 GNUnet e.V.
4
5   GNUnet is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published
7   by the Free Software Foundation; either version 3, or (at your
8   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   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with GNUnet; see the file COPYING.  If not, write to the
17   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18   Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * @file nat/gnunet-service-nat.c
23  * @brief network address translation traversal service
24  * @author Christian Grothoff
25  *
26  * The purpose of this service is to enable transports to
27  * traverse NAT routers, by providing traversal options and
28  * knowledge about the local network topology.
29  *
30  * TODO:
31  * - migrate test cases to new NAT service
32  * - add new traceroute-based logic for external IP detection
33  *
34  * - implement & test STUN processing to classify NAT;
35  *   basically, open port & try different methods.
36  */
37 #include "platform.h"
38 #include <math.h>
39 #include "gnunet_util_lib.h"
40 #include "gnunet_protocols.h"
41 #include "gnunet_signatures.h"
42 #include "gnunet_statistics_service.h"
43 #include "gnunet_resolver_service.h"
44 #include "gnunet_nat_service.h"
45 #include "gnunet-service-nat.h"
46 #include "gnunet-service-nat_externalip.h"
47 #include "gnunet-service-nat_stun.h"
48 #include "gnunet-service-nat_mini.h"
49 #include "gnunet-service-nat_helper.h"
50 #include "nat.h"
51 #include <gcrypt.h>
52
53
54 /**
55  * How often should we ask the OS about a list of active
56  * network interfaces?
57  */
58 #define SCAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
59
60 /**
61  * How long do we wait until we forcefully terminate autoconfiguration?
62  */
63 #define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
64
65 /**
66  * How often do we scan for changes in how our external (dyndns) hostname resolves?
67  */
68 #define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)
69
70
71 /**
72  * Information we track per client address.
73  */
74 struct ClientAddress
75 {
76   /**
77    * Network address used by the client.
78    */
79   struct sockaddr_storage ss;
80
81   /**
82    * Handle to active UPnP request where we asked upnpc to open
83    * a port at the NAT.  NULL if we do not have such a request
84    * pending.
85    */
86   struct GNUNET_NAT_MiniHandle *mh;
87
88 };
89
90
91 /**
92  * List of local addresses this system has.
93  */
94 struct LocalAddressList
95 {
96   /**
97    * This is a linked list.
98    */
99   struct LocalAddressList *next;
100
101   /**
102    * Previous entry.
103    */
104   struct LocalAddressList *prev;
105
106   /**
107    * Context for a gnunet-helper-nat-server used to listen
108    * for ICMP messages to this client for connection reversal.
109    */
110   struct HelperContext *hc;
111
112   /**
113    * The address itself (i.e. `struct sockaddr_in` or `struct
114    * sockaddr_in6`, in the respective byte order).
115    */
116   struct sockaddr_storage addr;
117
118   /**
119    * Address family. (FIXME: redundant, addr.ss_family! Remove!?)
120    */
121   int af;
122
123   /**
124    * #GNUNET_YES if we saw this one in the previous iteration,
125    * but not in the current iteration and thus might need to
126    * remove it at the end.
127    */
128   int old;
129
130   /**
131    * What type of address is this?
132    */
133   enum GNUNET_NAT_AddressClass ac;
134
135 };
136
137
138 /**
139  * Internal data structure we track for each of our clients.
140  */
141 struct ClientHandle
142 {
143
144   /**
145    * Kept in a DLL.
146    */
147   struct ClientHandle *next;
148
149   /**
150    * Kept in a DLL.
151    */
152   struct ClientHandle *prev;
153
154   /**
155    * Underlying handle for this client with the service.
156    */
157   struct GNUNET_SERVICE_Client *client;
158
159   /**
160    * Message queue for communicating with the client.
161    */
162   struct GNUNET_MQ_Handle *mq;
163
164   /**
165    * Array of addresses used by the service.
166    */
167   struct ClientAddress *caddrs;
168
169   /**
170    * External DNS name and port given by user due to manual
171    * hole punching.  Special DNS name 'AUTO' is used to indicate
172    * desire for automatic determination of the external IP
173    * (instead of DNS or manual configuration, i.e. to be used
174    * if the IP keeps changing and we have no DynDNS, but we do
175    * have a hole punched).
176    */
177   char *hole_external;
178
179   /**
180    * Name of the configuration section this client cares about.
181    */
182   char *section_name;
183
184   /**
185    * Task for periodically re-running the @e ext_dns DNS lookup.
186    */
187   struct GNUNET_SCHEDULER_Task *ext_dns_task;
188
189   /**
190    * Handle for (DYN)DNS lookup of our external IP as given in
191    * @e hole_external.
192    */
193   struct GNUNET_RESOLVER_RequestHandle *ext_dns;
194
195   /**
196    * Handle for monitoring external IP changes.
197    */
198   struct GN_ExternalIPMonitor *external_monitor;
199
200   /**
201    * DLL of external IP addresses as given in @e hole_external.
202    */
203   struct LocalAddressList *ext_addr_head;
204
205   /**
206    * DLL of external IP addresses as given in @e hole_external.
207    */
208   struct LocalAddressList *ext_addr_tail;
209
210   /**
211    * Port number we found in @e hole_external.
212    */
213   uint16_t ext_dns_port;
214
215   /**
216    * What does this client care about?
217    */
218   enum GNUNET_NAT_RegisterFlags flags;
219
220   /**
221    * Is any of the @e caddrs in a reserved subnet for NAT?
222    */
223   int natted_address;
224
225   /**
226    * Number of addresses that this service is bound to.
227    * Length of the @e caddrs array.
228    */
229   uint16_t num_caddrs;
230
231   /**
232    * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
233    */
234   uint8_t proto;
235
236 };
237
238
239 /**
240  * External IP address as given to us via some STUN server.
241  */
242 struct StunExternalIP
243 {
244   /**
245    * Kept in a DLL.
246    */
247   struct StunExternalIP *next;
248
249   /**
250    * Kept in a DLL.
251    */
252   struct StunExternalIP *prev;
253
254   /**
255    * Task we run to remove this entry when it is stale.
256    */
257   struct GNUNET_SCHEDULER_Task *timeout_task;
258
259   /**
260    * Our external IP address as reported by the
261    * STUN server.
262    */
263   struct sockaddr_in external_addr;
264
265   /**
266    * Address of the reporting STUN server.  Used to
267    * detect when a STUN server changes its opinion
268    * to more quickly remove stale results.
269    */
270   struct sockaddr_storage stun_server_addr;
271
272   /**
273    * Number of bytes used in @e stun_server_addr.
274    */
275   size_t stun_server_addr_len;
276 };
277
278
279 /**
280  * Timeout to use when STUN data is considered stale.
281  */
282 static struct GNUNET_TIME_Relative stun_stale_timeout;
283
284 /**
285  * How often do we scan for changes in how our external (dyndns) hostname resolves?
286  */
287 static struct GNUNET_TIME_Relative dyndns_frequency;
288
289 /**
290  * Handle to our current configuration.
291  */
292 static const struct GNUNET_CONFIGURATION_Handle *cfg;
293
294 /**
295  * Handle to the statistics service.
296  */
297 static struct GNUNET_STATISTICS_Handle *stats;
298
299 /**
300  * Task scheduled to periodically scan our network interfaces.
301  */
302 static struct GNUNET_SCHEDULER_Task *scan_task;
303
304 /**
305  * Head of client DLL.
306  */
307 static struct ClientHandle *ch_head;
308
309 /**
310  * Tail of client DLL.
311  */
312 static struct ClientHandle *ch_tail;
313
314 /**
315  * Head of DLL of local addresses.
316  */
317 static struct LocalAddressList *lal_head;
318
319 /**
320  * Tail of DLL of local addresses.
321  */
322 static struct LocalAddressList *lal_tail;
323
324 /**
325  * Kept in a DLL.
326  */
327 static struct StunExternalIP *se_head;
328
329 /**
330  * Kept in a DLL.
331  */
332 static struct StunExternalIP *se_tail;
333
334 /**
335  * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled,
336  * #GNUNET_SYSERR if configuration enabled but binary is unavailable.
337  */
338 int enable_upnp;
339
340
341 /**
342  * Remove and free an entry from the #lal_head DLL.
343  *
344  * @param lal entry to free
345  */
346 static void
347 free_lal (struct LocalAddressList *lal)
348 {
349   GNUNET_CONTAINER_DLL_remove (lal_head,
350                                lal_tail,
351                                lal);
352   if (NULL != lal->hc)
353   {
354     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
355                 "Lost NATed local address %s, stopping NAT server\n",
356                 GNUNET_a2s ((const struct sockaddr *) &lal->addr,
357                             sizeof (struct sockaddr_in)));
358
359     GN_stop_gnunet_nat_server_ (lal->hc);
360     lal->hc = NULL;
361   }
362   GNUNET_free (lal);
363 }
364
365
366 /**
367  * Free the DLL starting at #lal_head.
368  */
369 static void
370 destroy_lal ()
371 {
372   struct LocalAddressList *lal;
373
374   while (NULL != (lal = lal_head))
375     free_lal (lal);
376 }
377
378
379 /**
380  * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from
381  * client.
382  *
383  * @param cls client who sent the message
384  * @param message the message received
385  * @return #GNUNET_OK if message is well-formed
386  */
387 static int
388 check_register (void *cls,
389                 const struct GNUNET_NAT_RegisterMessage *message)
390 {
391   uint16_t num_addrs = ntohs (message->num_addrs);
392   const char *off = (const char *) &message[1];
393   size_t left = ntohs (message->header.size) - sizeof (*message);
394
395   for (unsigned int i=0;i<num_addrs;i++)
396   {
397     size_t alen;
398     const struct sockaddr *sa = (const struct sockaddr *) off;
399
400     if (sizeof (sa_family_t) > left)
401     {
402       GNUNET_break (0);
403       return GNUNET_SYSERR;
404     }
405     switch (sa->sa_family)
406     {
407     case AF_INET:
408       alen = sizeof (struct sockaddr_in);
409       break;
410     case AF_INET6:
411       alen = sizeof (struct sockaddr_in6);
412       break;
413 #if AF_UNIX
414     case AF_UNIX:
415       alen = sizeof (struct sockaddr_un);
416       break;
417 #endif
418     default:
419       GNUNET_break (0);
420       return GNUNET_SYSERR;
421     }
422     if (alen > left)
423     {
424       GNUNET_break (0);
425       return GNUNET_SYSERR;
426     }
427     off += alen;
428     left -= alen;
429   }
430   if (left != ntohs (message->str_len))
431   {
432     GNUNET_break (0);
433     return GNUNET_SYSERR;
434   }
435   return GNUNET_OK;
436 }
437
438
439 /**
440  * Check if @a ip is in @a network with @a bits netmask.
441  *
442  * @param network to test
443  * @param ip IP address to test
444  * @param bits bitmask for the network
445  * @return #GNUNET_YES if @a ip is in @a network
446  */
447 static int
448 match_ipv4 (const char *network,
449             const struct in_addr *ip,
450             uint8_t bits)
451 {
452   struct in_addr net;
453
454   if (0 == ip->s_addr)
455     return GNUNET_YES;
456   if (0 == bits)
457     return GNUNET_YES;
458   GNUNET_assert (1 == inet_pton (AF_INET,
459                                  network,
460                                  &net));
461   return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
462 }
463
464
465 /**
466  * Check if @a ip is in @a network with @a bits netmask.
467  *
468  * @param network to test
469  * @param ip IP address to test
470  * @param bits bitmask for the network
471  * @return #GNUNET_YES if @a ip is in @a network
472  */
473 static int
474 match_ipv6 (const char *network,
475             const struct in6_addr *ip,
476             uint8_t bits)
477 {
478   struct in6_addr net;
479   struct in6_addr mask;
480   unsigned int off;
481
482   if (0 == bits)
483     return GNUNET_YES;
484   GNUNET_assert (1 == inet_pton (AF_INET6,
485                                  network,
486                                  &net));
487   memset (&mask, 0, sizeof (mask));
488   if (0 == memcmp (&mask,
489                    ip,
490                    sizeof (mask)))
491     return GNUNET_YES;
492   off = 0;
493   while (bits > 8)
494   {
495     mask.s6_addr[off++] = 0xFF;
496     bits -= 8;
497   }
498   while (bits > 0)
499   {
500     mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
501     bits--;
502   }
503   for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++)
504     if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
505         (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
506       return GNUNET_NO;
507   return GNUNET_YES;
508 }
509
510
511 /**
512  * Test if the given IPv4 address is in a known range
513  * for private networks.
514  *
515  * @param ip address to test
516  * @return #GNUNET_YES if @a ip is in a NAT range
517  */
518 static int
519 is_nat_v4 (const struct in_addr *ip)
520 {
521   return
522     match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */
523     match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
524     match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */
525     match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
526     match_ipv4 ("172.16.0.0", ip, 16);  /* RFC 1918 */
527 }
528
529
530 /**
531  * Test if the given IPv6 address is in a known range
532  * for private networks.
533  *
534  * @param ip address to test
535  * @return #GNUNET_YES if @a ip is in a NAT range
536  */
537 static int
538 is_nat_v6 (const struct in6_addr *ip)
539 {
540   return
541     match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
542     match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
543     match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
544 }
545
546
547 /**
548  * Closure for #ifc_proc.
549  */
550 struct IfcProcContext
551 {
552
553   /**
554    * Head of DLL of local addresses.
555    */
556   struct LocalAddressList *lal_head;
557
558   /**
559    * Tail of DLL of local addresses.
560    */
561   struct LocalAddressList *lal_tail;
562
563 };
564
565
566 /**
567  * Callback function invoked for each interface found.  Adds them
568  * to our new address list.
569  *
570  * @param cls a `struct IfcProcContext *`
571  * @param name name of the interface (can be NULL for unknown)
572  * @param isDefault is this presumably the default interface
573  * @param addr address of this interface (can be NULL for unknown or unassigned)
574  * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
575  * @param netmask the network mask (can be NULL for unknown or unassigned)
576  * @param addrlen length of the address
577  * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
578  */
579 static int
580 ifc_proc (void *cls,
581           const char *name,
582           int isDefault,
583           const struct sockaddr *addr,
584           const struct sockaddr *broadcast_addr,
585           const struct sockaddr *netmask,
586           socklen_t addrlen)
587 {
588   struct IfcProcContext *ifc_ctx = cls;
589   struct LocalAddressList *lal;
590   size_t alen;
591   const struct in_addr *ip4;
592   const struct in6_addr *ip6;
593   enum GNUNET_NAT_AddressClass ac;
594
595   switch (addr->sa_family)
596   {
597   case AF_INET:
598     alen = sizeof (struct sockaddr_in);
599     ip4 = &((const struct sockaddr_in *) addr)->sin_addr;
600     if (match_ipv4 ("127.0.0.0", ip4, 8))
601       ac = GNUNET_NAT_AC_LOOPBACK;
602     else if (is_nat_v4 (ip4))
603       ac = GNUNET_NAT_AC_LAN;
604     else
605       ac = GNUNET_NAT_AC_GLOBAL;
606     break;
607   case AF_INET6:
608     alen = sizeof (struct sockaddr_in6);
609     ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr;
610     if (match_ipv6 ("::1", ip6, 128))
611       ac = GNUNET_NAT_AC_LOOPBACK;
612     else if (is_nat_v6 (ip6))
613       ac = GNUNET_NAT_AC_LAN;
614     else
615       ac = GNUNET_NAT_AC_GLOBAL;
616     if ( (ip6->s6_addr[11] == 0xFF) &&
617          (ip6->s6_addr[12] == 0xFE) )
618     {
619       /* contains a MAC, be extra careful! */
620       ac |= GNUNET_NAT_AC_PRIVATE;
621     }
622     break;
623 #if AF_UNIX
624   case AF_UNIX:
625     GNUNET_break (0);
626     return GNUNET_OK;
627 #endif
628   default:
629     GNUNET_break (0);
630     return GNUNET_OK;
631   }
632   lal = GNUNET_malloc (sizeof (*lal));
633   lal->af = addr->sa_family;
634   lal->ac = ac;
635   GNUNET_memcpy (&lal->addr,
636                  addr,
637                  alen);
638   GNUNET_CONTAINER_DLL_insert (ifc_ctx->lal_head,
639                                ifc_ctx->lal_tail,
640                                lal);
641   return GNUNET_OK;
642 }
643
644
645 /**
646  * Notify client about a change in the list of addresses this peer
647  * has.
648  *
649  * @param ac address class of the entry in the list that changed
650  * @param ch client to contact
651  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
652  * @param addr the address that changed
653  * @param addr_len number of bytes in @a addr
654  */
655 static void
656 notify_client (enum GNUNET_NAT_AddressClass ac,
657                struct ClientHandle *ch,
658                int add,
659                const void *addr,
660                size_t addr_len)
661 {
662   struct GNUNET_MQ_Envelope *env;
663   struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
664
665   env = GNUNET_MQ_msg_extra (msg,
666                              addr_len,
667                              GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
668   msg->add_remove = htonl (add);
669   msg->addr_class = htonl (ac);
670   GNUNET_memcpy (&msg[1],
671                  addr,
672                  addr_len);
673   GNUNET_MQ_send (ch->mq,
674                   env);
675 }
676
677
678 /**
679  * Check if we should bother to notify this client about this
680  * address change, and if so, do it.
681  *
682  * @param delta the entry in the list that changed
683  * @param ch client to check
684  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
685  */
686 static void
687 check_notify_client (struct LocalAddressList *delta,
688                      struct ClientHandle *ch,
689                      int add)
690 {
691   size_t alen;
692   struct sockaddr_in v4;
693   struct sockaddr_in6 v6;
694
695   if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
696     return;
697   switch (delta->af)
698   {
699   case AF_INET:
700     alen = sizeof (struct sockaddr_in);
701     GNUNET_memcpy (&v4,
702                    &delta->addr,
703                    alen);
704
705     /* Check for client notifications */
706     for (unsigned int i=0;i<ch->num_caddrs;i++)
707     {
708       const struct sockaddr_in *c4;
709
710       if (AF_INET != ch->caddrs[i].ss.ss_family)
711         continue; /* IPv4 not relevant */
712       c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
713       if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
714            (0 != c4->sin_addr.s_addr) &&
715            (! match_ipv4 ("127.0.0.1", &v4.sin_addr, 8)) )
716         continue; /* bound to loopback, but this is not loopback */
717       if ( (! match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) ) &&
718            (0 != c4->sin_addr.s_addr) &&
719            match_ipv4 ("127.0.0.1", &v4.sin_addr, 8) )
720         continue; /* bound to non-loopback, but this is loopback */
721       if ( (0 != (ch->flags & GNUNET_NAT_AC_EXTERN)) &&
722            (0 != c4->sin_addr.s_addr) &&
723            (! is_nat_v4 (&v4.sin_addr)) )
724         continue; /* based on external-IP, but this IP is not
725                      from private address range. */
726       if ( (0 != memcmp (&v4.sin_addr,
727                          &c4->sin_addr,
728                          sizeof (struct in_addr))) &&
729            (0 != c4->sin_addr.s_addr) &&
730            ( (! is_nat_v4 (&c4->sin_addr)) ||
731              (0 == (ch->flags & GNUNET_NAT_AC_EXTERN))) )
732         continue; /* this IP is not from private address range,
733                      and IP does not match. */
734
735       /* OK, IP seems relevant, notify client */
736       v4.sin_port = c4->sin_port;
737       notify_client (delta->ac,
738                      ch,
739                      add,
740                      &v4,
741                      alen);
742     }
743     break;
744   case AF_INET6:
745     alen = sizeof (struct sockaddr_in6);
746     GNUNET_memcpy (&v6,
747                    &delta->addr,
748                    alen);
749     for (unsigned int i=0;i<ch->num_caddrs;i++)
750     {
751       const struct sockaddr_in6 *c6;
752
753       if (AF_INET6 != ch->caddrs[i].ss.ss_family)
754         continue; /* IPv4 not relevant */
755       c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
756       if ( match_ipv6 ("::1", &c6->sin6_addr, 128) &&
757            (0 != memcmp (&c6->sin6_addr,
758                          &in6addr_any,
759                          sizeof (struct in6_addr))) &&
760            (! match_ipv6 ("::1", &v6.sin6_addr, 128)) )
761         continue; /* bound to loopback, but this is not loopback */
762       if ( (! match_ipv6 ("::1", &c6->sin6_addr, 128) ) &&
763            (0 != memcmp (&c6->sin6_addr,
764                          &in6addr_any,
765                          sizeof (struct in6_addr))) &&
766            match_ipv6 ("::1", &v6.sin6_addr, 128) )
767         continue; /* bound to non-loopback, but this is loopback */
768       if ( (0 != (ch->flags & GNUNET_NAT_AC_EXTERN)) &&
769            (0 != memcmp (&c6->sin6_addr,
770                          &in6addr_any,
771                          sizeof (struct in6_addr))) &&
772            (! is_nat_v6 (&v6.sin6_addr)) )
773         continue; /* based on external-IP, but this IP is not
774                      from private address range. */
775       if ( (0 != memcmp (&v6.sin6_addr,
776                          &c6->sin6_addr,
777                          sizeof (struct in6_addr))) &&
778            (0 != memcmp (&c6->sin6_addr,
779                          &in6addr_any,
780                          sizeof (struct in6_addr))) &&
781            (! is_nat_v6 (&c6->sin6_addr)) )
782         continue; /* this IP is not from private address range,
783                      and IP does not match. */
784       if ( (match_ipv6 ("fe80::", &c6->sin6_addr, 10)) &&
785            (0 != memcmp (&c6->sin6_addr,
786                          &in6addr_any,
787                          sizeof (struct in6_addr))) &&
788            (0 != memcmp (&v6.sin6_addr,
789                          &c6->sin6_addr,
790                          sizeof (struct in6_addr))) &&
791            (0 == (delta->ac & GNUNET_NAT_AC_EXTERN)) )
792         continue; /* client bound to link-local, and the other address
793                      does not match and is not an external IP */
794
795       /* OK, IP seems relevant, notify client */
796       v6.sin6_port = c6->sin6_port;
797       notify_client (delta->ac,
798                      ch,
799                      add,
800                      &v6,
801                      alen);
802     }
803     break;
804   default:
805     GNUNET_break (0);
806     return;
807   }
808 }
809
810
811 /**
812  * Notify all clients about a change in the list
813  * of addresses this peer has.
814  *
815  * @param delta the entry in the list that changed
816  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
817  */
818 static void
819 notify_clients (struct LocalAddressList *delta,
820                 int add)
821 {
822   for (struct ClientHandle *ch = ch_head;
823        NULL != ch;
824        ch = ch->next)
825     check_notify_client (delta,
826                          ch,
827                          add);
828 }
829
830
831 /**
832  * Tell relevant client about a change in our external
833  * IPv4 address.
834  *
835  * @param cls client to check if it cares and possibly notify
836  * @param v4 the external address that changed
837  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
838  */
839 static void
840 notify_client_external_ipv4_change (void *cls,
841                                     const struct in_addr *v4,
842                                     int add)
843 {
844   struct ClientHandle *ch = cls;
845   struct sockaddr_in sa;
846   int have_v4;
847
848   /* (0) check if this impacts 'hole_external' */
849   if ( (NULL != ch->hole_external) &&
850        (0 == strcasecmp (ch->hole_external,
851                          "AUTO")) )
852   {
853     struct LocalAddressList lal;
854     struct sockaddr_in *s4;
855
856     memset (&lal, 0, sizeof (lal));
857     s4 = (struct sockaddr_in *) &lal.addr;
858     s4->sin_family = AF_INET;
859     s4->sin_port = htons (ch->ext_dns_port);
860     s4->sin_addr = *v4;
861     lal.af = AF_INET;
862     lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
863     check_notify_client (&lal,
864                          ch,
865                          add);
866   }
867
868   /* (1) check if client cares. */
869   if (! ch->natted_address)
870     return;
871   if (0 == (GNUNET_NAT_RF_ADDRESSES & ch->flags))
872     return;
873   have_v4 = GNUNET_NO;
874   for (unsigned int i=0;i<ch->num_caddrs;i++)
875   {
876     const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
877
878     if (AF_INET != ss->ss_family)
879       continue;
880     have_v4 = GNUNET_YES;
881     break;
882   }
883   if (GNUNET_NO == have_v4)
884     return; /* IPv6-only */
885
886   /* (2) build address info */
887   memset (&sa,
888           0,
889           sizeof (sa));
890   sa.sin_family = AF_INET;
891   sa.sin_addr = *v4;
892   sa.sin_port = htons (0);
893
894   /* (3) notify client of change */
895   notify_client (is_nat_v4 (v4)
896                  ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN
897                  : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL,
898                  ch,
899                  add,
900                  &sa,
901                  sizeof (sa));
902 }
903
904
905 /**
906  * We got a connection reversal request from another peer.
907  * Notify applicable clients.
908  *
909  * @param cls closure with the `struct LocalAddressList`
910  * @param ra IP address of the peer who wants us to connect to it
911  */
912 static void
913 reversal_callback (void *cls,
914                    const struct sockaddr_in *ra)
915 {
916   struct LocalAddressList *lal = cls;
917   const struct sockaddr_in *l4;
918
919   GNUNET_assert (AF_INET == lal->af);
920   l4 = (const struct sockaddr_in *) &lal->addr;
921   for (struct ClientHandle *ch = ch_head;
922        NULL != ch;
923        ch = ch->next)
924   {
925     struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm;
926     struct GNUNET_MQ_Envelope *env;
927     int match;
928
929     /* Check if client is in applicable range for ICMP NAT traversal
930        for this local address */
931     if (! ch->natted_address)
932       continue;
933     match = GNUNET_NO;
934     for (unsigned int i=0;i<ch->num_caddrs;i++)
935     {
936       struct ClientAddress *ca = &ch->caddrs[i];
937       const struct sockaddr_in *c4;
938
939       if (AF_INET != ca->ss.ss_family)
940         continue;
941       c4 = (const struct sockaddr_in *) &ca->ss;
942       if ( (0 != c4->sin_addr.s_addr) &&
943            (l4->sin_addr.s_addr != c4->sin_addr.s_addr) )
944         continue;
945       match = GNUNET_YES;
946       break;
947     }
948     if (! match)
949       continue;
950
951     /* Notify applicable client about connection reversal request */
952     env = GNUNET_MQ_msg_extra (crrm,
953                                sizeof (struct sockaddr_in),
954                                GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED);
955     GNUNET_memcpy (&crrm[1],
956                    ra,
957                    sizeof (struct sockaddr_in));
958     GNUNET_MQ_send (ch->mq,
959                     env);
960   }
961 }
962
963
964 /**
965  * Task we run periodically to scan for network interfaces.
966  *
967  * @param cls NULL
968  */
969 static void
970 run_scan (void *cls)
971 {
972   struct IfcProcContext ifc_ctx;
973   int found;
974   int have_nat;
975   struct LocalAddressList *lnext;
976
977   scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
978                                             &run_scan,
979                                             NULL);
980   memset (&ifc_ctx,
981           0,
982           sizeof (ifc_ctx));
983   GNUNET_OS_network_interfaces_list (&ifc_proc,
984                                      &ifc_ctx);
985   /* remove addresses that disappeared */
986   for (struct LocalAddressList *lal = lal_head;
987        NULL != lal;
988        lal = lnext)
989   {
990     lnext = lal->next;
991     found = GNUNET_NO;
992     for (struct LocalAddressList *pos = ifc_ctx.lal_head;
993          NULL != pos;
994          pos = pos->next)
995     {
996       if ( (pos->af == lal->af) &&
997            (0 == memcmp (&lal->addr,
998                          &pos->addr,
999                          (AF_INET == lal->af)
1000                          ? sizeof (struct sockaddr_in)
1001                          : sizeof (struct sockaddr_in6))) )
1002       {
1003         found = GNUNET_YES;
1004       }
1005     }
1006     if (GNUNET_NO == found)
1007     {
1008       notify_clients (lal,
1009                       GNUNET_NO);
1010       free_lal (lal);
1011     }
1012   }
1013
1014   /* add addresses that appeared */
1015   have_nat = GNUNET_NO;
1016   for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1017        NULL != pos;
1018        pos = ifc_ctx.lal_head)
1019   {
1020     found = GNUNET_NO;
1021     if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
1022       have_nat = GNUNET_YES;
1023     for (struct LocalAddressList *lal = lal_head;
1024          NULL != lal;
1025          lal = lal->next)
1026     {
1027       if ( (pos->af == lal->af) &&
1028            (0 == memcmp (&lal->addr,
1029                          &pos->addr,
1030                          (AF_INET == lal->af)
1031                          ? sizeof (struct sockaddr_in)
1032                          : sizeof (struct sockaddr_in6))) )
1033         found = GNUNET_YES;
1034     }
1035     GNUNET_CONTAINER_DLL_remove (ifc_ctx.lal_head,
1036                                  ifc_ctx.lal_tail,
1037                                  pos);
1038     if (GNUNET_YES == found)
1039     {
1040       GNUNET_free (pos);
1041     }
1042     else
1043     {
1044       notify_clients (pos,
1045                       GNUNET_YES);
1046       GNUNET_CONTAINER_DLL_insert (lal_head,
1047                                    lal_tail,
1048                                    pos);
1049       if ( (AF_INET == pos->af) &&
1050            (NULL == pos->hc) &&
1051            (0 != (GNUNET_NAT_AC_LAN & pos->ac)) )
1052       {
1053         const struct sockaddr_in *s4
1054           = (const struct sockaddr_in *) &pos->addr;
1055
1056         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1057                     "Found NATed local address %s, starting NAT server\n",
1058                     GNUNET_a2s ((void *) &pos->addr, sizeof (*s4)));
1059         pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
1060                                                &reversal_callback,
1061                                                pos);
1062       }
1063     }
1064   }
1065   GN_nat_status_changed (have_nat);
1066 }
1067
1068
1069 /**
1070  * Function called whenever our set of external addresses
1071  * as created by `upnpc` changes.
1072  *
1073  * @param cls closure with our `struct ClientHandle *`
1074  * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
1075  *     the previous (now invalid) one, #GNUNET_SYSERR indicates an error
1076  * @param addr either the previous or the new public IP address
1077  * @param addrlen actual length of the @a addr
1078  * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
1079  */
1080 static void
1081 upnp_addr_change_cb (void *cls,
1082                      int add_remove,
1083                      const struct sockaddr *addr,
1084                      socklen_t addrlen,
1085                      enum GNUNET_NAT_StatusCode result)
1086 {
1087   struct ClientHandle *ch = cls;
1088   enum GNUNET_NAT_AddressClass ac;
1089
1090   switch (result)
1091   {
1092   case GNUNET_NAT_ERROR_SUCCESS:
1093     GNUNET_assert (NULL != addr);
1094     break;
1095   case GNUNET_NAT_ERROR_UPNPC_FAILED:
1096   case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
1097   case GNUNET_NAT_ERROR_IPC_FAILURE:
1098     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1099                 "Running upnpc failed: %d\n",
1100                 result);
1101     return;
1102   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
1103     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1104                 "external-ip binary not found\n");
1105     return;
1106   case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
1107     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1108                 "upnpc binary not found\n");
1109     return;
1110   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
1111     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1112                 "external-ip binary could not be run\n");
1113     return;
1114   case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
1115     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1116                 "upnpc failed to create port mapping\n");
1117     return;
1118   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
1119     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1120                 "Invalid output from upnpc\n");
1121     return;
1122   case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
1123     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1124                 "Invalid address returned by upnpc\n");
1125     return;
1126   default:
1127     GNUNET_break (0); /* should not be possible */
1128     return;
1129   }
1130   switch (addr->sa_family)
1131   {
1132   case AF_INET:
1133     ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr)
1134       ? GNUNET_NAT_AC_LAN
1135       : GNUNET_NAT_AC_EXTERN;
1136     break;
1137   case AF_INET6:
1138     ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr)
1139       ? GNUNET_NAT_AC_LAN
1140       : GNUNET_NAT_AC_EXTERN;
1141     break;
1142   default:
1143     GNUNET_break (0);
1144     return;
1145   }
1146   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1147               "upnp external address %s: %s\n",
1148               add_remove ? "added" : "removed",
1149               GNUNET_a2s (addr,
1150                           addrlen));
1151   notify_client (ac,
1152                  ch,
1153                  add_remove,
1154                  addr,
1155                  addrlen);
1156 }
1157
1158
1159 /**
1160  * Resolve the `hole_external` name to figure out our
1161  * external address from a manually punched hole.  The
1162  * port number has already been parsed, this task is
1163  * responsible for periodically doing a DNS lookup.
1164  *
1165  * @param ch client handle to act upon
1166  */
1167 static void
1168 dyndns_lookup (void *cls);
1169
1170
1171 /**
1172  * Our (external) hostname was resolved.  Update lists of
1173  * current external IPs (note that DNS may return multiple
1174  * addresses!) and notify client accordingly.
1175  *
1176  * @param cls the `struct ClientHandle`
1177  * @param addr NULL on error, otherwise result of DNS lookup
1178  * @param addrlen number of bytes in @a addr
1179  */
1180 static void
1181 process_external_ip (void *cls,
1182                      const struct sockaddr *addr,
1183                      socklen_t addrlen)
1184 {
1185   struct ClientHandle *ch = cls;
1186   struct LocalAddressList *lal;
1187   struct sockaddr_storage ss;
1188   struct sockaddr_in *v4;
1189   struct sockaddr_in6 *v6;
1190
1191   if (NULL == addr)
1192   {
1193     struct LocalAddressList *laln;
1194
1195     ch->ext_dns = NULL;
1196     ch->ext_dns_task
1197       = GNUNET_SCHEDULER_add_delayed (dyndns_frequency,
1198                                       &dyndns_lookup,
1199                                       ch);
1200     /* Current iteration is over, remove 'old' IPs now */
1201     for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1202     {
1203       laln = lal->next;
1204       if (GNUNET_YES == lal->old)
1205       {
1206         GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
1207                                      ch->ext_addr_tail,
1208                                      lal);
1209         check_notify_client (lal,
1210                              ch,
1211                              GNUNET_NO);
1212         GNUNET_free (lal);
1213       }
1214     }
1215     return;
1216   }
1217   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1218               "Got IP `%s' for external address `%s'\n",
1219               GNUNET_a2s (addr,
1220                           addrlen),
1221               ch->hole_external);
1222
1223   /* build sockaddr storage with port number */
1224   memset (&ss, 0, sizeof (ss));
1225   memcpy (&ss, addr, addrlen);
1226   switch (addr->sa_family)
1227   {
1228   case AF_INET:
1229     v4 = (struct sockaddr_in *) &ss;
1230     v4->sin_port = htons (ch->ext_dns_port);
1231     break;
1232   case AF_INET6:
1233     v6 = (struct sockaddr_in6 *) &ss;
1234     v6->sin6_port = htons (ch->ext_dns_port);
1235     break;
1236   default:
1237     GNUNET_break (0);
1238     return;
1239   }
1240   /* See if 'ss' matches any of our known addresses */
1241   for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1242   {
1243     if (GNUNET_NO == lal->old)
1244       continue; /* already processed, skip */
1245     if ( (addr->sa_family == lal->addr.ss_family) &&
1246          (0 == memcmp (&ss,
1247                        &lal->addr,
1248                        addrlen)) )
1249     {
1250       /* Address unchanged, remember so we do not remove */
1251       lal->old = GNUNET_NO;
1252       return; /* done here */
1253     }
1254   }
1255   /* notify client, and remember IP for later removal! */
1256   lal = GNUNET_new (struct LocalAddressList);
1257   lal->addr = ss;
1258   lal->af = ss.ss_family;
1259   lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1260   GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1261                                ch->ext_addr_tail,
1262                                lal);
1263   check_notify_client (lal,
1264                        ch,
1265                        GNUNET_YES);
1266 }
1267
1268
1269 /**
1270  * Resolve the `hole_external` name to figure out our
1271  * external address from a manually punched hole.  The
1272  * port number has already been parsed, this task is
1273  * responsible for periodically doing a DNS lookup.
1274  *
1275  * @param ch client handle to act upon
1276  */
1277 static void
1278 dyndns_lookup (void *cls)
1279 {
1280   struct ClientHandle *ch = cls;
1281   struct LocalAddressList *lal;
1282
1283   for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1284     lal->old = GNUNET_YES;
1285   ch->ext_dns_task = NULL;
1286   ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external,
1287                                         AF_UNSPEC,
1288                                         GNUNET_TIME_UNIT_MINUTES,
1289                                         &process_external_ip,
1290                                         ch);
1291 }
1292
1293
1294 /**
1295  * Resolve the `hole_external` name to figure out our
1296  * external address from a manually punched hole.  The
1297  * given name may be "AUTO" in which case we should use
1298  * the IP address(es) we have from upnpc or other methods.
1299  * The name can also be an IP address, in which case we
1300  * do not need to do DNS resolution.  Finally, we also
1301  * need to parse the port number.
1302  *
1303  * @param ch client handle to act upon
1304  */
1305 static void
1306 lookup_hole_external (struct ClientHandle *ch)
1307 {
1308   char *port;
1309   unsigned int pnum;
1310   struct sockaddr_in *s4;
1311   struct LocalAddressList *lal;
1312
1313   port = strrchr (ch->hole_external, ':');
1314   if (NULL == port)
1315   {
1316     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1317                 _("Malformed punched hole specification `%s' (lacks port)\n"),
1318                 ch->hole_external);
1319     return;
1320   }
1321   if ( (1 != sscanf (port + 1,
1322                      "%u",
1323                      &pnum)) ||
1324        (pnum > 65535) )
1325   {
1326     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1327                 _("Invalid port number in punched hole specification `%s' (lacks port)\n"),
1328                 port + 1);
1329     return;
1330   }
1331   ch->ext_dns_port = (uint16_t) pnum;
1332   *port = '\0';
1333
1334   lal = GNUNET_new (struct LocalAddressList);
1335   if ('[' == *ch->hole_external)
1336   {
1337     struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr;
1338
1339     s6->sin6_family = AF_INET6;
1340     if (']' != (ch->hole_external[strlen(ch->hole_external)-1]))
1341     {
1342       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1343                   _("Malformed punched hole specification `%s' (lacks `]')\n"),
1344                   ch->hole_external);
1345       GNUNET_free (lal);
1346       return;
1347     }
1348     ch->hole_external[strlen(ch->hole_external)-1] = '\0';
1349     if (1 != inet_pton (AF_INET6,
1350                         ch->hole_external + 1,
1351                         &s6->sin6_addr))
1352     {
1353       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1354                   _("Malformed punched hole specification `%s' (IPv6 address invalid)"),
1355                   ch->hole_external + 1);
1356       GNUNET_free (lal);
1357       return;
1358     }
1359     s6->sin6_port = htons (ch->ext_dns_port);
1360     lal->af = AF_INET6;
1361     lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1362     GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1363                                  ch->ext_addr_tail,
1364                                  lal);
1365     check_notify_client (lal,
1366                          ch,
1367                          GNUNET_YES);
1368     return;
1369   }
1370
1371   s4 = (struct sockaddr_in *) &lal->addr;
1372   s4->sin_family = AF_INET;
1373   if (1 == inet_pton (AF_INET,
1374                       ch->hole_external,
1375                       &s4->sin_addr))
1376   {
1377     s4->sin_port = htons (ch->ext_dns_port);
1378     lal->af = AF_INET;
1379     lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1380     GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1381                                  ch->ext_addr_tail,
1382                                  lal);
1383     check_notify_client (lal,
1384                          ch,
1385                          GNUNET_YES);
1386     return;
1387   }
1388   if (0 == strcasecmp (ch->hole_external,
1389                        "AUTO"))
1390   {
1391     /* handled in #notify_client_external_ipv4_change() */
1392     GNUNET_free (lal);
1393     return;
1394   }
1395   /* got a DNS name, trigger lookup! */
1396   GNUNET_free (lal);
1397   ch->ext_dns_task
1398     = GNUNET_SCHEDULER_add_now (&dyndns_lookup,
1399                                 ch);
1400 }
1401
1402
1403 /**
1404  * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
1405  * We remember the client for updates upon future NAT events.
1406  *
1407  * @param cls client who sent the message
1408  * @param message the message received
1409  */
1410 static void
1411 handle_register (void *cls,
1412                  const struct GNUNET_NAT_RegisterMessage *message)
1413 {
1414   struct ClientHandle *ch = cls;
1415   const char *off;
1416   size_t left;
1417
1418   if ( (0 != ch->proto) ||
1419        (NULL != ch->caddrs) )
1420   {
1421     /* double registration not allowed */
1422     GNUNET_break (0);
1423     GNUNET_SERVICE_client_drop (ch->client);
1424     return;
1425   }
1426   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1427               "Received REGISTER message from client\n");
1428   ch->flags = message->flags;
1429   ch->proto = message->proto;
1430   ch->num_caddrs = ntohs (message->num_addrs);
1431   ch->caddrs = GNUNET_new_array (ch->num_caddrs,
1432                                  struct ClientAddress);
1433   left = ntohs (message->header.size) - sizeof (*message);
1434   off = (const char *) &message[1];
1435   for (unsigned int i=0;i<ch->num_caddrs;i++)
1436   {
1437     size_t alen;
1438     const struct sockaddr *sa = (const struct sockaddr *) off;
1439     uint16_t port;
1440     int is_nat;
1441
1442     if (sizeof (sa_family_t) > left)
1443     {
1444       GNUNET_break (0);
1445       GNUNET_SERVICE_client_drop (ch->client);
1446       return;
1447     }
1448     is_nat = GNUNET_NO;
1449     switch (sa->sa_family)
1450     {
1451     case AF_INET:
1452       {
1453         const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa;
1454
1455         alen = sizeof (struct sockaddr_in);
1456         if (is_nat_v4 (&s4->sin_addr))
1457           is_nat = GNUNET_YES;
1458         port = ntohs (s4->sin_port);
1459       }
1460       break;
1461     case AF_INET6:
1462       {
1463         const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa;
1464
1465         alen = sizeof (struct sockaddr_in6);
1466         if (is_nat_v6 (&s6->sin6_addr))
1467           is_nat = GNUNET_YES;
1468         port = ntohs (s6->sin6_port);
1469       }
1470       break;
1471 #if AF_UNIX
1472     case AF_UNIX:
1473       alen = sizeof (struct sockaddr_un);
1474       port = 0;
1475       break;
1476 #endif
1477     default:
1478       GNUNET_break (0);
1479       GNUNET_SERVICE_client_drop (ch->client);
1480       return;
1481     }
1482     /* store address */
1483     GNUNET_assert (alen <= left);
1484     GNUNET_assert (alen <= sizeof (struct sockaddr_storage));
1485     GNUNET_memcpy (&ch->caddrs[i].ss,
1486                    sa,
1487                    alen);
1488
1489     /* If applicable, try UPNPC NAT punching */
1490     if ( (is_nat) &&
1491          (enable_upnp) &&
1492          ( (IPPROTO_TCP == ch->proto) ||
1493            (IPPROTO_UDP == ch->proto) ) )
1494     {
1495       ch->natted_address = GNUNET_YES;
1496       ch->caddrs[i].mh
1497         = GNUNET_NAT_mini_map_start (port,
1498                                      IPPROTO_TCP == ch->proto,
1499                                      &upnp_addr_change_cb,
1500                                      ch);
1501     }
1502
1503     off += alen;
1504   }
1505
1506   ch->section_name
1507     = GNUNET_strndup (off,
1508                       ntohs (message->str_len));
1509   if (GNUNET_OK ==
1510       GNUNET_CONFIGURATION_get_value_string (cfg,
1511                                              ch->section_name,
1512                                              "HOLE_EXTERNAL",
1513                                              &ch->hole_external))
1514     lookup_hole_external (ch);
1515
1516   /* Actually send IP address list to client */
1517   for (struct LocalAddressList *lal = lal_head;
1518        NULL != lal;
1519        lal = lal->next)
1520   {
1521     check_notify_client (lal,
1522                          ch,
1523                          GNUNET_YES);
1524   }
1525   /* Also consider IPv4 determined by `external-ip` */
1526   ch->external_monitor
1527     = GN_external_ipv4_monitor_start (&notify_client_external_ipv4_change,
1528                                       ch);
1529   GNUNET_SERVICE_client_continue (ch->client);
1530 }
1531
1532
1533 /**
1534  * Check validity of #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
1535  * client.
1536  *
1537  * @param cls client who sent the message
1538  * @param message the message received
1539  * @return #GNUNET_OK if message is well-formed
1540  */
1541 static int
1542 check_stun (void *cls,
1543             const struct GNUNET_NAT_HandleStunMessage *message)
1544 {
1545   size_t sa_len = ntohs (message->sender_addr_size);
1546   size_t expect = sa_len + ntohs (message->payload_size);
1547
1548   if (ntohs (message->header.size) - sizeof (*message) != expect)
1549   {
1550     GNUNET_break (0);
1551     return GNUNET_SYSERR;
1552   }
1553   if (sa_len < sizeof (sa_family_t))
1554   {
1555     GNUNET_break (0);
1556     return GNUNET_SYSERR;
1557   }
1558   return GNUNET_OK;
1559 }
1560
1561
1562 /**
1563  * Notify all clients about our external IP address
1564  * as reported by the STUN server.
1565  *
1566  * @param ip the external IP
1567  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
1568  */
1569 static void
1570 notify_clients_stun_change (const struct sockaddr_in *ip,
1571                             int add)
1572 {
1573   for (struct ClientHandle *ch = ch_head;
1574        NULL != ch;
1575        ch = ch->next)
1576   {
1577     struct sockaddr_in v4;
1578     struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
1579     struct GNUNET_MQ_Envelope *env;
1580
1581     if (! ch->natted_address)
1582       continue;
1583     v4 = *ip;
1584     v4.sin_port = htons (0);
1585     env = GNUNET_MQ_msg_extra (msg,
1586                                sizeof (v4),
1587                                GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
1588     msg->add_remove = htonl ((int32_t) add);
1589     msg->addr_class = htonl (GNUNET_NAT_AC_EXTERN |
1590                              GNUNET_NAT_AC_GLOBAL);
1591     GNUNET_memcpy (&msg[1],
1592                    &v4,
1593                    sizeof (v4));
1594     GNUNET_MQ_send (ch->mq,
1595                     env);
1596   }
1597 }
1598
1599
1600 /**
1601  * Function to be called when we decide that an
1602  * external IP address as told to us by a STUN
1603  * server has gone stale.
1604  *
1605  * @param cls the `struct StunExternalIP` to drop
1606  */
1607 static void
1608 stun_ip_timeout (void *cls)
1609 {
1610   struct StunExternalIP *se = cls;
1611
1612   se->timeout_task = NULL;
1613   notify_clients_stun_change (&se->external_addr,
1614                               GNUNET_NO);
1615   GNUNET_CONTAINER_DLL_remove (se_head,
1616                                se_tail,
1617                                se);
1618   GNUNET_free (se);
1619 }
1620
1621
1622 /**
1623  * Handler for #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
1624  * client.
1625  *
1626  * @param cls client who sent the message
1627  * @param message the message received
1628  */
1629 static void
1630 handle_stun (void *cls,
1631              const struct GNUNET_NAT_HandleStunMessage *message)
1632 {
1633   struct ClientHandle *ch = cls;
1634   const char *buf = (const char *) &message[1];
1635   const struct sockaddr *sa;
1636   const void *payload;
1637   size_t sa_len;
1638   size_t payload_size;
1639   struct sockaddr_in external_addr;
1640
1641   sa_len = ntohs (message->sender_addr_size);
1642   payload_size = ntohs (message->payload_size);
1643   sa = (const struct sockaddr *) &buf[0];
1644   payload = (const struct sockaddr *) &buf[sa_len];
1645   switch (sa->sa_family)
1646   {
1647   case AF_INET:
1648     if (sa_len != sizeof (struct sockaddr_in))
1649     {
1650       GNUNET_break (0);
1651       GNUNET_SERVICE_client_drop (ch->client);
1652       return;
1653     }
1654     break;
1655   case AF_INET6:
1656     if (sa_len != sizeof (struct sockaddr_in6))
1657     {
1658       GNUNET_break (0);
1659       GNUNET_SERVICE_client_drop (ch->client);
1660       return;
1661     }
1662     break;
1663   }
1664   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1665               "Received HANDLE_STUN message from client\n");
1666   if (GNUNET_OK ==
1667       GNUNET_NAT_stun_handle_packet_ (payload,
1668                                       payload_size,
1669                                       &external_addr))
1670   {
1671     /* We now know that a server at "sa" claims that
1672        we are visible at IP "external_addr".
1673
1674        We should (for some fixed period of time) tell
1675        all of our clients that listen to a NAT'ed address
1676        that they might want to consider the given 'external_ip'
1677        as their public IP address (this includes TCP and UDP
1678        clients, even if only UDP sends STUN requests).
1679
1680        If we do not get a renewal, the "external_addr" should be
1681        removed again.  The timeout frequency should be configurable
1682        (with a sane default), so that the UDP plugin can tell how
1683        often to re-request STUN.
1684     */
1685     struct StunExternalIP *se;
1686
1687     /* Check if we had a prior response from this STUN server */
1688     for (se = se_head; NULL != se; se = se->next)
1689     {
1690       if ( (se->stun_server_addr_len != sa_len) ||
1691            (0 != memcmp (sa,
1692                          &se->stun_server_addr,
1693                          sa_len)) )
1694         continue; /* different STUN server */
1695       if (0 != memcmp (&external_addr,
1696                        &se->external_addr,
1697                        sizeof (struct sockaddr_in)))
1698       {
1699         /* external IP changed, update! */
1700         notify_clients_stun_change (&se->external_addr,
1701                                     GNUNET_NO);
1702         se->external_addr = external_addr;
1703         notify_clients_stun_change (&se->external_addr,
1704                                     GNUNET_YES);
1705       }
1706       /* update timeout */
1707       GNUNET_SCHEDULER_cancel (se->timeout_task);
1708       se->timeout_task
1709         = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
1710                                         &stun_ip_timeout,
1711                                         se);
1712       return;
1713     }
1714     /* STUN server is completely new, create fresh entry */
1715     se = GNUNET_new (struct StunExternalIP);
1716     se->external_addr = external_addr;
1717     GNUNET_memcpy (&se->stun_server_addr,
1718                    sa,
1719                    sa_len);
1720     se->stun_server_addr_len = sa_len;
1721     se->timeout_task = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
1722                                                      &stun_ip_timeout,
1723                                                      se);
1724     GNUNET_CONTAINER_DLL_insert (se_head,
1725                                  se_tail,
1726                                  se);
1727     notify_clients_stun_change (&se->external_addr,
1728                                 GNUNET_NO);
1729   }
1730   GNUNET_SERVICE_client_continue (ch->client);
1731 }
1732
1733
1734 /**
1735  * Check validity of
1736  * #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from
1737  * client.
1738  *
1739  * @param cls client who sent the message
1740  * @param message the message received
1741  * @return #GNUNET_OK if message is well-formed
1742  */
1743 static int
1744 check_request_connection_reversal (void *cls,
1745                                    const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
1746 {
1747   size_t expect;
1748
1749   expect = ntohs (message->local_addr_size)
1750     + ntohs (message->remote_addr_size);
1751   if (ntohs (message->header.size) - sizeof (*message) != expect)
1752   {
1753     GNUNET_break (0);
1754     return GNUNET_SYSERR;
1755   }
1756   return GNUNET_OK;
1757 }
1758
1759
1760 /**
1761  * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL
1762  * message from client.
1763  *
1764  * @param cls client who sent the message
1765  * @param message the message received
1766  */
1767 static void
1768 handle_request_connection_reversal (void *cls,
1769                                     const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
1770 {
1771   struct ClientHandle *ch = cls;
1772   const char *buf = (const char *) &message[1];
1773   size_t local_sa_len = ntohs (message->local_addr_size);
1774   size_t remote_sa_len = ntohs (message->remote_addr_size);
1775   struct sockaddr_in l4;
1776   struct sockaddr_in r4;
1777   int ret;
1778
1779   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1780               "Received REQUEST CONNECTION REVERSAL message from client\n");
1781   if (local_sa_len != sizeof (struct sockaddr_in))
1782   {
1783     GNUNET_break_op (0);
1784     GNUNET_SERVICE_client_drop (ch->client);
1785     return;
1786   }
1787   if (remote_sa_len != sizeof (struct sockaddr_in))
1788   {
1789     GNUNET_break_op (0);
1790     GNUNET_SERVICE_client_drop (ch->client);
1791     return;
1792   }
1793   GNUNET_memcpy (&l4,
1794                  buf,
1795                  sizeof (struct sockaddr_in));
1796   GNUNET_break_op (AF_INET == l4.sin_family);
1797   buf += sizeof (struct sockaddr_in);
1798   GNUNET_memcpy (&r4,
1799                  buf,
1800                  sizeof (struct sockaddr_in));
1801   GNUNET_break_op (AF_INET == r4.sin_family);
1802   ret = GN_request_connection_reversal (&l4.sin_addr,
1803                                         ntohs (l4.sin_port),
1804                                         &r4.sin_addr);
1805   if (GNUNET_OK != ret)
1806     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1807                 _("Connection reversal request failed\n"));
1808   GNUNET_SERVICE_client_continue (ch->client);
1809 }
1810
1811
1812 /**
1813  * Task run during shutdown.
1814  *
1815  * @param cls unused
1816  */
1817 static void
1818 shutdown_task (void *cls)
1819 {
1820   struct StunExternalIP *se;
1821
1822   while (NULL != (se = se_head))
1823   {
1824     GNUNET_CONTAINER_DLL_remove (se_head,
1825                                  se_tail,
1826                                  se);
1827     GNUNET_SCHEDULER_cancel (se->timeout_task);
1828     GNUNET_free (se);
1829   }
1830   GN_nat_status_changed (GNUNET_NO);
1831   if (NULL != scan_task)
1832   {
1833     GNUNET_SCHEDULER_cancel (scan_task);
1834     scan_task = NULL;
1835   }
1836   if (NULL != stats)
1837   {
1838     GNUNET_STATISTICS_destroy (stats,
1839                                GNUNET_NO);
1840     stats = NULL;
1841   }
1842   destroy_lal ();
1843 }
1844
1845
1846 /**
1847  * Setup NAT service.
1848  *
1849  * @param cls closure
1850  * @param c configuration to use
1851  * @param service the initialized service
1852  */
1853 static void
1854 run (void *cls,
1855      const struct GNUNET_CONFIGURATION_Handle *c,
1856      struct GNUNET_SERVICE_Handle *service)
1857 {
1858   cfg = c;
1859   if (GNUNET_OK !=
1860       GNUNET_CONFIGURATION_get_value_time (cfg,
1861                                            "NAT",
1862                                            "STUN_STALE",
1863                                            &stun_stale_timeout))
1864     stun_stale_timeout = GNUNET_TIME_UNIT_HOURS;
1865
1866   /* Check for UPnP */
1867   enable_upnp
1868     = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1869                                             "NAT",
1870                                             "ENABLE_UPNP");
1871   if (GNUNET_YES == enable_upnp)
1872   {
1873     /* check if it works */
1874     if (GNUNET_SYSERR ==
1875         GNUNET_OS_check_helper_binary ("upnpc",
1876                                        GNUNET_NO,
1877                                        NULL))
1878     {
1879       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1880                   _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP\n"));
1881       enable_upnp = GNUNET_SYSERR;
1882     }
1883   }
1884   if (GNUNET_OK !=
1885       GNUNET_CONFIGURATION_get_value_time (cfg,
1886                                            "nat",
1887                                            "DYNDNS_FREQUENCY",
1888                                            &dyndns_frequency))
1889     dyndns_frequency = DYNDNS_FREQUENCY;
1890
1891   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1892                                  NULL);
1893   stats = GNUNET_STATISTICS_create ("nat",
1894                                     cfg);
1895   scan_task = GNUNET_SCHEDULER_add_now (&run_scan,
1896                                         NULL);
1897 }
1898
1899
1900 /**
1901  * Callback called when a client connects to the service.
1902  *
1903  * @param cls closure for the service
1904  * @param c the new client that connected to the service
1905  * @param mq the message queue used to send messages to the client
1906  * @return a `struct ClientHandle`
1907  */
1908 static void *
1909 client_connect_cb (void *cls,
1910                    struct GNUNET_SERVICE_Client *c,
1911                    struct GNUNET_MQ_Handle *mq)
1912 {
1913   struct ClientHandle *ch;
1914
1915   ch = GNUNET_new (struct ClientHandle);
1916   ch->mq = mq;
1917   ch->client = c;
1918   GNUNET_CONTAINER_DLL_insert (ch_head,
1919                                ch_tail,
1920                                ch);
1921   return ch;
1922 }
1923
1924
1925 /**
1926  * Callback called when a client disconnected from the service
1927  *
1928  * @param cls closure for the service
1929  * @param c the client that disconnected
1930  * @param internal_cls a `struct ClientHandle *`
1931  */
1932 static void
1933 client_disconnect_cb (void *cls,
1934                       struct GNUNET_SERVICE_Client *c,
1935                       void *internal_cls)
1936 {
1937   struct ClientHandle *ch = internal_cls;
1938   struct LocalAddressList *lal;
1939
1940   GNUNET_CONTAINER_DLL_remove (ch_head,
1941                                ch_tail,
1942                                ch);
1943   for (unsigned int i=0;i<ch->num_caddrs;i++)
1944   {
1945     if (NULL != ch->caddrs[i].mh)
1946     {
1947       GNUNET_NAT_mini_map_stop (ch->caddrs[i].mh);
1948       ch->caddrs[i].mh = NULL;
1949     }
1950   }
1951   GNUNET_free_non_null (ch->caddrs);
1952   while (NULL != (lal = ch->ext_addr_head))
1953   {
1954     GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
1955                                  ch->ext_addr_tail,
1956                                  lal);
1957     GNUNET_free (lal);
1958   }
1959   if (NULL != ch->ext_dns_task)
1960   {
1961     GNUNET_SCHEDULER_cancel (ch->ext_dns_task);
1962     ch->ext_dns_task = NULL;
1963   }
1964   if (NULL != ch->external_monitor)
1965   {
1966     GN_external_ipv4_monitor_stop (ch->external_monitor);
1967     ch->external_monitor = NULL;
1968   }
1969   if (NULL != ch->ext_dns)
1970   {
1971     GNUNET_RESOLVER_request_cancel (ch->ext_dns);
1972     ch->ext_dns = NULL;
1973   }
1974   GNUNET_free_non_null (ch->hole_external);
1975   GNUNET_free_non_null (ch->section_name);
1976   GNUNET_free (ch);
1977 }
1978
1979
1980 /**
1981  * Define "main" method using service macro.
1982  */
1983 GNUNET_SERVICE_MAIN
1984 ("nat",
1985  GNUNET_SERVICE_OPTION_NONE,
1986  &run,
1987  &client_connect_cb,
1988  &client_disconnect_cb,
1989  NULL,
1990  GNUNET_MQ_hd_var_size (register,
1991                         GNUNET_MESSAGE_TYPE_NAT_REGISTER,
1992                         struct GNUNET_NAT_RegisterMessage,
1993                         NULL),
1994  GNUNET_MQ_hd_var_size (stun,
1995                         GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN,
1996                         struct GNUNET_NAT_HandleStunMessage,
1997                         NULL),
1998  GNUNET_MQ_hd_var_size (request_connection_reversal,
1999                         GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
2000                         struct GNUNET_NAT_RequestConnectionReversalMessage,
2001                         NULL),
2002  GNUNET_MQ_handler_end ());
2003
2004
2005 #if defined(LINUX) && defined(__GLIBC__)
2006 #include <malloc.h>
2007
2008 /**
2009  * MINIMIZE heap size (way below 128k) since this process doesn't need much.
2010  */
2011 void __attribute__ ((constructor))
2012 GNUNET_ARM_memory_init ()
2013 {
2014   mallopt (M_TRIM_THRESHOLD, 4 * 1024);
2015   mallopt (M_TOP_PAD, 1 * 1024);
2016   malloc_trim (0);
2017 }
2018 #endif
2019
2020 /* end of gnunet-service-nat.c */