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 | |
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')
-rw-r--r-- | src/include/gnunet_nat_service.h | 4 | ||||
-rw-r--r-- | src/nat/gnunet-nat.c | 12 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat.c | 97 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat_helper.c | 17 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat_helper.h | 2 | ||||
-rw-r--r-- | src/nat/nat.h | 14 | ||||
-rw-r--r-- | src/nat/nat_api.c | 15 |
7 files changed, 115 insertions, 46 deletions
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h index 4df17b531..d9ce0e6f9 100644 --- a/src/include/gnunet_nat_service.h +++ b/src/include/gnunet_nat_service.h | |||
@@ -155,15 +155,11 @@ typedef void | |||
155 | * reversal. | 155 | * reversal. |
156 | * | 156 | * |
157 | * @param cls closure | 157 | * @param cls closure |
158 | * @param local_addr address where we received the request | ||
159 | * @param local_addrlen actual length of the @a local_addr | ||
160 | * @param remote_addr public IP address of the other peer | 158 | * @param remote_addr public IP address of the other peer |
161 | * @param remote_addrlen actual length of the @a remote_addr | 159 | * @param remote_addrlen actual length of the @a remote_addr |
162 | */ | 160 | */ |
163 | typedef void | 161 | typedef void |
164 | (*GNUNET_NAT_ReversalCallback) (void *cls, | 162 | (*GNUNET_NAT_ReversalCallback) (void *cls, |
165 | const struct sockaddr *local_addr, | ||
166 | socklen_t local_addrlen, | ||
167 | const struct sockaddr *remote_addr, | 163 | const struct sockaddr *remote_addr, |
168 | socklen_t remote_addrlen); | 164 | socklen_t remote_addrlen); |
169 | 165 | ||
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c index 4d0ed5723..a145dc800 100644 --- a/src/nat/gnunet-nat.c +++ b/src/nat/gnunet-nat.c | |||
@@ -338,15 +338,11 @@ address_cb (void *cls, | |||
338 | * reversal. | 338 | * reversal. |
339 | * | 339 | * |
340 | * @param cls closure, NULL | 340 | * @param cls closure, NULL |
341 | * @param local_addr address where we received the request | ||
342 | * @param local_addrlen actual length of the @a local_addr | ||
343 | * @param remote_addr public IP address of the other peer | 341 | * @param remote_addr public IP address of the other peer |
344 | * @param remote_addrlen actual length of the @a remote_addr | 342 | * @param remote_addrlen actual length of the @a remote_addr |
345 | */ | 343 | */ |
346 | static void | 344 | static void |
347 | reversal_cb (void *cls, | 345 | reversal_cb (void *cls, |
348 | const struct sockaddr *local_addr, | ||
349 | socklen_t local_addrlen, | ||
350 | const struct sockaddr *remote_addr, | 346 | const struct sockaddr *remote_addr, |
351 | socklen_t remote_addrlen) | 347 | socklen_t remote_addrlen) |
352 | { | 348 | { |
@@ -580,6 +576,14 @@ run (void *cls, | |||
580 | (listen_reversal) ? &reversal_cb : NULL, | 576 | (listen_reversal) ? &reversal_cb : NULL, |
581 | NULL); | 577 | NULL); |
582 | } | 578 | } |
579 | else if (listen_reversal) | ||
580 | { | ||
581 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
582 | "Use of `-W` only effective in combination with `-i`\n"); | ||
583 | global_ret = 1; | ||
584 | GNUNET_SCHEDULER_shutdown (); | ||
585 | return; | ||
586 | } | ||
583 | 587 | ||
584 | if (NULL != remote_addr) | 588 | if (NULL != remote_addr) |
585 | { | 589 | { |
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: |
diff --git a/src/nat/gnunet-service-nat_helper.c b/src/nat/gnunet-service-nat_helper.c index 379603ae2..febc3c2dd 100644 --- a/src/nat/gnunet-service-nat_helper.c +++ b/src/nat/gnunet-service-nat_helper.c | |||
@@ -39,7 +39,7 @@ struct HelperContext | |||
39 | /** | 39 | /** |
40 | * IP address we pass to the NAT helper. | 40 | * IP address we pass to the NAT helper. |
41 | */ | 41 | */ |
42 | const char *internal_address; | 42 | struct in_addr internal_address; |
43 | 43 | ||
44 | /** | 44 | /** |
45 | * Function to call if we receive a reversal request. | 45 | * Function to call if we receive a reversal request. |
@@ -220,6 +220,7 @@ restart_nat_server (void *cls) | |||
220 | { | 220 | { |
221 | struct HelperContext *h = cls; | 221 | struct HelperContext *h = cls; |
222 | char *binary; | 222 | char *binary; |
223 | char ia[INET_ADDRSTRLEN]; | ||
223 | 224 | ||
224 | h->server_read_task = NULL; | 225 | h->server_read_task = NULL; |
225 | h->server_stdout | 226 | h->server_stdout |
@@ -232,10 +233,15 @@ restart_nat_server (void *cls) | |||
232 | try_again (h); | 233 | try_again (h); |
233 | return; | 234 | return; |
234 | } | 235 | } |
236 | GNUNET_assert (NULL != | ||
237 | inet_ntop (AF_INET, | ||
238 | &h->internal_address, | ||
239 | ia, | ||
240 | sizeof (ia))); | ||
235 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 241 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
236 | "Starting `%s' at `%s'\n", | 242 | "Starting `%s' at `%s'\n", |
237 | "gnunet-helper-nat-server", | 243 | "gnunet-helper-nat-server", |
238 | h->internal_address); | 244 | ia); |
239 | /* Start the server process */ | 245 | /* Start the server process */ |
240 | binary | 246 | binary |
241 | = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); | 247 | = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); |
@@ -247,7 +253,7 @@ restart_nat_server (void *cls) | |||
247 | NULL, | 253 | NULL, |
248 | binary, | 254 | binary, |
249 | "gnunet-helper-nat-server", | 255 | "gnunet-helper-nat-server", |
250 | h->internal_address, | 256 | ia, |
251 | NULL); | 257 | NULL); |
252 | GNUNET_free (binary); | 258 | GNUNET_free (binary); |
253 | if (NULL == h->server_proc) | 259 | if (NULL == h->server_proc) |
@@ -285,7 +291,7 @@ restart_nat_server (void *cls) | |||
285 | * @return NULL on error | 291 | * @return NULL on error |
286 | */ | 292 | */ |
287 | struct HelperContext * | 293 | struct HelperContext * |
288 | GN_start_gnunet_nat_server_ (const char *internal_address, | 294 | GN_start_gnunet_nat_server_ (const struct in_addr *internal_address, |
289 | GN_ReversalCallback cb, | 295 | GN_ReversalCallback cb, |
290 | void *cb_cls) | 296 | void *cb_cls) |
291 | { | 297 | { |
@@ -294,8 +300,7 @@ GN_start_gnunet_nat_server_ (const char *internal_address, | |||
294 | h = GNUNET_new (struct HelperContext); | 300 | h = GNUNET_new (struct HelperContext); |
295 | h->cb = cb; | 301 | h->cb = cb; |
296 | h->cb_cls = cb_cls; | 302 | h->cb_cls = cb_cls; |
297 | h->internal_address | 303 | h->internal_address = *internal_address; |
298 | = internal_address; | ||
299 | if (NULL == h->server_stdout) | 304 | if (NULL == h->server_stdout) |
300 | { | 305 | { |
301 | GN_stop_gnunet_nat_server_ (h); | 306 | GN_stop_gnunet_nat_server_ (h); |
diff --git a/src/nat/gnunet-service-nat_helper.h b/src/nat/gnunet-service-nat_helper.h index d3f1a757c..026526b05 100644 --- a/src/nat/gnunet-service-nat_helper.h +++ b/src/nat/gnunet-service-nat_helper.h | |||
@@ -56,7 +56,7 @@ typedef void | |||
56 | * @return NULL on error | 56 | * @return NULL on error |
57 | */ | 57 | */ |
58 | struct HelperContext * | 58 | struct HelperContext * |
59 | GN_start_gnunet_nat_server_ (const char *internal_address, | 59 | GN_start_gnunet_nat_server_ (const struct in_addr *internal_address, |
60 | GN_ReversalCallback cb, | 60 | GN_ReversalCallback cb, |
61 | void *cb_cls); | 61 | void *cb_cls); |
62 | 62 | ||
diff --git a/src/nat/nat.h b/src/nat/nat.h index 3356b19ce..5cb1c1050 100644 --- a/src/nat/nat.h +++ b/src/nat/nat.h | |||
@@ -191,19 +191,7 @@ struct GNUNET_NAT_ConnectionReversalRequestedMessage | |||
191 | */ | 191 | */ |
192 | struct GNUNET_MessageHeader header; | 192 | struct GNUNET_MessageHeader header; |
193 | 193 | ||
194 | /** | 194 | /* followed by a `struct sockaddr_in` */ |
195 | * Size of the local address where we received the request, in NBO. | ||
196 | */ | ||
197 | uint16_t local_addr_size; | ||
198 | |||
199 | /** | ||
200 | * Size of the remote address making the request, in NBO. | ||
201 | */ | ||
202 | uint16_t remote_addr_size; | ||
203 | |||
204 | /* followed by a `struct sockaddr` of @e local_addr_size bytes */ | ||
205 | |||
206 | /* followed by a `struct sockaddr` of @e remote_addr_size bytes */ | ||
207 | 195 | ||
208 | }; | 196 | }; |
209 | 197 | ||
diff --git a/src/nat/nat_api.c b/src/nat/nat_api.c index 481bc6fde..ab36d6162 100644 --- a/src/nat/nat_api.c +++ b/src/nat/nat_api.c | |||
@@ -176,14 +176,7 @@ check_connection_reversal_request (void *cls, | |||
176 | { | 176 | { |
177 | if (ntohs (crm->header.size) != | 177 | if (ntohs (crm->header.size) != |
178 | sizeof (*crm) + | 178 | sizeof (*crm) + |
179 | ntohs (crm->local_addr_size) + | 179 | sizeof (struct sockaddr_in) ) |
180 | ntohs (crm->remote_addr_size) ) | ||
181 | { | ||
182 | GNUNET_break (0); | ||
183 | return GNUNET_SYSERR; | ||
184 | } | ||
185 | if ( (sizeof (struct sockaddr_in) != ntohs (crm->local_addr_size)) || | ||
186 | (sizeof (struct sockaddr_in) != ntohs (crm->remote_addr_size)) ) | ||
187 | { | 180 | { |
188 | GNUNET_break (0); | 181 | GNUNET_break (0); |
189 | return GNUNET_SYSERR; | 182 | return GNUNET_SYSERR; |
@@ -203,13 +196,9 @@ handle_connection_reversal_request (void *cls, | |||
203 | const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm) | 196 | const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm) |
204 | { | 197 | { |
205 | struct GNUNET_NAT_Handle *nh = cls; | 198 | struct GNUNET_NAT_Handle *nh = cls; |
206 | const struct sockaddr_in *local_sa = (const struct sockaddr_in *) &crm[1]; | ||
207 | const struct sockaddr_in *remote_sa = &local_sa[1]; | ||
208 | 199 | ||
209 | nh->reversal_callback (nh->callback_cls, | 200 | nh->reversal_callback (nh->callback_cls, |
210 | (const struct sockaddr *) local_sa, | 201 | (const struct sockaddr *) &crm[1], |
211 | sizeof (struct sockaddr_in), | ||
212 | (const struct sockaddr *) remote_sa, | ||
213 | sizeof (struct sockaddr_in)); | 202 | sizeof (struct sockaddr_in)); |
214 | } | 203 | } |
215 | 204 | ||