porting xdht to new service API, major code de-duplication effort
[oweals/gnunet.git] / src / nat / nat.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2010, 2011 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/nat.c
23  * @brief Library handling UPnP and NAT-PMP port forwarding and
24  *     external IP address retrieval
25  * @author Milan Bouchet-Valat
26  * @author Christian Grothoff
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_resolver_service.h"
31 #include "gnunet_nat_lib.h"
32 #include "nat.h"
33
34 #define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
35
36 /**
37  * How often do we scan for changes in our IP address from our local
38  * interfaces?
39  */
40 #define IFC_SCAN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
41
42 /**
43  * How often do we scan for changes in how our hostname resolves?
44  */
45 #define HOSTNAME_DNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 20)
46
47
48 /**
49  * How often do we scan for changes in how our external (dyndns) hostname resolves?
50  */
51 #define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)
52
53 /**
54  * How long until we give up trying to resolve our own hostname?
55  */
56 #define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
57
58
59 /**
60  * How often do we check a STUN server ?
61  */
62 #define STUN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
63
64
65 /**
66  * Where did the given local address originate from?
67  * To be used for debugging as well as in the future
68  * to remove all addresses from a certain source when
69  * we reevaluate the source.
70  */
71 enum LocalAddressSource
72 {
73   /**
74    * Address was obtained by DNS resolution of the external hostname
75    * given in the configuration (i.e. hole-punched DynDNS setup).
76    */
77   LAL_EXTERNAL_IP,
78
79    /**
80    * Address was obtained by an external STUN server
81    */
82   LAL_EXTERNAL_STUN_IP,
83
84   /**
85    * Address was obtained by DNS resolution of the external hostname
86    * given in the configuration (i.e. hole-punched DynDNS setup)
87    * during the previous iteration (see #3213).
88    */
89   LAL_EXTERNAL_IP_OLD,
90
91   /**
92    * Address was obtained by looking up our own hostname in DNS.
93    */
94   LAL_HOSTNAME_DNS,
95
96   /**
97    * Address was obtained by scanning our hosts's network interfaces
98    * and taking their address (no DNS involved).
99    */
100   LAL_INTERFACE_ADDRESS,
101
102   /**
103    * Addresses we were explicitly bound to.
104    */
105   LAL_BINDTO_ADDRESS,
106
107   /**
108    * Addresses from UPnP or PMP
109    */
110   LAL_UPNP,
111
112   /**
113    * End of the list.
114    */
115   LAL_END
116 };
117
118
119 /**
120  * List of local addresses that we currently deem valid.  Actual
121  * struct is followed by the 'struct sockaddr'.  Note that the code
122  * intentionally makes no attempt to ensure that a particular address
123  * is only listed once (especially since it may come from different
124  * sources, and the source is an "internal" construct).
125  */
126 struct LocalAddressList
127 {
128   /**
129    * This is a linked list.
130    */
131   struct LocalAddressList *next;
132
133   /**
134    * Previous entry.
135    */
136   struct LocalAddressList *prev;
137
138   /**
139    * Number of bytes of address that follow.
140    */
141   socklen_t addrlen;
142
143   /**
144    * Origin of the local address.
145    */
146   enum LocalAddressSource source;
147 };
148
149
150 /**
151  * Handle for miniupnp-based NAT traversal actions.
152  */
153 struct MiniList
154 {
155
156   /**
157    * Doubly-linked list.
158    */
159   struct MiniList *next;
160
161   /**
162    * Doubly-linked list.
163    */
164   struct MiniList *prev;
165
166   /**
167    * Handle to mini-action.
168    */
169   struct GNUNET_NAT_MiniHandle *mini;
170
171   /**
172    * Local port number that was mapped.
173    */
174   uint16_t port;
175
176 };
177
178
179 /**
180  * List of STUN servers
181  */
182 struct StunServerList
183 {
184
185   /**
186    * Doubly-linked list.
187    */
188   struct StunServerList *next;
189
190   /**
191    * Doubly-linked list.
192    */
193   struct StunServerList *prev;
194
195   /**
196    * Address
197    */
198   char * address;
199
200   /**
201    * Server Port
202    */
203   uint16_t port;
204
205 };
206
207
208 /**
209  * Handle for active NAT registrations.
210  */
211 struct GNUNET_NAT_Handle
212 {
213
214   /**
215    * Configuration to use.
216    */
217   const struct GNUNET_CONFIGURATION_Handle *cfg;
218
219   /**
220    * Function to call when we learn about a new address.
221    */
222   GNUNET_NAT_AddressCallback address_callback;
223
224   /**
225    * Function to call when we notice another peer asking for
226    * connection reversal.
227    */
228   GNUNET_NAT_ReversalCallback reversal_callback;
229
230   /**
231    * Closure for callbacks (@e address_callback and @e reversal_callback)
232    */
233   void *callback_cls;
234
235   /**
236    * Handle for (DYN)DNS lookup of our external IP.
237    */
238   struct GNUNET_RESOLVER_RequestHandle *ext_dns;
239
240   /**
241    * Handle for request of hostname resolution, non-NULL if pending.
242    */
243   struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
244
245   /**
246    * stdout pipe handle for the gnunet-helper-nat-server process
247    */
248   struct GNUNET_DISK_PipeHandle *server_stdout;
249
250   /**
251    * stdout file handle (for reading) for the gnunet-helper-nat-server process
252    */
253   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
254
255   /**
256    * Linked list of currently valid addresses (head).
257    */
258   struct LocalAddressList *lal_head;
259
260   /**
261    * Linked list of currently valid addresses (tail).
262    */
263   struct LocalAddressList *lal_tail;
264
265   /**
266    * How long do we wait for restarting a crashed gnunet-helper-nat-server?
267    */
268   struct GNUNET_TIME_Relative server_retry_delay;
269
270   /**
271    * ID of select gnunet-helper-nat-server stdout read task
272    */
273   struct GNUNET_SCHEDULER_Task *server_read_task;
274
275   /**
276    * ID of interface IP-scan task
277    */
278   struct GNUNET_SCHEDULER_Task *ifc_task;
279
280   /**
281    * ID of hostname DNS lookup task
282    */
283   struct GNUNET_SCHEDULER_Task *hostname_task;
284
285   /**
286    * ID of DynDNS lookup task
287    */
288   struct GNUNET_SCHEDULER_Task *dns_task;
289
290   /**
291    * Active STUN request, if any.
292    */
293   struct GNUNET_NAT_STUN_Handle *stun_request;
294
295   /**
296    * How often do we scan for changes in our IP address from our local
297    * interfaces?
298    */
299   struct GNUNET_TIME_Relative ifc_scan_frequency;
300
301   /**
302    * How often do we scan for changes in how our hostname resolves?
303    */
304   struct GNUNET_TIME_Relative hostname_dns_frequency;
305
306   /**
307    * How often do we scan for changes in how our external (dyndns) hostname resolves?
308    */
309   struct GNUNET_TIME_Relative dyndns_frequency;
310
311   /**
312    * The process id of the server process (if behind NAT)
313    */
314   struct GNUNET_OS_Process *server_proc;
315
316   /**
317    * LAN address as passed by the caller (array).
318    */
319   struct sockaddr **local_addrs;
320
321   /**
322    * Length of the @e local_addrs.
323    */
324   socklen_t *local_addrlens;
325
326   /**
327    * List of handles for UPnP-traversal, one per local port (if
328    * not IPv6-only).
329    */
330   struct MiniList *mini_head;
331
332   /**
333    * List of handles for UPnP-traversal, one per local port (if
334    * not IPv6-only).
335    */
336   struct MiniList *mini_tail;
337
338   /**
339    * Number of entries in 'local_addrs' array.
340    */
341   unsigned int num_local_addrs;
342
343   /**
344    * Our external address (according to config, UPnP may disagree...),
345    * in dotted decimal notation, IPv4-only. Or NULL if not known.
346    */
347   char *external_address;
348
349   /**
350    * Presumably our internal address (according to config)
351    */
352   char *internal_address;
353
354   /**
355    * Is this transport configured to be behind a NAT?
356    */
357   int behind_nat;
358
359   /**
360    * Has the NAT been punched? (according to config)
361    */
362   int nat_punched;
363
364   /**
365    * Is this transport configured to allow connections to NAT'd peers?
366    */
367   int enable_nat_client;
368
369   /**
370    * Should we run the gnunet-helper-nat-server?
371    */
372   int enable_nat_server;
373
374   /**
375    * Are we allowed to try UPnP/PMP for NAT traversal?
376    */
377   int enable_upnp;
378
379   /**
380    * Should we use local addresses (loopback)? (according to config)
381    */
382   int use_localaddresses;
383
384   /**
385    * Should we return local addresses to clients
386    */
387   int return_localaddress;
388
389   /**
390    * Should we do a DNS lookup of our hostname to find out our own IP?
391    */
392   int use_hostname;
393
394   /**
395    * Is using IPv6 disabled?
396    */
397   int disable_ipv6;
398
399   /**
400    * Is this TCP or UDP?
401    */
402   int is_tcp;
403
404   /**
405    * Port we advertise to the outside.
406    */
407   uint16_t adv_port;
408
409   /**
410    * Should we use STUN ?
411    */
412   int use_stun;
413
414   /**
415    * How often should we check STUN ?
416    */
417   struct GNUNET_TIME_Relative stun_frequency;
418
419   /**
420    * STUN socket
421    */
422   struct GNUNET_NETWORK_Handle* socket;
423
424   /*
425    * Am I waiting for a STUN response ?
426    */
427   int waiting_stun;
428
429   /**
430    * STUN request task
431    */
432   struct GNUNET_SCHEDULER_Task *stun_task;
433
434   /**
435    * Head of List of STUN servers
436    */
437   struct StunServerList *stun_servers_head;
438
439   /**
440    * Tail of List of STUN servers
441    */
442   struct StunServerList *stun_servers_tail;
443
444   /**
445    * Actual STUN Server
446    */
447   struct StunServerList *actual_stun_server;
448
449 };
450
451
452 /**
453  * Try to start the gnunet-helper-nat-server (if it is not
454  * already running).
455  *
456  * @param h handle to NAT
457  */
458 static void
459 start_gnunet_nat_server (struct GNUNET_NAT_Handle *h);
460
461
462 /**
463  * Remove all addresses from the list of 'local' addresses
464  * that originated from the given source.
465  *
466  * @param h handle to NAT
467  * @param src source that identifies addresses to remove
468  */
469 static void
470 remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h,
471                                     enum LocalAddressSource src)
472 {
473   struct LocalAddressList *pos;
474   struct LocalAddressList *next;
475
476   next = h->lal_head;
477   while (NULL != (pos = next))
478   {
479     next = pos->next;
480     if (pos->source != src)
481       continue;
482     GNUNET_CONTAINER_DLL_remove (h->lal_head,
483                                  h->lal_tail,
484                                  pos);
485     if (NULL != h->address_callback)
486       h->address_callback (h->callback_cls,
487                            GNUNET_NO,
488                            (const struct sockaddr *) &pos[1],
489                            pos->addrlen);
490     GNUNET_free (pos);
491   }
492 }
493
494
495 /**
496  * Add the given address to the list of 'local' addresses, thereby
497  * making it a 'legal' address for this peer to have.
498  *
499  * @param h handle to NAT
500  * @param src where did the local address originate from?
501  * @param arg the address, some `struct sockaddr`
502  * @param arg_size number of bytes in @a arg
503  */
504 static void
505 add_to_address_list_as_is (struct GNUNET_NAT_Handle *h,
506                            enum LocalAddressSource src,
507                            const struct sockaddr *arg,
508                            socklen_t arg_size)
509 {
510   struct LocalAddressList *lal;
511
512   lal = GNUNET_malloc (sizeof (struct LocalAddressList) + arg_size);
513   GNUNET_memcpy (&lal[1], arg, arg_size);
514   lal->addrlen = arg_size;
515   lal->source = src;
516   GNUNET_CONTAINER_DLL_insert (h->lal_head,
517                                h->lal_tail,
518                                lal);
519   LOG (GNUNET_ERROR_TYPE_DEBUG,
520        "Adding address `%s' from source %d\n",
521        GNUNET_a2s (arg, arg_size),
522        src);
523   if (NULL != h->address_callback)
524     h->address_callback (h->callback_cls,
525                          GNUNET_YES,
526                          arg,
527                          arg_size);
528 }
529
530
531 /**
532  * Add the given address to the list of 'local' addresses, thereby
533  * making it a 'legal' address for this peer to have.   Set the
534  * port number in the process to the advertised port and possibly
535  * also to zero (if we have the gnunet-helper-nat-server).
536  *
537  * @param h handle to NAT
538  * @param src where did the local address originate from?
539  * @param arg the address, some `struct sockaddr`
540  * @param arg_size number of bytes in @a arg
541  */
542 static void
543 add_to_address_list (struct GNUNET_NAT_Handle *h,
544                      enum LocalAddressSource src,
545                      const struct sockaddr *arg,
546                      socklen_t arg_size)
547 {
548   struct sockaddr_in s4;
549   const struct sockaddr_in *in4;
550   struct sockaddr_in6 s6;
551   const struct sockaddr_in6 *in6;
552
553   if (arg_size == sizeof (struct sockaddr_in))
554   {
555     in4 = (const struct sockaddr_in *) arg;
556     s4 = *in4;
557     s4.sin_port = htons (h->adv_port);
558     add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4,
559                                sizeof (struct sockaddr_in));
560     if (GNUNET_YES == h->enable_nat_server)
561     {
562       /* also add with PORT = 0 to indicate NAT server is enabled */
563       s4.sin_port = htons (0);
564       add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4,
565                                  sizeof (struct sockaddr_in));
566     }
567   }
568   else if (arg_size == sizeof (struct sockaddr_in6))
569   {
570     if (GNUNET_YES != h->disable_ipv6)
571     {
572       in6 = (const struct sockaddr_in6 *) arg;
573       s6 = *in6;
574       s6.sin6_port = htons (h->adv_port);
575       add_to_address_list_as_is (h, src, (const struct sockaddr *) &s6,
576                                  sizeof (struct sockaddr_in6));
577     }
578   }
579   else
580   {
581     GNUNET_assert (0);
582   }
583 }
584
585
586 /**
587  * Add the given IP address to the list of 'local' addresses, thereby
588  * making it a 'legal' address for this peer to have.
589  *
590  * @param h handle to NAT
591  * @param src where did the local address originate from?
592  * @param addr the address, some `struct in_addr` or `struct in6_addr`
593  * @param addrlen number of bytes in addr
594  */
595 static void
596 add_ip_to_address_list (struct GNUNET_NAT_Handle *h,
597                         enum LocalAddressSource src,
598                         const void *addr,
599                         socklen_t addrlen)
600 {
601   struct sockaddr_in s4;
602   const struct in_addr *in4;
603   struct sockaddr_in6 s6;
604   const struct in6_addr *in6;
605
606   if (addrlen == sizeof (struct in_addr))
607   {
608     in4 = (const struct in_addr *) addr;
609     memset (&s4, 0, sizeof (s4));
610     s4.sin_family = AF_INET;
611     s4.sin_port = 0;
612 #if HAVE_SOCKADDR_IN_SIN_LEN
613     s4.sin_len = (u_char) sizeof (struct sockaddr_in);
614 #endif
615     s4.sin_addr = *in4;
616     add_to_address_list (h, src, (const struct sockaddr *) &s4,
617                          sizeof (struct sockaddr_in));
618     if (GNUNET_YES == h->enable_nat_server)
619     {
620       /* also add with PORT = 0 to indicate NAT server is enabled */
621       s4.sin_port = htons (0);
622       add_to_address_list (h, src, (const struct sockaddr *) &s4,
623                            sizeof (struct sockaddr_in));
624
625     }
626   }
627   else if (addrlen == sizeof (struct in6_addr))
628   {
629     if (GNUNET_YES != h->disable_ipv6)
630     {
631       in6 = (const struct in6_addr *) addr;
632       memset (&s6, 0, sizeof (s6));
633       s6.sin6_family = AF_INET6;
634       s6.sin6_port = htons (h->adv_port);
635 #if HAVE_SOCKADDR_IN_SIN_LEN
636       s6.sin6_len = (u_char) sizeof (struct sockaddr_in6);
637 #endif
638       s6.sin6_addr = *in6;
639       add_to_address_list (h, src, (const struct sockaddr *) &s6,
640                            sizeof (struct sockaddr_in6));
641     }
642   }
643   else
644   {
645     GNUNET_assert (0);
646   }
647 }
648
649
650 /**
651  * Task to do DNS lookup on our external hostname to
652  * get DynDNS-IP addresses.
653  *
654  * @param cls the NAT handle
655  */
656 static void
657 resolve_dns (void *cls);
658
659
660 /**
661  * Our (external) hostname was resolved and the configuration says that
662  * the NAT was hole-punched.
663  *
664  * @param cls the `struct GNUNET_NAT_Handle`
665  * @param addr NULL on error, otherwise result of DNS lookup
666  * @param addrlen number of bytes in @a addr
667  */
668 static void
669 process_external_ip (void *cls,
670                      const struct sockaddr *addr,
671                      socklen_t addrlen)
672 {
673   struct GNUNET_NAT_Handle *h = cls;
674   struct in_addr dummy;
675
676   if (NULL == addr)
677   {
678     h->ext_dns = NULL;
679     /* Current iteration is over, remove 'old' IPs now */
680     LOG (GNUNET_ERROR_TYPE_DEBUG,
681          "Purging old IPs for external address\n");
682     remove_from_address_list_by_source (h,
683                                         LAL_EXTERNAL_IP_OLD);
684     if (1 == inet_pton (AF_INET,
685                         h->external_address,
686                         &dummy))
687     {
688       LOG (GNUNET_ERROR_TYPE_DEBUG,
689            "Got numeric IP for external address, not repeating lookup\n");
690       return;                   /* repated lookup pointless: was numeric! */
691     }
692     h->dns_task =
693       GNUNET_SCHEDULER_add_delayed (h->dyndns_frequency,
694                                     &resolve_dns, h);
695     return;
696   }
697   LOG (GNUNET_ERROR_TYPE_DEBUG,
698        "Got IP `%s' for external address `%s'\n",
699        GNUNET_a2s (addr,
700                    addrlen),
701        h->external_address);
702   add_to_address_list (h,
703                        LAL_EXTERNAL_IP,
704                        addr,
705                        addrlen);
706 }
707
708
709 /**
710  * Task to do a lookup on our hostname for IP addresses.
711  *
712  * @param cls the NAT handle
713  */
714 static void
715 resolve_hostname (void *cls);
716
717
718 /**
719  * Function called by the resolver for each address obtained from DNS
720  * for our own hostname.  Add the addresses to the list of our IP
721  * addresses.
722  *
723  * @param cls closure
724  * @param addr one of the addresses of the host, NULL for the last address
725  * @param addrlen length of the @a addr
726  */
727 static void
728 process_hostname_ip (void *cls,
729                      const struct sockaddr *addr,
730                      socklen_t addrlen)
731 {
732   struct GNUNET_NAT_Handle *h = cls;
733
734   if (NULL == addr)
735   {
736     h->hostname_dns = NULL;
737     h->hostname_task =
738         GNUNET_SCHEDULER_add_delayed (h->hostname_dns_frequency,
739                                       &resolve_hostname,
740                                       h);
741     return;
742   }
743   add_to_address_list (h,
744                        LAL_HOSTNAME_DNS,
745                        addr,
746                        addrlen);
747 }
748
749
750 /**
751  * Length of the interface names returned from os_network.c.
752  * (in that file, hardcoded at 11).
753  */
754 #define IF_NAME_LEN 11
755
756
757 /**
758  * Add the IP of our network interface to the list of
759  * our IP addresses.
760  *
761  * @param cls the `struct GNUNET_NAT_Handle`
762  * @param name name of the interface
763  * @param isDefault do we think this may be our default interface
764  * @param addr address of the interface
765  * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
766  * @param netmask the network mask (can be NULL for unknown or unassigned))
767  * @param addrlen number of bytes in @a addr and @a broadcast_addr
768  * @return #GNUNET_OK to continue iterating
769  */
770 static int
771 process_interfaces (void *cls,
772                     const char *name,
773                     int isDefault,
774                     const struct sockaddr *addr,
775                     const struct sockaddr *broadcast_addr,
776                     const struct sockaddr *netmask,
777                     socklen_t addrlen)
778 {
779   const static struct in6_addr any6 = IN6ADDR_ANY_INIT;
780   struct GNUNET_NAT_Handle *h = cls;
781   const struct sockaddr_in *s4;
782   const struct sockaddr_in6 *s6;
783   const void *ip;
784   char buf[INET6_ADDRSTRLEN];
785   unsigned int i;
786   int have_any;
787   char *tun_if;
788
789   /* skip virtual interfaces created by GNUnet-vpn */
790   if (GNUNET_OK ==
791       GNUNET_CONFIGURATION_get_value_string (h->cfg,
792                                              "vpn",
793                                              "IFNAME",
794                                              &tun_if))
795   {
796     if (0 == strncasecmp (name,
797                           tun_if,
798                           IF_NAME_LEN))
799     {
800       GNUNET_free (tun_if);
801       return GNUNET_OK;
802     }
803     GNUNET_free (tun_if);
804   }
805   /* skip virtual interfaces created by GNUnet-dns */
806   if (GNUNET_OK ==
807       GNUNET_CONFIGURATION_get_value_string (h->cfg,
808                                              "dns",
809                                              "IFNAME",
810                                              &tun_if))
811   {
812     if (0 == strncasecmp (name,
813                           tun_if,
814                           IF_NAME_LEN))
815     {
816       GNUNET_free (tun_if);
817       return GNUNET_OK;
818     }
819     GNUNET_free (tun_if);
820   }
821   /* skip virtual interfaces created by GNUnet-exit */
822   if (GNUNET_OK ==
823       GNUNET_CONFIGURATION_get_value_string (h->cfg,
824                                              "exit",
825                                              "TUN_IFNAME",
826                                              &tun_if))
827   {
828     if (0 == strncasecmp (name,
829                           tun_if,
830                           IF_NAME_LEN))
831     {
832       GNUNET_free (tun_if);
833       return GNUNET_OK;
834     }
835     GNUNET_free (tun_if);
836   }
837
838   switch (addr->sa_family)
839   {
840   case AF_INET:
841     /* check if we're bound to the "ANY" IP address */
842     have_any = GNUNET_NO;
843     for (i=0;i<h->num_local_addrs;i++)
844       {
845         if (h->local_addrs[i]->sa_family != AF_INET)
846           continue;
847 #ifndef INADDR_ANY
848 #define INADDR_ANY 0
849 #endif
850         if (INADDR_ANY == ((struct sockaddr_in*) h->local_addrs[i])->sin_addr.s_addr)
851           {
852             have_any = GNUNET_YES;
853             break;
854           }
855       }
856     if (GNUNET_NO == have_any)
857       return GNUNET_OK; /* not bound to IP 0.0.0.0 but to specific IP addresses,
858                            do not use those from interfaces */
859     s4 = (struct sockaddr_in *) addr;
860     ip = &s4->sin_addr;
861
862     /* Check if address is in 127.0.0.0/8 */
863     uint32_t address = ntohl ((uint32_t) (s4->sin_addr.s_addr));
864     uint32_t value = (address & 0xFF000000) ^ 0x7F000000;
865
866     if ((h->return_localaddress == GNUNET_NO) && (value == 0))
867     {
868       return GNUNET_OK;
869     }
870     if ((GNUNET_YES == h->use_localaddresses) || (value != 0))
871     {
872       add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr,
873                               sizeof (struct in_addr));
874     }
875     break;
876   case AF_INET6:
877     /* check if we're bound to the "ANY" IP address */
878     have_any = GNUNET_NO;
879     for (i=0;i<h->num_local_addrs;i++)
880       {
881         if (h->local_addrs[i]->sa_family != AF_INET6)
882           continue;
883         if (0 == memcmp (&any6,
884                          &((struct sockaddr_in6*) h->local_addrs[i])->sin6_addr,
885                          sizeof (struct in6_addr)))
886           {
887             have_any = GNUNET_YES;
888             break;
889           }
890       }
891     if (GNUNET_NO == have_any)
892       return GNUNET_OK; /* not bound to "ANY" IP (::0) but to specific IP addresses,
893                            do not use those from interfaces */
894
895     s6 = (struct sockaddr_in6 *) addr;
896     if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
897     {
898       /* skip link local addresses */
899       return GNUNET_OK;
900     }
901     if ((h->return_localaddress == GNUNET_NO) &&
902         (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr)))
903     {
904       return GNUNET_OK;
905     }
906     ip = &s6->sin6_addr;
907     if (GNUNET_YES == h->use_localaddresses)
908     {
909       add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s6->sin6_addr,
910                               sizeof (struct in6_addr));
911     }
912     break;
913   default:
914     GNUNET_break (0);
915     return GNUNET_OK;
916   }
917   if ( (h->internal_address == NULL) &&
918        (h->server_proc == NULL) &&
919        (h->server_read_task == NULL) &&
920        (GNUNET_YES == isDefault) &&
921        ( (addr->sa_family == AF_INET) ||
922          (addr->sa_family == AF_INET6) ) )
923   {
924     /* no internal address configured, but we found a "default"
925      * interface, try using that as our 'internal' address */
926     h->internal_address =
927         GNUNET_strdup (inet_ntop (addr->sa_family, ip, buf, sizeof (buf)));
928     start_gnunet_nat_server (h);
929   }
930   return GNUNET_OK;
931 }
932
933
934 /**
935  * Task that restarts the gnunet-helper-nat-server process after a crash
936  * after a certain delay.
937  *
938  * @param cls the `struct GNUNET_NAT_Handle`
939  */
940 static void
941 restart_nat_server (void *cls)
942 {
943   struct GNUNET_NAT_Handle *h = cls;
944
945   h->server_read_task = NULL;
946   start_gnunet_nat_server (h);
947 }
948
949
950 /**
951  * We have been notified that gnunet-helper-nat-server has written
952  * something to stdout.  Handle the output, then reschedule this
953  * function to be called again once more is available.
954  *
955  * @param cls the NAT handle
956  */
957 static void
958 nat_server_read (void *cls)
959 {
960   struct GNUNET_NAT_Handle *h = cls;
961   char mybuf[40];
962   ssize_t bytes;
963   size_t i;
964   int port;
965   const char *port_start;
966   struct sockaddr_in sin_addr;
967
968   h->server_read_task = NULL;
969   memset (mybuf, 0, sizeof (mybuf));
970   bytes =
971     GNUNET_DISK_file_read (h->server_stdout_handle, mybuf, sizeof (mybuf));
972   if (bytes < 1)
973   {
974     LOG (GNUNET_ERROR_TYPE_DEBUG,
975          "Finished reading from server stdout with code: %d\n",
976          bytes);
977     if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG))
978       GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill");
979     GNUNET_OS_process_wait (h->server_proc);
980     GNUNET_OS_process_destroy (h->server_proc);
981     h->server_proc = NULL;
982     GNUNET_DISK_pipe_close (h->server_stdout);
983     h->server_stdout = NULL;
984     h->server_stdout_handle = NULL;
985     /* now try to restart it */
986     h->server_retry_delay = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay);
987     h->server_read_task =
988         GNUNET_SCHEDULER_add_delayed (h->server_retry_delay,
989                                       &restart_nat_server, h);
990     return;
991   }
992
993   port_start = NULL;
994   for (i = 0; i < sizeof (mybuf); i++)
995   {
996     if (mybuf[i] == '\n')
997     {
998       mybuf[i] = '\0';
999       break;
1000     }
1001     if ((mybuf[i] == ':') && (i + 1 < sizeof (mybuf)))
1002     {
1003       mybuf[i] = '\0';
1004       port_start = &mybuf[i + 1];
1005     }
1006   }
1007
1008   /* construct socket address of sender */
1009   memset (&sin_addr, 0, sizeof (sin_addr));
1010   sin_addr.sin_family = AF_INET;
1011 #if HAVE_SOCKADDR_IN_SIN_LEN
1012   sin_addr.sin_len = sizeof (sin_addr);
1013 #endif
1014   if ((NULL == port_start) || (1 != SSCANF (port_start, "%d", &port)) ||
1015       (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr)))
1016   {
1017     /* should we restart gnunet-helper-nat-server? */
1018     LOG (GNUNET_ERROR_TYPE_WARNING, "nat",
1019          _("gnunet-helper-nat-server generated malformed address `%s'\n"),
1020          mybuf);
1021     h->server_read_task =
1022         GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1023                                         h->server_stdout_handle,
1024                                         &nat_server_read, h);
1025     return;
1026   }
1027   sin_addr.sin_port = htons ((uint16_t) port);
1028   LOG (GNUNET_ERROR_TYPE_DEBUG, "gnunet-helper-nat-server read: %s:%d\n", mybuf,
1029        port);
1030   h->reversal_callback (h->callback_cls, (const struct sockaddr *) &sin_addr,
1031                         sizeof (sin_addr));
1032   h->server_read_task =
1033       GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1034                                       h->server_stdout_handle,
1035                                       &nat_server_read,
1036                                       h);
1037 }
1038
1039
1040 /**
1041  * Try to start the gnunet-helper-nat-server (if it is not
1042  * already running).
1043  *
1044  * @param h handle to NAT
1045  */
1046 static void
1047 start_gnunet_nat_server (struct GNUNET_NAT_Handle *h)
1048 {
1049   char *binary;
1050
1051   if ((h->behind_nat == GNUNET_YES) && (h->enable_nat_server == GNUNET_YES) &&
1052       (h->internal_address != NULL) &&
1053       (NULL !=
1054        (h->server_stdout =
1055         GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES))))
1056   {
1057     LOG (GNUNET_ERROR_TYPE_DEBUG,
1058          "Starting `%s' at `%s'\n",
1059          "gnunet-helper-nat-server", h->internal_address);
1060     /* Start the server process */
1061     binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
1062     h->server_proc =
1063         GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, NULL,
1064                                  binary,
1065                                  "gnunet-helper-nat-server",
1066                                  h->internal_address, NULL);
1067     GNUNET_free (binary);
1068     if (h->server_proc == NULL)
1069     {
1070       LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("Failed to start %s\n"),
1071            "gnunet-helper-nat-server");
1072       GNUNET_DISK_pipe_close (h->server_stdout);
1073       h->server_stdout = NULL;
1074     }
1075     else
1076     {
1077       /* Close the write end of the read pipe */
1078       GNUNET_DISK_pipe_close_end (h->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1079       h->server_stdout_handle =
1080           GNUNET_DISK_pipe_handle (h->server_stdout, GNUNET_DISK_PIPE_END_READ);
1081       h->server_read_task =
1082           GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1083                                           h->server_stdout_handle,
1084                                           &nat_server_read, h);
1085     }
1086   }
1087 }
1088
1089
1090 /**
1091  * Task to scan the local network interfaces for IP addresses.
1092  *
1093  * @param cls the NAT handle
1094  */
1095 static void
1096 list_interfaces (void *cls)
1097 {
1098   struct GNUNET_NAT_Handle *h = cls;
1099
1100   h->ifc_task = NULL;
1101   remove_from_address_list_by_source (h, LAL_INTERFACE_ADDRESS);
1102   GNUNET_OS_network_interfaces_list (&process_interfaces, h);
1103   h->ifc_task =
1104     GNUNET_SCHEDULER_add_delayed (h->ifc_scan_frequency,
1105                                   &list_interfaces, h);
1106 }
1107
1108
1109 /**
1110  * Callback with the result from the STUN request.
1111  *
1112  * @param cls the NAT handle
1113  * @param result the status
1114  */
1115 static void
1116 stun_request_callback (void *cls,
1117                        enum GNUNET_NAT_StatusCode result)
1118 {
1119   struct GNUNET_NAT_Handle *h = cls;
1120
1121   h->stun_request = NULL;
1122   switch (result)
1123   {
1124   case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
1125     LOG (GNUNET_ERROR_TYPE_WARNING,
1126          "Failed to transmit STUN request\n");
1127     break;
1128   case GNUNET_NAT_ERROR_NOT_ONLINE:
1129     LOG (GNUNET_ERROR_TYPE_WARNING,
1130          "Failed to resolve STUN server (are we online?)\n");
1131     break;
1132   case GNUNET_NAT_ERROR_SUCCESS:
1133     /* all good, STUN request active */
1134     h->waiting_stun = GNUNET_YES;
1135     break;
1136   default:
1137     /* unexpected error code for STUN */
1138     GNUNET_break (0);
1139   }
1140 }
1141
1142
1143 /**
1144  * CHECK if is a valid STUN packet sending to GNUNET_NAT_stun_handle_packet().
1145  * It also check if it can handle the packet based on the NAT handler.
1146  * You don't need to call anything else to check if the packet is valid,
1147  *
1148  * @param cls the NAT handle
1149  * @param data packet
1150  * @param len packet length
1151  * @return #GNUNET_NO if it can't decode, #GNUNET_YES if is a packet
1152  */
1153 int
1154 GNUNET_NAT_is_valid_stun_packet (void *cls,
1155                                  const void *data,
1156                                  size_t len)
1157 {
1158   struct GNUNET_NAT_Handle *h = cls;
1159   struct sockaddr_in answer;
1160
1161   /* We are not expecting a STUN message */
1162   if (GNUNET_YES != h->waiting_stun)
1163     return GNUNET_NO;
1164
1165   /* We dont have STUN installed */
1166   if (! h->use_stun)
1167     return GNUNET_NO;
1168
1169   /* Empty the answer structure */
1170   memset (&answer,
1171           0,
1172           sizeof(struct sockaddr_in));
1173
1174   /* Lets handle the packet*/
1175   if (GNUNET_NO ==
1176       GNUNET_NAT_stun_handle_packet (data,
1177                                      len,
1178                                      &answer))
1179     return GNUNET_NO;
1180
1181   LOG (GNUNET_ERROR_TYPE_INFO,
1182        "STUN server returned %s:%d\n",
1183        inet_ntoa (answer.sin_addr),
1184        ntohs (answer.sin_port));
1185   /* Remove old IPs from previous STUN calls */
1186   remove_from_address_list_by_source (h,
1187                                       LAL_EXTERNAL_STUN_IP);
1188   /* Add new IP from STUN packet */
1189   add_to_address_list (h,
1190                        LAL_EXTERNAL_STUN_IP,
1191                        (const struct sockaddr *) &answer,
1192                        sizeof (struct sockaddr_in));
1193   h->waiting_stun = GNUNET_NO;
1194   return GNUNET_YES;
1195 }
1196
1197
1198 /**
1199  * Task to do a STUN request
1200  *
1201  * @param cls the NAT handle
1202  */
1203 static void
1204 process_stun (void *cls)
1205 {
1206   struct GNUNET_NAT_Handle *h = cls;
1207   struct StunServerList *elem = h->actual_stun_server;
1208
1209   h->stun_task = NULL;
1210   /* Make the request */
1211   LOG (GNUNET_ERROR_TYPE_INFO,
1212        "I will request the stun server %s:%i\n",
1213        elem->address,
1214        elem->port);
1215   if (NULL != h->stun_request)
1216   {
1217     GNUNET_NAT_stun_make_request_cancel (h->stun_request);
1218     h->stun_request = NULL;
1219   }
1220   h->waiting_stun = GNUNET_NO;
1221   h->stun_request
1222     = GNUNET_NAT_stun_make_request (elem->address,
1223                                     elem->port,
1224                                     h->socket,
1225                                     &stun_request_callback,
1226                                     h);
1227   if (NULL == h->stun_request)
1228   {
1229     LOG (GNUNET_ERROR_TYPE_ERROR,
1230          "STUN request to %s:%i failed\n",
1231          elem->address,
1232          elem->port);
1233   }
1234   h->stun_task =
1235     GNUNET_SCHEDULER_add_delayed (h->stun_frequency,
1236                                   &process_stun,
1237                                   h);
1238
1239   /* Set actual Server*/
1240   if (NULL != elem->next)
1241   {
1242     h->actual_stun_server = elem->next;
1243   }
1244   else
1245   {
1246     h->actual_stun_server = h->stun_servers_head;
1247   }
1248 }
1249
1250
1251 /**
1252  * Task to do a lookup on our hostname for IP addresses.
1253  *
1254  * @param cls the NAT handle
1255  */
1256 static void
1257 resolve_hostname (void *cls)
1258 {
1259   struct GNUNET_NAT_Handle *h = cls;
1260
1261   h->hostname_task = NULL;
1262   remove_from_address_list_by_source (h, LAL_HOSTNAME_DNS);
1263   GNUNET_assert (NULL == h->hostname_dns);
1264   h->hostname_dns =
1265       GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC,
1266                                         HOSTNAME_RESOLVE_TIMEOUT,
1267                                         &process_hostname_ip,
1268                                         h);
1269 }
1270
1271
1272 /**
1273  * Task to do DNS lookup on our external hostname to
1274  * get DynDNS-IP addresses.
1275  *
1276  * @param cls the NAT handle
1277  */
1278 static void
1279 resolve_dns (void *cls)
1280 {
1281   struct GNUNET_NAT_Handle *h = cls;
1282   struct LocalAddressList *pos;
1283
1284   h->dns_task = NULL;
1285   for (pos = h->lal_head; NULL != pos; pos = pos->next)
1286     if (pos->source == LAL_EXTERNAL_IP)
1287       pos->source = LAL_EXTERNAL_IP_OLD;
1288   LOG (GNUNET_ERROR_TYPE_DEBUG,
1289        "Resolving external address `%s'\n",
1290        h->external_address);
1291   GNUNET_assert (NULL == h->ext_dns);
1292   h->ext_dns =
1293       GNUNET_RESOLVER_ip_get (h->external_address,
1294                               AF_INET,
1295                               GNUNET_TIME_UNIT_MINUTES,
1296                               &process_external_ip,
1297                               h);
1298 }
1299
1300
1301 /**
1302  * Add or remove UPnP-mapped addresses.
1303  *
1304  * @param cls the `struct GNUNET_NAT_Handle`
1305  * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
1306  *     the previous (now invalid) one
1307  * @param addr either the previous or the new public IP address
1308  * @param addrlen actual lenght of @a addr
1309  * @param ret GNUNET_NAT_ERROR_SUCCESS on success, otherwise an error code
1310  */
1311 static void
1312 upnp_add (void *cls,
1313           int add_remove,
1314           const struct sockaddr *addr,
1315           socklen_t addrlen,
1316           enum GNUNET_NAT_StatusCode ret)
1317 {
1318   struct GNUNET_NAT_Handle *h = cls;
1319   struct LocalAddressList *pos;
1320   struct LocalAddressList *next;
1321
1322
1323   if (GNUNET_NAT_ERROR_SUCCESS != ret)
1324   {
1325     /* Error while running upnp client */
1326     LOG (GNUNET_ERROR_TYPE_ERROR,
1327           _("Error while running upnp client:\n"));
1328     //FIXME: convert error code to string
1329     return;
1330   }
1331
1332   if (GNUNET_YES == add_remove)
1333   {
1334     add_to_address_list (h,
1335                          LAL_UPNP,
1336                          addr,
1337                          addrlen);
1338     return;
1339   }
1340   else if (GNUNET_NO == add_remove)
1341   {
1342     /* remove address */
1343     next = h->lal_head;
1344     while (NULL != (pos = next))
1345     {
1346       next = pos->next;
1347       if ((pos->source != LAL_UPNP) || (pos->addrlen != addrlen) ||
1348           (0 != memcmp (&pos[1], addr, addrlen)))
1349         continue;
1350       GNUNET_CONTAINER_DLL_remove (h->lal_head,
1351                                    h->lal_tail,
1352                                    pos);
1353       if (NULL != h->address_callback)
1354         h->address_callback (h->callback_cls,
1355                              GNUNET_NO,
1356                              (const struct sockaddr *) &pos[1],
1357                              pos->addrlen);
1358       GNUNET_free (pos);
1359       return;                     /* only remove once */
1360     }
1361     /* asked to remove address that does not exist */
1362     LOG (GNUNET_ERROR_TYPE_ERROR,
1363          "Asked to remove unkown address `%s'\n",
1364          GNUNET_a2s(addr, addrlen));
1365     GNUNET_break (0);
1366   }
1367   else
1368   {
1369
1370     GNUNET_break (0);
1371   }
1372 }
1373
1374
1375 /**
1376  * Try to add a port mapping using UPnP.
1377  *
1378  * @param h overall NAT handle
1379  * @param port port to map with UPnP
1380  */
1381 static void
1382 add_minis (struct GNUNET_NAT_Handle *h,
1383            uint16_t port)
1384 {
1385   struct MiniList *ml;
1386
1387   ml = h->mini_head;
1388   while (NULL != ml)
1389   {
1390     if (port == ml->port)
1391       return;                   /* already got this port */
1392     ml = ml->next;
1393   }
1394
1395   ml = GNUNET_new (struct MiniList);
1396   ml->port = port;
1397   ml->mini = GNUNET_NAT_mini_map_start (port, h->is_tcp, &upnp_add, h);
1398
1399   if (NULL == ml->mini)
1400   {
1401     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1402         _("Failed to run upnp client for port %u\n"), ml->port);
1403     GNUNET_free (ml);
1404     return;
1405   }
1406
1407   GNUNET_CONTAINER_DLL_insert (h->mini_head,
1408                                h->mini_tail,
1409                                ml);
1410 }
1411
1412
1413 /**
1414  * Task to add addresses from original bind to set of valid addrs.
1415  *
1416  * @param h the NAT handle
1417  */
1418 static void
1419 add_from_bind (struct GNUNET_NAT_Handle *h)
1420 {
1421   static struct in6_addr any = IN6ADDR_ANY_INIT;
1422
1423   unsigned int i;
1424   struct sockaddr *sa;
1425   const struct sockaddr_in *v4;
1426
1427   for (i = 0; i < h->num_local_addrs; i++)
1428   {
1429     sa = h->local_addrs[i];
1430     switch (sa->sa_family)
1431     {
1432     case AF_INET:
1433       if (sizeof (struct sockaddr_in) != h->local_addrlens[i])
1434       {
1435         GNUNET_break (0);
1436         break;
1437       }
1438       v4 = (const struct sockaddr_in *) sa;
1439       if (0 != v4->sin_addr.s_addr)
1440         add_to_address_list (h,
1441                              LAL_BINDTO_ADDRESS, sa,
1442                              sizeof (struct sockaddr_in));
1443       if (h->enable_upnp)
1444       {
1445         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1446                     "Running upnp client for address `%s'\n",
1447                     GNUNET_a2s (sa,sizeof (struct sockaddr_in)));
1448         add_minis (h, ntohs (v4->sin_port));
1449       }
1450       break;
1451     case AF_INET6:
1452       if (sizeof (struct sockaddr_in6) != h->local_addrlens[i])
1453       {
1454         GNUNET_break (0);
1455         break;
1456       }
1457       if (0 !=
1458           memcmp (&((const struct sockaddr_in6 *) sa)->sin6_addr,
1459                   &any,
1460                   sizeof (struct in6_addr)))
1461         add_to_address_list (h,
1462                              LAL_BINDTO_ADDRESS,
1463                              sa,
1464                              sizeof (struct sockaddr_in6));
1465       break;
1466     default:
1467       break;
1468     }
1469   }
1470 }
1471
1472
1473 /**
1474  * Attempt to enable port redirection and detect public IP address contacting
1475  * UPnP or NAT-PMP routers on the local network. Use addr to specify to which
1476  * of the local host's addresses should the external port be mapped. The port
1477  * is taken from the corresponding sockaddr_in[6] field.
1478  *
1479  * @param cfg configuration to use
1480  * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP
1481  * @param adv_port advertised port (port we are either bound to or that our OS
1482  *                 locally performs redirection from to our bound port).
1483  * @param num_addrs number of addresses in @a addrs
1484  * @param addrs the local addresses packets should be redirected to
1485  * @param addrlens actual lengths of the addresses
1486  * @param address_callback function to call everytime the public IP address changes
1487  * @param reversal_callback function to call if someone wants connection reversal from us
1488  * @param callback_cls closure for callbacks
1489  * @param sock used socket
1490  * @return NULL on error, otherwise handle that can be used to unregister
1491  */
1492 struct GNUNET_NAT_Handle *
1493 GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1494                      int is_tcp,
1495                      uint16_t adv_port,
1496                      unsigned int num_addrs,
1497                      const struct sockaddr **addrs,
1498                      const socklen_t *addrlens,
1499                      GNUNET_NAT_AddressCallback address_callback,
1500                      GNUNET_NAT_ReversalCallback reversal_callback,
1501                      void *callback_cls,
1502                      struct GNUNET_NETWORK_Handle *sock)
1503 {
1504   struct GNUNET_NAT_Handle *h;
1505   struct in_addr in_addr;
1506   unsigned int i;
1507   char *binary;
1508
1509   LOG (GNUNET_ERROR_TYPE_DEBUG,
1510        "Registered with NAT service at port %u with %u IP bound local addresses\n",
1511        (unsigned int) adv_port, num_addrs);
1512   h = GNUNET_new (struct GNUNET_NAT_Handle);
1513   h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS;
1514   h->cfg = cfg;
1515   h->is_tcp = is_tcp;
1516   h->address_callback = address_callback;
1517   h->reversal_callback = reversal_callback;
1518   h->callback_cls = callback_cls;
1519   h->num_local_addrs = num_addrs;
1520   h->adv_port = adv_port;
1521   if (0 != num_addrs)
1522   {
1523     h->local_addrs = GNUNET_malloc (num_addrs * sizeof (struct sockaddr *));
1524     h->local_addrlens = GNUNET_malloc (num_addrs * sizeof (socklen_t));
1525     for (i = 0; i < num_addrs; i++)
1526     {
1527       GNUNET_assert (addrlens[i] > 0);
1528       GNUNET_assert (addrs[i] != NULL);
1529       h->local_addrlens[i] = addrlens[i];
1530       h->local_addrs[i] = GNUNET_malloc (addrlens[i]);
1531       GNUNET_memcpy (h->local_addrs[i], addrs[i], addrlens[i]);
1532     }
1533   }
1534   if (GNUNET_OK ==
1535       GNUNET_CONFIGURATION_have_value (cfg, "nat", "INTERNAL_ADDRESS"))
1536   {
1537     (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat",
1538                                                   "INTERNAL_ADDRESS",
1539                                                   &h->internal_address);
1540   }
1541   if ((h->internal_address != NULL) &&
1542       (inet_pton (AF_INET, h->internal_address, &in_addr) != 1))
1543   {
1544     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1545                                "nat", "INTERNAL_ADDRESS",
1546                                _("malformed"));
1547     GNUNET_free (h->internal_address);
1548     h->internal_address = NULL;
1549   }
1550
1551   if (GNUNET_OK ==
1552       GNUNET_CONFIGURATION_have_value (cfg, "nat", "EXTERNAL_ADDRESS"))
1553   {
1554     (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat",
1555                                                   "EXTERNAL_ADDRESS",
1556                                                   &h->external_address);
1557   }
1558   h->behind_nat =
1559       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "BEHIND_NAT");
1560   h->nat_punched =
1561       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "PUNCHED_NAT");
1562   h->enable_nat_client =
1563       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_CLIENT");
1564   h->enable_nat_server =
1565       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_SERVER");
1566   h->enable_upnp =
1567       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_UPNP");
1568   h->use_localaddresses =
1569       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_LOCALADDR");
1570   h->return_localaddress =
1571       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat",
1572                                             "RETURN_LOCAL_ADDRESSES");
1573
1574   h->use_hostname =
1575       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_HOSTNAME");
1576   h->disable_ipv6 =
1577       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "DISABLEV6");
1578   if (GNUNET_OK !=
1579       GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "DYNDNS_FREQUENCY",
1580                                            &h->dyndns_frequency))
1581     h->dyndns_frequency = DYNDNS_FREQUENCY;
1582   if (GNUNET_OK !=
1583       GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "IFC_SCAN_FREQUENCY",
1584                                            &h->ifc_scan_frequency))
1585     h->ifc_scan_frequency = IFC_SCAN_FREQUENCY;
1586   if (GNUNET_OK !=
1587       GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "HOSTNAME_DNS_FREQUENCY",
1588                                            &h->hostname_dns_frequency))
1589     h->hostname_dns_frequency = HOSTNAME_DNS_FREQUENCY;
1590
1591   if (NULL == reversal_callback)
1592     h->enable_nat_server = GNUNET_NO;
1593
1594   /* Check for UPnP client, disable immediately if not available */
1595   if ( (GNUNET_YES == h->enable_upnp) &&
1596        (GNUNET_SYSERR ==
1597         GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) )
1598   {
1599     LOG (GNUNET_ERROR_TYPE_ERROR,
1600         _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP \n"));
1601     h->enable_upnp = GNUNET_NO;
1602   }
1603
1604   /* STUN */
1605   h->use_stun =
1606     GNUNET_CONFIGURATION_get_value_yesno (cfg,
1607                                           "nat",
1608                                           "USE_STUN");
1609
1610   if (GNUNET_OK !=
1611       GNUNET_CONFIGURATION_get_value_time (cfg,
1612                                            "nat",
1613                                            "STUN_FREQUENCY",
1614                                            &h->stun_frequency))
1615     h->stun_frequency = STUN_FREQUENCY;
1616
1617
1618   /* Check if NAT was hole-punched */
1619   if ((NULL != h->address_callback) &&
1620       (NULL != h->external_address) &&
1621       (GNUNET_YES == h->nat_punched))
1622   {
1623     h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h);
1624     h->enable_nat_server = GNUNET_NO;
1625     h->enable_upnp = GNUNET_NO;
1626     h->use_stun = GNUNET_NO;
1627   }
1628   else
1629   {
1630     LOG (GNUNET_ERROR_TYPE_DEBUG,
1631          "No external IP address given to add to our list of addresses\n");
1632   }
1633
1634   /* ENABLE STUN ONLY ON UDP */
1635   if( (! is_tcp) &&
1636       (NULL != sock) &&
1637       h->use_stun)
1638   {
1639     char *stun_servers;
1640     size_t urls;
1641     ssize_t pos;
1642     size_t pos_port;
1643
1644     h->socket = sock;
1645     stun_servers = NULL;
1646     /* Lets process the servers*/
1647     (void) GNUNET_CONFIGURATION_get_value_string (cfg,
1648                                                   "nat",
1649                                                   "STUN_SERVERS",
1650                                                   &stun_servers);
1651     urls = 0;
1652     if ( (NULL != stun_servers) &&
1653          (strlen (stun_servers) > 0) )
1654     {
1655       pos_port = 0;
1656       for (pos = strlen (stun_servers) - 1;
1657            pos >= 0;
1658            pos--)
1659       {
1660         if (stun_servers[pos] == ':')
1661         {
1662           pos_port = pos + 1;
1663           stun_servers[pos] = '\0';
1664           continue;
1665         }
1666         if ((stun_servers[pos] == ' ') || (0 == pos))
1667         {
1668           struct StunServerList *ml;
1669
1670           /* Check if we do have a port */
1671           if ((0 == pos_port) || (pos_port <= pos))
1672           {
1673             LOG (GNUNET_ERROR_TYPE_WARNING,
1674                  "STUN server format mistake\n");
1675             break;
1676           }
1677           urls++;
1678           ml = GNUNET_new (struct StunServerList);
1679           ml->port = atoi (&stun_servers[pos_port]);
1680
1681           /* Remove trailing space */
1682           if (stun_servers[pos] == ' ')
1683             ml->address = GNUNET_strdup (&stun_servers[pos + 1]);
1684           else
1685             ml->address = GNUNET_strdup (&stun_servers[pos]);
1686           LOG (GNUNET_ERROR_TYPE_DEBUG,
1687                "Found STUN server %s:%i\n",
1688                ml->address,
1689                ml->port);
1690           GNUNET_CONTAINER_DLL_insert (h->stun_servers_head,
1691                                        h->stun_servers_tail,
1692                                        ml);
1693           stun_servers[pos] = '\0';
1694         }
1695       }
1696     }
1697     if (0 == urls)
1698     {
1699       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
1700                                  "nat",
1701                                  "STUN_SERVERS");
1702     }
1703     else
1704     {
1705       /* Set the actual STUN server*/
1706       h->actual_stun_server = h->stun_servers_head;
1707     }
1708     h->stun_task = GNUNET_SCHEDULER_add_now (&process_stun,
1709                                              h);
1710     GNUNET_free_non_null (stun_servers);
1711   }
1712
1713
1714   /* Test for SUID binaries */
1715   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
1716   if ( (GNUNET_YES == h->behind_nat) &&
1717        (GNUNET_YES == h->enable_nat_server) &&
1718        (GNUNET_YES !=
1719         GNUNET_OS_check_helper_binary (binary,
1720                                        GNUNET_YES,
1721                                        "-d 127.0.0.1" )))
1722   {
1723     // use localhost as source for that one udp-port, ok for testing
1724     h->enable_nat_server = GNUNET_NO;
1725     LOG (GNUNET_ERROR_TYPE_WARNING,
1726          _("Configuration requires `%s', but binary is not installed properly (SUID bit not set).  Option disabled.\n"),
1727          "gnunet-helper-nat-server");
1728   }
1729   GNUNET_free (binary);
1730   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
1731   if ((GNUNET_YES == h->enable_nat_client) &&
1732       (GNUNET_YES !=
1733        GNUNET_OS_check_helper_binary (binary,
1734                                       GNUNET_YES,
1735                                       "-d 127.0.0.1 127.0.0.2 42"))) /* none of these parameters are actually used in privilege testing mode */
1736   {
1737     h->enable_nat_client = GNUNET_NO;
1738     LOG (GNUNET_ERROR_TYPE_WARNING,
1739          _("Configuration requires `%s', but binary is not installed properly (SUID bit not set).  Option disabled.\n"),
1740          "gnunet-helper-nat-client");
1741   }
1742   GNUNET_free (binary);
1743   start_gnunet_nat_server (h);
1744
1745   /* FIXME: add support for UPnP, etc */
1746
1747   if (NULL != h->address_callback)
1748   {
1749     h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces,
1750                                             h);
1751     if (GNUNET_YES == h->use_hostname)
1752       h->hostname_task = GNUNET_SCHEDULER_add_now (&resolve_hostname,
1753                                                    h);
1754   }
1755   add_from_bind (h);
1756
1757   return h;
1758 }
1759
1760
1761 /**
1762  * Stop port redirection and public IP address detection for the given handle.
1763  * This frees the handle, after having sent the needed commands to close open ports.
1764  *
1765  * @param h the handle to stop
1766  */
1767 void
1768 GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
1769 {
1770   unsigned int i;
1771   struct LocalAddressList *lal;
1772   struct MiniList *ml;
1773   struct StunServerList *ssl;
1774   
1775   LOG (GNUNET_ERROR_TYPE_DEBUG,
1776        "NAT unregister called\n");
1777   while (NULL != (ssl = h->stun_servers_head))
1778   {
1779     GNUNET_CONTAINER_DLL_remove (h->stun_servers_head,
1780                                  h->stun_servers_tail,
1781                                  ssl);
1782     GNUNET_free (ssl->address);
1783     GNUNET_free (ssl);
1784   }
1785   while (NULL != (lal = h->lal_head))
1786   {
1787     GNUNET_CONTAINER_DLL_remove (h->lal_head,
1788                                  h->lal_tail,
1789                                  lal);
1790     if (NULL != h->address_callback)
1791       h->address_callback (h->callback_cls,
1792                            GNUNET_NO,
1793                            (const struct sockaddr *) &lal[1],
1794                            lal->addrlen);
1795     GNUNET_free (lal);
1796   }
1797   while (NULL != (ml = h->mini_head))
1798   {
1799     GNUNET_CONTAINER_DLL_remove (h->mini_head,
1800                                  h->mini_tail,
1801                                  ml);
1802     if (NULL != ml->mini)
1803       GNUNET_NAT_mini_map_stop (ml->mini);
1804     GNUNET_free (ml);
1805   }
1806   if (NULL != h->ext_dns)
1807   {
1808     GNUNET_RESOLVER_request_cancel (h->ext_dns);
1809     h->ext_dns = NULL;
1810   }
1811   if (NULL != h->hostname_dns)
1812   {
1813     GNUNET_RESOLVER_request_cancel (h->hostname_dns);
1814     h->hostname_dns = NULL;
1815   }
1816   if (NULL != h->server_read_task)
1817   {
1818     GNUNET_SCHEDULER_cancel (h->server_read_task);
1819     h->server_read_task = NULL;
1820   }
1821   if (NULL != h->ifc_task)
1822   {
1823     GNUNET_SCHEDULER_cancel (h->ifc_task);
1824     h->ifc_task = NULL;
1825   }
1826   if (NULL != h->hostname_task)
1827   {
1828     GNUNET_SCHEDULER_cancel (h->hostname_task);
1829     h->hostname_task = NULL;
1830   }
1831   if (NULL != h->dns_task)
1832   {
1833     GNUNET_SCHEDULER_cancel (h->dns_task);
1834     h->dns_task = NULL;
1835   }
1836   if (NULL != h->stun_task)
1837   {
1838     GNUNET_SCHEDULER_cancel (h->stun_task);
1839     h->stun_task = NULL;
1840   }
1841   if (NULL != h->stun_request)
1842   {
1843     GNUNET_NAT_stun_make_request_cancel (h->stun_request);
1844     h->stun_request = NULL;
1845   }
1846   if (NULL != h->server_proc)
1847   {
1848     if (0 != GNUNET_OS_process_kill (h->server_proc,
1849                                      GNUNET_TERM_SIG))
1850       GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
1851                                 "nat",
1852                                 "kill");
1853     GNUNET_OS_process_wait (h->server_proc);
1854     GNUNET_OS_process_destroy (h->server_proc);
1855     h->server_proc = NULL;
1856     GNUNET_DISK_pipe_close (h->server_stdout);
1857     h->server_stdout = NULL;
1858     h->server_stdout_handle = NULL;
1859   }
1860   if (NULL != h->server_stdout)
1861   {
1862     GNUNET_DISK_pipe_close (h->server_stdout);
1863     h->server_stdout = NULL;
1864     h->server_stdout_handle = NULL;
1865   }
1866   for (i = 0; i < h->num_local_addrs; i++)
1867     GNUNET_free (h->local_addrs[i]);
1868   GNUNET_free_non_null (h->local_addrs);
1869   GNUNET_free_non_null (h->local_addrlens);
1870   GNUNET_free_non_null (h->external_address);
1871   GNUNET_free_non_null (h->internal_address);
1872   GNUNET_free (h);
1873 }
1874
1875
1876 /**
1877  * We learned about a peer (possibly behind NAT) so run the
1878  * gnunet-helper-nat-client to send dummy ICMP responses to cause
1879  * that peer to connect to us (connection reversal).
1880  *
1881  * @param h handle (used for configuration)
1882  * @param sa the address of the peer (IPv4-only)
1883  * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled,
1884  *         #GNUNET_OK otherwise
1885  */
1886 int
1887 GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
1888                        const struct sockaddr_in *sa)
1889
1890
1891 {
1892   char inet4[INET_ADDRSTRLEN];
1893   char port_as_string[6];
1894   struct GNUNET_OS_Process *proc;
1895   char *binary;
1896
1897   if (GNUNET_YES != h->enable_nat_client)
1898     return GNUNET_NO;                     /* not permitted / possible */
1899
1900   if (h->internal_address == NULL)
1901   {
1902     LOG (GNUNET_ERROR_TYPE_WARNING, "nat",
1903          _("Internal IP address not known, cannot use ICMP NAT traversal method\n"));
1904     return GNUNET_SYSERR;
1905   }
1906   GNUNET_assert (sa->sin_family == AF_INET);
1907   if (NULL == inet_ntop (AF_INET, &sa->sin_addr, inet4, INET_ADDRSTRLEN))
1908   {
1909     GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
1910                               "nat",
1911                               "inet_ntop");
1912     return GNUNET_SYSERR;
1913   }
1914   GNUNET_snprintf (port_as_string,
1915                    sizeof (port_as_string),
1916                    "%d",
1917                    h->adv_port);
1918   LOG (GNUNET_ERROR_TYPE_DEBUG,
1919        _("Running gnunet-helper-nat-client %s %s %u\n"),
1920        h->internal_address,
1921        inet4,
1922        (unsigned int) h->adv_port);
1923   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
1924   proc =
1925       GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL,
1926                                binary,
1927                                "gnunet-helper-nat-client",
1928                                h->internal_address,
1929                                inet4, port_as_string, NULL);
1930   GNUNET_free (binary);
1931   if (NULL == proc)
1932     return GNUNET_SYSERR;
1933   /* we know that the gnunet-helper-nat-client will terminate virtually
1934    * instantly */
1935   GNUNET_OS_process_wait (proc);
1936   GNUNET_OS_process_destroy (proc);
1937   return GNUNET_OK;
1938 }
1939
1940
1941 /**
1942  * Test if the given address is (currently) a plausible IP address for this peer.
1943  *
1944  * @param h the handle returned by register
1945  * @param addr IP address to test (IPv4 or IPv6)
1946  * @param addrlen number of bytes in @a addr
1947  * @return #GNUNET_YES if the address is plausible,
1948  *         #GNUNET_NO if the address is not plausible,
1949  *         #GNUNET_SYSERR if the address is malformed
1950  */
1951 int
1952 GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
1953                          const void *addr,
1954                          socklen_t addrlen)
1955 {
1956   struct LocalAddressList *pos;
1957   const struct sockaddr_in *in4;
1958   const struct sockaddr_in6 *in6;
1959   char pbuf[INET6_ADDRSTRLEN+1];
1960
1961   if ((addrlen != sizeof (struct in_addr)) &&
1962       (addrlen != sizeof (struct in6_addr)))
1963   {
1964     GNUNET_break (0);
1965     return GNUNET_SYSERR;
1966   }
1967   for (pos = h->lal_head; NULL != pos; pos = pos->next)
1968   {
1969     if (pos->addrlen == sizeof (struct sockaddr_in))
1970     {
1971       in4 = (struct sockaddr_in *) &pos[1];
1972       if ((addrlen == sizeof (struct in_addr)) &&
1973           (0 == memcmp (&in4->sin_addr, addr, sizeof (struct in_addr))))
1974         return GNUNET_YES;
1975     }
1976     else if (pos->addrlen == sizeof (struct sockaddr_in6))
1977     {
1978       in6 = (struct sockaddr_in6 *) &pos[1];
1979       if ((addrlen == sizeof (struct in6_addr)) &&
1980           (0 == memcmp (&in6->sin6_addr, addr, sizeof (struct in6_addr))))
1981         return GNUNET_YES;
1982     }
1983     else
1984     {
1985       GNUNET_assert (0);
1986     }
1987   }
1988   LOG (GNUNET_ERROR_TYPE_WARNING,
1989        "Asked to validate one of my addresses (%s) and validation failed!\n",
1990        inet_ntop ((addrlen == sizeof(struct in_addr))
1991                   ? AF_INET
1992                   : AF_INET6,
1993                   addr,
1994                   pbuf, sizeof (pbuf)));
1995   return GNUNET_NO;
1996 }
1997
1998 /**
1999  * Converts enum GNUNET_NAT_StatusCode to a string
2000  *
2001  * @param err error code to resolve to a string
2002  * @return pointer to a static string containing the error code
2003  */
2004 const char *
2005 GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
2006 {
2007   switch (err)
2008   {
2009   case GNUNET_NAT_ERROR_SUCCESS:
2010     return _ ("Operation Successful");
2011   case GNUNET_NAT_ERROR_IPC_FAILURE:
2012     return _ ("Internal Failure (IPC, ...)");
2013   case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
2014     return _ ("Failure in network subsystem, check permissions.");
2015   case GNUNET_NAT_ERROR_TIMEOUT:
2016     return _ ("Encountered timeout while performing operation");
2017   case GNUNET_NAT_ERROR_NOT_ONLINE:
2018     return _ ("detected that we are offline");
2019   case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
2020     return _ ("`upnpc` command not found");
2021   case GNUNET_NAT_ERROR_UPNPC_FAILED:
2022     return _ ("Failed to run `upnpc` command");
2023   case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
2024     return _ ("`upnpc' command took too long, process killed");
2025   case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
2026     return _ ("`upnpc' command failed to establish port mapping");
2027   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
2028     return _ ("`external-ip' command not found");
2029   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
2030     return _ ("Failed to run `external-ip` command");
2031   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
2032     return _ ("`external-ip' command output invalid");
2033   case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
2034     return _ ("no valid address was returned by `external-ip'");
2035   case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
2036     return _ ("Could not determine interface with internal/local network address");
2037   case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
2038     return _ ("No functioning gnunet-helper-nat-server installation found");
2039   case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
2040     return _ ("NAT test could not be initialized");
2041   case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
2042     return _ ("NAT test timeout reached");
2043   case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
2044     return _ ("could not register NAT");
2045   case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
2046     return _ ("No working gnunet-helper-nat-client installation found");
2047 /*  case:
2048     return _ ("");*/
2049   default:
2050     return "unknown status code";
2051   }
2052 }
2053
2054 /* end of nat.c */