aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-02 09:47:37 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-02 09:47:37 +0100
commit1082a8e39e4f3d9b908b14995653ac262f640adb (patch)
tree7f9228753dd499d819916f69193804406e196fba /src
parentab31d0d5b13f9361f6312c4eadbb2054922b1a61 (diff)
downloadgnunet-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.h4
-rw-r--r--src/nat/gnunet-nat.c12
-rw-r--r--src/nat/gnunet-service-nat.c97
-rw-r--r--src/nat/gnunet-service-nat_helper.c17
-rw-r--r--src/nat/gnunet-service-nat_helper.h2
-rw-r--r--src/nat/nat.h14
-rw-r--r--src/nat/nat_api.c15
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 */
163typedef void 161typedef 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 */
346static void 344static void
347reversal_cb (void *cls, 345reversal_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 */
1028static void
1029reversal_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 */
287struct HelperContext * 293struct HelperContext *
288GN_start_gnunet_nat_server_ (const char *internal_address, 294GN_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 */
58struct HelperContext * 58struct HelperContext *
59GN_start_gnunet_nat_server_ (const char *internal_address, 59GN_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