summaryrefslogtreecommitdiff
path: root/src/nat/gnunet-service-nat.c
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/nat/gnunet-service-nat.c
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/nat/gnunet-service-nat.c')
-rw-r--r--src/nat/gnunet-service-nat.c97
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 */
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: