diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-07 23:38:44 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-07 23:38:44 +0000 |
commit | 41d3e0863d932024f76d9085b53b84232efdf380 (patch) | |
tree | 40e23b7197629ea89e18351950276e521593d3eb /src | |
parent | 6429f7e56bcbe50863e05e284c0174f252ca1d5b (diff) | |
download | gnunet-41d3e0863d932024f76d9085b53b84232efdf380.tar.gz gnunet-41d3e0863d932024f76d9085b53b84232efdf380.zip |
-implement local address allocation
Diffstat (limited to 'src')
-rw-r--r-- | src/vpn/gnunet-service-vpn.c | 99 |
1 files changed, 92 insertions, 7 deletions
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c index 5ad5ff1db..f405bab78 100644 --- a/src/vpn/gnunet-service-vpn.c +++ b/src/vpn/gnunet-service-vpn.c | |||
@@ -27,7 +27,6 @@ | |||
27 | * @author Christian Grothoff | 27 | * @author Christian Grothoff |
28 | * | 28 | * |
29 | * TODO: | 29 | * TODO: |
30 | * - implement service message handlers | ||
31 | * - define mesh message formats between VPN and EXIT! | 30 | * - define mesh message formats between VPN and EXIT! |
32 | * - build mesh messages | 31 | * - build mesh messages |
33 | * - parse mesh replies | 32 | * - parse mesh replies |
@@ -297,6 +296,11 @@ static struct GNUNET_HELPER_Handle *helper_handle; | |||
297 | static char *vpn_argv[7]; | 296 | static char *vpn_argv[7]; |
298 | 297 | ||
299 | /** | 298 | /** |
299 | * Length of the prefix of the VPN's IPv6 network. | ||
300 | */ | ||
301 | static unsigned long long ipv6prefix; | ||
302 | |||
303 | /** | ||
300 | * Notification context for sending replies to clients. | 304 | * Notification context for sending replies to clients. |
301 | */ | 305 | */ |
302 | static struct GNUNET_SERVER_NotificationContext *nc; | 306 | static struct GNUNET_SERVER_NotificationContext *nc; |
@@ -1116,8 +1120,43 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1116 | static int | 1120 | static int |
1117 | allocate_v4_address (struct in_addr *v4) | 1121 | allocate_v4_address (struct in_addr *v4) |
1118 | { | 1122 | { |
1119 | // FIXME: implement! | 1123 | const char *ipv4addr = vpn_argv[4]; |
1120 | return GNUNET_SYSERR; | 1124 | const char *ipv4mask = vpn_argv[5]; |
1125 | struct in_addr addr; | ||
1126 | struct in_addr mask; | ||
1127 | struct in_addr rnd; | ||
1128 | GNUNET_HashCode key; | ||
1129 | unsigned int tries; | ||
1130 | |||
1131 | GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr)); | ||
1132 | GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask)); | ||
1133 | /* Given 192.168.0.1/255.255.0.0, we want a mask | ||
1134 | of '192.168.255.255', thus: */ | ||
1135 | mask.s_addr = addr.s_addr | ~mask.s_addr; | ||
1136 | tries = 0; | ||
1137 | do | ||
1138 | { | ||
1139 | tries++; | ||
1140 | if (tries > 16) | ||
1141 | { | ||
1142 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1143 | _("Failed to find unallocated IPv4 address in VPN's range\n")); | ||
1144 | return GNUNET_SYSERR; | ||
1145 | } | ||
1146 | /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */ | ||
1147 | rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1148 | UINT32_MAX); | ||
1149 | v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr; | ||
1150 | get_destination_key_from_ip (AF_INET, | ||
1151 | v4, | ||
1152 | &key); | ||
1153 | } | ||
1154 | while ( (GNUNET_YES == | ||
1155 | GNUNET_CONTAINER_multihashmap_contains (destination_map, | ||
1156 | &key)) || | ||
1157 | (v4->s_addr == addr.s_addr) || | ||
1158 | (v4->s_addr == mask.s_addr) ); | ||
1159 | return GNUNET_OK; | ||
1121 | } | 1160 | } |
1122 | 1161 | ||
1123 | 1162 | ||
@@ -1130,10 +1169,57 @@ allocate_v4_address (struct in_addr *v4) | |||
1130 | * GNUNET_SYSERR on error | 1169 | * GNUNET_SYSERR on error |
1131 | */ | 1170 | */ |
1132 | static int | 1171 | static int |
1133 | allocate_v6_address (struct in6_addr *v4) | 1172 | allocate_v6_address (struct in6_addr *v6) |
1134 | { | 1173 | { |
1135 | // FIXME: implement! | 1174 | const char *ipv6addr = vpn_argv[2]; |
1136 | return GNUNET_SYSERR; | 1175 | struct in6_addr addr; |
1176 | struct in6_addr mask; | ||
1177 | struct in6_addr rnd; | ||
1178 | int i; | ||
1179 | GNUNET_HashCode key; | ||
1180 | unsigned int tries; | ||
1181 | |||
1182 | GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr)); | ||
1183 | GNUNET_assert (ipv6prefix < 128); | ||
1184 | /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF, | ||
1185 | thus: */ | ||
1186 | mask = addr; | ||
1187 | for (i=127;i>=128-ipv6prefix;i--) | ||
1188 | mask.s6_addr[i / 8] |= (1 << (i % 8)); | ||
1189 | |||
1190 | /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */ | ||
1191 | tries = 0; | ||
1192 | do | ||
1193 | { | ||
1194 | tries++; | ||
1195 | if (tries > 16) | ||
1196 | { | ||
1197 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1198 | _("Failed to find unallocated IPv6 address in VPN's range\n")); | ||
1199 | return GNUNET_SYSERR; | ||
1200 | |||
1201 | } | ||
1202 | for (i=0;i<16;i++) | ||
1203 | { | ||
1204 | rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1205 | 256); | ||
1206 | v6->s6_addr[i] | ||
1207 | = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i]; | ||
1208 | } | ||
1209 | get_destination_key_from_ip (AF_INET6, | ||
1210 | v6, | ||
1211 | &key); | ||
1212 | } | ||
1213 | while ( (GNUNET_YES == | ||
1214 | GNUNET_CONTAINER_multihashmap_contains (destination_map, | ||
1215 | &key)) || | ||
1216 | (0 == memcmp (v6, | ||
1217 | &addr, | ||
1218 | sizeof (struct in6_addr))) || | ||
1219 | (0 == memcmp (v6, | ||
1220 | &mask, | ||
1221 | sizeof (struct in6_addr))) ); | ||
1222 | return GNUNET_OK; | ||
1137 | } | 1223 | } |
1138 | 1224 | ||
1139 | 1225 | ||
@@ -1640,7 +1726,6 @@ run (void *cls, | |||
1640 | char *ipv4mask; | 1726 | char *ipv4mask; |
1641 | struct in_addr v4; | 1727 | struct in_addr v4; |
1642 | struct in6_addr v6; | 1728 | struct in6_addr v6; |
1643 | unsigned long long ipv6prefix; | ||
1644 | 1729 | ||
1645 | cfg = cfg_; | 1730 | cfg = cfg_; |
1646 | if (GNUNET_OK != | 1731 | if (GNUNET_OK != |