aboutsummaryrefslogtreecommitdiff
path: root/src/nat
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-12-17 09:00:48 +0100
committerChristian Grothoff <christian@grothoff.org>2016-12-17 09:00:48 +0100
commit714a98ab0c0d29e9d2a4226a41fa4cf7d45291bd (patch)
tree1496cde5f138cc4a32d735656b1f6b635fe15dfd /src/nat
parentc4815dbb193e507dac71ea8f9f926932b54b0fed (diff)
downloadgnunet-714a98ab0c0d29e9d2a4226a41fa4cf7d45291bd.tar.gz
gnunet-714a98ab0c0d29e9d2a4226a41fa4cf7d45291bd.zip
towards notifying clients about external-ip results
Diffstat (limited to 'src/nat')
-rw-r--r--src/nat/gnunet-service-nat.c224
1 files changed, 216 insertions, 8 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 5ae24c456..bf82ce7eb 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -57,6 +57,24 @@
57 */ 57 */
58#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 58#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
59 59
60/**
61 * How long do we wait until we re-try running `external-ip` if the
62 * command failed to terminate nicely?
63 */
64#define EXTERN_IP_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
65
66/**
67 * How long do we wait until we re-try running `external-ip` if the
68 * command failed (but terminated)?
69 */
70#define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
71
72/**
73 * How long do we wait until we re-try running `external-ip` if the
74 * command succeeded?
75 */
76#define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
77
60 78
61/** 79/**
62 * Internal data structure we track for each of our clients. 80 * Internal data structure we track for each of our clients.
@@ -322,6 +340,22 @@ static struct StunExternalIP *se_tail;
322 */ 340 */
323static int enable_upnp; 341static int enable_upnp;
324 342
343/**
344 * Task run to obtain our external IP (if #enable_upnp is set
345 * and if we find we have a NATed IP address).
346 */
347static struct GNUNET_SCHEDULER_Task *probe_external_ip_task;
348
349/**
350 * Handle to our operation to run `external-ip`.
351 */
352static struct GNUNET_NAT_ExternalHandle *probe_external_ip_op;
353
354/**
355 * What is our external IP address as claimed by `external-ip`?
356 * 0 for unknown.
357 */
358static struct in_addr mini_external_ipv4;
325 359
326/** 360/**
327 * Free the DLL starting at #lal_head. 361 * Free the DLL starting at #lal_head.
@@ -604,14 +638,14 @@ ifc_proc (void *cls,
604 * Notify client about a change in the list of addresses this peer 638 * Notify client about a change in the list of addresses this peer
605 * has. 639 * has.
606 * 640 *
607 * @param delta the entry in the list that changed 641 * @param ac address class of the entry in the list that changed
608 * @param ch client to contact 642 * @param ch client to contact
609 * @param add #GNUNET_YES to add, #GNUNET_NO to remove 643 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
610 * @param addr the address that changed 644 * @param addr the address that changed
611 * @param addr_len number of bytes in @a addr 645 * @param addr_len number of bytes in @a addr
612 */ 646 */
613static void 647static void
614notify_client (struct LocalAddressList *delta, 648notify_client (enum GNUNET_NAT_AddressClass ac,
615 struct ClientHandle *ch, 649 struct ClientHandle *ch,
616 int add, 650 int add,
617 const void *addr, 651 const void *addr,
@@ -624,7 +658,7 @@ notify_client (struct LocalAddressList *delta,
624 addr_len, 658 addr_len,
625 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); 659 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
626 msg->add_remove = htonl (add); 660 msg->add_remove = htonl (add);
627 msg->addr_class = htonl (delta->ac); 661 msg->addr_class = htonl (ac);
628 GNUNET_memcpy (&msg[1], 662 GNUNET_memcpy (&msg[1],
629 addr, 663 addr,
630 addr_len); 664 addr_len);
@@ -667,7 +701,7 @@ check_notify_client (struct LocalAddressList *delta,
667 return; /* IPv4 not relevant */ 701 return; /* IPv4 not relevant */
668 c4 = (const struct sockaddr_in *) ch->addrs[i]; 702 c4 = (const struct sockaddr_in *) ch->addrs[i];
669 v4.sin_port = c4->sin_port; 703 v4.sin_port = c4->sin_port;
670 notify_client (delta, 704 notify_client (delta->ac,
671 ch, 705 ch,
672 add, 706 add,
673 &v4, 707 &v4,
@@ -687,7 +721,7 @@ check_notify_client (struct LocalAddressList *delta,
687 return; /* IPv4 not relevant */ 721 return; /* IPv4 not relevant */
688 c6 = (const struct sockaddr_in6 *) ch->addrs[i]; 722 c6 = (const struct sockaddr_in6 *) ch->addrs[i];
689 v6.sin6_port = c6->sin6_port; 723 v6.sin6_port = c6->sin6_port;
690 notify_client (delta, 724 notify_client (delta->ac,
691 ch, 725 ch,
692 add, 726 add,
693 &v6, 727 &v6,
@@ -722,6 +756,142 @@ notify_clients (struct LocalAddressList *delta,
722 756
723 757
724/** 758/**
759 * Tell relevant client about a change in our external
760 * IPv4 address.
761 *
762 * @param v4 the external address that changed
763 * @param ch client to check if it cares and possibly notify
764 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
765 */
766static void
767check_notify_client_external_ipv4_change (const struct in_addr *v4,
768 struct ClientHandle *ch,
769 int add)
770{
771 struct sockaddr_in sa;
772
773 // FIXME: (1) check if client cares;
774 GNUNET_break (0); // FIXME: implement!
775
776 /* (2) figure out external port, build sockaddr */
777 memset (&sa,
778 0,
779 sizeof (sa));
780 sa.sin_family = AF_INET;
781 sa.sin_addr = *v4;
782 sa.sin_port = 42; // FIXME
783
784 /* (3) notify client of change */
785
786 // FIXME: handle case where 'v4' is still in the NAT range
787 // (in case of double-NAT!)
788 notify_client (GNUNET_NAT_AC_GLOBAL_EXTERN,
789 ch,
790 add,
791 &sa,
792 sizeof (sa));
793}
794
795
796/**
797 * Tell relevant clients about a change in our external
798 * IPv4 address.
799 *
800 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
801 * @param v4 the external address that changed
802 */
803static void
804notify_clients_external_ipv4_change (int add,
805 const struct in_addr *v4)
806{
807 for (struct ClientHandle *ch = ch_head;
808 NULL != ch;
809 ch = ch->next)
810 check_notify_client_external_ipv4_change (v4,
811 ch,
812 add);
813}
814
815
816/**
817 * Task used to run `external-ip` to get our external IPv4
818 * address and pass it to NATed clients if possible.
819 *
820 * @param cls NULL
821 */
822static void
823run_external_ip (void *cls);
824
825
826/**
827 * We learn our current external IP address. If it changed,
828 * notify all of our applicable clients. Also re-schedule
829 * #run_external_ip with an appropriate timeout.
830 *
831 * @param cls NULL
832 * @param addr the address, NULL on errors
833 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
834 */
835static void
836handle_external_ip (void *cls,
837 const struct in_addr *addr,
838 enum GNUNET_NAT_StatusCode result)
839{
840 probe_external_ip_op = NULL;
841 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
842 probe_external_ip_task
843 = GNUNET_SCHEDULER_add_delayed ((NULL == addr)
844 ? EXTERN_IP_RETRY_FAILURE
845 : EXTERN_IP_RETRY_SUCCESS,
846 &run_external_ip,
847 NULL);
848 switch (result)
849 {
850 case GNUNET_NAT_ERROR_SUCCESS:
851 if (addr->s_addr == mini_external_ipv4.s_addr)
852 return; /* not change */
853 if (0 != mini_external_ipv4.s_addr)
854 notify_clients_external_ipv4_change (GNUNET_NO,
855 &mini_external_ipv4);
856 mini_external_ipv4 = *addr;
857 notify_clients_external_ipv4_change (GNUNET_YES,
858 &mini_external_ipv4);
859 break;
860 default:
861 if (0 != mini_external_ipv4.s_addr)
862 notify_clients_external_ipv4_change (GNUNET_NO,
863 &mini_external_ipv4);
864 mini_external_ipv4.s_addr = 0;
865 break;
866 }
867}
868
869
870/**
871 * Task used to run `external-ip` to get our external IPv4
872 * address and pass it to NATed clients if possible.
873 *
874 * @param cls NULL
875 */
876static void
877run_external_ip (void *cls)
878{
879 probe_external_ip_task
880 = GNUNET_SCHEDULER_add_delayed (EXTERN_IP_RETRY_TIMEOUT,
881 &run_external_ip,
882 NULL);
883 if (NULL != probe_external_ip_op)
884 {
885 GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
886 probe_external_ip_op = NULL;
887 }
888 probe_external_ip_op
889 = GNUNET_NAT_mini_get_external_ipv4_ (&handle_external_ip,
890 NULL);
891}
892
893
894/**
725 * Task we run periodically to scan for network interfaces. 895 * Task we run periodically to scan for network interfaces.
726 * 896 *
727 * @param cls NULL 897 * @param cls NULL
@@ -731,6 +901,7 @@ run_scan (void *cls)
731{ 901{
732 struct IfcProcContext ifc_ctx; 902 struct IfcProcContext ifc_ctx;
733 int found; 903 int found;
904 int have_nat;
734 905
735 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ, 906 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
736 &run_scan, 907 &run_scan,
@@ -764,11 +935,14 @@ run_scan (void *cls)
764 } 935 }
765 936
766 /* add addresses that appeared */ 937 /* add addresses that appeared */
938 have_nat = GNUNET_NO;
767 for (struct LocalAddressList *pos = ifc_ctx.lal_head; 939 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
768 NULL != pos; 940 NULL != pos;
769 pos = pos->next) 941 pos = pos->next)
770 { 942 {
771 found = GNUNET_NO; 943 found = GNUNET_NO;
944 if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
945 have_nat = GNUNET_YES;
772 for (struct LocalAddressList *lal = lal_head; 946 for (struct LocalAddressList *lal = lal_head;
773 NULL != lal; 947 NULL != lal;
774 lal = lal->next) 948 lal = lal->next)
@@ -785,7 +959,30 @@ run_scan (void *cls)
785 notify_clients (pos, 959 notify_clients (pos,
786 GNUNET_YES); 960 GNUNET_YES);
787 } 961 }
788 962 if ( (GNUNET_YES == have_nat) &&
963 (GNUNET_YES == enable_upnp) &&
964 (NULL == probe_external_ip_task) &&
965 (NULL == probe_external_ip_op) )
966 {
967 probe_external_ip_task
968 = GNUNET_SCHEDULER_add_now (&run_external_ip,
969 NULL);
970 }
971 if ( (GNUNET_NO == have_nat) &&
972 (GNUNET_YES == enable_upnp) )
973 {
974 if (NULL != probe_external_ip_task)
975 {
976 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
977 probe_external_ip_task = NULL;
978 }
979 if (NULL != probe_external_ip_op)
980 {
981 GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
982 probe_external_ip_op = NULL;
983 }
984 }
985
789 destroy_lal (); 986 destroy_lal ();
790 lal_head = ifc_ctx.lal_head; 987 lal_head = ifc_ctx.lal_head;
791 lal_tail = ifc_ctx.lal_tail; 988 lal_tail = ifc_ctx.lal_tail;
@@ -882,6 +1079,13 @@ handle_register (void *cls,
882 ch, 1079 ch,
883 GNUNET_YES); 1080 GNUNET_YES);
884 } 1081 }
1082 /* Also consider IPv4 determined by `external-ip` */
1083 if (0 != mini_external_ipv4.s_addr)
1084 {
1085 check_notify_client_external_ipv4_change (&mini_external_ipv4,
1086 ch,
1087 GNUNET_YES);
1088 }
885 GNUNET_SERVICE_client_continue (ch->client); 1089 GNUNET_SERVICE_client_continue (ch->client);
886} 1090}
887 1091
@@ -1318,13 +1522,13 @@ update_enable_upnpc_option (struct AutoconfigContext *ac)
1318 case GNUNET_YES: 1522 case GNUNET_YES:
1319 GNUNET_CONFIGURATION_set_value_string (ac->c, 1523 GNUNET_CONFIGURATION_set_value_string (ac->c,
1320 "NAT", 1524 "NAT",
1321 "ENABLE_UPNPC", 1525 "ENABLE_UPNP",
1322 "YES"); 1526 "YES");
1323 break; 1527 break;
1324 case GNUNET_NO: 1528 case GNUNET_NO:
1325 GNUNET_CONFIGURATION_set_value_string (ac->c, 1529 GNUNET_CONFIGURATION_set_value_string (ac->c,
1326 "NAT", 1530 "NAT",
1327 "ENABLE_UPNPC", 1531 "ENABLE_UPNP",
1328 "NO"); 1532 "NO");
1329 break; 1533 break;
1330 case GNUNET_SYSERR: 1534 case GNUNET_SYSERR:
@@ -1358,6 +1562,9 @@ auto_external_result_cb (void *cls,
1358 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID: 1562 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
1359 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID: 1563 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
1360 case GNUNET_NAT_ERROR_IPC_FAILURE: 1564 case GNUNET_NAT_ERROR_IPC_FAILURE:
1565 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1566 "Disabling UPNPC: %d\n",
1567 (int) result);
1361 ac->enable_upnpc = GNUNET_NO; /* did not work */ 1568 ac->enable_upnpc = GNUNET_NO; /* did not work */
1362 break; 1569 break;
1363 default: 1570 default:
@@ -1387,6 +1594,7 @@ handle_autoconfig_request (void *cls,
1387 struct AutoconfigContext *ac; 1594 struct AutoconfigContext *ac;
1388 1595
1389 ac = GNUNET_new (struct AutoconfigContext); 1596 ac = GNUNET_new (struct AutoconfigContext);
1597 ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
1390 ac->ch = ch; 1598 ac->ch = ch;
1391 ac->c = GNUNET_CONFIGURATION_create (); 1599 ac->c = GNUNET_CONFIGURATION_create ();
1392 if (GNUNET_OK != 1600 if (GNUNET_OK !=