diff options
Diffstat (limited to 'src/nat/gnunet-service-nat.c')
-rw-r--r-- | src/nat/gnunet-service-nat.c | 1168 |
1 files changed, 480 insertions, 688 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index e29f37108..98d87262e 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c | |||
@@ -23,20 +23,16 @@ | |||
23 | * @brief network address translation traversal service | 23 | * @brief network address translation traversal service |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | 25 | * |
26 | * The purpose of this service is to enable transports to | 26 | * The purpose of this service is to enable transports to |
27 | * traverse NAT routers, by providing traversal options and | 27 | * traverse NAT routers, by providing traversal options and |
28 | * knowledge about the local network topology. | 28 | * knowledge about the local network topology. |
29 | * | 29 | * |
30 | * TODO: | 30 | * TODO: |
31 | * - test and document (!) ICMP based NAT traversal | 31 | * - migrate test cases to new NAT service |
32 | * - implement manual hole punching support (incl. DNS | 32 | * - add new traceroute-based logic for external IP detection |
33 | * lookup for DynDNS setups!) | 33 | * |
34 | * - implement "more" autoconfig: | ||
35 | * re-work gnunet-nat-server & integrate! | ||
36 | * + test manually punched NAT (how?) | ||
37 | * - implement & test STUN processing to classify NAT; | 34 | * - implement & test STUN processing to classify NAT; |
38 | * basically, open port & try different methods. | 35 | * basically, open port & try different methods. |
39 | * - implement NEW logic for external IP detection | ||
40 | */ | 36 | */ |
41 | #include "platform.h" | 37 | #include "platform.h" |
42 | #include <math.h> | 38 | #include <math.h> |
@@ -44,7 +40,10 @@ | |||
44 | #include "gnunet_protocols.h" | 40 | #include "gnunet_protocols.h" |
45 | #include "gnunet_signatures.h" | 41 | #include "gnunet_signatures.h" |
46 | #include "gnunet_statistics_service.h" | 42 | #include "gnunet_statistics_service.h" |
43 | #include "gnunet_resolver_service.h" | ||
47 | #include "gnunet_nat_service.h" | 44 | #include "gnunet_nat_service.h" |
45 | #include "gnunet-service-nat.h" | ||
46 | #include "gnunet-service-nat_externalip.h" | ||
48 | #include "gnunet-service-nat_stun.h" | 47 | #include "gnunet-service-nat_stun.h" |
49 | #include "gnunet-service-nat_mini.h" | 48 | #include "gnunet-service-nat_mini.h" |
50 | #include "gnunet-service-nat_helper.h" | 49 | #include "gnunet-service-nat_helper.h" |
@@ -64,26 +63,13 @@ | |||
64 | #define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | 63 | #define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) |
65 | 64 | ||
66 | /** | 65 | /** |
67 | * How long do we wait until we re-try running `external-ip` if the | 66 | * How often do we scan for changes in how our external (dyndns) hostname resolves? |
68 | * command failed to terminate nicely? | ||
69 | */ | 67 | */ |
70 | #define EXTERN_IP_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) | 68 | #define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7) |
71 | 69 | ||
72 | /** | ||
73 | * How long do we wait until we re-try running `external-ip` if the | ||
74 | * command failed (but terminated)? | ||
75 | */ | ||
76 | #define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) | ||
77 | 70 | ||
78 | /** | 71 | /** |
79 | * How long do we wait until we re-try running `external-ip` if the | 72 | * Information we track per client address. |
80 | * command succeeded? | ||
81 | */ | ||
82 | #define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Information we track per client address. | ||
87 | */ | 73 | */ |
88 | struct ClientAddress | 74 | struct ClientAddress |
89 | { | 75 | { |
@@ -98,7 +84,54 @@ struct ClientAddress | |||
98 | * pending. | 84 | * pending. |
99 | */ | 85 | */ |
100 | struct GNUNET_NAT_MiniHandle *mh; | 86 | struct GNUNET_NAT_MiniHandle *mh; |
101 | 87 | ||
88 | }; | ||
89 | |||
90 | |||
91 | /** | ||
92 | * List of local addresses this system has. | ||
93 | */ | ||
94 | struct LocalAddressList | ||
95 | { | ||
96 | /** | ||
97 | * This is a linked list. | ||
98 | */ | ||
99 | struct LocalAddressList *next; | ||
100 | |||
101 | /** | ||
102 | * Previous entry. | ||
103 | */ | ||
104 | struct LocalAddressList *prev; | ||
105 | |||
106 | /** | ||
107 | * Context for a gnunet-helper-nat-server used to listen | ||
108 | * for ICMP messages to this client for connection reversal. | ||
109 | */ | ||
110 | struct HelperContext *hc; | ||
111 | |||
112 | /** | ||
113 | * The address itself (i.e. `struct sockaddr_in` or `struct | ||
114 | * sockaddr_in6`, in the respective byte order). | ||
115 | */ | ||
116 | struct sockaddr_storage addr; | ||
117 | |||
118 | /** | ||
119 | * Address family. (FIXME: redundant, addr.ss_family! Remove!?) | ||
120 | */ | ||
121 | int af; | ||
122 | |||
123 | /** | ||
124 | * #GNUNET_YES if we saw this one in the previous iteration, | ||
125 | * but not in the current iteration and thus might need to | ||
126 | * remove it at the end. | ||
127 | */ | ||
128 | int old; | ||
129 | |||
130 | /** | ||
131 | * What type of address is this? | ||
132 | */ | ||
133 | enum GNUNET_NAT_AddressClass ac; | ||
134 | |||
102 | }; | 135 | }; |
103 | 136 | ||
104 | 137 | ||
@@ -112,7 +145,7 @@ struct ClientHandle | |||
112 | * Kept in a DLL. | 145 | * Kept in a DLL. |
113 | */ | 146 | */ |
114 | struct ClientHandle *next; | 147 | struct ClientHandle *next; |
115 | 148 | ||
116 | /** | 149 | /** |
117 | * Kept in a DLL. | 150 | * Kept in a DLL. |
118 | */ | 151 | */ |
@@ -120,7 +153,7 @@ struct ClientHandle | |||
120 | 153 | ||
121 | /** | 154 | /** |
122 | * Underlying handle for this client with the service. | 155 | * Underlying handle for this client with the service. |
123 | */ | 156 | */ |
124 | struct GNUNET_SERVICE_Client *client; | 157 | struct GNUNET_SERVICE_Client *client; |
125 | 158 | ||
126 | /** | 159 | /** |
@@ -136,74 +169,70 @@ struct ClientHandle | |||
136 | /** | 169 | /** |
137 | * External DNS name and port given by user due to manual | 170 | * External DNS name and port given by user due to manual |
138 | * hole punching. Special DNS name 'AUTO' is used to indicate | 171 | * hole punching. Special DNS name 'AUTO' is used to indicate |
139 | * desire for automatic determination of the external IP | 172 | * desire for automatic determination of the external IP |
140 | * (instead of DNS or manual configuration, i.e. to be used | 173 | * (instead of DNS or manual configuration, i.e. to be used |
141 | * if the IP keeps changing and we have no DynDNS, but we do | 174 | * if the IP keeps changing and we have no DynDNS, but we do |
142 | * have a hole punched). | 175 | * have a hole punched). |
143 | */ | 176 | */ |
144 | char *hole_external; | 177 | char *hole_external; |
145 | 178 | ||
146 | /** | 179 | /** |
147 | * What does this client care about? | 180 | * Name of the configuration section this client cares about. |
148 | */ | 181 | */ |
149 | enum GNUNET_NAT_RegisterFlags flags; | 182 | char *section_name; |
150 | 183 | ||
151 | /** | 184 | /** |
152 | * Is any of the @e caddrs in a reserved subnet for NAT? | 185 | * Task for periodically re-running the @e ext_dns DNS lookup. |
153 | */ | 186 | */ |
154 | int natted_address; | 187 | struct GNUNET_SCHEDULER_Task *ext_dns_task; |
155 | 188 | ||
156 | /** | 189 | /** |
157 | * Number of addresses that this service is bound to. | 190 | * Handle for (DYN)DNS lookup of our external IP as given in |
158 | * Length of the @e caddrs array. | 191 | * @e hole_external. |
159 | */ | 192 | */ |
160 | uint16_t num_caddrs; | 193 | struct GNUNET_RESOLVER_RequestHandle *ext_dns; |
161 | 194 | ||
162 | /** | 195 | /** |
163 | * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP. | 196 | * Handle for monitoring external IP changes. |
164 | */ | 197 | */ |
165 | uint8_t proto; | 198 | struct GN_ExternalIPMonitor *external_monitor; |
166 | |||
167 | }; | ||
168 | 199 | ||
200 | /** | ||
201 | * DLL of external IP addresses as given in @e hole_external. | ||
202 | */ | ||
203 | struct LocalAddressList *ext_addr_head; | ||
169 | 204 | ||
170 | /** | ||
171 | * List of local addresses this system has. | ||
172 | */ | ||
173 | struct LocalAddressList | ||
174 | { | ||
175 | /** | 205 | /** |
176 | * This is a linked list. | 206 | * DLL of external IP addresses as given in @e hole_external. |
177 | */ | 207 | */ |
178 | struct LocalAddressList *next; | 208 | struct LocalAddressList *ext_addr_tail; |
179 | 209 | ||
180 | /** | 210 | /** |
181 | * Previous entry. | 211 | * Port number we found in @e hole_external. |
182 | */ | 212 | */ |
183 | struct LocalAddressList *prev; | 213 | uint16_t ext_dns_port; |
184 | 214 | ||
185 | /** | 215 | /** |
186 | * Context for a gnunet-helper-nat-server used to listen | 216 | * What does this client care about? |
187 | * for ICMP messages to this client for connection reversal. | ||
188 | */ | 217 | */ |
189 | struct HelperContext *hc; | 218 | enum GNUNET_NAT_RegisterFlags flags; |
190 | 219 | ||
191 | /** | 220 | /** |
192 | * The address itself (i.e. `struct sockaddr_in` or `struct | 221 | * Is any of the @e caddrs in a reserved subnet for NAT? |
193 | * sockaddr_in6`, in the respective byte order). | ||
194 | */ | 222 | */ |
195 | struct sockaddr_storage addr; | 223 | int natted_address; |
196 | 224 | ||
197 | /** | 225 | /** |
198 | * Address family. | 226 | * Number of addresses that this service is bound to. |
227 | * Length of the @e caddrs array. | ||
199 | */ | 228 | */ |
200 | int af; | 229 | uint16_t num_caddrs; |
201 | 230 | ||
202 | /** | 231 | /** |
203 | * What type of address is this? | 232 | * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP. |
204 | */ | 233 | */ |
205 | enum GNUNET_NAT_AddressClass ac; | 234 | uint8_t proto; |
206 | 235 | ||
207 | }; | 236 | }; |
208 | 237 | ||
209 | 238 | ||
@@ -214,12 +243,12 @@ struct StunExternalIP | |||
214 | { | 243 | { |
215 | /** | 244 | /** |
216 | * Kept in a DLL. | 245 | * Kept in a DLL. |
217 | */ | 246 | */ |
218 | struct StunExternalIP *next; | 247 | struct StunExternalIP *next; |
219 | 248 | ||
220 | /** | 249 | /** |
221 | * Kept in a DLL. | 250 | * Kept in a DLL. |
222 | */ | 251 | */ |
223 | struct StunExternalIP *prev; | 252 | struct StunExternalIP *prev; |
224 | 253 | ||
225 | /** | 254 | /** |
@@ -228,13 +257,13 @@ struct StunExternalIP | |||
228 | struct GNUNET_SCHEDULER_Task *timeout_task; | 257 | struct GNUNET_SCHEDULER_Task *timeout_task; |
229 | 258 | ||
230 | /** | 259 | /** |
231 | * Our external IP address as reported by the | 260 | * Our external IP address as reported by the |
232 | * STUN server. | 261 | * STUN server. |
233 | */ | 262 | */ |
234 | struct sockaddr_in external_addr; | 263 | struct sockaddr_in external_addr; |
235 | 264 | ||
236 | /** | 265 | /** |
237 | * Address of the reporting STUN server. Used to | 266 | * Address of the reporting STUN server. Used to |
238 | * detect when a STUN server changes its opinion | 267 | * detect when a STUN server changes its opinion |
239 | * to more quickly remove stale results. | 268 | * to more quickly remove stale results. |
240 | */ | 269 | */ |
@@ -248,83 +277,14 @@ struct StunExternalIP | |||
248 | 277 | ||
249 | 278 | ||
250 | /** | 279 | /** |
251 | * Context for autoconfiguration operations. | 280 | * Timeout to use when STUN data is considered stale. |
252 | */ | ||
253 | struct AutoconfigContext | ||
254 | { | ||
255 | /** | ||
256 | * Kept in a DLL. | ||
257 | */ | ||
258 | struct AutoconfigContext *prev; | ||
259 | |||
260 | /** | ||
261 | * Kept in a DLL. | ||
262 | */ | ||
263 | struct AutoconfigContext *next; | ||
264 | |||
265 | /** | ||
266 | * Which client asked the question. | ||
267 | */ | ||
268 | struct ClientHandle *ch; | ||
269 | |||
270 | /** | ||
271 | * Configuration we are creating. | ||
272 | */ | ||
273 | struct GNUNET_CONFIGURATION_Handle *c; | ||
274 | |||
275 | /** | ||
276 | * Original configuration (for diffing). | ||
277 | */ | ||
278 | struct GNUNET_CONFIGURATION_Handle *orig; | ||
279 | |||
280 | /** | ||
281 | * Timeout task to force termination. | ||
282 | */ | ||
283 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
284 | |||
285 | /** | ||
286 | * What type of system are we on? | ||
287 | */ | ||
288 | char *system_type; | ||
289 | |||
290 | /** | ||
291 | * Handle to activity to probe for our external IP. | ||
292 | */ | ||
293 | struct GNUNET_NAT_ExternalHandle *probe_external; | ||
294 | |||
295 | /** | ||
296 | * #GNUNET_YES if upnpc should be used, | ||
297 | * #GNUNET_NO if upnpc should not be used, | ||
298 | * #GNUNET_SYSERR if we should simply not change the option. | ||
299 | */ | ||
300 | int enable_upnpc; | ||
301 | |||
302 | /** | ||
303 | * Status code to return to the client. | ||
304 | */ | ||
305 | enum GNUNET_NAT_StatusCode status_code; | ||
306 | |||
307 | /** | ||
308 | * NAT type to return to the client. | ||
309 | */ | ||
310 | enum GNUNET_NAT_Type type; | ||
311 | }; | ||
312 | |||
313 | |||
314 | /** | ||
315 | * DLL of our autoconfiguration operations. | ||
316 | */ | ||
317 | static struct AutoconfigContext *ac_head; | ||
318 | |||
319 | /** | ||
320 | * DLL of our autoconfiguration operations. | ||
321 | */ | 281 | */ |
322 | static struct AutoconfigContext *ac_tail; | 282 | static struct GNUNET_TIME_Relative stun_stale_timeout; |
323 | 283 | ||
324 | /** | 284 | /** |
325 | * Timeout to use when STUN data is considered stale. | 285 | * How often do we scan for changes in how our external (dyndns) hostname resolves? |
326 | */ | 286 | */ |
327 | static struct GNUNET_TIME_Relative stun_stale_timeout; | 287 | static struct GNUNET_TIME_Relative dyndns_frequency; |
328 | 288 | ||
329 | /** | 289 | /** |
330 | * Handle to our current configuration. | 290 | * Handle to our current configuration. |
@@ -345,7 +305,7 @@ static struct GNUNET_SCHEDULER_Task *scan_task; | |||
345 | * Head of client DLL. | 305 | * Head of client DLL. |
346 | */ | 306 | */ |
347 | static struct ClientHandle *ch_head; | 307 | static struct ClientHandle *ch_head; |
348 | 308 | ||
349 | /** | 309 | /** |
350 | * Tail of client DLL. | 310 | * Tail of client DLL. |
351 | */ | 311 | */ |
@@ -363,36 +323,19 @@ static struct LocalAddressList *lal_tail; | |||
363 | 323 | ||
364 | /** | 324 | /** |
365 | * Kept in a DLL. | 325 | * Kept in a DLL. |
366 | */ | 326 | */ |
367 | static struct StunExternalIP *se_head; | 327 | static struct StunExternalIP *se_head; |
368 | 328 | ||
369 | /** | 329 | /** |
370 | * Kept in a DLL. | 330 | * Kept in a DLL. |
371 | */ | 331 | */ |
372 | static struct StunExternalIP *se_tail; | 332 | static struct StunExternalIP *se_tail; |
373 | 333 | ||
374 | /** | 334 | /** |
375 | * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled, | 335 | * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled, |
376 | * #GNUNET_SYSERR if configuration enabled but binary is unavailable. | 336 | * #GNUNET_SYSERR if configuration enabled but binary is unavailable. |
377 | */ | 337 | */ |
378 | static int enable_upnp; | 338 | int enable_upnp; |
379 | |||
380 | /** | ||
381 | * Task run to obtain our external IP (if #enable_upnp is set | ||
382 | * and if we find we have a NATed IP address). | ||
383 | */ | ||
384 | static struct GNUNET_SCHEDULER_Task *probe_external_ip_task; | ||
385 | |||
386 | /** | ||
387 | * Handle to our operation to run `external-ip`. | ||
388 | */ | ||
389 | static struct GNUNET_NAT_ExternalHandle *probe_external_ip_op; | ||
390 | |||
391 | /** | ||
392 | * What is our external IP address as claimed by `external-ip`? | ||
393 | * 0 for unknown. | ||
394 | */ | ||
395 | static struct in_addr mini_external_ipv4; | ||
396 | 339 | ||
397 | 340 | ||
398 | /** | 341 | /** |
@@ -422,7 +365,7 @@ free_lal (struct LocalAddressList *lal) | |||
422 | 365 | ||
423 | /** | 366 | /** |
424 | * Free the DLL starting at #lal_head. | 367 | * Free the DLL starting at #lal_head. |
425 | */ | 368 | */ |
426 | static void | 369 | static void |
427 | destroy_lal () | 370 | destroy_lal () |
428 | { | 371 | { |
@@ -474,22 +417,22 @@ check_register (void *cls, | |||
474 | #endif | 417 | #endif |
475 | default: | 418 | default: |
476 | GNUNET_break (0); | 419 | GNUNET_break (0); |
477 | return GNUNET_SYSERR; | 420 | return GNUNET_SYSERR; |
478 | } | 421 | } |
479 | if (alen > left) | 422 | if (alen > left) |
480 | { | 423 | { |
481 | GNUNET_break (0); | 424 | GNUNET_break (0); |
482 | return GNUNET_SYSERR; | 425 | return GNUNET_SYSERR; |
483 | } | 426 | } |
484 | off += alen; | 427 | off += alen; |
485 | left -= alen; | 428 | left -= alen; |
486 | } | 429 | } |
487 | if (left != ntohs (message->hole_external_len)) | 430 | if (left != ntohs (message->str_len)) |
488 | { | 431 | { |
489 | GNUNET_break (0); | 432 | GNUNET_break (0); |
490 | return GNUNET_SYSERR; | 433 | return GNUNET_SYSERR; |
491 | } | 434 | } |
492 | return GNUNET_OK; | 435 | return GNUNET_OK; |
493 | } | 436 | } |
494 | 437 | ||
495 | 438 | ||
@@ -535,7 +478,7 @@ match_ipv6 (const char *network, | |||
535 | struct in6_addr net; | 478 | struct in6_addr net; |
536 | struct in6_addr mask; | 479 | struct in6_addr mask; |
537 | unsigned int off; | 480 | unsigned int off; |
538 | 481 | ||
539 | if (0 == bits) | 482 | if (0 == bits) |
540 | return GNUNET_YES; | 483 | return GNUNET_YES; |
541 | GNUNET_assert (1 == inet_pton (AF_INET6, | 484 | GNUNET_assert (1 == inet_pton (AF_INET6, |
@@ -607,7 +550,7 @@ is_nat_v6 (const struct in6_addr *ip) | |||
607 | struct IfcProcContext | 550 | struct IfcProcContext |
608 | { | 551 | { |
609 | 552 | ||
610 | /** | 553 | /** |
611 | * Head of DLL of local addresses. | 554 | * Head of DLL of local addresses. |
612 | */ | 555 | */ |
613 | struct LocalAddressList *lal_head; | 556 | struct LocalAddressList *lal_head; |
@@ -718,7 +661,7 @@ notify_client (enum GNUNET_NAT_AddressClass ac, | |||
718 | { | 661 | { |
719 | struct GNUNET_MQ_Envelope *env; | 662 | struct GNUNET_MQ_Envelope *env; |
720 | struct GNUNET_NAT_AddressChangeNotificationMessage *msg; | 663 | struct GNUNET_NAT_AddressChangeNotificationMessage *msg; |
721 | 664 | ||
722 | env = GNUNET_MQ_msg_extra (msg, | 665 | env = GNUNET_MQ_msg_extra (msg, |
723 | addr_len, | 666 | addr_len, |
724 | GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); | 667 | GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); |
@@ -729,7 +672,7 @@ notify_client (enum GNUNET_NAT_AddressClass ac, | |||
729 | addr_len); | 672 | addr_len); |
730 | GNUNET_MQ_send (ch->mq, | 673 | GNUNET_MQ_send (ch->mq, |
731 | env); | 674 | env); |
732 | } | 675 | } |
733 | 676 | ||
734 | 677 | ||
735 | /** | 678 | /** |
@@ -748,7 +691,7 @@ check_notify_client (struct LocalAddressList *delta, | |||
748 | size_t alen; | 691 | size_t alen; |
749 | struct sockaddr_in v4; | 692 | struct sockaddr_in v4; |
750 | struct sockaddr_in6 v6; | 693 | struct sockaddr_in6 v6; |
751 | 694 | ||
752 | if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES)) | 695 | if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES)) |
753 | return; | 696 | return; |
754 | switch (delta->af) | 697 | switch (delta->af) |
@@ -758,14 +701,14 @@ check_notify_client (struct LocalAddressList *delta, | |||
758 | GNUNET_memcpy (&v4, | 701 | GNUNET_memcpy (&v4, |
759 | &delta->addr, | 702 | &delta->addr, |
760 | alen); | 703 | alen); |
761 | 704 | ||
762 | /* Check for client notifications */ | 705 | /* Check for client notifications */ |
763 | for (unsigned int i=0;i<ch->num_caddrs;i++) | 706 | for (unsigned int i=0;i<ch->num_caddrs;i++) |
764 | { | 707 | { |
765 | const struct sockaddr_in *c4; | 708 | const struct sockaddr_in *c4; |
766 | 709 | ||
767 | if (AF_INET != ch->caddrs[i].ss.ss_family) | 710 | if (AF_INET != ch->caddrs[i].ss.ss_family) |
768 | return; /* IPv4 not relevant */ | 711 | continue; /* IPv4 not relevant */ |
769 | c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss; | 712 | c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss; |
770 | if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) && | 713 | if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) && |
771 | (0 != c4->sin_addr.s_addr) && | 714 | (0 != c4->sin_addr.s_addr) && |
@@ -806,9 +749,9 @@ check_notify_client (struct LocalAddressList *delta, | |||
806 | for (unsigned int i=0;i<ch->num_caddrs;i++) | 749 | for (unsigned int i=0;i<ch->num_caddrs;i++) |
807 | { | 750 | { |
808 | const struct sockaddr_in6 *c6; | 751 | const struct sockaddr_in6 *c6; |
809 | 752 | ||
810 | if (AF_INET6 != ch->caddrs[i].ss.ss_family) | 753 | if (AF_INET6 != ch->caddrs[i].ss.ss_family) |
811 | return; /* IPv4 not relevant */ | 754 | continue; /* IPv4 not relevant */ |
812 | c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss; | 755 | c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss; |
813 | if ( match_ipv6 ("::1", &c6->sin6_addr, 128) && | 756 | if ( match_ipv6 ("::1", &c6->sin6_addr, 128) && |
814 | (0 != memcmp (&c6->sin6_addr, | 757 | (0 != memcmp (&c6->sin6_addr, |
@@ -888,19 +831,40 @@ notify_clients (struct LocalAddressList *delta, | |||
888 | /** | 831 | /** |
889 | * Tell relevant client about a change in our external | 832 | * Tell relevant client about a change in our external |
890 | * IPv4 address. | 833 | * IPv4 address. |
891 | * | 834 | * |
835 | * @param cls client to check if it cares and possibly notify | ||
892 | * @param v4 the external address that changed | 836 | * @param v4 the external address that changed |
893 | * @param ch client to check if it cares and possibly notify | ||
894 | * @param add #GNUNET_YES to add, #GNUNET_NO to remove | 837 | * @param add #GNUNET_YES to add, #GNUNET_NO to remove |
895 | */ | 838 | */ |
896 | static void | 839 | static void |
897 | check_notify_client_external_ipv4_change (const struct in_addr *v4, | 840 | notify_client_external_ipv4_change (void *cls, |
898 | struct ClientHandle *ch, | 841 | const struct in_addr *v4, |
899 | int add) | 842 | int add) |
900 | { | 843 | { |
844 | struct ClientHandle *ch = cls; | ||
901 | struct sockaddr_in sa; | 845 | struct sockaddr_in sa; |
902 | int have_v4; | 846 | int have_v4; |
903 | 847 | ||
848 | /* (0) check if this impacts 'hole_external' */ | ||
849 | if ( (NULL != ch->hole_external) && | ||
850 | (0 == strcasecmp (ch->hole_external, | ||
851 | "AUTO")) ) | ||
852 | { | ||
853 | struct LocalAddressList lal; | ||
854 | struct sockaddr_in *s4; | ||
855 | |||
856 | memset (&lal, 0, sizeof (lal)); | ||
857 | s4 = (struct sockaddr_in *) &lal.addr; | ||
858 | s4->sin_family = AF_INET; | ||
859 | s4->sin_port = htons (ch->ext_dns_port); | ||
860 | s4->sin_addr = *v4; | ||
861 | lal.af = AF_INET; | ||
862 | lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; | ||
863 | check_notify_client (&lal, | ||
864 | ch, | ||
865 | add); | ||
866 | } | ||
867 | |||
904 | /* (1) check if client cares. */ | 868 | /* (1) check if client cares. */ |
905 | if (! ch->natted_address) | 869 | if (! ch->natted_address) |
906 | return; | 870 | return; |
@@ -919,17 +883,17 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4, | |||
919 | if (GNUNET_NO == have_v4) | 883 | if (GNUNET_NO == have_v4) |
920 | return; /* IPv6-only */ | 884 | return; /* IPv6-only */ |
921 | 885 | ||
922 | /* build address info */ | 886 | /* (2) build address info */ |
923 | memset (&sa, | 887 | memset (&sa, |
924 | 0, | 888 | 0, |
925 | sizeof (sa)); | 889 | sizeof (sa)); |
926 | sa.sin_family = AF_INET; | 890 | sa.sin_family = AF_INET; |
927 | sa.sin_addr = *v4; | 891 | sa.sin_addr = *v4; |
928 | sa.sin_port = htons (0); | 892 | sa.sin_port = htons (0); |
929 | 893 | ||
930 | /* (3) notify client of change */ | 894 | /* (3) notify client of change */ |
931 | notify_client (is_nat_v4 (v4) | 895 | notify_client (is_nat_v4 (v4) |
932 | ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN | 896 | ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN |
933 | : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL, | 897 | : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL, |
934 | ch, | 898 | ch, |
935 | add, | 899 | add, |
@@ -939,117 +903,11 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4, | |||
939 | 903 | ||
940 | 904 | ||
941 | /** | 905 | /** |
942 | * Tell relevant clients about a change in our external | ||
943 | * IPv4 address. | ||
944 | * | ||
945 | * @param add #GNUNET_YES to add, #GNUNET_NO to remove | ||
946 | * @param v4 the external address that changed | ||
947 | */ | ||
948 | static void | ||
949 | notify_clients_external_ipv4_change (int add, | ||
950 | const struct in_addr *v4) | ||
951 | { | ||
952 | for (struct ClientHandle *ch = ch_head; | ||
953 | NULL != ch; | ||
954 | ch = ch->next) | ||
955 | check_notify_client_external_ipv4_change (v4, | ||
956 | ch, | ||
957 | add); | ||
958 | } | ||
959 | |||
960 | |||
961 | /** | ||
962 | * Task used to run `external-ip` to get our external IPv4 | ||
963 | * address and pass it to NATed clients if possible. | ||
964 | * | ||
965 | * @param cls NULL | ||
966 | */ | ||
967 | static void | ||
968 | run_external_ip (void *cls); | ||
969 | |||
970 | |||
971 | /** | ||
972 | * We learn our current external IP address. If it changed, | ||
973 | * notify all of our applicable clients. Also re-schedule | ||
974 | * #run_external_ip with an appropriate timeout. | ||
975 | * | ||
976 | * @param cls NULL | ||
977 | * @param addr the address, NULL on errors | ||
978 | * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code | ||
979 | */ | ||
980 | static void | ||
981 | handle_external_ip (void *cls, | ||
982 | const struct in_addr *addr, | ||
983 | enum GNUNET_NAT_StatusCode result) | ||
984 | { | ||
985 | char buf[INET_ADDRSTRLEN]; | ||
986 | |||
987 | probe_external_ip_op = NULL; | ||
988 | GNUNET_SCHEDULER_cancel (probe_external_ip_task); | ||
989 | probe_external_ip_task | ||
990 | = GNUNET_SCHEDULER_add_delayed ((NULL == addr) | ||
991 | ? EXTERN_IP_RETRY_FAILURE | ||
992 | : EXTERN_IP_RETRY_SUCCESS, | ||
993 | &run_external_ip, | ||
994 | NULL); | ||
995 | switch (result) | ||
996 | { | ||
997 | case GNUNET_NAT_ERROR_SUCCESS: | ||
998 | if (addr->s_addr == mini_external_ipv4.s_addr) | ||
999 | return; /* not change */ | ||
1000 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1001 | "Our external IP is now %s\n", | ||
1002 | inet_ntop (AF_INET, | ||
1003 | addr, | ||
1004 | buf, | ||
1005 | sizeof (buf))); | ||
1006 | if (0 != mini_external_ipv4.s_addr) | ||
1007 | notify_clients_external_ipv4_change (GNUNET_NO, | ||
1008 | &mini_external_ipv4); | ||
1009 | mini_external_ipv4 = *addr; | ||
1010 | notify_clients_external_ipv4_change (GNUNET_YES, | ||
1011 | &mini_external_ipv4); | ||
1012 | break; | ||
1013 | default: | ||
1014 | if (0 != mini_external_ipv4.s_addr) | ||
1015 | notify_clients_external_ipv4_change (GNUNET_NO, | ||
1016 | &mini_external_ipv4); | ||
1017 | mini_external_ipv4.s_addr = 0; | ||
1018 | break; | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | |||
1023 | /** | ||
1024 | * Task used to run `external-ip` to get our external IPv4 | ||
1025 | * address and pass it to NATed clients if possible. | ||
1026 | * | ||
1027 | * @param cls NULL | ||
1028 | */ | ||
1029 | static void | ||
1030 | run_external_ip (void *cls) | ||
1031 | { | ||
1032 | probe_external_ip_task | ||
1033 | = GNUNET_SCHEDULER_add_delayed (EXTERN_IP_RETRY_TIMEOUT, | ||
1034 | &run_external_ip, | ||
1035 | NULL); | ||
1036 | if (NULL != probe_external_ip_op) | ||
1037 | { | ||
1038 | GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op); | ||
1039 | probe_external_ip_op = NULL; | ||
1040 | } | ||
1041 | probe_external_ip_op | ||
1042 | = GNUNET_NAT_mini_get_external_ipv4_ (&handle_external_ip, | ||
1043 | NULL); | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | /** | ||
1048 | * We got a connection reversal request from another peer. | 906 | * We got a connection reversal request from another peer. |
1049 | * Notify applicable clients. | 907 | * Notify applicable clients. |
1050 | * | 908 | * |
1051 | * @param cls closure with the `struct LocalAddressList` | 909 | * @param cls closure with the `struct LocalAddressList` |
1052 | * @param ra IP address of the peer who wants us to connect to it | 910 | * @param ra IP address of the peer who wants us to connect to it |
1053 | */ | 911 | */ |
1054 | static void | 912 | static void |
1055 | reversal_callback (void *cls, | 913 | reversal_callback (void *cls, |
@@ -1063,7 +921,7 @@ reversal_callback (void *cls, | |||
1063 | for (struct ClientHandle *ch = ch_head; | 921 | for (struct ClientHandle *ch = ch_head; |
1064 | NULL != ch; | 922 | NULL != ch; |
1065 | ch = ch->next) | 923 | ch = ch->next) |
1066 | { | 924 | { |
1067 | struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm; | 925 | struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm; |
1068 | struct GNUNET_MQ_Envelope *env; | 926 | struct GNUNET_MQ_Envelope *env; |
1069 | int match; | 927 | int match; |
@@ -1077,7 +935,7 @@ reversal_callback (void *cls, | |||
1077 | { | 935 | { |
1078 | struct ClientAddress *ca = &ch->caddrs[i]; | 936 | struct ClientAddress *ca = &ch->caddrs[i]; |
1079 | const struct sockaddr_in *c4; | 937 | const struct sockaddr_in *c4; |
1080 | 938 | ||
1081 | if (AF_INET != ca->ss.ss_family) | 939 | if (AF_INET != ca->ss.ss_family) |
1082 | continue; | 940 | continue; |
1083 | c4 = (const struct sockaddr_in *) &ca->ss; | 941 | c4 = (const struct sockaddr_in *) &ca->ss; |
@@ -1107,7 +965,7 @@ reversal_callback (void *cls, | |||
1107 | * Task we run periodically to scan for network interfaces. | 965 | * Task we run periodically to scan for network interfaces. |
1108 | * | 966 | * |
1109 | * @param cls NULL | 967 | * @param cls NULL |
1110 | */ | 968 | */ |
1111 | static void | 969 | static void |
1112 | run_scan (void *cls) | 970 | run_scan (void *cls) |
1113 | { | 971 | { |
@@ -1115,7 +973,7 @@ run_scan (void *cls) | |||
1115 | int found; | 973 | int found; |
1116 | int have_nat; | 974 | int have_nat; |
1117 | struct LocalAddressList *lnext; | 975 | struct LocalAddressList *lnext; |
1118 | 976 | ||
1119 | scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ, | 977 | scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ, |
1120 | &run_scan, | 978 | &run_scan, |
1121 | NULL); | 979 | NULL); |
@@ -1194,8 +1052,8 @@ run_scan (void *cls) | |||
1194 | { | 1052 | { |
1195 | const struct sockaddr_in *s4 | 1053 | const struct sockaddr_in *s4 |
1196 | = (const struct sockaddr_in *) &pos->addr; | 1054 | = (const struct sockaddr_in *) &pos->addr; |
1197 | 1055 | ||
1198 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | 1056 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1199 | "Found NATed local address %s, starting NAT server\n", | 1057 | "Found NATed local address %s, starting NAT server\n", |
1200 | GNUNET_a2s ((void *) &pos->addr, sizeof (*s4))); | 1058 | GNUNET_a2s ((void *) &pos->addr, sizeof (*s4))); |
1201 | pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr, | 1059 | pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr, |
@@ -1204,29 +1062,7 @@ run_scan (void *cls) | |||
1204 | } | 1062 | } |
1205 | } | 1063 | } |
1206 | } | 1064 | } |
1207 | if ( (GNUNET_YES == have_nat) && | 1065 | GN_nat_status_changed (have_nat); |
1208 | (GNUNET_YES == enable_upnp) && | ||
1209 | (NULL == probe_external_ip_task) && | ||
1210 | (NULL == probe_external_ip_op) ) | ||
1211 | { | ||
1212 | probe_external_ip_task | ||
1213 | = GNUNET_SCHEDULER_add_now (&run_external_ip, | ||
1214 | NULL); | ||
1215 | } | ||
1216 | if ( (GNUNET_NO == have_nat) && | ||
1217 | (GNUNET_YES == enable_upnp) ) | ||
1218 | { | ||
1219 | if (NULL != probe_external_ip_task) | ||
1220 | { | ||
1221 | GNUNET_SCHEDULER_cancel (probe_external_ip_task); | ||
1222 | probe_external_ip_task = NULL; | ||
1223 | } | ||
1224 | if (NULL != probe_external_ip_op) | ||
1225 | { | ||
1226 | GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op); | ||
1227 | probe_external_ip_op = NULL; | ||
1228 | } | ||
1229 | } | ||
1230 | } | 1066 | } |
1231 | 1067 | ||
1232 | 1068 | ||
@@ -1267,6 +1103,10 @@ upnp_addr_change_cb (void *cls, | |||
1267 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1103 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1268 | "external-ip binary not found\n"); | 1104 | "external-ip binary not found\n"); |
1269 | return; | 1105 | return; |
1106 | case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND: | ||
1107 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1108 | "upnpc binary not found\n"); | ||
1109 | return; | ||
1270 | case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED: | 1110 | case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED: |
1271 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1111 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1272 | "external-ip binary could not be run\n"); | 1112 | "external-ip binary could not be run\n"); |
@@ -1317,6 +1157,250 @@ upnp_addr_change_cb (void *cls, | |||
1317 | 1157 | ||
1318 | 1158 | ||
1319 | /** | 1159 | /** |
1160 | * Resolve the `hole_external` name to figure out our | ||
1161 | * external address from a manually punched hole. The | ||
1162 | * port number has already been parsed, this task is | ||
1163 | * responsible for periodically doing a DNS lookup. | ||
1164 | * | ||
1165 | * @param ch client handle to act upon | ||
1166 | */ | ||
1167 | static void | ||
1168 | dyndns_lookup (void *cls); | ||
1169 | |||
1170 | |||
1171 | /** | ||
1172 | * Our (external) hostname was resolved. Update lists of | ||
1173 | * current external IPs (note that DNS may return multiple | ||
1174 | * addresses!) and notify client accordingly. | ||
1175 | * | ||
1176 | * @param cls the `struct ClientHandle` | ||
1177 | * @param addr NULL on error, otherwise result of DNS lookup | ||
1178 | * @param addrlen number of bytes in @a addr | ||
1179 | */ | ||
1180 | static void | ||
1181 | process_external_ip (void *cls, | ||
1182 | const struct sockaddr *addr, | ||
1183 | socklen_t addrlen) | ||
1184 | { | ||
1185 | struct ClientHandle *ch = cls; | ||
1186 | struct LocalAddressList *lal; | ||
1187 | struct sockaddr_storage ss; | ||
1188 | struct sockaddr_in *v4; | ||
1189 | struct sockaddr_in6 *v6; | ||
1190 | |||
1191 | if (NULL == addr) | ||
1192 | { | ||
1193 | struct LocalAddressList *laln; | ||
1194 | |||
1195 | ch->ext_dns = NULL; | ||
1196 | ch->ext_dns_task | ||
1197 | = GNUNET_SCHEDULER_add_delayed (dyndns_frequency, | ||
1198 | &dyndns_lookup, | ||
1199 | ch); | ||
1200 | /* Current iteration is over, remove 'old' IPs now */ | ||
1201 | for (lal = ch->ext_addr_head; NULL != lal; lal = laln) | ||
1202 | { | ||
1203 | laln = lal->next; | ||
1204 | if (GNUNET_YES == lal->old) | ||
1205 | { | ||
1206 | GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head, | ||
1207 | ch->ext_addr_tail, | ||
1208 | lal); | ||
1209 | check_notify_client (lal, | ||
1210 | ch, | ||
1211 | GNUNET_NO); | ||
1212 | GNUNET_free (lal); | ||
1213 | } | ||
1214 | } | ||
1215 | return; | ||
1216 | } | ||
1217 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1218 | "Got IP `%s' for external address `%s'\n", | ||
1219 | GNUNET_a2s (addr, | ||
1220 | addrlen), | ||
1221 | ch->hole_external); | ||
1222 | |||
1223 | /* build sockaddr storage with port number */ | ||
1224 | memset (&ss, 0, sizeof (ss)); | ||
1225 | memcpy (&ss, addr, addrlen); | ||
1226 | switch (addr->sa_family) | ||
1227 | { | ||
1228 | case AF_INET: | ||
1229 | v4 = (struct sockaddr_in *) &ss; | ||
1230 | v4->sin_port = htons (ch->ext_dns_port); | ||
1231 | break; | ||
1232 | case AF_INET6: | ||
1233 | v6 = (struct sockaddr_in6 *) &ss; | ||
1234 | v6->sin6_port = htons (ch->ext_dns_port); | ||
1235 | break; | ||
1236 | default: | ||
1237 | GNUNET_break (0); | ||
1238 | return; | ||
1239 | } | ||
1240 | /* See if 'ss' matches any of our known addresses */ | ||
1241 | for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next) | ||
1242 | { | ||
1243 | if (GNUNET_NO == lal->old) | ||
1244 | continue; /* already processed, skip */ | ||
1245 | if ( (addr->sa_family == lal->addr.ss_family) && | ||
1246 | (0 == memcmp (&ss, | ||
1247 | &lal->addr, | ||
1248 | addrlen)) ) | ||
1249 | { | ||
1250 | /* Address unchanged, remember so we do not remove */ | ||
1251 | lal->old = GNUNET_NO; | ||
1252 | return; /* done here */ | ||
1253 | } | ||
1254 | } | ||
1255 | /* notify client, and remember IP for later removal! */ | ||
1256 | lal = GNUNET_new (struct LocalAddressList); | ||
1257 | lal->addr = ss; | ||
1258 | lal->af = ss.ss_family; | ||
1259 | lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; | ||
1260 | GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head, | ||
1261 | ch->ext_addr_tail, | ||
1262 | lal); | ||
1263 | check_notify_client (lal, | ||
1264 | ch, | ||
1265 | GNUNET_YES); | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | /** | ||
1270 | * Resolve the `hole_external` name to figure out our | ||
1271 | * external address from a manually punched hole. The | ||
1272 | * port number has already been parsed, this task is | ||
1273 | * responsible for periodically doing a DNS lookup. | ||
1274 | * | ||
1275 | * @param ch client handle to act upon | ||
1276 | */ | ||
1277 | static void | ||
1278 | dyndns_lookup (void *cls) | ||
1279 | { | ||
1280 | struct ClientHandle *ch = cls; | ||
1281 | struct LocalAddressList *lal; | ||
1282 | |||
1283 | for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next) | ||
1284 | lal->old = GNUNET_YES; | ||
1285 | ch->ext_dns_task = NULL; | ||
1286 | ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external, | ||
1287 | AF_UNSPEC, | ||
1288 | GNUNET_TIME_UNIT_MINUTES, | ||
1289 | &process_external_ip, | ||
1290 | ch); | ||
1291 | } | ||
1292 | |||
1293 | |||
1294 | /** | ||
1295 | * Resolve the `hole_external` name to figure out our | ||
1296 | * external address from a manually punched hole. The | ||
1297 | * given name may be "AUTO" in which case we should use | ||
1298 | * the IP address(es) we have from upnpc or other methods. | ||
1299 | * The name can also be an IP address, in which case we | ||
1300 | * do not need to do DNS resolution. Finally, we also | ||
1301 | * need to parse the port number. | ||
1302 | * | ||
1303 | * @param ch client handle to act upon | ||
1304 | */ | ||
1305 | static void | ||
1306 | lookup_hole_external (struct ClientHandle *ch) | ||
1307 | { | ||
1308 | char *port; | ||
1309 | unsigned int pnum; | ||
1310 | struct sockaddr_in *s4; | ||
1311 | struct LocalAddressList *lal; | ||
1312 | |||
1313 | port = strrchr (ch->hole_external, ':'); | ||
1314 | if (NULL == port) | ||
1315 | { | ||
1316 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1317 | _("Malformed punched hole specification `%s' (lacks port)\n"), | ||
1318 | ch->hole_external); | ||
1319 | return; | ||
1320 | } | ||
1321 | if ( (1 != sscanf (port + 1, | ||
1322 | "%u", | ||
1323 | &pnum)) || | ||
1324 | (pnum > 65535) ) | ||
1325 | { | ||
1326 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1327 | _("Invalid port number in punched hole specification `%s' (lacks port)\n"), | ||
1328 | port + 1); | ||
1329 | return; | ||
1330 | } | ||
1331 | ch->ext_dns_port = (uint16_t) pnum; | ||
1332 | *port = '\0'; | ||
1333 | |||
1334 | lal = GNUNET_new (struct LocalAddressList); | ||
1335 | if ('[' == *ch->hole_external) | ||
1336 | { | ||
1337 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr; | ||
1338 | |||
1339 | s6->sin6_family = AF_INET6; | ||
1340 | if (']' != (ch->hole_external[strlen(ch->hole_external)-1])) | ||
1341 | { | ||
1342 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1343 | _("Malformed punched hole specification `%s' (lacks `]')\n"), | ||
1344 | ch->hole_external); | ||
1345 | GNUNET_free (lal); | ||
1346 | return; | ||
1347 | } | ||
1348 | ch->hole_external[strlen(ch->hole_external)-1] = '\0'; | ||
1349 | if (1 != inet_pton (AF_INET6, | ||
1350 | ch->hole_external + 1, | ||
1351 | &s6->sin6_addr)) | ||
1352 | { | ||
1353 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1354 | _("Malformed punched hole specification `%s' (IPv6 address invalid)"), | ||
1355 | ch->hole_external + 1); | ||
1356 | GNUNET_free (lal); | ||
1357 | return; | ||
1358 | } | ||
1359 | s6->sin6_port = htons (ch->ext_dns_port); | ||
1360 | lal->af = AF_INET6; | ||
1361 | lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; | ||
1362 | GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head, | ||
1363 | ch->ext_addr_tail, | ||
1364 | lal); | ||
1365 | check_notify_client (lal, | ||
1366 | ch, | ||
1367 | GNUNET_YES); | ||
1368 | return; | ||
1369 | } | ||
1370 | |||
1371 | s4 = (struct sockaddr_in *) &lal->addr; | ||
1372 | s4->sin_family = AF_INET; | ||
1373 | if (1 == inet_pton (AF_INET, | ||
1374 | ch->hole_external, | ||
1375 | &s4->sin_addr)) | ||
1376 | { | ||
1377 | s4->sin_port = htons (ch->ext_dns_port); | ||
1378 | lal->af = AF_INET; | ||
1379 | lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; | ||
1380 | GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head, | ||
1381 | ch->ext_addr_tail, | ||
1382 | lal); | ||
1383 | check_notify_client (lal, | ||
1384 | ch, | ||
1385 | GNUNET_YES); | ||
1386 | return; | ||
1387 | } | ||
1388 | if (0 == strcasecmp (ch->hole_external, | ||
1389 | "AUTO")) | ||
1390 | { | ||
1391 | /* handled in #notify_client_external_ipv4_change() */ | ||
1392 | GNUNET_free (lal); | ||
1393 | return; | ||
1394 | } | ||
1395 | /* got a DNS name, trigger lookup! */ | ||
1396 | GNUNET_free (lal); | ||
1397 | ch->ext_dns_task | ||
1398 | = GNUNET_SCHEDULER_add_now (&dyndns_lookup, | ||
1399 | ch); | ||
1400 | } | ||
1401 | |||
1402 | |||
1403 | /** | ||
1320 | * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client. | 1404 | * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client. |
1321 | * We remember the client for updates upon future NAT events. | 1405 | * We remember the client for updates upon future NAT events. |
1322 | * | 1406 | * |
@@ -1367,7 +1451,7 @@ handle_register (void *cls, | |||
1367 | case AF_INET: | 1451 | case AF_INET: |
1368 | { | 1452 | { |
1369 | const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa; | 1453 | const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa; |
1370 | 1454 | ||
1371 | alen = sizeof (struct sockaddr_in); | 1455 | alen = sizeof (struct sockaddr_in); |
1372 | if (is_nat_v4 (&s4->sin_addr)) | 1456 | if (is_nat_v4 (&s4->sin_addr)) |
1373 | is_nat = GNUNET_YES; | 1457 | is_nat = GNUNET_YES; |
@@ -1377,7 +1461,7 @@ handle_register (void *cls, | |||
1377 | case AF_INET6: | 1461 | case AF_INET6: |
1378 | { | 1462 | { |
1379 | const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa; | 1463 | const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa; |
1380 | 1464 | ||
1381 | alen = sizeof (struct sockaddr_in6); | 1465 | alen = sizeof (struct sockaddr_in6); |
1382 | if (is_nat_v6 (&s6->sin6_addr)) | 1466 | if (is_nat_v6 (&s6->sin6_addr)) |
1383 | is_nat = GNUNET_YES; | 1467 | is_nat = GNUNET_YES; |
@@ -1393,14 +1477,14 @@ handle_register (void *cls, | |||
1393 | default: | 1477 | default: |
1394 | GNUNET_break (0); | 1478 | GNUNET_break (0); |
1395 | GNUNET_SERVICE_client_drop (ch->client); | 1479 | GNUNET_SERVICE_client_drop (ch->client); |
1396 | return; | 1480 | return; |
1397 | } | 1481 | } |
1398 | /* store address */ | 1482 | /* store address */ |
1399 | GNUNET_assert (alen <= left); | 1483 | GNUNET_assert (alen <= left); |
1400 | GNUNET_assert (alen <= sizeof (struct sockaddr_storage)); | 1484 | GNUNET_assert (alen <= sizeof (struct sockaddr_storage)); |
1401 | GNUNET_memcpy (&ch->caddrs[i].ss, | 1485 | GNUNET_memcpy (&ch->caddrs[i].ss, |
1402 | sa, | 1486 | sa, |
1403 | alen); | 1487 | alen); |
1404 | 1488 | ||
1405 | /* If applicable, try UPNPC NAT punching */ | 1489 | /* If applicable, try UPNPC NAT punching */ |
1406 | if ( (is_nat) && | 1490 | if ( (is_nat) && |
@@ -1419,10 +1503,16 @@ handle_register (void *cls, | |||
1419 | off += alen; | 1503 | off += alen; |
1420 | } | 1504 | } |
1421 | 1505 | ||
1422 | ch->hole_external | 1506 | ch->section_name |
1423 | = GNUNET_strndup (off, | 1507 | = GNUNET_strndup (off, |
1424 | ntohs (message->hole_external_len)); | 1508 | ntohs (message->str_len)); |
1425 | 1509 | if (GNUNET_OK == | |
1510 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
1511 | ch->section_name, | ||
1512 | "HOLE_EXTERNAL", | ||
1513 | &ch->hole_external)) | ||
1514 | lookup_hole_external (ch); | ||
1515 | |||
1426 | /* Actually send IP address list to client */ | 1516 | /* Actually send IP address list to client */ |
1427 | for (struct LocalAddressList *lal = lal_head; | 1517 | for (struct LocalAddressList *lal = lal_head; |
1428 | NULL != lal; | 1518 | NULL != lal; |
@@ -1433,12 +1523,9 @@ handle_register (void *cls, | |||
1433 | GNUNET_YES); | 1523 | GNUNET_YES); |
1434 | } | 1524 | } |
1435 | /* Also consider IPv4 determined by `external-ip` */ | 1525 | /* Also consider IPv4 determined by `external-ip` */ |
1436 | if (0 != mini_external_ipv4.s_addr) | 1526 | ch->external_monitor |
1437 | { | 1527 | = GN_external_ipv4_monitor_start (¬ify_client_external_ipv4_change, |
1438 | check_notify_client_external_ipv4_change (&mini_external_ipv4, | 1528 | ch); |
1439 | ch, | ||
1440 | GNUNET_YES); | ||
1441 | } | ||
1442 | GNUNET_SERVICE_client_continue (ch->client); | 1529 | GNUNET_SERVICE_client_continue (ch->client); |
1443 | } | 1530 | } |
1444 | 1531 | ||
@@ -1457,7 +1544,7 @@ check_stun (void *cls, | |||
1457 | { | 1544 | { |
1458 | size_t sa_len = ntohs (message->sender_addr_size); | 1545 | size_t sa_len = ntohs (message->sender_addr_size); |
1459 | size_t expect = sa_len + ntohs (message->payload_size); | 1546 | size_t expect = sa_len + ntohs (message->payload_size); |
1460 | 1547 | ||
1461 | if (ntohs (message->header.size) - sizeof (*message) != expect) | 1548 | if (ntohs (message->header.size) - sizeof (*message) != expect) |
1462 | { | 1549 | { |
1463 | GNUNET_break (0); | 1550 | GNUNET_break (0); |
@@ -1490,7 +1577,7 @@ notify_clients_stun_change (const struct sockaddr_in *ip, | |||
1490 | struct sockaddr_in v4; | 1577 | struct sockaddr_in v4; |
1491 | struct GNUNET_NAT_AddressChangeNotificationMessage *msg; | 1578 | struct GNUNET_NAT_AddressChangeNotificationMessage *msg; |
1492 | struct GNUNET_MQ_Envelope *env; | 1579 | struct GNUNET_MQ_Envelope *env; |
1493 | 1580 | ||
1494 | if (! ch->natted_address) | 1581 | if (! ch->natted_address) |
1495 | continue; | 1582 | continue; |
1496 | v4 = *ip; | 1583 | v4 = *ip; |
@@ -1580,9 +1667,9 @@ handle_stun (void *cls, | |||
1580 | GNUNET_NAT_stun_handle_packet_ (payload, | 1667 | GNUNET_NAT_stun_handle_packet_ (payload, |
1581 | payload_size, | 1668 | payload_size, |
1582 | &external_addr)) | 1669 | &external_addr)) |
1583 | { | 1670 | { |
1584 | /* We now know that a server at "sa" claims that | 1671 | /* We now know that a server at "sa" claims that |
1585 | we are visible at IP "external_addr". | 1672 | we are visible at IP "external_addr". |
1586 | 1673 | ||
1587 | We should (for some fixed period of time) tell | 1674 | We should (for some fixed period of time) tell |
1588 | all of our clients that listen to a NAT'ed address | 1675 | all of our clients that listen to a NAT'ed address |
@@ -1685,347 +1772,44 @@ handle_request_connection_reversal (void *cls, | |||
1685 | const char *buf = (const char *) &message[1]; | 1772 | const char *buf = (const char *) &message[1]; |
1686 | size_t local_sa_len = ntohs (message->local_addr_size); | 1773 | size_t local_sa_len = ntohs (message->local_addr_size); |
1687 | size_t remote_sa_len = ntohs (message->remote_addr_size); | 1774 | size_t remote_sa_len = ntohs (message->remote_addr_size); |
1688 | const struct sockaddr *local_sa = (const struct sockaddr *) &buf[0]; | 1775 | struct sockaddr_in l4; |
1689 | const struct sockaddr *remote_sa = (const struct sockaddr *) &buf[local_sa_len]; | 1776 | struct sockaddr_in r4; |
1690 | const struct sockaddr_in *l4 = NULL; | ||
1691 | const struct sockaddr_in *r4; | ||
1692 | int ret; | 1777 | int ret; |
1693 | 1778 | ||
1694 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1779 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1695 | "Received REQUEST CONNECTION REVERSAL message from client\n"); | 1780 | "Received REQUEST CONNECTION REVERSAL message from client\n"); |
1696 | switch (local_sa->sa_family) | 1781 | if (local_sa_len != sizeof (struct sockaddr_in)) |
1697 | { | 1782 | { |
1698 | case AF_INET: | 1783 | GNUNET_break_op (0); |
1699 | if (local_sa_len != sizeof (struct sockaddr_in)) | ||
1700 | { | ||
1701 | GNUNET_break (0); | ||
1702 | GNUNET_SERVICE_client_drop (ch->client); | ||
1703 | return; | ||
1704 | } | ||
1705 | l4 = (const struct sockaddr_in *) local_sa; | ||
1706 | break; | ||
1707 | case AF_INET6: | ||
1708 | if (local_sa_len != sizeof (struct sockaddr_in6)) | ||
1709 | { | ||
1710 | GNUNET_break (0); | ||
1711 | GNUNET_SERVICE_client_drop (ch->client); | ||
1712 | return; | ||
1713 | } | ||
1714 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1715 | _("Connection reversal for IPv6 not supported yet\n")); | ||
1716 | ret = GNUNET_SYSERR; | ||
1717 | break; | ||
1718 | default: | ||
1719 | GNUNET_break (0); | ||
1720 | GNUNET_SERVICE_client_drop (ch->client); | 1784 | GNUNET_SERVICE_client_drop (ch->client); |
1721 | return; | 1785 | return; |
1722 | } | 1786 | } |
1723 | switch (remote_sa->sa_family) | 1787 | if (remote_sa_len != sizeof (struct sockaddr_in)) |
1724 | { | 1788 | { |
1725 | case AF_INET: | 1789 | GNUNET_break_op (0); |
1726 | if (remote_sa_len != sizeof (struct sockaddr_in)) | ||
1727 | { | ||
1728 | GNUNET_break (0); | ||
1729 | GNUNET_SERVICE_client_drop (ch->client); | ||
1730 | return; | ||
1731 | } | ||
1732 | r4 = (const struct sockaddr_in *) remote_sa; | ||
1733 | ret = GN_request_connection_reversal (&l4->sin_addr, | ||
1734 | ntohs (l4->sin_port), | ||
1735 | &r4->sin_addr); | ||
1736 | break; | ||
1737 | case AF_INET6: | ||
1738 | if (remote_sa_len != sizeof (struct sockaddr_in6)) | ||
1739 | { | ||
1740 | GNUNET_break (0); | ||
1741 | GNUNET_SERVICE_client_drop (ch->client); | ||
1742 | return; | ||
1743 | } | ||
1744 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1745 | _("Connection reversal for IPv6 not supported yet\n")); | ||
1746 | ret = GNUNET_SYSERR; | ||
1747 | break; | ||
1748 | default: | ||
1749 | GNUNET_break (0); | ||
1750 | GNUNET_SERVICE_client_drop (ch->client); | 1790 | GNUNET_SERVICE_client_drop (ch->client); |
1751 | return; | 1791 | return; |
1752 | } | 1792 | } |
1793 | GNUNET_memcpy (&l4, | ||
1794 | buf, | ||
1795 | sizeof (struct sockaddr_in)); | ||
1796 | GNUNET_break_op (AF_INET == l4.sin_family); | ||
1797 | buf += sizeof (struct sockaddr_in); | ||
1798 | GNUNET_memcpy (&r4, | ||
1799 | buf, | ||
1800 | sizeof (struct sockaddr_in)); | ||
1801 | GNUNET_break_op (AF_INET == r4.sin_family); | ||
1802 | ret = GN_request_connection_reversal (&l4.sin_addr, | ||
1803 | ntohs (l4.sin_port), | ||
1804 | &r4.sin_addr); | ||
1753 | if (GNUNET_OK != ret) | 1805 | if (GNUNET_OK != ret) |
1754 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1806 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1755 | _("Connection reversal request failed\n")); | 1807 | _("Connection reversal request failed\n")); |
1756 | GNUNET_SERVICE_client_continue (ch->client); | 1808 | GNUNET_SERVICE_client_continue (ch->client); |
1757 | } | 1809 | } |
1758 | 1810 | ||
1759 | 1811 | ||
1760 | /** | 1812 | /** |
1761 | * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message | ||
1762 | * from client. | ||
1763 | * | ||
1764 | * @param cls client who sent the message | ||
1765 | * @param message the message received | ||
1766 | * @return #GNUNET_OK if message is well-formed | ||
1767 | */ | ||
1768 | static int | ||
1769 | check_autoconfig_request (void *cls, | ||
1770 | const struct GNUNET_NAT_AutoconfigRequestMessage *message) | ||
1771 | { | ||
1772 | return GNUNET_OK; /* checked later */ | ||
1773 | } | ||
1774 | |||
1775 | |||
1776 | /** | ||
1777 | * Stop all pending activities with respect to the @a ac | ||
1778 | * | ||
1779 | * @param ac autoconfiguration to terminate activities for | ||
1780 | */ | ||
1781 | static void | ||
1782 | terminate_ac_activities (struct AutoconfigContext *ac) | ||
1783 | { | ||
1784 | if (NULL != ac->probe_external) | ||
1785 | { | ||
1786 | GNUNET_NAT_mini_get_external_ipv4_cancel_ (ac->probe_external); | ||
1787 | ac->probe_external = NULL; | ||
1788 | } | ||
1789 | if (NULL != ac->timeout_task) | ||
1790 | { | ||
1791 | GNUNET_SCHEDULER_cancel (ac->timeout_task); | ||
1792 | ac->timeout_task = NULL; | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | |||
1797 | /** | ||
1798 | * Finish handling the autoconfiguration request and send | ||
1799 | * the response to the client. | ||
1800 | * | ||
1801 | * @param cls the `struct AutoconfigContext` to conclude | ||
1802 | */ | ||
1803 | static void | ||
1804 | conclude_autoconfig_request (void *cls) | ||
1805 | { | ||
1806 | struct AutoconfigContext *ac = cls; | ||
1807 | struct ClientHandle *ch = ac->ch; | ||
1808 | struct GNUNET_NAT_AutoconfigResultMessage *arm; | ||
1809 | struct GNUNET_MQ_Envelope *env; | ||
1810 | size_t c_size; | ||
1811 | char *buf; | ||
1812 | struct GNUNET_CONFIGURATION_Handle *diff; | ||
1813 | |||
1814 | ac->timeout_task = NULL; | ||
1815 | terminate_ac_activities (ac); | ||
1816 | |||
1817 | /* Send back response */ | ||
1818 | diff = GNUNET_CONFIGURATION_get_diff (ac->orig, | ||
1819 | ac->c); | ||
1820 | buf = GNUNET_CONFIGURATION_serialize (diff, | ||
1821 | &c_size); | ||
1822 | GNUNET_CONFIGURATION_destroy (diff); | ||
1823 | env = GNUNET_MQ_msg_extra (arm, | ||
1824 | c_size, | ||
1825 | GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT); | ||
1826 | arm->status_code = htonl ((uint32_t) ac->status_code); | ||
1827 | arm->type = htonl ((uint32_t) ac->type); | ||
1828 | GNUNET_memcpy (&arm[1], | ||
1829 | buf, | ||
1830 | c_size); | ||
1831 | GNUNET_free (buf); | ||
1832 | GNUNET_MQ_send (ch->mq, | ||
1833 | env); | ||
1834 | |||
1835 | /* clean up */ | ||
1836 | GNUNET_free (ac->system_type); | ||
1837 | GNUNET_CONFIGURATION_destroy (ac->orig); | ||
1838 | GNUNET_CONFIGURATION_destroy (ac->c); | ||
1839 | GNUNET_CONTAINER_DLL_remove (ac_head, | ||
1840 | ac_tail, | ||
1841 | ac); | ||
1842 | GNUNET_free (ac); | ||
1843 | GNUNET_SERVICE_client_continue (ch->client); | ||
1844 | } | ||
1845 | |||
1846 | |||
1847 | /** | ||
1848 | * Check if all autoconfiguration operations have concluded, | ||
1849 | * and if they have, send the result back to the client. | ||
1850 | * | ||
1851 | * @param ac autoconfiguation context to check | ||
1852 | */ | ||
1853 | static void | ||
1854 | check_autoconfig_finished (struct AutoconfigContext *ac) | ||
1855 | { | ||
1856 | if (NULL != ac->probe_external) | ||
1857 | return; | ||
1858 | GNUNET_SCHEDULER_cancel (ac->timeout_task); | ||
1859 | ac->timeout_task | ||
1860 | = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request, | ||
1861 | ac); | ||
1862 | } | ||
1863 | |||
1864 | |||
1865 | /** | ||
1866 | * Update ENABLE_UPNPC configuration option. | ||
1867 | * | ||
1868 | * @param ac autoconfiguration to update | ||
1869 | */ | ||
1870 | static void | ||
1871 | update_enable_upnpc_option (struct AutoconfigContext *ac) | ||
1872 | { | ||
1873 | switch (ac->enable_upnpc) | ||
1874 | { | ||
1875 | case GNUNET_YES: | ||
1876 | GNUNET_CONFIGURATION_set_value_string (ac->c, | ||
1877 | "NAT", | ||
1878 | "ENABLE_UPNP", | ||
1879 | "YES"); | ||
1880 | break; | ||
1881 | case GNUNET_NO: | ||
1882 | GNUNET_CONFIGURATION_set_value_string (ac->c, | ||
1883 | "NAT", | ||
1884 | "ENABLE_UPNP", | ||
1885 | "NO"); | ||
1886 | break; | ||
1887 | case GNUNET_SYSERR: | ||
1888 | /* We are unsure, do not change option */ | ||
1889 | break; | ||
1890 | } | ||
1891 | } | ||
1892 | |||
1893 | |||
1894 | /** | ||
1895 | * Handle result from external IP address probe during | ||
1896 | * autoconfiguration. | ||
1897 | * | ||
1898 | * @param cls our `struct AutoconfigContext` | ||
1899 | * @param addr the address, NULL on errors | ||
1900 | * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code | ||
1901 | */ | ||
1902 | static void | ||
1903 | auto_external_result_cb (void *cls, | ||
1904 | const struct in_addr *addr, | ||
1905 | enum GNUNET_NAT_StatusCode result) | ||
1906 | { | ||
1907 | struct AutoconfigContext *ac = cls; | ||
1908 | |||
1909 | ac->probe_external = NULL; | ||
1910 | switch (result) | ||
1911 | { | ||
1912 | case GNUNET_NAT_ERROR_SUCCESS: | ||
1913 | ac->enable_upnpc = GNUNET_YES; | ||
1914 | break; | ||
1915 | case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID: | ||
1916 | case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID: | ||
1917 | case GNUNET_NAT_ERROR_IPC_FAILURE: | ||
1918 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1919 | "Disabling UPNPC: %d\n", | ||
1920 | (int) result); | ||
1921 | ac->enable_upnpc = GNUNET_NO; /* did not work */ | ||
1922 | break; | ||
1923 | default: | ||
1924 | GNUNET_break (0); /* unexpected */ | ||
1925 | ac->enable_upnpc = GNUNET_SYSERR; | ||
1926 | break; | ||
1927 | } | ||
1928 | update_enable_upnpc_option (ac); | ||
1929 | check_autoconfig_finished (ac); | ||
1930 | } | ||
1931 | |||
1932 | |||
1933 | /** | ||
1934 | * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from | ||
1935 | * client. | ||
1936 | * | ||
1937 | * @param cls client who sent the message | ||
1938 | * @param message the message received | ||
1939 | */ | ||
1940 | static void | ||
1941 | handle_autoconfig_request (void *cls, | ||
1942 | const struct GNUNET_NAT_AutoconfigRequestMessage *message) | ||
1943 | { | ||
1944 | struct ClientHandle *ch = cls; | ||
1945 | size_t left = ntohs (message->header.size) - sizeof (*message); | ||
1946 | struct LocalAddressList *lal; | ||
1947 | struct AutoconfigContext *ac; | ||
1948 | |||
1949 | ac = GNUNET_new (struct AutoconfigContext); | ||
1950 | ac->status_code = GNUNET_NAT_ERROR_SUCCESS; | ||
1951 | ac->ch = ch; | ||
1952 | ac->c = GNUNET_CONFIGURATION_create (); | ||
1953 | if (GNUNET_OK != | ||
1954 | GNUNET_CONFIGURATION_deserialize (ac->c, | ||
1955 | (const char *) &message[1], | ||
1956 | left, | ||
1957 | GNUNET_NO)) | ||
1958 | { | ||
1959 | GNUNET_break (0); | ||
1960 | GNUNET_SERVICE_client_drop (ch->client); | ||
1961 | GNUNET_CONFIGURATION_destroy (ac->c); | ||
1962 | GNUNET_free (ac); | ||
1963 | return; | ||
1964 | } | ||
1965 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1966 | "Received REQUEST_AUTO_CONFIG message from client\n"); | ||
1967 | |||
1968 | if (GNUNET_OK != | ||
1969 | GNUNET_CONFIGURATION_get_value_string (ac->c, | ||
1970 | "PEER", | ||
1971 | "SYSTEM_TYPE", | ||
1972 | &ac->system_type)) | ||
1973 | ac->system_type = GNUNET_strdup ("UNKNOWN"); | ||
1974 | |||
1975 | GNUNET_CONTAINER_DLL_insert (ac_head, | ||
1976 | ac_tail, | ||
1977 | ac); | ||
1978 | ac->orig | ||
1979 | = GNUNET_CONFIGURATION_dup (ac->c); | ||
1980 | ac->timeout_task | ||
1981 | = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT, | ||
1982 | &conclude_autoconfig_request, | ||
1983 | ac); | ||
1984 | ac->enable_upnpc = GNUNET_SYSERR; /* undecided */ | ||
1985 | |||
1986 | /* Probe for upnpc */ | ||
1987 | if (GNUNET_SYSERR == | ||
1988 | GNUNET_OS_check_helper_binary ("upnpc", | ||
1989 | GNUNET_NO, | ||
1990 | NULL)) | ||
1991 | { | ||
1992 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1993 | _("UPnP client `upnpc` command not found, disabling UPnP\n")); | ||
1994 | ac->enable_upnpc = GNUNET_NO; | ||
1995 | } | ||
1996 | else | ||
1997 | { | ||
1998 | for (lal = lal_head; NULL != lal; lal = lal->next) | ||
1999 | if (GNUNET_NAT_AC_LAN == (lal->ac & GNUNET_NAT_AC_LAN)) | ||
2000 | /* we are behind NAT, useful to try upnpc */ | ||
2001 | ac->enable_upnpc = GNUNET_YES; | ||
2002 | } | ||
2003 | if (GNUNET_YES == ac->enable_upnpc) | ||
2004 | { | ||
2005 | /* If we are a mobile device, always leave it on as the network | ||
2006 | may change to one that supports UPnP anytime. If we are | ||
2007 | stationary, check if our network actually supports UPnP, and if | ||
2008 | not, disable it. */ | ||
2009 | if ( (0 == strcasecmp (ac->system_type, | ||
2010 | "INFRASTRUCTURE")) || | ||
2011 | (0 == strcasecmp (ac->system_type, | ||
2012 | "DESKTOP")) ) | ||
2013 | { | ||
2014 | /* Check if upnpc gives us an external IP */ | ||
2015 | ac->probe_external | ||
2016 | = GNUNET_NAT_mini_get_external_ipv4_ (&auto_external_result_cb, | ||
2017 | ac); | ||
2018 | } | ||
2019 | } | ||
2020 | if (NULL == ac->probe_external) | ||
2021 | update_enable_upnpc_option (ac); | ||
2022 | |||
2023 | /* Finally, check if we are already done */ | ||
2024 | check_autoconfig_finished (ac); | ||
2025 | } | ||
2026 | |||
2027 | |||
2028 | /** | ||
2029 | * Task run during shutdown. | 1813 | * Task run during shutdown. |
2030 | * | 1814 | * |
2031 | * @param cls unused | 1815 | * @param cls unused |
@@ -2034,16 +1818,7 @@ static void | |||
2034 | shutdown_task (void *cls) | 1818 | shutdown_task (void *cls) |
2035 | { | 1819 | { |
2036 | struct StunExternalIP *se; | 1820 | struct StunExternalIP *se; |
2037 | struct AutoconfigContext *ac; | ||
2038 | 1821 | ||
2039 | while (NULL != (ac = ac_head)) | ||
2040 | { | ||
2041 | GNUNET_CONTAINER_DLL_remove (ac_head, | ||
2042 | ac_tail, | ||
2043 | ac); | ||
2044 | terminate_ac_activities (ac); | ||
2045 | GNUNET_free (ac); | ||
2046 | } | ||
2047 | while (NULL != (se = se_head)) | 1822 | while (NULL != (se = se_head)) |
2048 | { | 1823 | { |
2049 | GNUNET_CONTAINER_DLL_remove (se_head, | 1824 | GNUNET_CONTAINER_DLL_remove (se_head, |
@@ -2052,16 +1827,7 @@ shutdown_task (void *cls) | |||
2052 | GNUNET_SCHEDULER_cancel (se->timeout_task); | 1827 | GNUNET_SCHEDULER_cancel (se->timeout_task); |
2053 | GNUNET_free (se); | 1828 | GNUNET_free (se); |
2054 | } | 1829 | } |
2055 | if (NULL != probe_external_ip_task) | 1830 | GN_nat_status_changed (GNUNET_NO); |
2056 | { | ||
2057 | GNUNET_SCHEDULER_cancel (probe_external_ip_task); | ||
2058 | probe_external_ip_task = NULL; | ||
2059 | } | ||
2060 | if (NULL != probe_external_ip_op) | ||
2061 | { | ||
2062 | GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op); | ||
2063 | probe_external_ip_op = NULL; | ||
2064 | } | ||
2065 | if (NULL != scan_task) | 1831 | if (NULL != scan_task) |
2066 | { | 1832 | { |
2067 | GNUNET_SCHEDULER_cancel (scan_task); | 1833 | GNUNET_SCHEDULER_cancel (scan_task); |
@@ -2098,7 +1864,7 @@ run (void *cls, | |||
2098 | stun_stale_timeout = GNUNET_TIME_UNIT_HOURS; | 1864 | stun_stale_timeout = GNUNET_TIME_UNIT_HOURS; |
2099 | 1865 | ||
2100 | /* Check for UPnP */ | 1866 | /* Check for UPnP */ |
2101 | enable_upnp | 1867 | enable_upnp |
2102 | = GNUNET_CONFIGURATION_get_value_yesno (cfg, | 1868 | = GNUNET_CONFIGURATION_get_value_yesno (cfg, |
2103 | "NAT", | 1869 | "NAT", |
2104 | "ENABLE_UPNP"); | 1870 | "ENABLE_UPNP"); |
@@ -2115,7 +1881,13 @@ run (void *cls, | |||
2115 | enable_upnp = GNUNET_SYSERR; | 1881 | enable_upnp = GNUNET_SYSERR; |
2116 | } | 1882 | } |
2117 | } | 1883 | } |
2118 | 1884 | if (GNUNET_OK != | |
1885 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
1886 | "nat", | ||
1887 | "DYNDNS_FREQUENCY", | ||
1888 | &dyndns_frequency)) | ||
1889 | dyndns_frequency = DYNDNS_FREQUENCY; | ||
1890 | |||
2119 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | 1891 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, |
2120 | NULL); | 1892 | NULL); |
2121 | stats = GNUNET_STATISTICS_create ("nat", | 1893 | stats = GNUNET_STATISTICS_create ("nat", |
@@ -2163,6 +1935,7 @@ client_disconnect_cb (void *cls, | |||
2163 | void *internal_cls) | 1935 | void *internal_cls) |
2164 | { | 1936 | { |
2165 | struct ClientHandle *ch = internal_cls; | 1937 | struct ClientHandle *ch = internal_cls; |
1938 | struct LocalAddressList *lal; | ||
2166 | 1939 | ||
2167 | GNUNET_CONTAINER_DLL_remove (ch_head, | 1940 | GNUNET_CONTAINER_DLL_remove (ch_head, |
2168 | ch_tail, | 1941 | ch_tail, |
@@ -2176,7 +1949,30 @@ client_disconnect_cb (void *cls, | |||
2176 | } | 1949 | } |
2177 | } | 1950 | } |
2178 | GNUNET_free_non_null (ch->caddrs); | 1951 | GNUNET_free_non_null (ch->caddrs); |
2179 | GNUNET_free (ch->hole_external); | 1952 | while (NULL != (lal = ch->ext_addr_head)) |
1953 | { | ||
1954 | GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head, | ||
1955 | ch->ext_addr_tail, | ||
1956 | lal); | ||
1957 | GNUNET_free (lal); | ||
1958 | } | ||
1959 | if (NULL != ch->ext_dns_task) | ||
1960 | { | ||
1961 | GNUNET_SCHEDULER_cancel (ch->ext_dns_task); | ||
1962 | ch->ext_dns_task = NULL; | ||
1963 | } | ||
1964 | if (NULL != ch->external_monitor) | ||
1965 | { | ||
1966 | GN_external_ipv4_monitor_stop (ch->external_monitor); | ||
1967 | ch->external_monitor = NULL; | ||
1968 | } | ||
1969 | if (NULL != ch->ext_dns) | ||
1970 | { | ||
1971 | GNUNET_RESOLVER_request_cancel (ch->ext_dns); | ||
1972 | ch->ext_dns = NULL; | ||
1973 | } | ||
1974 | GNUNET_free_non_null (ch->hole_external); | ||
1975 | GNUNET_free_non_null (ch->section_name); | ||
2180 | GNUNET_free (ch); | 1976 | GNUNET_free (ch); |
2181 | } | 1977 | } |
2182 | 1978 | ||
@@ -2203,10 +1999,6 @@ GNUNET_SERVICE_MAIN | |||
2203 | GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, | 1999 | GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, |
2204 | struct GNUNET_NAT_RequestConnectionReversalMessage, | 2000 | struct GNUNET_NAT_RequestConnectionReversalMessage, |
2205 | NULL), | 2001 | NULL), |
2206 | GNUNET_MQ_hd_var_size (autoconfig_request, | ||
2207 | GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG, | ||
2208 | struct GNUNET_NAT_AutoconfigRequestMessage, | ||
2209 | NULL), | ||
2210 | GNUNET_MQ_handler_end ()); | 2002 | GNUNET_MQ_handler_end ()); |
2211 | 2003 | ||
2212 | 2004 | ||