diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-09-01 13:36:01 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-09-01 13:36:01 +0000 |
commit | 75bf71e92c81b966df11ad3c00228658f46a6e8f (patch) | |
tree | 610fecea7e6ce4b4bfda0f3a205f355dd0ef30be /src/nat/nat.c | |
parent | c09f6eb6d32f57778cf8f8baf0456cbe7158eb79 (diff) | |
download | gnunet-75bf71e92c81b966df11ad3c00228658f46a6e8f.tar.gz gnunet-75bf71e92c81b966df11ad3c00228658f46a6e8f.zip |
starting NAT code cleanup
Diffstat (limited to 'src/nat/nat.c')
-rw-r--r-- | src/nat/nat.c | 293 |
1 files changed, 161 insertions, 132 deletions
diff --git a/src/nat/nat.c b/src/nat/nat.c index 1df0da81a..cb031d35d 100644 --- a/src/nat/nat.c +++ b/src/nat/nat.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2010 Christian Grothoff (and other contributing authors) |
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 |
@@ -31,152 +31,161 @@ | |||
31 | * | 31 | * |
32 | * @author Milan Bouchet-Valat | 32 | * @author Milan Bouchet-Valat |
33 | */ | 33 | */ |
34 | #include <errno.h> | ||
35 | #include <string.h> | ||
36 | #include <stdio.h> | ||
37 | |||
38 | #include <sys/types.h> | ||
39 | |||
40 | #include "platform.h" | 34 | #include "platform.h" |
41 | #include "gnunet_common.h" | ||
42 | #include "gnunet_util_lib.h" | 35 | #include "gnunet_util_lib.h" |
43 | #include "gnunet_nat_lib.h" | 36 | #include "gnunet_nat_lib.h" |
37 | #include "nat.h" | ||
44 | #include "natpmp.h" | 38 | #include "natpmp.h" |
45 | #include "upnp.h" | 39 | #include "upnp.h" |
46 | 40 | ||
47 | /* Component name for logging */ | 41 | /** |
48 | #define COMP_NAT _("NAT") | 42 | * Handle for active NAT registrations. |
49 | #define DEBUG | 43 | */ |
50 | |||
51 | struct GNUNET_NAT_Handle | 44 | struct GNUNET_NAT_Handle |
52 | { | 45 | { |
53 | int is_enabled; | 46 | /** |
54 | 47 | * Handle for UPnP operations. | |
55 | enum GNUNET_NAT_port_forwarding natpmp_status; | 48 | */ |
56 | enum GNUNET_NAT_port_forwarding upnp_status; | ||
57 | |||
58 | int should_change; | ||
59 | u_short public_port; | ||
60 | |||
61 | GNUNET_NAT_UPNP_Handle *upnp; | 49 | GNUNET_NAT_UPNP_Handle *upnp; |
50 | |||
51 | /** | ||
52 | * Handle for NAT PMP operations. | ||
53 | */ | ||
62 | GNUNET_NAT_NATPMP_Handle *natpmp; | 54 | GNUNET_NAT_NATPMP_Handle *natpmp; |
63 | 55 | ||
56 | /** | ||
57 | * Scheduler. | ||
58 | */ | ||
64 | struct GNUNET_SCHEDULER_Handle *sched; | 59 | struct GNUNET_SCHEDULER_Handle *sched; |
65 | GNUNET_SCHEDULER_TaskIdentifier pulse_timer; | ||
66 | 60 | ||
67 | struct sockaddr *local_addr; /* LAN address as passed by the caller */ | 61 | /** |
68 | struct sockaddr *ext_addr; /* External address as reported by NAT box */ | 62 | * LAN address as passed by the caller |
69 | struct sockaddr *contact_addr; /* External address and port where paquets are redirected*/ | 63 | */ |
64 | struct sockaddr *local_addr; | ||
65 | |||
66 | /** | ||
67 | * External address as reported by NAT box | ||
68 | */ | ||
69 | struct sockaddr *ext_addr; | ||
70 | |||
71 | /** | ||
72 | * External address and port where packets are redirected | ||
73 | */ | ||
74 | struct sockaddr *contact_addr; | ||
75 | |||
70 | GNUNET_NAT_AddressCallback callback; | 76 | GNUNET_NAT_AddressCallback callback; |
77 | |||
78 | /** | ||
79 | * Closure for 'callback'. | ||
80 | */ | ||
71 | void *callback_cls; | 81 | void *callback_cls; |
82 | |||
83 | GNUNET_SCHEDULER_TaskIdentifier pulse_timer; | ||
84 | |||
85 | enum GNUNET_NAT_PortState natpmp_status; | ||
86 | |||
87 | enum GNUNET_NAT_PortState upnp_status; | ||
88 | |||
89 | int is_enabled; | ||
90 | |||
91 | int should_change; | ||
92 | |||
93 | int port_mapped; | ||
94 | |||
95 | int did_warn; | ||
96 | |||
97 | uint16_t public_port; | ||
98 | |||
72 | }; | 99 | }; |
73 | 100 | ||
74 | #ifdef DEBUG | 101 | #ifdef DEBUG |
75 | static const char * | 102 | static const char * |
76 | get_nat_state_str (int state) | 103 | get_nat_state_str (enum GNUNET_NAT_PortState state) |
77 | { | 104 | { |
78 | switch (state) | 105 | switch (state) |
79 | { | 106 | { |
80 | /* we're in the process of trying to set up port forwarding */ | ||
81 | case GNUNET_NAT_PORT_MAPPING: | 107 | case GNUNET_NAT_PORT_MAPPING: |
82 | return "Starting"; | 108 | return "Starting"; |
83 | |||
84 | /* we've successfully forwarded the port */ | ||
85 | case GNUNET_NAT_PORT_MAPPED: | 109 | case GNUNET_NAT_PORT_MAPPED: |
86 | return "Forwarded"; | 110 | return "Forwarded"; |
87 | |||
88 | /* we're cancelling the port forwarding */ | ||
89 | case GNUNET_NAT_PORT_UNMAPPING: | 111 | case GNUNET_NAT_PORT_UNMAPPING: |
90 | return "Stopping"; | 112 | return "Stopping"; |
91 | |||
92 | /* the port isn't forwarded */ | ||
93 | case GNUNET_NAT_PORT_UNMAPPED: | 113 | case GNUNET_NAT_PORT_UNMAPPED: |
94 | return "Not forwarded"; | 114 | return "Not forwarded"; |
95 | |||
96 | case GNUNET_NAT_PORT_ERROR: | 115 | case GNUNET_NAT_PORT_ERROR: |
97 | return "Redirection failed"; | 116 | return "Redirection failed"; |
117 | default: | ||
118 | return "not found"; | ||
98 | } | 119 | } |
99 | |||
100 | return "notfound"; | ||
101 | } | 120 | } |
102 | #endif | 121 | #endif |
103 | 122 | ||
123 | |||
104 | static int | 124 | static int |
105 | get_traversal_status (const struct GNUNET_NAT_Handle * s) | 125 | get_traversal_status (const struct GNUNET_NAT_Handle * s) |
106 | { | 126 | { |
107 | return MAX (s->natpmp_status, s->upnp_status); | 127 | return MAX (s->natpmp_status, s->upnp_status); |
108 | } | 128 | } |
109 | 129 | ||
130 | |||
110 | /** | 131 | /** |
111 | * Compare the sin(6)_addr fields of AF_INET or AF_INET(6) sockaddr. | 132 | * Compare the sin(6)_addr fields of AF_INET or AF_INET(6) sockaddr. |
112 | * @param a first sockaddr | 133 | * @param a first sockaddr |
113 | * @param b second sockaddr | 134 | * @param b second sockaddr |
114 | * @return 0 if addresses are equal, non-null value otherwise */ | 135 | * @return 0 if addresses are equal, non-null value otherwise */ |
115 | int | 136 | int |
116 | GNUNET_NAT_cmp_addr (const struct sockaddr *a, const struct sockaddr *b) | 137 | GNUNET_NAT_cmp_addr (const struct sockaddr *a, |
138 | const struct sockaddr *b) | ||
117 | { | 139 | { |
118 | if (!(a && b)) | 140 | if (!(a && b)) |
119 | return -1; | 141 | return -1; |
120 | 142 | if ( (a->sa_family == AF_INET) && (b->sa_family == AF_INET) ) | |
121 | if (a->sa_family == AF_INET && b->sa_family == AF_INET) | ||
122 | return memcmp (&(((struct sockaddr_in *) a)->sin_addr), | 143 | return memcmp (&(((struct sockaddr_in *) a)->sin_addr), |
123 | &(((struct sockaddr_in *) b)->sin_addr), | 144 | &(((struct sockaddr_in *) b)->sin_addr), |
124 | sizeof (struct in_addr)); | 145 | sizeof (struct in_addr)); |
125 | else if (a->sa_family == AF_INET6 && b->sa_family == AF_INET6) | 146 | if ( (a->sa_family == AF_INET6) && (b->sa_family == AF_INET6) ) |
126 | return memcmp (&(((struct sockaddr_in6 *) a)->sin6_addr), | 147 | return memcmp (&(((struct sockaddr_in6 *) a)->sin6_addr), |
127 | &(((struct sockaddr_in6 *) b)->sin6_addr), | 148 | &(((struct sockaddr_in6 *) b)->sin6_addr), |
128 | sizeof (struct in6_addr)); | 149 | sizeof (struct in6_addr)); |
129 | else | 150 | return -1; |
130 | return -1; | ||
131 | } | 151 | } |
132 | 152 | ||
133 | /* Deal with a new IP address or port redirection: | 153 | |
154 | /** | ||
155 | * Deal with a new IP address or port redirection: | ||
134 | * Send signals with the appropriate sockaddr (IP and port), free and changes | 156 | * Send signals with the appropriate sockaddr (IP and port), free and changes |
135 | * or nullify the previous sockaddr. Change the port if needed. | 157 | * or nullify the previous sockaddr. Change the port if needed. |
136 | */ | 158 | */ |
137 | static void | 159 | static void |
138 | notify_change (struct GNUNET_NAT_Handle *nat, struct sockaddr *addr, int new_port_mapped) | 160 | notify_change (struct GNUNET_NAT_Handle *nat, |
161 | struct sockaddr *addr, | ||
162 | size_t addrlen, | ||
163 | int new_port_mapped) | ||
139 | { | 164 | { |
140 | static int port_mapped = GNUNET_NO; | 165 | if (new_port_mapped == nat->port_mapped) |
141 | |||
142 | /* Nothing to do. We already check in nat_pulse() that addr has changed */ | ||
143 | if (new_port_mapped == port_mapped) | ||
144 | return; | 166 | return; |
145 | 167 | nat->port_mapped = new_port_mapped; | |
146 | port_mapped = new_port_mapped; | 168 | |
147 | 169 | if ( (NULL != nat->contact_addr) && | |
148 | if (nat->contact_addr && nat->callback) | 170 | (NULL != nat->callback) ) |
149 | (*nat->callback) (nat->callback_cls, GNUNET_NO, (struct sockaddr *) &nat->contact_addr, | 171 | nat->callback (nat->callback_cls, |
150 | sizeof (nat->contact_addr)); | 172 | GNUNET_NO, |
151 | 173 | nat->contact_addr, | |
152 | /* At this point, we're sure contact_addr has changed */ | 174 | sizeof (nat->contact_addr)); |
153 | if (nat->contact_addr) | 175 | GNUNET_free_non_null (nat->contact_addr); |
154 | { | 176 | nat->contact_addr = NULL; |
155 | GNUNET_free (nat->contact_addr); | 177 | GNUNET_free_non_null (nat->ext_addr); |
156 | nat->contact_addr = NULL; | 178 | nat->ext_addr = NULL; |
157 | } | 179 | if (NULL == addr) |
158 | 180 | return; | |
159 | /* No address, don't signal a new one */ | 181 | nat->ext_addr = GNUNET_malloc (addrlen); |
160 | if (!addr) | 182 | memcpy (nat->ext_addr, addr, addrlen); |
161 | { | ||
162 | if (nat->ext_addr) | ||
163 | GNUNET_free (nat->ext_addr); | ||
164 | nat->ext_addr = NULL; | ||
165 | return; | ||
166 | } | ||
167 | /* Copy the new address and use it */ | ||
168 | else if (addr != nat->ext_addr) | ||
169 | { | ||
170 | if (nat->ext_addr) | ||
171 | GNUNET_free (nat->ext_addr); | ||
172 | nat->ext_addr = GNUNET_malloc (sizeof (*addr)); | ||
173 | memcpy (nat->ext_addr, addr, sizeof (*addr)); | ||
174 | } | ||
175 | 183 | ||
176 | /* Recreate the ext_addr:public_port bogus address to pass to the callback */ | 184 | /* Recreate the ext_addr:public_port bogus address to pass to the callback */ |
177 | if (nat->ext_addr->sa_family == AF_INET) | 185 | if (nat->ext_addr->sa_family == AF_INET) |
178 | { | 186 | { |
179 | struct sockaddr_in *tmp_addr; | 187 | struct sockaddr_in tmp_addr; |
188 | |||
180 | tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in)); | 189 | tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in)); |
181 | tmp_addr->sin_family = AF_INET; | 190 | tmp_addr->sin_family = AF_INET; |
182 | #ifdef HAVE_SOCKADDR_IN_SIN_LEN | 191 | #ifdef HAVE_SOCKADDR_IN_SIN_LEN |
@@ -185,13 +194,16 @@ notify_change (struct GNUNET_NAT_Handle *nat, struct sockaddr *addr, int new_por | |||
185 | tmp_addr->sin_port = port_mapped ? htons (nat->public_port) : 0; | 194 | tmp_addr->sin_port = port_mapped ? htons (nat->public_port) : 0; |
186 | tmp_addr->sin_addr = ((struct sockaddr_in *) nat->ext_addr)->sin_addr; | 195 | tmp_addr->sin_addr = ((struct sockaddr_in *) nat->ext_addr)->sin_addr; |
187 | nat->contact_addr = (struct sockaddr *) tmp_addr; | 196 | nat->contact_addr = (struct sockaddr *) tmp_addr; |
188 | if (nat->callback) | 197 | if (NULL != nat->callback) |
189 | (*nat->callback) (nat->callback_cls, GNUNET_YES, nat->contact_addr, | 198 | nat->callback (nat->callback_cls, |
190 | sizeof (struct sockaddr_in)); | 199 | GNUNET_YES, |
200 | nat->contact_addr, | ||
201 | sizeof (struct sockaddr_in)); | ||
191 | } | 202 | } |
192 | else if (nat->ext_addr->sa_family == AF_INET6) | 203 | else if (nat->ext_addr->sa_family == AF_INET6) |
193 | { | 204 | { |
194 | struct sockaddr_in6 *tmp_addr; | 205 | struct sockaddr_in6 *tmp_addr; |
206 | |||
195 | tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in6)); | 207 | tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in6)); |
196 | tmp_addr->sin6_family = AF_INET6; | 208 | tmp_addr->sin6_family = AF_INET6; |
197 | #ifdef HAVE_SOCKADDR_IN_SIN_LEN | 209 | #ifdef HAVE_SOCKADDR_IN_SIN_LEN |
@@ -200,23 +212,31 @@ notify_change (struct GNUNET_NAT_Handle *nat, struct sockaddr *addr, int new_por | |||
200 | tmp_addr->sin6_port = port_mapped ? htons (nat->public_port) : 0; | 212 | tmp_addr->sin6_port = port_mapped ? htons (nat->public_port) : 0; |
201 | tmp_addr->sin6_addr = ((struct sockaddr_in6 *) nat->ext_addr)->sin6_addr; | 213 | tmp_addr->sin6_addr = ((struct sockaddr_in6 *) nat->ext_addr)->sin6_addr; |
202 | nat->contact_addr = (struct sockaddr *) tmp_addr; | 214 | nat->contact_addr = (struct sockaddr *) tmp_addr; |
203 | if (nat->callback) | 215 | if (NULL != nat->callback) |
204 | (*nat->callback) (nat->callback_cls, GNUNET_YES, nat->contact_addr, | 216 | nat->callback (nat->callback_cls, |
205 | sizeof (struct sockaddr_in6)); | 217 | GNUNET_YES, |
218 | nat->contact_addr, | ||
219 | sizeof (struct sockaddr_in6)); | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | GNUNET_break (0); | ||
206 | } | 224 | } |
207 | } | 225 | } |
208 | 226 | ||
227 | |||
209 | static void | 228 | static void |
210 | nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 229 | nat_pulse (void *cls, |
230 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
211 | { | 231 | { |
212 | struct GNUNET_NAT_Handle *nat = cls; | 232 | struct GNUNET_NAT_Handle *nat = cls; |
213 | static int first_warning = GNUNET_YES; | ||
214 | int old_status; | 233 | int old_status; |
215 | int new_status; | 234 | int new_status; |
216 | int port_mapped; | 235 | int port_mapped; |
217 | struct sockaddr *ext_addr_upnp = NULL; | 236 | struct sockaddr *ext_addr_upnp = NULL; |
218 | struct sockaddr *ext_addr_natpmp = NULL; | 237 | struct sockaddr *ext_addr_natpmp = NULL; |
219 | 238 | ||
239 | nat->pulse_timer = GNUNET_SCHEDULER_NO_TASK; | ||
220 | old_status = get_traversal_status (nat); | 240 | old_status = get_traversal_status (nat); |
221 | 241 | ||
222 | /* Only update the protocol that has been successful until now */ | 242 | /* Only update the protocol that has been successful until now */ |
@@ -230,6 +250,7 @@ nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
230 | &ext_addr_natpmp); | 250 | &ext_addr_natpmp); |
231 | else | 251 | else |
232 | { | 252 | { |
253 | /* try both */ | ||
233 | nat->upnp_status = | 254 | nat->upnp_status = |
234 | GNUNET_NAT_UPNP_pulse (nat->upnp, nat->is_enabled, GNUNET_YES, | 255 | GNUNET_NAT_UPNP_pulse (nat->upnp, nat->is_enabled, GNUNET_YES, |
235 | &ext_addr_upnp); | 256 | &ext_addr_upnp); |
@@ -237,18 +258,17 @@ nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
237 | GNUNET_NAT_NATPMP_pulse (nat->natpmp, nat->is_enabled, | 258 | GNUNET_NAT_NATPMP_pulse (nat->natpmp, nat->is_enabled, |
238 | &ext_addr_natpmp); | 259 | &ext_addr_natpmp); |
239 | } | 260 | } |
240 | |||
241 | new_status = get_traversal_status (nat); | 261 | new_status = get_traversal_status (nat); |
242 | 262 | if ( (old_status != new_status) && | |
243 | if (old_status != new_status && | 263 | ( (new_status == GNUNET_NAT_PORT_UNMAPPED) || |
244 | (new_status == GNUNET_NAT_PORT_UNMAPPED || new_status == GNUNET_NAT_PORT_ERROR)) | 264 | (new_status == GNUNET_NAT_PORT_ERROR) ) ) |
245 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, | 265 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, |
266 | "NAT", | ||
246 | _("Port redirection failed: no UPnP or NAT-PMP routers supporting this feature found\n")); | 267 | _("Port redirection failed: no UPnP or NAT-PMP routers supporting this feature found\n")); |
247 | |||
248 | #ifdef DEBUG | 268 | #ifdef DEBUG |
249 | if (new_status != old_status) | 269 | if (new_status != old_status) |
250 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, COMP_NAT, | 270 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "NAT", |
251 | _("State changed from \"%s\" to \"%s\"\n"), | 271 | _("State changed from `%s' to `%s'\n"), |
252 | get_nat_state_str (old_status), | 272 | get_nat_state_str (old_status), |
253 | get_nat_state_str (new_status)); | 273 | get_nat_state_str (new_status)); |
254 | #endif | 274 | #endif |
@@ -257,53 +277,64 @@ nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
257 | if (!(ext_addr_upnp || ext_addr_natpmp)) | 277 | if (!(ext_addr_upnp || ext_addr_natpmp)) |
258 | { | 278 | { |
259 | /* Address has just changed and we could not get it, or it's the first try */ | 279 | /* Address has just changed and we could not get it, or it's the first try */ |
260 | if (nat->ext_addr || first_warning) | 280 | if ( (NULL != nat->ext_addr) || |
281 | (GNUNET_NO == nat->did_warn) ) | ||
261 | { | 282 | { |
262 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, | 283 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, |
263 | _("Could not determine external IP address\n")); | 284 | "NAT", |
264 | first_warning = GNUNET_NO; | 285 | _("Could not determine external IP address\n")); |
286 | nat->did_warn = GNUNET_YES; | ||
265 | } | 287 | } |
266 | |||
267 | notify_change (nat, NULL, port_mapped); | 288 | notify_change (nat, NULL, port_mapped); |
268 | } | 289 | } |
269 | else if (ext_addr_upnp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_upnp) != 0) | 290 | else if (ext_addr_upnp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_upnp) != 0) |
270 | { | 291 | { |
271 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, | 292 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, |
272 | _("External IP address changed from %s to %s\n"), | 293 | "NAT", |
273 | GNUNET_a2s (nat->ext_addr, sizeof (nat->ext_addr)), | 294 | _("External IP address changed to %s\n"), |
274 | GNUNET_a2s (ext_addr_upnp, sizeof (ext_addr_upnp))); | 295 | GNUNET_a2s (ext_addr_upnp, sizeof (ext_addr_upnp))); |
275 | |||
276 | notify_change (nat, ext_addr_upnp, port_mapped); | 296 | notify_change (nat, ext_addr_upnp, port_mapped); |
277 | } | 297 | } |
278 | else if (ext_addr_natpmp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_natpmp) != 0) | 298 | else if (ext_addr_natpmp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_natpmp) != 0) |
279 | { | 299 | { |
280 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, | 300 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "NAT", |
281 | _("External IP address changed from %s to %s\n"), | 301 | _("External IP address changed to `%s'\n"), |
282 | GNUNET_a2s (nat->ext_addr, sizeof (nat->ext_addr)), | 302 | GNUNET_a2s (ext_addr_natpmp, sizeof (ext_addr_natpmp))); |
283 | GNUNET_a2s (ext_addr_natpmp, sizeof (ext_addr_natpmp))); | ||
284 | |||
285 | notify_change (nat, ext_addr_natpmp, port_mapped); | 303 | notify_change (nat, ext_addr_natpmp, port_mapped); |
286 | } | 304 | } |
287 | |||
288 | nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (nat->sched, | 305 | nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (nat->sched, |
289 | GNUNET_TIME_UNIT_SECONDS, | 306 | GNUNET_TIME_UNIT_SECONDS, |
290 | &nat_pulse, nat); | 307 | &nat_pulse, nat); |
291 | } | 308 | } |
292 | 309 | ||
310 | |||
311 | /** | ||
312 | * Attempt to enable port redirection and detect public IP address contacting | ||
313 | * UPnP or NAT-PMP routers on the local network. Use addr to specify to which | ||
314 | * of the local host's addresses should the external port be mapped. The port | ||
315 | * is taken from the corresponding sockaddr_in[6] field. | ||
316 | * | ||
317 | * @param sched the sheduler used in the program | ||
318 | * @param addr the local address packets should be redirected to | ||
319 | * @param addrlen actual lenght of the address | ||
320 | * @param callback function to call everytime the public IP address changes | ||
321 | * @param callback_cls closure for callback | ||
322 | * @return NULL on error, otherwise handle that can be used to unregister | ||
323 | */ | ||
293 | struct GNUNET_NAT_Handle * | 324 | struct GNUNET_NAT_Handle * |
294 | GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched, | 325 | GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched, |
295 | const struct sockaddr *addr, socklen_t addrlen, | 326 | const struct sockaddr *addr, socklen_t addrlen, |
296 | GNUNET_NAT_AddressCallback callback, void *callback_cls) | 327 | GNUNET_NAT_AddressCallback callback, void *callback_cls) |
297 | { | 328 | { |
298 | struct GNUNET_NAT_Handle *nat = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle)); | 329 | struct GNUNET_NAT_Handle *nat; |
299 | 330 | ||
331 | nat = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle)); | ||
300 | if (addr) | 332 | if (addr) |
301 | { | 333 | { |
302 | GNUNET_assert (addr->sa_family == AF_INET | 334 | GNUNET_assert ( (addr->sa_family == AF_INET) || |
303 | || addr->sa_family == AF_INET6); | 335 | (addr->sa_family == AF_INET6) ); |
304 | nat->local_addr = GNUNET_malloc (addrlen); | 336 | nat->local_addr = GNUNET_malloc (addrlen); |
305 | memcpy (nat->local_addr, addr, addrlen); | 337 | memcpy (nat->local_addr, addr, addrlen); |
306 | |||
307 | if (addr->sa_family == AF_INET) | 338 | if (addr->sa_family == AF_INET) |
308 | { | 339 | { |
309 | nat->public_port = ntohs (((struct sockaddr_in *) addr)->sin_port); | 340 | nat->public_port = ntohs (((struct sockaddr_in *) addr)->sin_port); |
@@ -315,12 +346,6 @@ GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched, | |||
315 | ((struct sockaddr_in6 *) nat->local_addr)->sin6_port = 0; | 346 | ((struct sockaddr_in6 *) nat->local_addr)->sin6_port = 0; |
316 | } | 347 | } |
317 | } | 348 | } |
318 | else | ||
319 | { | ||
320 | nat->local_addr = NULL; | ||
321 | nat->public_port = 0; | ||
322 | } | ||
323 | |||
324 | nat->should_change = GNUNET_YES; | 349 | nat->should_change = GNUNET_YES; |
325 | nat->sched = sched; | 350 | nat->sched = sched; |
326 | nat->is_enabled = GNUNET_YES; | 351 | nat->is_enabled = GNUNET_YES; |
@@ -328,37 +353,41 @@ GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched, | |||
328 | nat->natpmp_status = GNUNET_NAT_PORT_UNMAPPED; | 353 | nat->natpmp_status = GNUNET_NAT_PORT_UNMAPPED; |
329 | nat->callback = callback; | 354 | nat->callback = callback; |
330 | nat->callback_cls = callback_cls; | 355 | nat->callback_cls = callback_cls; |
331 | nat->ext_addr = NULL; | ||
332 | nat->contact_addr = NULL; | ||
333 | nat->natpmp = GNUNET_NAT_NATPMP_init (nat->local_addr, addrlen, nat->public_port); | 356 | nat->natpmp = GNUNET_NAT_NATPMP_init (nat->local_addr, addrlen, nat->public_port); |
334 | nat->upnp = GNUNET_NAT_UPNP_init (nat->local_addr, addrlen, nat->public_port); | 357 | nat->upnp = GNUNET_NAT_UPNP_init (nat->local_addr, addrlen, nat->public_port); |
335 | |||
336 | nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (sched, | 358 | nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (sched, |
337 | GNUNET_TIME_UNIT_SECONDS, | 359 | GNUNET_TIME_UNIT_SECONDS, |
338 | &nat_pulse, nat); | 360 | &nat_pulse, nat); |
339 | |||
340 | return nat; | 361 | return nat; |
341 | } | 362 | } |
342 | 363 | ||
364 | |||
365 | /** | ||
366 | * Stop port redirection and public IP address detection for the given handle. | ||
367 | * This frees the handle, after having sent the needed commands to close open ports. | ||
368 | * | ||
369 | * @param h the handle to stop | ||
370 | */ | ||
343 | void | 371 | void |
344 | GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nat) | 372 | GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nat) |
345 | { | 373 | { |
346 | struct sockaddr *addr; | 374 | struct sockaddr *addr; |
347 | GNUNET_SCHEDULER_cancel (nat->sched, nat->pulse_timer); | ||
348 | 375 | ||
376 | GNUNET_SCHEDULER_cancel (nat->sched, | ||
377 | nat->pulse_timer); | ||
349 | nat->upnp_status = | 378 | nat->upnp_status = |
350 | GNUNET_NAT_UPNP_pulse (nat->upnp, GNUNET_NO, GNUNET_NO, | 379 | GNUNET_NAT_UPNP_pulse (nat->upnp, |
380 | GNUNET_NO, GNUNET_NO, | ||
351 | &addr); | 381 | &addr); |
352 | nat->natpmp_status = | 382 | nat->natpmp_status = |
353 | GNUNET_NAT_NATPMP_pulse (nat->natpmp, GNUNET_NO, | 383 | GNUNET_NAT_NATPMP_pulse (nat->natpmp, GNUNET_NO, |
354 | &addr); | 384 | &addr); |
355 | |||
356 | GNUNET_NAT_NATPMP_close (nat->natpmp); | 385 | GNUNET_NAT_NATPMP_close (nat->natpmp); |
357 | GNUNET_NAT_UPNP_close (nat->upnp); | 386 | GNUNET_NAT_UPNP_close (nat->upnp); |
358 | 387 | GNUNET_free_non_null (nat->local_addr); | |
359 | if (nat->local_addr) | 388 | GNUNET_free_non_null (nat->ext_addr); |
360 | GNUNET_free (nat->local_addr); | ||
361 | if (nat->ext_addr) | ||
362 | GNUNET_free (nat->ext_addr); | ||
363 | GNUNET_free (nat); | 389 | GNUNET_free (nat); |
364 | } | 390 | } |
391 | |||
392 | /* end of nat.c */ | ||
393 | |||