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