diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-02 09:47:37 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-02 09:47:37 +0100 |
commit | 1082a8e39e4f3d9b908b14995653ac262f640adb (patch) | |
tree | 7f9228753dd499d819916f69193804406e196fba /src/nat/gnunet-service-nat.c | |
parent | ab31d0d5b13f9361f6312c4eadbb2054922b1a61 (diff) | |
download | gnunet-1082a8e39e4f3d9b908b14995653ac262f640adb.tar.gz gnunet-1082a8e39e4f3d9b908b14995653ac262f640adb.zip |
improve/fix handling of NAT server logic for ICMP-based autonomous NAT traversal
Diffstat (limited to 'src/nat/gnunet-service-nat.c')
-rw-r--r-- | src/nat/gnunet-service-nat.c | 97 |
1 files changed, 92 insertions, 5 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index 762175437..b547e773a 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2016 GNUnet e.V. | 3 | Copyright (C) 2016, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -176,6 +176,12 @@ struct LocalAddressList | |||
176 | struct LocalAddressList *prev; | 176 | struct LocalAddressList *prev; |
177 | 177 | ||
178 | /** | 178 | /** |
179 | * Context for a gnunet-helper-nat-server used to listen | ||
180 | * for ICMP messages to this client for connection reversal. | ||
181 | */ | ||
182 | struct HelperContext *hc; | ||
183 | |||
184 | /** | ||
179 | * The address itself (i.e. `struct sockaddr_in` or `struct | 185 | * The address itself (i.e. `struct sockaddr_in` or `struct |
180 | * sockaddr_in6`, in the respective byte order). | 186 | * sockaddr_in6`, in the respective byte order). |
181 | */ | 187 | */ |
@@ -395,6 +401,11 @@ destroy_lal () | |||
395 | GNUNET_CONTAINER_DLL_remove (lal_head, | 401 | GNUNET_CONTAINER_DLL_remove (lal_head, |
396 | lal_tail, | 402 | lal_tail, |
397 | lal); | 403 | lal); |
404 | if (NULL != lal->hc) | ||
405 | { | ||
406 | GN_stop_gnunet_nat_server_ (lal->hc); | ||
407 | lal->hc = NULL; | ||
408 | } | ||
398 | GNUNET_free (lal); | 409 | GNUNET_free (lal); |
399 | } | 410 | } |
400 | } | 411 | } |
@@ -718,10 +729,12 @@ check_notify_client (struct LocalAddressList *delta, | |||
718 | GNUNET_memcpy (&v4, | 729 | GNUNET_memcpy (&v4, |
719 | &delta->addr, | 730 | &delta->addr, |
720 | alen); | 731 | alen); |
732 | |||
733 | /* Check for client notifications */ | ||
721 | for (unsigned int i=0;i<ch->num_caddrs;i++) | 734 | for (unsigned int i=0;i<ch->num_caddrs;i++) |
722 | { | 735 | { |
723 | const struct sockaddr_in *c4; | 736 | const struct sockaddr_in *c4; |
724 | 737 | ||
725 | if (AF_INET != ch->caddrs[i].ss.ss_family) | 738 | if (AF_INET != ch->caddrs[i].ss.ss_family) |
726 | return; /* IPv4 not relevant */ | 739 | return; /* IPv4 not relevant */ |
727 | c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss; | 740 | c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss; |
@@ -890,7 +903,7 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4, | |||
890 | 903 | ||
891 | /* (3) notify client of change */ | 904 | /* (3) notify client of change */ |
892 | notify_client (is_nat_v4 (v4) | 905 | notify_client (is_nat_v4 (v4) |
893 | ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN_PRIVATE | 906 | ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN |
894 | : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL, | 907 | : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL, |
895 | ch, | 908 | ch, |
896 | add, | 909 | add, |
@@ -1006,6 +1019,65 @@ run_external_ip (void *cls) | |||
1006 | 1019 | ||
1007 | 1020 | ||
1008 | /** | 1021 | /** |
1022 | * We got a connection reversal request from another peer. | ||
1023 | * Notify applicable clients. | ||
1024 | * | ||
1025 | * @param cls closure with the `struct LocalAddressList` | ||
1026 | * @param ra IP address of the peer who wants us to connect to it | ||
1027 | */ | ||
1028 | static void | ||
1029 | reversal_callback (void *cls, | ||
1030 | const struct sockaddr_in *ra) | ||
1031 | { | ||
1032 | struct LocalAddressList *lal = cls; | ||
1033 | const struct sockaddr_in *l4; | ||
1034 | |||
1035 | GNUNET_assert (AF_INET == lal->af); | ||
1036 | l4 = (const struct sockaddr_in *) &lal->addr; | ||
1037 | for (struct ClientHandle *ch = ch_head; | ||
1038 | NULL != ch; | ||
1039 | ch = ch->next) | ||
1040 | { | ||
1041 | struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm; | ||
1042 | struct GNUNET_MQ_Envelope *env; | ||
1043 | int match; | ||
1044 | |||
1045 | /* Check if client is in applicable range for ICMP NAT traversal | ||
1046 | for this local address */ | ||
1047 | if (! ch->natted_address) | ||
1048 | continue; | ||
1049 | match = GNUNET_NO; | ||
1050 | for (unsigned int i=0;i<ch->num_caddrs;i++) | ||
1051 | { | ||
1052 | struct ClientAddress *ca = &ch->caddrs[i]; | ||
1053 | const struct sockaddr_in *c4; | ||
1054 | |||
1055 | if (AF_INET != ca->ss.ss_family) | ||
1056 | continue; | ||
1057 | c4 = (const struct sockaddr_in *) &ca->ss; | ||
1058 | if ( (0 != c4->sin_addr.s_addr) && | ||
1059 | (l4->sin_addr.s_addr != c4->sin_addr.s_addr) ) | ||
1060 | continue; | ||
1061 | match = GNUNET_YES; | ||
1062 | break; | ||
1063 | } | ||
1064 | if (! match) | ||
1065 | continue; | ||
1066 | |||
1067 | /* Notify applicable client about connection reversal request */ | ||
1068 | env = GNUNET_MQ_msg_extra (crrm, | ||
1069 | sizeof (struct sockaddr_in), | ||
1070 | GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED); | ||
1071 | GNUNET_memcpy (&crrm[1], | ||
1072 | ra, | ||
1073 | sizeof (struct sockaddr_in)); | ||
1074 | GNUNET_MQ_send (ch->mq, | ||
1075 | env); | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | /** | ||
1009 | * Task we run periodically to scan for network interfaces. | 1081 | * Task we run periodically to scan for network interfaces. |
1010 | * | 1082 | * |
1011 | * @param cls NULL | 1083 | * @param cls NULL |
@@ -1041,7 +1113,11 @@ run_scan (void *cls) | |||
1041 | (AF_INET == lal->af) | 1113 | (AF_INET == lal->af) |
1042 | ? sizeof (struct sockaddr_in) | 1114 | ? sizeof (struct sockaddr_in) |
1043 | : sizeof (struct sockaddr_in6))) ) | 1115 | : sizeof (struct sockaddr_in6))) ) |
1116 | { | ||
1044 | found = GNUNET_YES; | 1117 | found = GNUNET_YES; |
1118 | pos->hc = lal->hc; | ||
1119 | lal->hc = NULL; | ||
1120 | } | ||
1045 | } | 1121 | } |
1046 | if (GNUNET_NO == found) | 1122 | if (GNUNET_NO == found) |
1047 | notify_clients (lal, | 1123 | notify_clients (lal, |
@@ -1072,6 +1148,17 @@ run_scan (void *cls) | |||
1072 | if (GNUNET_NO == found) | 1148 | if (GNUNET_NO == found) |
1073 | notify_clients (pos, | 1149 | notify_clients (pos, |
1074 | GNUNET_YES); | 1150 | GNUNET_YES); |
1151 | if ( (AF_INET == pos->af) && | ||
1152 | (NULL == pos->hc) && | ||
1153 | (0 != (GNUNET_NAT_AC_LAN & pos->ac)) ) | ||
1154 | { | ||
1155 | const struct sockaddr_in *s4 | ||
1156 | = (const struct sockaddr_in *) &pos->addr; | ||
1157 | |||
1158 | pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr, | ||
1159 | &reversal_callback, | ||
1160 | pos); | ||
1161 | } | ||
1075 | } | 1162 | } |
1076 | if ( (GNUNET_YES == have_nat) && | 1163 | if ( (GNUNET_YES == have_nat) && |
1077 | (GNUNET_YES == enable_upnp) && | 1164 | (GNUNET_YES == enable_upnp) && |
@@ -1164,12 +1251,12 @@ upnp_addr_change_cb (void *cls, | |||
1164 | { | 1251 | { |
1165 | case AF_INET: | 1252 | case AF_INET: |
1166 | ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr) | 1253 | ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr) |
1167 | ? GNUNET_NAT_AC_LAN_PRIVATE | 1254 | ? GNUNET_NAT_AC_LAN |
1168 | : GNUNET_NAT_AC_EXTERN; | 1255 | : GNUNET_NAT_AC_EXTERN; |
1169 | break; | 1256 | break; |
1170 | case AF_INET6: | 1257 | case AF_INET6: |
1171 | ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr) | 1258 | ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr) |
1172 | ? GNUNET_NAT_AC_LAN_PRIVATE | 1259 | ? GNUNET_NAT_AC_LAN |
1173 | : GNUNET_NAT_AC_EXTERN; | 1260 | : GNUNET_NAT_AC_EXTERN; |
1174 | break; | 1261 | break; |
1175 | default: | 1262 | default: |