2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
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.
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.
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.
22 * @file nat/gnunet-service-nat.c
23 * @brief network address translation traversal service
24 * @author Christian Grothoff
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.
31 * - call GN_start_gnunet_nat_server_() if possible (i.e.
32 * when we find we have a non-global IPv4 address)
33 * - implement handle_test
34 * - implement autoconfig
35 * - implmeent UPnPC/PMP-based NAT traversal
36 * - implement NEW logic for external IP detection
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_helper.h"
52 * How often should we ask the OS about a list of active
55 #define SCAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
59 * Internal data structure we track for each of our clients.
67 struct ClientHandle *next;
72 struct ClientHandle *prev;
75 * Underlying handle for this client with the service.
77 struct GNUNET_SERVICE_Client *client;
80 * Message queue for communicating with the client.
82 struct GNUNET_MQ_Handle *mq;
85 * Array of addresses used by the service.
87 struct sockaddr **addrs;
90 * What does this client care about?
92 enum GNUNET_NAT_RegisterFlags flags;
95 * Port we would like as we are configured to use this one for
96 * advertising (in addition to the one we are binding to).
101 * Number of addresses that this service is bound to.
106 * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
114 * List of local addresses this system has.
116 struct LocalAddressList
119 * This is a linked list.
121 struct LocalAddressList *next;
126 struct LocalAddressList *prev;
129 * The address itself (i.e. `struct sockaddr_in` or `struct
130 * sockaddr_in6`, in the respective byte order).
132 struct sockaddr_storage addr;
140 * What type of address is this?
142 enum GNUNET_NAT_AddressClass ac;
148 * Handle to our current configuration.
150 static const struct GNUNET_CONFIGURATION_Handle *cfg;
153 * Handle to the statistics service.
155 static struct GNUNET_STATISTICS_Handle *stats;
158 * Task scheduled to periodically scan our network interfaces.
160 static struct GNUNET_SCHEDULER_Task *scan_task;
163 * Head of client DLL.
165 static struct ClientHandle *ch_head;
168 * Tail of client DLL.
170 static struct ClientHandle *ch_tail;
173 * Head of DLL of local addresses.
175 static struct LocalAddressList *lal_head;
178 * Tail of DLL of local addresses.
180 static struct LocalAddressList *lal_tail;
184 * Free the DLL starting at #lal_head.
189 struct LocalAddressList *lal;
191 while (NULL != (lal = lal_head))
193 GNUNET_CONTAINER_DLL_remove (lal_head,
202 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from
205 * @param cls client who sent the message
206 * @param message the message received
207 * @return #GNUNET_OK if message is well-formed
210 check_register (void *cls,
211 const struct GNUNET_NAT_RegisterMessage *message)
213 uint16_t num_addrs = ntohs (message->num_addrs);
214 const char *off = (const char *) &message[1];
215 size_t left = ntohs (message->header.size) - sizeof (*message);
217 for (unsigned int i=0;i<num_addrs;i++)
220 const struct sockaddr *sa = (const struct sockaddr *) off;
222 if (sizeof (sa_family_t) > left)
225 return GNUNET_SYSERR;
227 switch (sa->sa_family)
230 alen = sizeof (struct sockaddr_in);
233 alen = sizeof (struct sockaddr_in6);
237 alen = sizeof (struct sockaddr_un);
242 return GNUNET_SYSERR;
247 return GNUNET_SYSERR;
255 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
256 * We remember the client for updates upon future NAT events.
258 * @param cls client who sent the message
259 * @param message the message received
262 handle_register (void *cls,
263 const struct GNUNET_NAT_RegisterMessage *message)
265 struct ClientHandle *ch = cls;
269 if ( (0 != ch->proto) ||
270 (NULL != ch->addrs) )
272 /* double registration not allowed */
274 GNUNET_SERVICE_client_drop (ch->client);
277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
278 "Received REGISTER message from client\n");
279 ch->flags = message->flags;
280 ch->proto = message->proto;
281 ch->adv_port = ntohs (message->adv_port);
282 ch->num_addrs = ntohs (message->adv_port);
283 ch->addrs = GNUNET_new_array (ch->num_addrs,
285 left = ntohs (message->header.size) - sizeof (*message);
286 off = (const char *) &message[1];
287 for (unsigned int i=0;i<ch->num_addrs;i++)
290 const struct sockaddr *sa = (const struct sockaddr *) off;
292 if (sizeof (sa_family_t) > left)
295 GNUNET_SERVICE_client_drop (ch->client);
298 switch (sa->sa_family)
301 alen = sizeof (struct sockaddr_in);
304 alen = sizeof (struct sockaddr_in6);
308 alen = sizeof (struct sockaddr_un);
313 GNUNET_SERVICE_client_drop (ch->client);
316 GNUNET_assert (alen <= left);
317 ch->addrs[i] = GNUNET_malloc (alen);
318 GNUNET_memcpy (ch->addrs[i],
323 GNUNET_SERVICE_client_continue (ch->client);
328 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
331 * @param cls client who sent the message
332 * @param message the message received
333 * @return #GNUNET_OK if message is well-formed
336 check_stun (void *cls,
337 const struct GNUNET_NAT_HandleStunMessage *message)
339 size_t sa_len = ntohs (message->sender_addr_size);
340 size_t expect = sa_len + ntohs (message->payload_size);
342 if (ntohs (message->header.size) - sizeof (*message) != expect)
345 return GNUNET_SYSERR;
347 if (sa_len < sizeof (sa_family_t))
350 return GNUNET_SYSERR;
357 * Handler for #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
360 * @param cls client who sent the message
361 * @param message the message received
364 handle_stun (void *cls,
365 const struct GNUNET_NAT_HandleStunMessage *message)
367 struct ClientHandle *ch = cls;
368 const char *buf = (const char *) &message[1];
369 const struct sockaddr *sa;
373 struct sockaddr_in external_addr;
375 sa_len = ntohs (message->sender_addr_size);
376 payload_size = ntohs (message->payload_size);
377 sa = (const struct sockaddr *) &buf[0];
378 payload = (const struct sockaddr *) &buf[sa_len];
379 switch (sa->sa_family)
382 if (sa_len != sizeof (struct sockaddr_in))
385 GNUNET_SERVICE_client_drop (ch->client);
390 if (sa_len != sizeof (struct sockaddr_in6))
393 GNUNET_SERVICE_client_drop (ch->client);
398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
399 "Received HANDLE_STUN message from client\n");
401 GNUNET_NAT_stun_handle_packet_ (payload,
405 /* FIXME: do something with "external_addr"! We
406 now know that a server at "sa" claims that
407 we are visible at IP "external_addr".
409 We should (for some fixed period of time) tell
410 all of our clients that listen to a NAT'ed address
411 that they might want to consider the given 'external_ip'
412 as their public IP address (this includes TCP and UDP
413 clients, even if only UDP sends STUN requests).
415 If we do not get a renewal, the "external_addr" should be
416 removed again. The timeout frequency should be configurable
417 (with a sane default), so that the UDP plugin can tell how
418 often to re-request STUN.
422 GNUNET_SERVICE_client_continue (ch->client);
428 * #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from
431 * @param cls client who sent the message
432 * @param message the message received
433 * @return #GNUNET_OK if message is well-formed
436 check_request_connection_reversal (void *cls,
437 const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
441 expect = ntohs (message->local_addr_size)
442 + ntohs (message->remote_addr_size);
443 if (ntohs (message->header.size) - sizeof (*message) != expect)
446 return GNUNET_SYSERR;
453 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL
454 * message from client.
456 * @param cls client who sent the message
457 * @param message the message received
460 handle_request_connection_reversal (void *cls,
461 const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
463 struct ClientHandle *ch = cls;
464 const char *buf = (const char *) &message[1];
465 size_t local_sa_len = ntohs (message->local_addr_size);
466 size_t remote_sa_len = ntohs (message->remote_addr_size);
467 const struct sockaddr *local_sa = (const struct sockaddr *) &buf[0];
468 const struct sockaddr *remote_sa = (const struct sockaddr *) &buf[local_sa_len];
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
471 "Received REQUEST CONNECTION REVERSAL message from client\n");
472 switch (local_sa->sa_family)
475 if (local_sa_len != sizeof (struct sockaddr_in))
478 GNUNET_SERVICE_client_drop (ch->client);
483 if (local_sa_len != sizeof (struct sockaddr_in6))
486 GNUNET_SERVICE_client_drop (ch->client);
492 GNUNET_SERVICE_client_drop (ch->client);
495 switch (remote_sa->sa_family)
498 if (remote_sa_len != sizeof (struct sockaddr_in))
501 GNUNET_SERVICE_client_drop (ch->client);
506 if (remote_sa_len != sizeof (struct sockaddr_in6))
509 GNUNET_SERVICE_client_drop (ch->client);
515 GNUNET_SERVICE_client_drop (ch->client);
518 /* FIXME: actually run the logic by
519 calling 'GN_request_connection_reversal()' */
521 GNUNET_SERVICE_client_continue (ch->client);
526 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
529 * @param cls client who sent the message
530 * @param message the message received
531 * @return #GNUNET_OK if message is well-formed
534 check_autoconfig_request (void *cls,
535 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
537 return GNUNET_OK; /* checked later */
542 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
545 * @param cls client who sent the message
546 * @param message the message received
549 handle_autoconfig_request (void *cls,
550 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
552 struct ClientHandle *ch = cls;
553 size_t left = ntohs (message->header.size);
554 struct GNUNET_CONFIGURATION_Handle *c;
556 c = GNUNET_CONFIGURATION_create ();
558 GNUNET_CONFIGURATION_deserialize (c,
559 (const char *) &message[1],
564 GNUNET_SERVICE_client_drop (ch->client);
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
568 "Received REQUEST_AUTO_CONFIG message from client\n");
569 // FIXME: actually handle request...
570 GNUNET_CONFIGURATION_destroy (c);
571 GNUNET_SERVICE_client_continue (ch->client);
576 * Task run during shutdown.
581 shutdown_task (void *cls)
583 if (NULL != scan_task)
585 GNUNET_SCHEDULER_cancel (scan_task);
590 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
598 * Closure for #ifc_proc.
600 struct IfcProcContext
604 * Head of DLL of local addresses.
606 struct LocalAddressList *lal_head;
609 * Tail of DLL of local addresses.
611 struct LocalAddressList *lal_tail;
617 * Check if @a ip is in @a network with @a bits netmask.
619 * @param network to test
620 * @param ip IP address to test
621 * @param bits bitmask for the network
622 * @return #GNUNET_YES if @a ip is in @a network
625 match_ipv4 (const char *network,
626 const struct in_addr *ip,
633 GNUNET_assert (1 == inet_pton (AF_INET,
636 return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
641 * Check if @a ip is in @a network with @a bits netmask.
643 * @param network to test
644 * @param ip IP address to test
645 * @param bits bitmask for the network
646 * @return #GNUNET_YES if @a ip is in @a network
649 match_ipv6 (const char *network,
650 const struct in6_addr *ip,
654 struct in6_addr mask;
659 GNUNET_assert (1 == inet_pton (AF_INET,
662 memset (&mask, 0, sizeof (mask));
666 mask.s6_addr[off++] = 0xFF;
671 mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
674 for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++)
675 if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
676 (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
683 * Test if the given IPv4 address is in a known range
684 * for private networks.
686 * @param ip address to test
687 * @return #GNUNET_YES if @a ip is in a NAT range
690 is_nat_v4 (const struct in_addr *ip)
693 match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */
694 match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
695 match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */
696 match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
697 match_ipv4 ("172.16.0.0", ip, 16); /* RFC 1918 */
702 * Test if the given IPv6 address is in a known range
703 * for private networks.
705 * @param ip address to test
706 * @return #GNUNET_YES if @a ip is in a NAT range
709 is_nat_v6 (const struct in6_addr *ip)
712 match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
713 match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
714 match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
719 * Callback function invoked for each interface found. Adds them
720 * to our new address list.
722 * @param cls a `struct IfcProcContext *`
723 * @param name name of the interface (can be NULL for unknown)
724 * @param isDefault is this presumably the default interface
725 * @param addr address of this interface (can be NULL for unknown or unassigned)
726 * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
727 * @param netmask the network mask (can be NULL for unknown or unassigned)
728 * @param addrlen length of the address
729 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
735 const struct sockaddr *addr,
736 const struct sockaddr *broadcast_addr,
737 const struct sockaddr *netmask,
740 struct IfcProcContext *ifc_ctx = cls;
741 struct LocalAddressList *lal;
743 const struct in_addr *ip4;
744 const struct in6_addr *ip6;
745 enum GNUNET_NAT_AddressClass ac;
747 switch (addr->sa_family)
750 alen = sizeof (struct sockaddr_in);
751 ip4 = &((const struct sockaddr_in *) addr)->sin_addr;
752 if (match_ipv4 ("127.0.0.0", ip4, 8))
753 ac = GNUNET_NAT_AC_LOOPBACK;
754 else if (is_nat_v4 (ip4))
755 ac = GNUNET_NAT_AC_LAN;
757 ac = GNUNET_NAT_AC_GLOBAL;
760 alen = sizeof (struct sockaddr_in6);
761 ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr;
762 if (match_ipv6 ("::1", ip6, 128))
763 ac = GNUNET_NAT_AC_LOOPBACK;
764 else if (is_nat_v6 (ip6))
765 ac = GNUNET_NAT_AC_LAN;
767 ac = GNUNET_NAT_AC_GLOBAL;
768 if ( (ip6->s6_addr[11] == 0xFF) &&
769 (ip6->s6_addr[12] == 0xFE) )
771 /* contains a MAC, be extra careful! */
772 ac |= GNUNET_NAT_AC_PRIVATE;
784 lal = GNUNET_malloc (sizeof (*lal));
785 lal->af = addr->sa_family;
787 GNUNET_memcpy (&lal->addr,
790 GNUNET_CONTAINER_DLL_insert (ifc_ctx->lal_head,
798 * Notify client about a change in the list
799 * of addresses this peer has.
801 * @param delta the entry in the list that changed
802 * @param ch client to contact
803 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
804 * @param addr the address that changed
805 * @param addr_len number of bytes in @a addr
808 notify_client (struct LocalAddressList *delta,
809 struct ClientHandle *ch,
814 struct GNUNET_MQ_Envelope *env;
815 struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
817 env = GNUNET_MQ_msg_extra (msg,
819 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
820 msg->add_remove = htonl (add);
821 msg->addr_class = htonl (delta->ac);
822 GNUNET_memcpy (&msg[1],
825 GNUNET_MQ_send (ch->mq,
831 * Notify all clients about a change in the list
832 * of addresses this peer has.
834 * @param delta the entry in the list that changed
835 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
838 notify_clients (struct LocalAddressList *delta,
841 for (struct ClientHandle *ch = ch_head;
846 struct sockaddr_in v4;
847 struct sockaddr_in6 v6;
849 if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
854 alen = sizeof (struct sockaddr_in);
858 for (unsigned int i=0;i<ch->num_addrs;i++)
860 const struct sockaddr_in *c4;
862 if (AF_INET != ch->addrs[i]->sa_family)
863 continue; /* IPv4 not relevant */
864 c4 = (const struct sockaddr_in *) ch->addrs[i];
865 v4.sin_port = c4->sin_port;
866 notify_client (delta,
874 alen = sizeof (struct sockaddr_in6);
878 for (unsigned int i=0;i<ch->num_addrs;i++)
880 const struct sockaddr_in6 *c6;
882 if (AF_INET6 != ch->addrs[i]->sa_family)
883 continue; /* IPv4 not relevant */
884 c6 = (const struct sockaddr_in6 *) ch->addrs[i];
885 v6.sin6_port = c6->sin6_port;
886 notify_client (delta,
902 * Task we run periodically to scan for network interfaces.
909 struct IfcProcContext ifc_ctx;
912 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
918 GNUNET_OS_network_interfaces_list (&ifc_proc,
920 for (struct LocalAddressList *lal = lal_head;
925 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
929 if ( (pos->af == lal->af) &&
930 (0 == memcmp (&lal->addr,
933 ? sizeof (struct sockaddr_in)
934 : sizeof (struct sockaddr_in6))) )
937 if (GNUNET_NO == found)
942 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
947 for (struct LocalAddressList *lal = lal_head;
951 if ( (pos->af == lal->af) &&
952 (0 == memcmp (&lal->addr,
955 ? sizeof (struct sockaddr_in)
956 : sizeof (struct sockaddr_in6))) )
959 if (GNUNET_NO == found)
965 lal_head = ifc_ctx.lal_head;
966 lal_tail = ifc_ctx.lal_tail;
971 * Handle network size estimate clients.
974 * @param c configuration to use
975 * @param service the initialized service
979 const struct GNUNET_CONFIGURATION_Handle *c,
980 struct GNUNET_SERVICE_Handle *service)
983 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
985 stats = GNUNET_STATISTICS_create ("nat",
987 scan_task = GNUNET_SCHEDULER_add_now (&run_scan,
993 * Callback called when a client connects to the service.
995 * @param cls closure for the service
996 * @param c the new client that connected to the service
997 * @param mq the message queue used to send messages to the client
998 * @return a `struct ClientHandle`
1001 client_connect_cb (void *cls,
1002 struct GNUNET_SERVICE_Client *c,
1003 struct GNUNET_MQ_Handle *mq)
1005 struct ClientHandle *ch;
1007 ch = GNUNET_new (struct ClientHandle);
1010 GNUNET_CONTAINER_DLL_insert (ch_head,
1018 * Callback called when a client disconnected from the service
1020 * @param cls closure for the service
1021 * @param c the client that disconnected
1022 * @param internal_cls a `struct ClientHandle *`
1025 client_disconnect_cb (void *cls,
1026 struct GNUNET_SERVICE_Client *c,
1029 struct ClientHandle *ch = internal_cls;
1031 GNUNET_CONTAINER_DLL_remove (ch_head,
1034 for (unsigned int i=0;i<ch->num_addrs;i++)
1035 GNUNET_free_non_null (ch->addrs[i]);
1036 GNUNET_free_non_null (ch->addrs);
1042 * Define "main" method using service macro.
1046 GNUNET_SERVICE_OPTION_NONE,
1049 &client_disconnect_cb,
1051 GNUNET_MQ_hd_var_size (register,
1052 GNUNET_MESSAGE_TYPE_NAT_REGISTER,
1053 struct GNUNET_NAT_RegisterMessage,
1055 GNUNET_MQ_hd_var_size (stun,
1056 GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN,
1057 struct GNUNET_NAT_HandleStunMessage,
1059 GNUNET_MQ_hd_var_size (request_connection_reversal,
1060 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
1061 struct GNUNET_NAT_RequestConnectionReversalMessage,
1063 GNUNET_MQ_hd_var_size (autoconfig_request,
1064 GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG,
1065 struct GNUNET_NAT_AutoconfigRequestMessage,
1067 GNUNET_MQ_handler_end ());
1070 #if defined(LINUX) && defined(__GLIBC__)
1074 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1076 void __attribute__ ((constructor))
1077 GNUNET_ARM_memory_init ()
1079 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1080 mallopt (M_TOP_PAD, 1 * 1024);
1085 /* end of gnunet-service-nat.c */