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  * - implement UPnPC/PMP-based NAT traversal
32  * - implement autoconfig
33  * - implement NEW logic for external IP detection
34  */
35 #include "platform.h"
36 #include <math.h>
37 #include "gnunet_util_lib.h"
38 #include "gnunet_protocols.h"
39 #include "gnunet_signatures.h"
40 #include "gnunet_statistics_service.h"
41 #include "gnunet_nat_service.h"
42 #include "gnunet-service-nat_stun.h"
43 #include "gnunet-service-nat_helper.h"
44 #include "nat.h"
45 #include <gcrypt.h>
46
47
48 /**
49  * How often should we ask the OS about a list of active
50  * network interfaces?
51  */
52 #define SCAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
53
54
55 /**
56  * Internal data structure we track for each of our clients.
57  */
58 struct ClientHandle
59 {
60
61   /**
62    * Kept in a DLL.
63    */
64   struct ClientHandle *next;
65   
66   /**
67    * Kept in a DLL.
68    */
69   struct ClientHandle *prev;
70
71   /**
72    * Underlying handle for this client with the service.
73    */ 
74   struct GNUNET_SERVICE_Client *client;
75
76   /**
77    * Message queue for communicating with the client.
78    */
79   struct GNUNET_MQ_Handle *mq;
80
81   /**
82    * Array of addresses used by the service.
83    */
84   struct sockaddr **addrs;
85   
86   /**
87    * What does this client care about?
88    */
89   enum GNUNET_NAT_RegisterFlags flags;
90
91   /**
92    * Is any of the @e addrs in a reserved subnet for NAT?
93    */
94   int natted_address;
95   
96   /**
97    * Port we would like as we are configured to use this one for
98    * advertising (in addition to the one we are binding to).
99    */
100   uint16_t adv_port;
101
102   /**
103    * Number of addresses that this service is bound to.
104    */
105   uint16_t num_addrs;
106   
107   /**
108    * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
109    */
110   uint8_t proto;
111
112 };
113
114
115 /**
116  * List of local addresses this system has.
117  */
118 struct LocalAddressList
119 {
120   /**
121    * This is a linked list.
122    */
123   struct LocalAddressList *next;
124
125   /**
126    * Previous entry.
127    */
128   struct LocalAddressList *prev;
129
130   /**
131    * The address itself (i.e. `struct sockaddr_in` or `struct
132    * sockaddr_in6`, in the respective byte order).
133    */
134   struct sockaddr_storage addr;
135
136   /**
137    * Address family.
138    */
139   int af;
140
141   /**
142    * What type of address is this?
143    */
144   enum GNUNET_NAT_AddressClass ac;
145   
146 };
147
148
149 /**
150  * External IP address as given to us via some STUN server.
151  */
152 struct StunExternalIP
153 {
154   /**
155    * Kept in a DLL.
156    */ 
157   struct StunExternalIP *next;
158
159   /**
160    * Kept in a DLL.
161    */ 
162   struct StunExternalIP *prev;
163
164   /**
165    * Task we run to remove this entry when it is stale.
166    */
167   struct GNUNET_SCHEDULER_Task *timeout_task;
168
169   /**
170    * Our external IP address as reported by the 
171    * STUN server.
172    */
173   struct sockaddr_in external_addr;
174
175   /**
176    * Address of the reporting STUN server.  Used to 
177    * detect when a STUN server changes its opinion
178    * to more quickly remove stale results.
179    */
180   struct sockaddr_storage stun_server_addr;
181
182   /**
183    * Number of bytes used in @e stun_server_addr.
184    */
185   size_t stun_server_addr_len;
186 };
187
188
189 /**
190  * Timeout to use when STUN data is considered stale.
191  */
192 static struct GNUNET_TIME_Relative stun_stale_timeout;
193
194 /**
195  * Handle to our current configuration.
196  */
197 static const struct GNUNET_CONFIGURATION_Handle *cfg;
198
199 /**
200  * Handle to the statistics service.
201  */
202 static struct GNUNET_STATISTICS_Handle *stats;
203
204 /**
205  * Task scheduled to periodically scan our network interfaces.
206  */
207 static struct GNUNET_SCHEDULER_Task *scan_task;
208
209 /**
210  * Head of client DLL.
211  */
212 static struct ClientHandle *ch_head;
213   
214 /**
215  * Tail of client DLL.
216  */
217 static struct ClientHandle *ch_tail;
218
219 /**
220  * Head of DLL of local addresses.
221  */
222 static struct LocalAddressList *lal_head;
223
224 /**
225  * Tail of DLL of local addresses.
226  */
227 static struct LocalAddressList *lal_tail;
228
229 /**
230  * Kept in a DLL.
231  */ 
232 static struct StunExternalIP *se_head;
233
234 /**
235  * Kept in a DLL.
236  */ 
237 static struct StunExternalIP *se_tail;
238
239
240 /**
241  * Free the DLL starting at #lal_head.
242  */ 
243 static void
244 destroy_lal ()
245 {
246   struct LocalAddressList *lal;
247
248   while (NULL != (lal = lal_head))
249   {
250     GNUNET_CONTAINER_DLL_remove (lal_head,
251                                  lal_tail,
252                                  lal);
253     GNUNET_free (lal);
254   }
255 }
256
257
258 /**
259  * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from
260  * client.
261  *
262  * @param cls client who sent the message
263  * @param message the message received
264  * @return #GNUNET_OK if message is well-formed
265  */
266 static int
267 check_register (void *cls,
268                 const struct GNUNET_NAT_RegisterMessage *message)
269 {
270   uint16_t num_addrs = ntohs (message->num_addrs);
271   const char *off = (const char *) &message[1];
272   size_t left = ntohs (message->header.size) - sizeof (*message);
273
274   for (unsigned int i=0;i<num_addrs;i++)
275   {
276     size_t alen;
277     const struct sockaddr *sa = (const struct sockaddr *) off;
278
279     if (sizeof (sa_family_t) > left)
280     {
281       GNUNET_break (0);
282       return GNUNET_SYSERR;
283     }
284     switch (sa->sa_family)
285     {
286     case AF_INET:
287       alen = sizeof (struct sockaddr_in);
288       break;
289     case AF_INET6:
290       alen = sizeof (struct sockaddr_in6);
291       break;
292 #if AF_UNIX
293     case AF_UNIX:
294       alen = sizeof (struct sockaddr_un);
295       break;
296 #endif
297     default:
298       GNUNET_break (0);
299       return GNUNET_SYSERR;      
300     }
301     if (alen > left)
302     {
303       GNUNET_break (0);
304       return GNUNET_SYSERR;      
305     }
306   }  
307   return GNUNET_OK; 
308 }
309
310
311 /**
312  * Check if @a ip is in @a network with @a bits netmask.
313  *
314  * @param network to test
315  * @param ip IP address to test
316  * @param bits bitmask for the network
317  * @return #GNUNET_YES if @a ip is in @a network
318  */
319 static int
320 match_ipv4 (const char *network,
321             const struct in_addr *ip,
322             uint8_t bits)
323 {
324   struct in_addr net;
325   
326   if (0 == bits)
327     return GNUNET_YES;
328   GNUNET_assert (1 == inet_pton (AF_INET,
329                                  network,
330                                  &net));
331   return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
332 }
333
334
335 /**
336  * Check if @a ip is in @a network with @a bits netmask.
337  *
338  * @param network to test
339  * @param ip IP address to test
340  * @param bits bitmask for the network
341  * @return #GNUNET_YES if @a ip is in @a network
342  */
343 static int
344 match_ipv6 (const char *network,
345             const struct in6_addr *ip,
346             uint8_t bits)
347 {
348   struct in6_addr net;
349   struct in6_addr mask;
350   unsigned int off;
351   
352   if (0 == bits)
353     return GNUNET_YES;
354   GNUNET_assert (1 == inet_pton (AF_INET6,
355                                  network,
356                                  &net));
357   memset (&mask, 0, sizeof (mask));
358   off = 0;
359   while (bits > 8)
360   {
361     mask.s6_addr[off++] = 0xFF;
362     bits -= 8;
363   }
364   while (bits > 0)
365   {
366     mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
367     bits--;
368   }
369   for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++)
370     if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
371         (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
372       return GNUNET_NO;
373   return GNUNET_YES;
374 }
375
376
377 /**
378  * Test if the given IPv4 address is in a known range
379  * for private networks.
380  *
381  * @param ip address to test
382  * @return #GNUNET_YES if @a ip is in a NAT range
383  */
384 static int
385 is_nat_v4 (const struct in_addr *ip)
386 {
387   return
388     match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */
389     match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
390     match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */
391     match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
392     match_ipv4 ("172.16.0.0", ip, 16);  /* RFC 1918 */
393 }
394
395
396 /**
397  * Test if the given IPv6 address is in a known range
398  * for private networks.
399  *
400  * @param ip address to test
401  * @return #GNUNET_YES if @a ip is in a NAT range
402  */
403 static int
404 is_nat_v6 (const struct in6_addr *ip)
405 {
406   return
407     match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
408     match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
409     match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
410 }
411
412
413 /**
414  * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
415  * We remember the client for updates upon future NAT events.
416  *
417  * @param cls client who sent the message
418  * @param message the message received
419  */
420 static void
421 handle_register (void *cls,
422                  const struct GNUNET_NAT_RegisterMessage *message)
423 {
424   struct ClientHandle *ch = cls;
425   const char *off;
426   size_t left;
427
428   if ( (0 != ch->proto) ||
429        (NULL != ch->addrs) )
430   {
431     /* double registration not allowed */
432     GNUNET_break (0);
433     GNUNET_SERVICE_client_drop (ch->client);
434     return;
435   }
436   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
437               "Received REGISTER message from client\n");
438   ch->flags = message->flags;
439   ch->proto = message->proto;
440   ch->adv_port = ntohs (message->adv_port);
441   ch->num_addrs = ntohs (message->adv_port);
442   ch->addrs = GNUNET_new_array (ch->num_addrs,
443                                 struct sockaddr *);
444   left = ntohs (message->header.size) - sizeof (*message);
445   off = (const char *) &message[1];
446   for (unsigned int i=0;i<ch->num_addrs;i++)
447   {
448     size_t alen;
449     const struct sockaddr *sa = (const struct sockaddr *) off;
450
451     if (sizeof (sa_family_t) > left)
452     {
453       GNUNET_break (0);
454       GNUNET_SERVICE_client_drop (ch->client);
455       return;
456     }
457     switch (sa->sa_family)
458     {
459     case AF_INET:
460       {
461         const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa;
462         
463         alen = sizeof (struct sockaddr_in);
464         if (is_nat_v4 (&s4->sin_addr))
465           ch->natted_address = GNUNET_YES;
466       }
467       break;
468     case AF_INET6:
469       {
470         const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa;
471         
472         alen = sizeof (struct sockaddr_in6);
473         if (is_nat_v6 (&s6->sin6_addr))
474           ch->natted_address = GNUNET_YES;
475       }
476       break;
477 #if AF_UNIX
478     case AF_UNIX:
479       alen = sizeof (struct sockaddr_un);
480       break;
481 #endif
482     default:
483       GNUNET_break (0);
484       GNUNET_SERVICE_client_drop (ch->client);
485       return;      
486     }
487     GNUNET_assert (alen <= left);
488     ch->addrs[i] = GNUNET_malloc (alen);
489     GNUNET_memcpy (ch->addrs[i],
490                    sa,
491                    alen);    
492     off += alen;
493   }  
494   GNUNET_SERVICE_client_continue (ch->client);
495 }
496
497
498 /**
499  * Check validity of #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
500  * client.
501  *
502  * @param cls client who sent the message
503  * @param message the message received
504  * @return #GNUNET_OK if message is well-formed
505  */
506 static int
507 check_stun (void *cls,
508             const struct GNUNET_NAT_HandleStunMessage *message)
509 {
510   size_t sa_len = ntohs (message->sender_addr_size);
511   size_t expect = sa_len + ntohs (message->payload_size);
512   
513   if (ntohs (message->header.size) - sizeof (*message) != expect)
514   {
515     GNUNET_break (0);
516     return GNUNET_SYSERR;
517   }
518   if (sa_len < sizeof (sa_family_t))
519   {
520     GNUNET_break (0);
521     return GNUNET_SYSERR;
522   }
523   return GNUNET_OK;
524 }
525
526
527 /**
528  * Notify all clients about our external IP address
529  * as reported by the STUN server.
530  *
531  * @param ip the external IP
532  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
533  */
534 static void
535 notify_clients_stun_change (const struct sockaddr_in *ip,
536                             int add)
537 {
538   for (struct ClientHandle *ch = ch_head;
539        NULL != ch;
540        ch = ch->next)
541   {
542     struct sockaddr_in v4;
543     struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
544     struct GNUNET_MQ_Envelope *env;
545     
546     if (! ch->natted_address)
547       continue;
548     v4 = *ip;
549     v4.sin_port = htons (ch->adv_port);
550     env = GNUNET_MQ_msg_extra (msg,
551                                sizeof (v4),
552                                GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
553     msg->add_remove = htonl ((int32_t) add);
554     msg->addr_class = htonl (GNUNET_NAT_AC_GLOBAL_EXTERN |
555                              GNUNET_NAT_AC_GLOBAL);
556     GNUNET_memcpy (&msg[1],
557                    &v4,
558                    sizeof (v4));
559     GNUNET_MQ_send (ch->mq,
560                     env);
561   }
562 }
563
564
565 /**
566  * Function to be called when we decide that an
567  * external IP address as told to us by a STUN
568  * server has gone stale.
569  *
570  * @param cls the `struct StunExternalIP` to drop
571  */
572 static void
573 stun_ip_timeout (void *cls)
574 {
575   struct StunExternalIP *se = cls;
576
577   se->timeout_task = NULL;
578   notify_clients_stun_change (&se->external_addr,
579                               GNUNET_NO);
580   GNUNET_CONTAINER_DLL_remove (se_head,
581                                se_tail,
582                                se);
583   GNUNET_free (se);
584 }
585
586
587 /**
588  * Handler for #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
589  * client.
590  *
591  * @param cls client who sent the message
592  * @param message the message received
593  */
594 static void
595 handle_stun (void *cls,
596              const struct GNUNET_NAT_HandleStunMessage *message)
597 {
598   struct ClientHandle *ch = cls;
599   const char *buf = (const char *) &message[1];
600   const struct sockaddr *sa;
601   const void *payload;
602   size_t sa_len;
603   size_t payload_size;
604   struct sockaddr_in external_addr;
605
606   sa_len = ntohs (message->sender_addr_size);
607   payload_size = ntohs (message->payload_size);
608   sa = (const struct sockaddr *) &buf[0];
609   payload = (const struct sockaddr *) &buf[sa_len];
610   switch (sa->sa_family)
611   {
612   case AF_INET:
613     if (sa_len != sizeof (struct sockaddr_in))
614     {
615       GNUNET_break (0);
616       GNUNET_SERVICE_client_drop (ch->client);
617       return;
618     }
619     break;
620   case AF_INET6:
621     if (sa_len != sizeof (struct sockaddr_in6))
622     {
623       GNUNET_break (0);
624       GNUNET_SERVICE_client_drop (ch->client);
625       return;
626     }
627     break;
628   }
629   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630               "Received HANDLE_STUN message from client\n");
631   if (GNUNET_OK ==
632       GNUNET_NAT_stun_handle_packet_ (payload,
633                                       payload_size,
634                                       &external_addr))
635   {     
636     /* We now know that a server at "sa" claims that
637        we are visible at IP "external_addr". 
638
639        We should (for some fixed period of time) tell
640        all of our clients that listen to a NAT'ed address
641        that they might want to consider the given 'external_ip'
642        as their public IP address (this includes TCP and UDP
643        clients, even if only UDP sends STUN requests).
644
645        If we do not get a renewal, the "external_addr" should be
646        removed again.  The timeout frequency should be configurable
647        (with a sane default), so that the UDP plugin can tell how
648        often to re-request STUN.
649     */
650     struct StunExternalIP *se;
651
652     /* Check if we had a prior response from this STUN server */
653     for (se = se_head; NULL != se; se = se->next)
654     {
655       if ( (se->stun_server_addr_len != sa_len) ||
656            (0 != memcmp (sa,
657                          &se->stun_server_addr,
658                          sa_len)) )
659         continue; /* different STUN server */
660       if (0 != memcmp (&external_addr,
661                        &se->external_addr,
662                        sizeof (struct sockaddr_in)))
663       {
664         /* external IP changed, update! */
665         notify_clients_stun_change (&se->external_addr,
666                                     GNUNET_NO);
667         se->external_addr = external_addr;
668         notify_clients_stun_change (&se->external_addr,
669                                     GNUNET_YES);
670       }
671       /* update timeout */
672       GNUNET_SCHEDULER_cancel (se->timeout_task);
673       se->timeout_task
674         = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
675                                         &stun_ip_timeout,
676                                         se);
677       return;
678     }
679     /* STUN server is completely new, create fresh entry */
680     se = GNUNET_new (struct StunExternalIP);
681     se->external_addr = external_addr;
682     GNUNET_memcpy (&se->stun_server_addr,
683                    sa,
684                    sa_len);
685     se->stun_server_addr_len = sa_len;
686     se->timeout_task = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
687                                                      &stun_ip_timeout,
688                                                      se);
689     GNUNET_CONTAINER_DLL_insert (se_head,
690                                  se_tail,
691                                  se);
692     notify_clients_stun_change (&se->external_addr,
693                                 GNUNET_NO);
694   }
695   GNUNET_SERVICE_client_continue (ch->client);
696 }
697
698
699 /**
700  * Check validity of
701  * #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from
702  * client.
703  *
704  * @param cls client who sent the message
705  * @param message the message received
706  * @return #GNUNET_OK if message is well-formed
707  */
708 static int
709 check_request_connection_reversal (void *cls,
710                                    const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
711 {
712   size_t expect;
713
714   expect = ntohs (message->local_addr_size)
715     + ntohs (message->remote_addr_size);
716   if (ntohs (message->header.size) - sizeof (*message) != expect)
717   {
718     GNUNET_break (0);
719     return GNUNET_SYSERR;
720   }
721   return GNUNET_OK;
722 }
723
724
725 /**
726  * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL
727  * message from client.
728  *
729  * @param cls client who sent the message
730  * @param message the message received
731  */
732 static void
733 handle_request_connection_reversal (void *cls,
734                                     const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
735 {
736   struct ClientHandle *ch = cls;
737   const char *buf = (const char *) &message[1];
738   size_t local_sa_len = ntohs (message->local_addr_size);
739   size_t remote_sa_len = ntohs (message->remote_addr_size);
740   const struct sockaddr *local_sa = (const struct sockaddr *) &buf[0];
741   const struct sockaddr *remote_sa = (const struct sockaddr *) &buf[local_sa_len];
742   const struct sockaddr_in *l4 = NULL;
743   const struct sockaddr_in *r4;
744   int ret;
745   
746   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
747               "Received REQUEST CONNECTION REVERSAL message from client\n");
748   switch (local_sa->sa_family)
749   {
750   case AF_INET:
751     if (local_sa_len != sizeof (struct sockaddr_in))
752     {
753       GNUNET_break (0);
754       GNUNET_SERVICE_client_drop (ch->client);
755       return;
756     }
757     l4 = (const struct sockaddr_in *) local_sa;    
758     break;
759   case AF_INET6:
760     if (local_sa_len != sizeof (struct sockaddr_in6))
761     {
762       GNUNET_break (0);
763       GNUNET_SERVICE_client_drop (ch->client);
764       return;
765     }
766     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
767                 _("Connection reversal for IPv6 not supported yet\n"));
768     ret = GNUNET_SYSERR;
769     break;
770   default:
771     GNUNET_break (0);
772     GNUNET_SERVICE_client_drop (ch->client);
773     return;
774   }
775   switch (remote_sa->sa_family)
776   {
777   case AF_INET:
778     if (remote_sa_len != sizeof (struct sockaddr_in))
779     {
780       GNUNET_break (0);
781       GNUNET_SERVICE_client_drop (ch->client);
782       return;
783     }
784     r4 = (const struct sockaddr_in *) remote_sa;
785     ret = GN_request_connection_reversal (&l4->sin_addr,
786                                           ntohs (l4->sin_port),
787                                           &r4->sin_addr);
788     break;
789   case AF_INET6:
790     if (remote_sa_len != sizeof (struct sockaddr_in6))
791     {
792       GNUNET_break (0);
793       GNUNET_SERVICE_client_drop (ch->client);
794       return;
795     }
796     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
797                 _("Connection reversal for IPv6 not supported yet\n"));
798     ret = GNUNET_SYSERR;
799     break;
800   default:
801     GNUNET_break (0);
802     GNUNET_SERVICE_client_drop (ch->client);
803     return;
804   }
805   if (GNUNET_OK != ret)
806     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
807                 _("Connection reversal request failed\n"));  
808   GNUNET_SERVICE_client_continue (ch->client);
809 }
810
811
812 /**
813  * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
814  * from client.
815  *
816  * @param cls client who sent the message
817  * @param message the message received
818  * @return #GNUNET_OK if message is well-formed
819  */
820 static int
821 check_autoconfig_request (void *cls,
822                           const struct GNUNET_NAT_AutoconfigRequestMessage *message)
823 {
824   return GNUNET_OK;  /* checked later */
825 }
826
827
828 /**
829  * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
830  * client.
831  *
832  * @param cls client who sent the message
833  * @param message the message received
834  */
835 static void
836 handle_autoconfig_request (void *cls,
837                            const struct GNUNET_NAT_AutoconfigRequestMessage *message)
838 {
839   struct ClientHandle *ch = cls;
840   size_t left = ntohs (message->header.size) - sizeof (*message);
841   struct GNUNET_CONFIGURATION_Handle *c;
842
843   c = GNUNET_CONFIGURATION_create ();
844   if (GNUNET_OK !=
845       GNUNET_CONFIGURATION_deserialize (c,
846                                         (const char *) &message[1],
847                                         left,
848                                         GNUNET_NO))
849   {
850     GNUNET_break (0);
851     GNUNET_SERVICE_client_drop (ch->client);
852     return;
853   }
854   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
855               "Received REQUEST_AUTO_CONFIG message from client\n");
856   // FIXME: actually handle request...
857   GNUNET_CONFIGURATION_destroy (c);
858   GNUNET_SERVICE_client_continue (ch->client);
859 }
860
861
862 /**
863  * Task run during shutdown.
864  *
865  * @param cls unused
866  */
867 static void
868 shutdown_task (void *cls)
869 {
870   struct StunExternalIP *se;
871
872   while (NULL != (se = se_head))
873   {
874     GNUNET_CONTAINER_DLL_remove (se_head,
875                                  se_tail,
876                                  se);
877     GNUNET_SCHEDULER_cancel (se->timeout_task);
878     GNUNET_free (se);
879   }
880   if (NULL != scan_task)
881   {
882     GNUNET_SCHEDULER_cancel (scan_task);
883     scan_task = NULL;
884   }
885   if (NULL != stats)
886   {
887     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
888     stats = NULL;
889   }
890   destroy_lal ();
891 }
892
893
894 /**
895  * Closure for #ifc_proc.
896  */
897 struct IfcProcContext
898 {
899
900   /** 
901    * Head of DLL of local addresses.
902    */
903   struct LocalAddressList *lal_head;
904
905   /**
906    * Tail of DLL of local addresses.
907    */
908   struct LocalAddressList *lal_tail;
909
910 };
911
912
913 /**
914  * Callback function invoked for each interface found.  Adds them
915  * to our new address list.
916  *
917  * @param cls a `struct IfcProcContext *`
918  * @param name name of the interface (can be NULL for unknown)
919  * @param isDefault is this presumably the default interface
920  * @param addr address of this interface (can be NULL for unknown or unassigned)
921  * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
922  * @param netmask the network mask (can be NULL for unknown or unassigned)
923  * @param addrlen length of the address
924  * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
925  */
926 static int
927 ifc_proc (void *cls,
928           const char *name,
929           int isDefault,
930           const struct sockaddr *addr,
931           const struct sockaddr *broadcast_addr,
932           const struct sockaddr *netmask,
933           socklen_t addrlen)
934 {
935   struct IfcProcContext *ifc_ctx = cls;
936   struct LocalAddressList *lal;
937   size_t alen;
938   const struct in_addr *ip4;
939   const struct in6_addr *ip6;
940   enum GNUNET_NAT_AddressClass ac;
941
942   switch (addr->sa_family)
943   {
944   case AF_INET:
945     alen = sizeof (struct sockaddr_in);
946     ip4 = &((const struct sockaddr_in *) addr)->sin_addr;
947     if (match_ipv4 ("127.0.0.0", ip4, 8))
948       ac = GNUNET_NAT_AC_LOOPBACK;
949     else if (is_nat_v4 (ip4))
950       ac = GNUNET_NAT_AC_LAN;
951     else
952       ac = GNUNET_NAT_AC_GLOBAL;
953     break;
954   case AF_INET6:
955     alen = sizeof (struct sockaddr_in6);
956     ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr;
957     if (match_ipv6 ("::1", ip6, 128))
958       ac = GNUNET_NAT_AC_LOOPBACK;
959     else if (is_nat_v6 (ip6))
960       ac = GNUNET_NAT_AC_LAN;
961     else
962       ac = GNUNET_NAT_AC_GLOBAL;
963     if ( (ip6->s6_addr[11] == 0xFF) &&
964          (ip6->s6_addr[12] == 0xFE) )
965     {
966       /* contains a MAC, be extra careful! */
967       ac |= GNUNET_NAT_AC_PRIVATE;
968     }
969     break;
970 #if AF_UNIX
971   case AF_UNIX:
972     GNUNET_break (0);
973     return GNUNET_OK;
974 #endif
975   default:
976     GNUNET_break (0);
977     return GNUNET_OK;
978   }
979   lal = GNUNET_malloc (sizeof (*lal));
980   lal->af = addr->sa_family;
981   lal->ac = ac;
982   GNUNET_memcpy (&lal->addr,
983                  addr,
984                  alen);
985   GNUNET_CONTAINER_DLL_insert (ifc_ctx->lal_head,
986                                ifc_ctx->lal_tail,
987                                lal);
988   return GNUNET_OK;
989 }
990
991
992 /**
993  * Notify client about a change in the list
994  * of addresses this peer has.
995  *
996  * @param delta the entry in the list that changed
997  * @param ch client to contact
998  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
999  * @param addr the address that changed
1000  * @param addr_len number of bytes in @a addr
1001  */
1002 static void
1003 notify_client (struct LocalAddressList *delta,
1004                struct ClientHandle *ch,
1005                int add,
1006                const void *addr,
1007                size_t addr_len)
1008 {
1009   struct GNUNET_MQ_Envelope *env;
1010   struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
1011
1012   env = GNUNET_MQ_msg_extra (msg,
1013                              addr_len,
1014                              GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
1015   msg->add_remove = htonl (add);
1016   msg->addr_class = htonl (delta->ac);
1017   GNUNET_memcpy (&msg[1],
1018                  addr,
1019                  addr_len);
1020   GNUNET_MQ_send (ch->mq,
1021                   env);
1022 }                      
1023
1024
1025 /**
1026  * Notify all clients about a change in the list
1027  * of addresses this peer has.
1028  *
1029  * @param delta the entry in the list that changed
1030  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
1031  */
1032 static void
1033 notify_clients (struct LocalAddressList *delta,
1034                 int add)
1035 {
1036   for (struct ClientHandle *ch = ch_head;
1037        NULL != ch;
1038        ch = ch->next)
1039   {
1040     size_t alen;
1041     struct sockaddr_in v4;
1042     struct sockaddr_in6 v6;
1043     
1044     if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
1045       continue;
1046     switch (delta->af)
1047     {
1048     case AF_INET:
1049       alen = sizeof (struct sockaddr_in);
1050       GNUNET_memcpy (&v4,
1051                      &delta->addr,
1052                      alen);
1053       for (unsigned int i=0;i<ch->num_addrs;i++)
1054       {
1055         const struct sockaddr_in *c4;
1056         
1057         if (AF_INET != ch->addrs[i]->sa_family)
1058           continue; /* IPv4 not relevant */
1059         c4 = (const struct sockaddr_in *) ch->addrs[i];
1060         v4.sin_port = c4->sin_port;
1061         notify_client (delta,
1062                        ch,
1063                        add,
1064                        &v4,
1065                        alen);
1066       }
1067       break;
1068     case AF_INET6:
1069       alen = sizeof (struct sockaddr_in6);
1070       GNUNET_memcpy (&v6,
1071                      &delta->addr,
1072                      alen);
1073       for (unsigned int i=0;i<ch->num_addrs;i++)
1074       {
1075         const struct sockaddr_in6 *c6;
1076         
1077         if (AF_INET6 != ch->addrs[i]->sa_family)
1078           continue; /* IPv4 not relevant */
1079         c6 = (const struct sockaddr_in6 *) ch->addrs[i];
1080         v6.sin6_port = c6->sin6_port;
1081         notify_client (delta,
1082                        ch,
1083                        add,
1084                        &v6,
1085                        alen);
1086       }
1087       break;
1088     default:
1089       GNUNET_break (0);
1090       continue;
1091     }
1092   }
1093 }
1094
1095
1096 /**
1097  * Task we run periodically to scan for network interfaces.
1098  *
1099  * @param cls NULL
1100  */ 
1101 static void
1102 run_scan (void *cls)
1103 {
1104   struct IfcProcContext ifc_ctx;
1105   int found;
1106   
1107   scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
1108                                             &run_scan,
1109                                             NULL);
1110   memset (&ifc_ctx,
1111           0,
1112           sizeof (ifc_ctx));
1113   GNUNET_OS_network_interfaces_list (&ifc_proc,
1114                                      &ifc_ctx);
1115   for (struct LocalAddressList *lal = lal_head;
1116        NULL != lal;
1117        lal = lal->next)
1118   {
1119     found = GNUNET_NO;
1120     for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1121          NULL != pos;
1122          pos = pos->next)
1123     {
1124       if ( (pos->af == lal->af) &&
1125            (0 == memcmp (&lal->addr,
1126                          &pos->addr,
1127                          (AF_INET == lal->af)
1128                          ? sizeof (struct sockaddr_in)
1129                          : sizeof (struct sockaddr_in6))) )
1130         found = GNUNET_YES;
1131     }
1132     if (GNUNET_NO == found)
1133       notify_clients (lal,
1134                       GNUNET_NO);
1135   }
1136
1137   for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1138        NULL != pos;
1139        pos = pos->next)
1140   {
1141     found = GNUNET_NO;
1142     for (struct LocalAddressList *lal = lal_head;
1143          NULL != lal;
1144          lal = lal->next)
1145     {
1146       if ( (pos->af == lal->af) &&
1147            (0 == memcmp (&lal->addr,
1148                          &pos->addr,
1149                          (AF_INET == lal->af)
1150                          ? sizeof (struct sockaddr_in)
1151                          : sizeof (struct sockaddr_in6))) )
1152         found = GNUNET_YES;
1153     }
1154     if (GNUNET_NO == found)
1155       notify_clients (pos,
1156                       GNUNET_YES);
1157   }
1158
1159   destroy_lal ();
1160   lal_head = ifc_ctx.lal_head;
1161   lal_tail = ifc_ctx.lal_tail;
1162 }
1163
1164
1165 /**
1166  * Handle network size estimate clients.
1167  *
1168  * @param cls closure
1169  * @param c configuration to use
1170  * @param service the initialized service
1171  */
1172 static void
1173 run (void *cls,
1174      const struct GNUNET_CONFIGURATION_Handle *c,
1175      struct GNUNET_SERVICE_Handle *service)
1176 {
1177   cfg = c;
1178   if (GNUNET_OK !=
1179       GNUNET_CONFIGURATION_get_value_time (cfg,
1180                                            "NAT",
1181                                            "STUN_STALE",
1182                                            &stun_stale_timeout))
1183     stun_stale_timeout = GNUNET_TIME_UNIT_HOURS;
1184   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1185                                  NULL);
1186   stats = GNUNET_STATISTICS_create ("nat",
1187                                     cfg);
1188   scan_task = GNUNET_SCHEDULER_add_now (&run_scan,
1189                                         NULL);
1190 }
1191
1192
1193 /**
1194  * Callback called when a client connects to the service.
1195  *
1196  * @param cls closure for the service
1197  * @param c the new client that connected to the service
1198  * @param mq the message queue used to send messages to the client
1199  * @return a `struct ClientHandle`
1200  */
1201 static void *
1202 client_connect_cb (void *cls,
1203                    struct GNUNET_SERVICE_Client *c,
1204                    struct GNUNET_MQ_Handle *mq)
1205 {
1206   struct ClientHandle *ch;
1207
1208   ch = GNUNET_new (struct ClientHandle);
1209   ch->mq = mq;
1210   ch->client = c;
1211   GNUNET_CONTAINER_DLL_insert (ch_head,
1212                                ch_tail,
1213                                ch);
1214   return ch;
1215 }
1216
1217
1218 /**
1219  * Callback called when a client disconnected from the service
1220  *
1221  * @param cls closure for the service
1222  * @param c the client that disconnected
1223  * @param internal_cls a `struct ClientHandle *`
1224  */
1225 static void
1226 client_disconnect_cb (void *cls,
1227                       struct GNUNET_SERVICE_Client *c,
1228                       void *internal_cls)
1229 {
1230   struct ClientHandle *ch = internal_cls;
1231
1232   GNUNET_CONTAINER_DLL_remove (ch_head,
1233                                ch_tail,
1234                                ch);
1235   for (unsigned int i=0;i<ch->num_addrs;i++)
1236     GNUNET_free_non_null (ch->addrs[i]);
1237   GNUNET_free_non_null (ch->addrs);
1238   GNUNET_free (ch);
1239 }
1240
1241
1242 /**
1243  * Define "main" method using service macro.
1244  */
1245 GNUNET_SERVICE_MAIN
1246 ("nat",
1247  GNUNET_SERVICE_OPTION_NONE,
1248  &run,
1249  &client_connect_cb,
1250  &client_disconnect_cb,
1251  NULL,
1252  GNUNET_MQ_hd_var_size (register,
1253                         GNUNET_MESSAGE_TYPE_NAT_REGISTER,
1254                         struct GNUNET_NAT_RegisterMessage,
1255                         NULL),
1256  GNUNET_MQ_hd_var_size (stun,
1257                         GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN,
1258                         struct GNUNET_NAT_HandleStunMessage,
1259                         NULL),
1260  GNUNET_MQ_hd_var_size (request_connection_reversal,
1261                         GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
1262                         struct GNUNET_NAT_RequestConnectionReversalMessage,
1263                         NULL),
1264  GNUNET_MQ_hd_var_size (autoconfig_request,
1265                         GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG,
1266                         struct GNUNET_NAT_AutoconfigRequestMessage,
1267                         NULL),
1268  GNUNET_MQ_handler_end ());
1269
1270
1271 #if defined(LINUX) && defined(__GLIBC__)
1272 #include <malloc.h>
1273
1274 /**
1275  * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1276  */
1277 void __attribute__ ((constructor))
1278 GNUNET_ARM_memory_init ()
1279 {
1280   mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1281   mallopt (M_TOP_PAD, 1 * 1024);
1282   malloc_trim (0);
1283 }
1284 #endif
1285
1286 /* end of gnunet-service-nat.c */