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