diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-10-07 09:51:33 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-10-07 09:51:33 +0000 |
commit | 117a6b2f87eab48523f3ecd0d72d28ad9903c849 (patch) | |
tree | dc47d59f75047a2dfab458f116f4f80fa84ad57c /src/nat | |
parent | 886d8cda082a8005c1a73a6d6603b9791121a7ae (diff) | |
download | gnunet-117a6b2f87eab48523f3ecd0d72d28ad9903c849.tar.gz gnunet-117a6b2f87eab48523f3ecd0d72d28ad9903c849.zip |
stylistic fixes
Diffstat (limited to 'src/nat')
-rw-r--r-- | src/nat/nat.c | 6 | ||||
-rw-r--r-- | src/nat/nat_stun.c | 718 | ||||
-rw-r--r-- | src/nat/nat_stun.h | 103 |
3 files changed, 398 insertions, 429 deletions
diff --git a/src/nat/nat.c b/src/nat/nat.c index 709a13f03..3573ec497 100644 --- a/src/nat/nat.c +++ b/src/nat/nat.c | |||
@@ -1734,7 +1734,9 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
1734 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); | 1734 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); |
1735 | if ((GNUNET_YES == h->enable_nat_client) && | 1735 | if ((GNUNET_YES == h->enable_nat_client) && |
1736 | (GNUNET_YES != | 1736 | (GNUNET_YES != |
1737 | GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d 127.0.0.1 127.0.0.2 42"))) // none of these parameters are actually used in privilege testing mode | 1737 | GNUNET_OS_check_helper_binary (binary, |
1738 | GNUNET_YES, | ||
1739 | "-d 127.0.0.1 127.0.0.2 42"))) /* none of these parameters are actually used in privilege testing mode */ | ||
1738 | { | 1740 | { |
1739 | h->enable_nat_client = GNUNET_NO; | 1741 | h->enable_nat_client = GNUNET_NO; |
1740 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1742 | LOG (GNUNET_ERROR_TYPE_WARNING, |
@@ -1814,7 +1816,7 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h) | |||
1814 | GNUNET_SCHEDULER_cancel (h->dns_task); | 1816 | GNUNET_SCHEDULER_cancel (h->dns_task); |
1815 | h->dns_task = NULL; | 1817 | h->dns_task = NULL; |
1816 | } | 1818 | } |
1817 | if (NULL != h->stun_task) | 1819 | if (NULL != h->stun_task) |
1818 | { | 1820 | { |
1819 | GNUNET_SCHEDULER_cancel (h->stun_task); | 1821 | GNUNET_SCHEDULER_cancel (h->stun_task); |
1820 | h->stun_task = NULL; | 1822 | h->stun_task = NULL; |
diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c index 5c819356c..66b4265a8 100644 --- a/src/nat/nat_stun.c +++ b/src/nat/nat_stun.c | |||
@@ -17,9 +17,7 @@ | |||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | |||
21 | /** | 20 | /** |
22 | * | ||
23 | * This code provides some support for doing STUN transactions. | 21 | * This code provides some support for doing STUN transactions. |
24 | * We send simplest possible packet ia REQUEST with BIND to a STUN server. | 22 | * We send simplest possible packet ia REQUEST with BIND to a STUN server. |
25 | * | 23 | * |
@@ -32,7 +30,6 @@ | |||
32 | * | 30 | * |
33 | * This code was based on ministun.c. | 31 | * This code was based on ministun.c. |
34 | * | 32 | * |
35 | * | ||
36 | * @file nat/nat_stun.c | 33 | * @file nat/nat_stun.c |
37 | * @brief Functions for STUN functionality | 34 | * @brief Functions for STUN functionality |
38 | * @author Bruno Souza Cabral | 35 | * @author Bruno Souza Cabral |
@@ -56,51 +53,52 @@ | |||
56 | * the request prior to the timeout or successful execution. Also | 53 | * the request prior to the timeout or successful execution. Also |
57 | * used to track our internal state for the request. | 54 | * used to track our internal state for the request. |
58 | */ | 55 | */ |
59 | struct GNUNET_NAT_STUN_Handle { | 56 | struct GNUNET_NAT_STUN_Handle |
60 | 57 | { | |
61 | /** | ||
62 | * Handle to a pending DNS lookup request. | ||
63 | */ | ||
64 | struct GNUNET_RESOLVER_RequestHandle *dns_active; | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Handle to the listen socket | ||
69 | */ | ||
70 | struct GNUNET_NETWORK_Handle * sock; | ||
71 | |||
72 | /** | ||
73 | * Stun server address | ||
74 | */ | ||
75 | char *stun_server ; | ||
76 | |||
77 | /** | ||
78 | * STUN port | ||
79 | */ | ||
80 | int stun_port; | ||
81 | |||
82 | /** | ||
83 | * Function to call when a error occours | ||
84 | */ | ||
85 | GNUNET_NAT_STUN_ErrorCallback cb; | ||
86 | |||
87 | /** | ||
88 | * Closure for @e cb. | ||
89 | */ | ||
90 | void *cb_cls; | ||
91 | |||
92 | /** | ||
93 | * Do we got a DNS resolution successfully ? | ||
94 | */ | ||
95 | int dns_success; | ||
96 | 58 | ||
59 | /** | ||
60 | * Handle to a pending DNS lookup request. | ||
61 | */ | ||
62 | struct GNUNET_RESOLVER_RequestHandle *dns_active; | ||
63 | |||
64 | /** | ||
65 | * Handle to the listen socket | ||
66 | */ | ||
67 | struct GNUNET_NETWORK_Handle *sock; | ||
68 | |||
69 | /** | ||
70 | * Stun server address | ||
71 | */ | ||
72 | char *stun_server; | ||
73 | |||
74 | /** | ||
75 | * Function to call when a error occours | ||
76 | */ | ||
77 | GNUNET_NAT_STUN_ErrorCallback cb; | ||
78 | |||
79 | /** | ||
80 | * Closure for @e cb. | ||
81 | */ | ||
82 | void *cb_cls; | ||
83 | |||
84 | /** | ||
85 | * Do we got a DNS resolution successfully? | ||
86 | */ | ||
87 | int dns_success; | ||
88 | |||
89 | /** | ||
90 | * STUN port | ||
91 | */ | ||
92 | uint16_t stun_port; | ||
97 | 93 | ||
98 | }; | 94 | }; |
99 | 95 | ||
100 | 96 | ||
101 | 97 | /** | |
102 | /* here we store credentials extracted from a message */ | 98 | * here we store credentials extracted from a message |
103 | struct StunState { | 99 | */ |
100 | struct StunState | ||
101 | { | ||
104 | uint16_t attr; | 102 | uint16_t attr; |
105 | }; | 103 | }; |
106 | 104 | ||
@@ -114,8 +112,8 @@ struct StunState { | |||
114 | static int | 112 | static int |
115 | decode_class(int msg) | 113 | decode_class(int msg) |
116 | { | 114 | { |
117 | /* Sorry for the magic, but this maps the class according to rfc5245 */ | 115 | /* Sorry for the magic, but this maps the class according to rfc5245 */ |
118 | return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); | 116 | return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); |
119 | } | 117 | } |
120 | 118 | ||
121 | /** | 119 | /** |
@@ -127,9 +125,10 @@ decode_class(int msg) | |||
127 | static int | 125 | static int |
128 | decode_method(int msg) | 126 | decode_method(int msg) |
129 | { | 127 | { |
130 | return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); | 128 | return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); |
131 | } | 129 | } |
132 | 130 | ||
131 | |||
133 | /** | 132 | /** |
134 | * Encode a class and method to a compatible STUN format | 133 | * Encode a class and method to a compatible STUN format |
135 | * | 134 | * |
@@ -138,12 +137,14 @@ decode_method(int msg) | |||
138 | * @return message in a STUN compatible format | 137 | * @return message in a STUN compatible format |
139 | */ | 138 | */ |
140 | static int | 139 | static int |
141 | encode_message(StunClasses msg_class, StunMethods method) | 140 | encode_message (enum StunClasses msg_class, |
141 | enum StunMethods method) | ||
142 | { | 142 | { |
143 | return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | | 143 | return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | |
144 | (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); | 144 | (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); |
145 | } | 145 | } |
146 | 146 | ||
147 | |||
147 | /** | 148 | /** |
148 | * Print a class and method from a STUN message | 149 | * Print a class and method from a STUN message |
149 | * | 150 | * |
@@ -153,44 +154,46 @@ encode_message(StunClasses msg_class, StunMethods method) | |||
153 | static const char * | 154 | static const char * |
154 | stun_msg2str(int msg) | 155 | stun_msg2str(int msg) |
155 | { | 156 | { |
156 | 157 | static const struct { enum StunClasses value; const char *name; } classes[] = { | |
157 | const struct { enum StunClasses value; const char *name; } classes[] = { | 158 | { STUN_REQUEST, "Request" }, |
158 | { STUN_REQUEST, "Request" }, | 159 | { STUN_INDICATION, "Indication" }, |
159 | { STUN_INDICATION, "Indication" }, | 160 | { STUN_RESPONSE, "Response" }, |
160 | { STUN_RESPONSE, "Response" }, | 161 | { STUN_ERROR_RESPONSE, "Error Response" }, |
161 | { STUN_ERROR_RESPONSE, "Error Response" }, | 162 | { 0, NULL } |
162 | { 0, NULL } | 163 | }; |
163 | }; | 164 | static const struct { enum StunMethods value; const char *name; } methods[] = { |
164 | 165 | { STUN_BINDING, "Binding" }, | |
165 | const struct { enum StunMethods value; const char *name; } methods[] = { | 166 | { 0, NULL } |
166 | { STUN_BINDING, "Binding" }, | 167 | }; |
167 | { 0, NULL } | 168 | static char result[32]; |
168 | }; | 169 | const char *msg_class = NULL; |
169 | 170 | const char *method = NULL; | |
170 | static char result[32]; | 171 | int i; |
171 | const char *msg_class = NULL; | 172 | int value; |
172 | const char *method = NULL; | 173 | |
173 | int i; | 174 | value = decode_class(msg); |
174 | int value; | 175 | for (i = 0; classes[i].name; i++) |
175 | 176 | { | |
176 | value = decode_class(msg); | 177 | msg_class = classes[i].name; |
177 | for (i = 0; classes[i].name; i++) { | 178 | if (classes[i].value == value) |
178 | msg_class = classes[i].name; | 179 | break; |
179 | if (classes[i].value == value) | 180 | } |
180 | break; | 181 | value = decode_method(msg); |
181 | } | 182 | for (i = 0; methods[i].name; i++) |
182 | value = decode_method(msg); | 183 | { |
183 | for (i = 0; methods[i].name; i++) { | 184 | method = methods[i].name; |
184 | method = methods[i].name; | 185 | if (methods[i].value == value) |
185 | if (methods[i].value == value) | 186 | break; |
186 | break; | 187 | } |
187 | } | 188 | GNUNET_snprintf (result, |
188 | GNUNET_snprintf(result, sizeof(result), "%s %s", | 189 | sizeof(result), |
189 | method ? : "Unknown Method", | 190 | "%s %s", |
190 | msg_class ? : "Unknown Class Message"); | 191 | method ? : "Unknown Method", |
191 | return result; | 192 | msg_class ? : "Unknown Class Message"); |
193 | return result; | ||
192 | } | 194 | } |
193 | 195 | ||
196 | |||
194 | /** | 197 | /** |
195 | * Print attribute name | 198 | * Print attribute name |
196 | * | 199 | * |
@@ -200,69 +203,39 @@ stun_msg2str(int msg) | |||
200 | static const char * | 203 | static const char * |
201 | stun_attr2str(int msg) | 204 | stun_attr2str(int msg) |
202 | { | 205 | { |
203 | const struct { enum StunAttributes value; const char *name; } attrs[] = { | 206 | const struct { enum StunAttributes value; const char *name; } attrs[] = { |
204 | { STUN_MAPPED_ADDRESS, "Mapped Address" }, | 207 | { STUN_MAPPED_ADDRESS, "Mapped Address" }, |
205 | { STUN_RESPONSE_ADDRESS, "Response Address" }, | 208 | { STUN_RESPONSE_ADDRESS, "Response Address" }, |
206 | { STUN_CHANGE_ADDRESS, "Change Address" }, | 209 | { STUN_CHANGE_ADDRESS, "Change Address" }, |
207 | { STUN_SOURCE_ADDRESS, "Source Address" }, | 210 | { STUN_SOURCE_ADDRESS, "Source Address" }, |
208 | { STUN_CHANGED_ADDRESS, "Changed Address" }, | 211 | { STUN_CHANGED_ADDRESS, "Changed Address" }, |
209 | { STUN_USERNAME, "Username" }, | 212 | { STUN_USERNAME, "Username" }, |
210 | { STUN_PASSWORD, "Password" }, | 213 | { STUN_PASSWORD, "Password" }, |
211 | { STUN_MESSAGE_INTEGRITY, "Message Integrity" }, | 214 | { STUN_MESSAGE_INTEGRITY, "Message Integrity" }, |
212 | { STUN_ERROR_CODE, "Error Code" }, | 215 | { STUN_ERROR_CODE, "Error Code" }, |
213 | { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" }, | 216 | { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" }, |
214 | { STUN_REFLECTED_FROM, "Reflected From" }, | 217 | { STUN_REFLECTED_FROM, "Reflected From" }, |
215 | { STUN_REALM, "Realm" }, | 218 | { STUN_REALM, "Realm" }, |
216 | { STUN_NONCE, "Nonce" }, | 219 | { STUN_NONCE, "Nonce" }, |
217 | { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" }, | 220 | { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" }, |
218 | { STUN_MS_VERSION, "MS Version" }, | 221 | { STUN_MS_VERSION, "MS Version" }, |
219 | { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" }, | 222 | { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" }, |
220 | { STUN_SOFTWARE, "Software" }, | 223 | { STUN_SOFTWARE, "Software" }, |
221 | { STUN_ALTERNATE_SERVER, "Alternate Server" }, | 224 | { STUN_ALTERNATE_SERVER, "Alternate Server" }, |
222 | { STUN_FINGERPRINT, "Fingerprint" }, | 225 | { STUN_FINGERPRINT, "Fingerprint" }, |
223 | { 0, NULL } | 226 | { 0, NULL } |
224 | }; | 227 | }; |
225 | int i; | 228 | unsigned int i; |
226 | 229 | ||
227 | for (i = 0; attrs[i].name; i++) { | 230 | for (i = 0; attrs[i].name; i++) |
228 | if (attrs[i].value == msg) | 231 | { |
229 | return attrs[i].name; | 232 | if (attrs[i].value == msg) |
230 | } | 233 | return attrs[i].name; |
231 | return "Unknown Attribute"; | 234 | } |
232 | } | 235 | return "Unknown Attribute"; |
233 | |||
234 | |||
235 | /** | ||
236 | * Fill the stun_header with a random request_id | ||
237 | * | ||
238 | * @param state, STUN attribute type | ||
239 | * @param attr , the actual attribute | ||
240 | * | ||
241 | * @param req, stun header to be filled | ||
242 | */ | ||
243 | static int | ||
244 | stun_process_attr(struct StunState *state, struct stun_attr *attr) | ||
245 | { | ||
246 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
247 | "Found STUN Attribute %s (%04x), length %d\n", | ||
248 | stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); | ||
249 | |||
250 | switch (ntohs(attr->attr)) { | ||
251 | case STUN_MAPPED_ADDRESS: | ||
252 | case STUN_XOR_MAPPED_ADDRESS: | ||
253 | case STUN_MS_XOR_MAPPED_ADDRESS: | ||
254 | break; | ||
255 | default: | ||
256 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
257 | "Ignoring STUN Attribute %s (%04x), length %d\n", | ||
258 | stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); | ||
259 | |||
260 | } | ||
261 | return 0; | ||
262 | } | 236 | } |
263 | 237 | ||
264 | 238 | ||
265 | |||
266 | /** | 239 | /** |
267 | * Fill the stun_header with a random request_id | 240 | * Fill the stun_header with a random request_id |
268 | * | 241 | * |
@@ -271,11 +244,12 @@ stun_process_attr(struct StunState *state, struct stun_attr *attr) | |||
271 | static void | 244 | static void |
272 | generate_request_id(struct stun_header *req) | 245 | generate_request_id(struct stun_header *req) |
273 | { | 246 | { |
274 | unsigned int x; | 247 | unsigned int x; |
275 | req->magic = htonl(STUN_MAGIC_COOKIE); | 248 | |
276 | for (x = 0; x < 3; x++) | 249 | req->magic = htonl(STUN_MAGIC_COOKIE); |
277 | req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | 250 | for (x = 0; x < 3; x++) |
278 | UINT32_MAX); | 251 | req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, |
252 | UINT32_MAX); | ||
279 | } | 253 | } |
280 | 254 | ||
281 | 255 | ||
@@ -292,38 +266,41 @@ generate_request_id(struct stun_header *req) | |||
292 | * @return 0 on success, other value otherwise | 266 | * @return 0 on success, other value otherwise |
293 | */ | 267 | */ |
294 | static int | 268 | static int |
295 | stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in *arg, unsigned int magic) | 269 | stun_get_mapped (struct StunState *st, |
270 | struct stun_attr *attr, | ||
271 | struct sockaddr_in *arg, | ||
272 | unsigned int magic) | ||
296 | { | 273 | { |
297 | struct stun_addr *returned_addr = (struct stun_addr *)(attr + 1); | 274 | struct stun_addr *returned_addr = (struct stun_addr *)(attr + 1); |
298 | struct sockaddr_in *sa = (struct sockaddr_in *)arg; | 275 | struct sockaddr_in *sa = (struct sockaddr_in *)arg; |
299 | unsigned short type = ntohs(attr->attr); | 276 | unsigned short type = ntohs(attr->attr); |
300 | |||
301 | switch (type) { | ||
302 | case STUN_MAPPED_ADDRESS: | ||
303 | if (st->attr == STUN_XOR_MAPPED_ADDRESS || | ||
304 | st->attr == STUN_MS_XOR_MAPPED_ADDRESS) | ||
305 | return 1; | ||
306 | magic = 0; | ||
307 | break; | ||
308 | case STUN_MS_XOR_MAPPED_ADDRESS: | ||
309 | if (st->attr == STUN_XOR_MAPPED_ADDRESS) | ||
310 | return 1; | ||
311 | break; | ||
312 | case STUN_XOR_MAPPED_ADDRESS: | ||
313 | break; | ||
314 | default: | ||
315 | return 1; | ||
316 | } | ||
317 | if (ntohs(attr->len) < 8 && returned_addr->family != 1) { | ||
318 | return 1; | ||
319 | } | ||
320 | 277 | ||
321 | st->attr = type; | 278 | switch (type) |
322 | 279 | { | |
323 | sa->sin_family = AF_INET; | 280 | case STUN_MAPPED_ADDRESS: |
324 | sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); | 281 | if (st->attr == STUN_XOR_MAPPED_ADDRESS || |
325 | sa->sin_addr.s_addr = returned_addr->addr ^ magic; | 282 | st->attr == STUN_MS_XOR_MAPPED_ADDRESS) |
326 | return 0; | 283 | return 1; |
284 | magic = 0; | ||
285 | break; | ||
286 | case STUN_MS_XOR_MAPPED_ADDRESS: | ||
287 | if (st->attr == STUN_XOR_MAPPED_ADDRESS) | ||
288 | return 1; | ||
289 | break; | ||
290 | case STUN_XOR_MAPPED_ADDRESS: | ||
291 | break; | ||
292 | default: | ||
293 | return 1; | ||
294 | } | ||
295 | if (ntohs(attr->len) < 8 && returned_addr->family != 1) | ||
296 | { | ||
297 | return 1; | ||
298 | } | ||
299 | st->attr = type; | ||
300 | sa->sin_family = AF_INET; | ||
301 | sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); | ||
302 | sa->sin_addr.s_addr = returned_addr->addr ^ magic; | ||
303 | return 0; | ||
327 | } | 304 | } |
328 | 305 | ||
329 | 306 | ||
@@ -334,123 +311,122 @@ stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in | |||
334 | * the externally visible address of the request. | 311 | * the externally visible address of the request. |
335 | * If a callback is specified, invoke it with the attribute. | 312 | * If a callback is specified, invoke it with the attribute. |
336 | * | 313 | * |
337 | * @param data, the packet | 314 | * @param data the packet |
338 | * @param len, the length of the packet | 315 | * @param len the length of the packet |
339 | * @param arg, sockaddr_in where we will set our discovered packet | 316 | * @param arg sockaddr_in where we will set our discovered packet |
340 | * | 317 | * |
341 | * @return, #GNUNET_OK on OK, #GNUNET_NO if the packet is invalid ( not a stun packet) | 318 | * @return, #GNUNET_OK on OK, #GNUNET_NO if the packet is invalid (not a stun packet) |
342 | */ | 319 | */ |
343 | int | 320 | int |
344 | GNUNET_NAT_stun_handle_packet(const void *data, size_t len, struct sockaddr_in *arg) | 321 | GNUNET_NAT_stun_handle_packet (const void *data, |
322 | size_t len, | ||
323 | struct sockaddr_in *arg) | ||
345 | { | 324 | { |
346 | const struct stun_header *hdr = (const struct stun_header *)data; | 325 | const struct stun_header *hdr = (const struct stun_header *)data; |
347 | struct stun_attr *attr; | 326 | struct stun_attr *attr; |
348 | struct StunState st; | 327 | struct StunState st; |
349 | int ret = GNUNET_OK; | 328 | int ret = GNUNET_OK; |
350 | 329 | uint32_t advertised_message_size; | |
351 | uint32_t advertised_message_size; | 330 | uint32_t message_magic_cookie; |
352 | uint32_t message_magic_cookie; | 331 | |
353 | 332 | /* On entry, 'len' is the length of the udp payload. After the | |
354 | 333 | * initial checks it becomes the size of unprocessed options, | |
355 | /* On entry, 'len' is the length of the udp payload. After the | 334 | * while 'data' is advanced accordingly. |
356 | * initial checks it becomes the size of unprocessed options, | 335 | */ |
357 | * while 'data' is advanced accordingly. | 336 | if (len < sizeof(struct stun_header)) |
358 | */ | 337 | { |
359 | if (len < sizeof(struct stun_header)) { | 338 | LOG (GNUNET_ERROR_TYPE_INFO, |
360 | LOG (GNUNET_ERROR_TYPE_INFO, | 339 | "STUN packet too short (only %d, wanting at least %d)\n", |
361 | "STUN packet too short (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header)); | 340 | (int) len, |
362 | GNUNET_break_op (0); | 341 | (int) sizeof(struct stun_header)); |
363 | return GNUNET_NO; | 342 | GNUNET_break_op (0); |
364 | } | 343 | return GNUNET_NO; |
365 | /* Skip header as it is already in hdr */ | 344 | } |
366 | len -= sizeof(struct stun_header); | 345 | /* Skip header as it is already in hdr */ |
367 | data += sizeof(struct stun_header); | 346 | len -= sizeof(struct stun_header); |
368 | 347 | data += sizeof(struct stun_header); | |
369 | /* len as advertised in the message */ | ||
370 | advertised_message_size = ntohs(hdr->msglen); | ||
371 | |||
372 | message_magic_cookie = ntohl(hdr->magic); | ||
373 | /* Compare if the cookie match */ | ||
374 | if(STUN_MAGIC_COOKIE != message_magic_cookie){ | ||
375 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
376 | "Invalid magic cookie \n"); | ||
377 | return GNUNET_NO; | ||
378 | } | ||
379 | 348 | ||
349 | /* len as advertised in the message */ | ||
350 | advertised_message_size = ntohs(hdr->msglen); | ||
380 | 351 | ||
381 | LOG (GNUNET_ERROR_TYPE_INFO, "STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), | 352 | message_magic_cookie = ntohl(hdr->magic); |
382 | ntohs(hdr->msgtype), | 353 | /* Compare if the cookie match */ |
383 | advertised_message_size); | 354 | if(STUN_MAGIC_COOKIE != message_magic_cookie) |
355 | { | ||
356 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
357 | "Invalid magic cookie \n"); | ||
358 | return GNUNET_NO; | ||
359 | } | ||
384 | 360 | ||
361 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
362 | "STUN Packet, msg %s (%04x), length: %d\n", | ||
363 | stun_msg2str(ntohs(hdr->msgtype)), | ||
364 | ntohs(hdr->msgtype), | ||
365 | advertised_message_size); | ||
366 | if (advertised_message_size > len) | ||
367 | { | ||
368 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
369 | "Scrambled STUN packet length (got %d, expecting %d)\n", | ||
370 | advertised_message_size, | ||
371 | (int)len); | ||
372 | return GNUNET_NO; | ||
373 | } | ||
374 | else | ||
375 | { | ||
376 | len = advertised_message_size; | ||
377 | } | ||
378 | memset (&st,0, sizeof(st)); | ||
385 | 379 | ||
386 | if (advertised_message_size > len) { | 380 | while (len > 0) |
387 | LOG (GNUNET_ERROR_TYPE_INFO, "Scrambled STUN packet length (got %d, expecting %d)\n", advertised_message_size, | 381 | { |
388 | (int)len); | 382 | if (len < sizeof(struct stun_attr)) |
389 | return GNUNET_NO; | 383 | { |
390 | } else { | 384 | LOG (GNUNET_ERROR_TYPE_INFO, |
391 | len = advertised_message_size; | 385 | "Attribute too short (got %d, expecting %d)\n", |
386 | (int)len, | ||
387 | (int) sizeof(struct stun_attr)); | ||
388 | break; | ||
392 | } | 389 | } |
390 | attr = (struct stun_attr *)data; | ||
393 | 391 | ||
394 | memset(&st,0, sizeof(st)); | 392 | /* compute total attribute length */ |
395 | 393 | advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr); | |
396 | while (len > 0) { | ||
397 | if (len < sizeof(struct stun_attr)) { | ||
398 | LOG (GNUNET_ERROR_TYPE_INFO, "Attribute too short (got %d, expecting %d)\n", (int)len, | ||
399 | (int) sizeof(struct stun_attr)); | ||
400 | break; | ||
401 | } | ||
402 | attr = (struct stun_attr *)data; | ||
403 | |||
404 | /* compute total attribute length */ | ||
405 | advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr); | ||
406 | |||
407 | /* Check if we still have space in our buffer */ | ||
408 | if (advertised_message_size > len ) { | ||
409 | LOG (GNUNET_ERROR_TYPE_INFO, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", advertised_message_size, | ||
410 | (int)len); | ||
411 | break; | ||
412 | } | ||
413 | |||
414 | |||
415 | stun_get_mapped(&st, attr, arg, hdr->magic); | ||
416 | |||
417 | if (stun_process_attr(&st, attr)) { | ||
418 | LOG (GNUNET_ERROR_TYPE_INFO, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), | ||
419 | ntohs(attr->attr)); | ||
420 | break; | ||
421 | } | ||
422 | /** Clear attribute id: in case previous entry was a string, | ||
423 | * this will act as the terminator for the string. | ||
424 | **/ | ||
425 | attr->attr = 0; | ||
426 | data += advertised_message_size; | ||
427 | len -= advertised_message_size; | ||
428 | ret = GNUNET_OK; | ||
429 | } | ||
430 | 394 | ||
431 | return ret; | 395 | /* Check if we still have space in our buffer */ |
396 | if (advertised_message_size > len ) | ||
397 | { | ||
398 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
399 | "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", | ||
400 | advertised_message_size, | ||
401 | (int)len); | ||
402 | break; | ||
403 | } | ||
404 | stun_get_mapped (&st, attr, arg, hdr->magic); | ||
405 | /* Clear attribute id: in case previous entry was a string, | ||
406 | * this will act as the terminator for the string. | ||
407 | */ | ||
408 | attr->attr = 0; | ||
409 | data += advertised_message_size; | ||
410 | len -= advertised_message_size; | ||
411 | ret = GNUNET_OK; | ||
412 | } | ||
413 | return ret; | ||
432 | } | 414 | } |
433 | 415 | ||
434 | 416 | ||
435 | |||
436 | /** | 417 | /** |
437 | * Clean-up used memory | 418 | * Clean-up used memory |
438 | * | 419 | * |
439 | * @param cls our `struct GNUNET_NAT_STUN_Handle *` | 420 | * @param handle handle to release memory for |
440 | */ | 421 | */ |
441 | static void | 422 | static void |
442 | clean(struct GNUNET_NAT_STUN_Handle * handle) | 423 | clean (struct GNUNET_NAT_STUN_Handle *handle) |
443 | { | 424 | { |
444 | if(handle->stun_server) | 425 | GNUNET_free (handle->stun_server); |
445 | { | 426 | GNUNET_free (handle); |
446 | GNUNET_free(handle->stun_server); | ||
447 | } | ||
448 | GNUNET_free(handle); | ||
449 | |||
450 | } | 427 | } |
451 | 428 | ||
452 | 429 | ||
453 | |||
454 | /** | 430 | /** |
455 | * Try to establish a connection given the specified address. | 431 | * Try to establish a connection given the specified address. |
456 | * | 432 | * |
@@ -461,120 +437,112 @@ clean(struct GNUNET_NAT_STUN_Handle * handle) | |||
461 | static void | 437 | static void |
462 | stun_dns_callback (void *cls, | 438 | stun_dns_callback (void *cls, |
463 | const struct sockaddr *addr, | 439 | const struct sockaddr *addr, |
464 | socklen_t addrlen) { | 440 | socklen_t addrlen) |
465 | 441 | { | |
466 | 442 | struct GNUNET_NAT_STUN_Handle *request = cls; | |
467 | struct GNUNET_NAT_STUN_Handle *request = cls; | 443 | struct stun_header *req; |
468 | 444 | uint8_t reqdata[1024]; | |
469 | struct stun_header *req; | 445 | int reqlen; |
470 | uint8_t reqdata[1024]; | 446 | struct sockaddr_in server; |
471 | int reqlen; | ||
472 | struct sockaddr_in server; | ||
473 | |||
474 | |||
475 | if(NULL == request) { | ||
476 | |||
477 | if( GNUNET_NO == request->dns_success){ | ||
478 | LOG (GNUNET_ERROR_TYPE_INFO, "Empty request\n"); | ||
479 | request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); | ||
480 | clean(request); | ||
481 | |||
482 | } | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | if (NULL == addr) { | ||
487 | request->dns_active = NULL; | ||
488 | |||
489 | if( GNUNET_NO == request->dns_success){ | ||
490 | LOG (GNUNET_ERROR_TYPE_INFO, "Error resolving host %s\n", request->stun_server); | ||
491 | request->cb(request->cb_cls, GNUNET_NAT_ERROR_NOT_ONLINE); | ||
492 | clean(request); | ||
493 | |||
494 | } | ||
495 | 447 | ||
496 | return; | 448 | if (NULL == request) |
449 | { | ||
450 | if (GNUNET_NO == request->dns_success) | ||
451 | { | ||
452 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
453 | "Empty request\n"); | ||
454 | request->cb (request->cb_cls, | ||
455 | GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); | ||
456 | clean (request); | ||
497 | } | 457 | } |
498 | 458 | return; | |
499 | 459 | } | |
500 | request->dns_success= GNUNET_YES; | 460 | if (NULL == addr) |
501 | memset(&server,0, sizeof(server)); | 461 | { |
502 | server.sin_family = AF_INET; | 462 | request->dns_active = NULL; |
503 | server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr; | 463 | if (GNUNET_NO == request->dns_success) |
504 | server.sin_port = htons(request->stun_port); | ||
505 | |||
506 | |||
507 | /*Craft the simplest possible STUN packet. A request binding*/ | ||
508 | req = (struct stun_header *)reqdata; | ||
509 | generate_request_id(req); | ||
510 | reqlen = 0; | ||
511 | req->msgtype = 0; | ||
512 | req->msglen = 0; | ||
513 | req->msglen = htons(reqlen); | ||
514 | req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING)); | ||
515 | |||
516 | /* Send the packet */ | ||
517 | if (-1 == GNUNET_NETWORK_socket_sendto (request->sock, req, ntohs(req->msglen) + sizeof(*req), | ||
518 | (const struct sockaddr *) &server, sizeof (server))) | ||
519 | { | 464 | { |
520 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Fail to sendto"); | 465 | LOG (GNUNET_ERROR_TYPE_INFO, |
521 | request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); | 466 | "Error resolving host %s\n", |
522 | clean(request); | 467 | request->stun_server); |
523 | return; | 468 | request->cb (request->cb_cls, |
469 | GNUNET_NAT_ERROR_NOT_ONLINE); | ||
470 | clean (request); | ||
524 | } | 471 | } |
472 | return; | ||
473 | } | ||
525 | 474 | ||
526 | 475 | request->dns_success= GNUNET_YES; | |
476 | memset(&server,0, sizeof(server)); | ||
477 | server.sin_family = AF_INET; | ||
478 | server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr; | ||
479 | server.sin_port = htons(request->stun_port); | ||
480 | |||
481 | /*Craft the simplest possible STUN packet. A request binding*/ | ||
482 | req = (struct stun_header *)reqdata; | ||
483 | generate_request_id(req); | ||
484 | reqlen = 0; | ||
485 | req->msgtype = 0; | ||
486 | req->msglen = 0; | ||
487 | req->msglen = htons(reqlen); | ||
488 | req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING)); | ||
489 | |||
490 | /* Send the packet */ | ||
491 | if (-1 == GNUNET_NETWORK_socket_sendto (request->sock, | ||
492 | req, | ||
493 | ntohs(req->msglen) + sizeof(*req), | ||
494 | (const struct sockaddr *) &server, | ||
495 | sizeof (server))) | ||
496 | { | ||
497 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
498 | "Fail to sendto"); | ||
499 | request->cb (request->cb_cls, | ||
500 | GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); | ||
501 | clean (request); | ||
502 | return; | ||
503 | } | ||
527 | } | 504 | } |
528 | 505 | ||
529 | 506 | ||
530 | |||
531 | |||
532 | |||
533 | /** | 507 | /** |
534 | * Make Generic STUN request and | 508 | * Make Generic STUN request. Sends a generic stun request to the |
535 | * Send a generic stun request to the server specified using the specified socket. | 509 | * server specified using the specified socket, possibly waiting for |
536 | * possibly waiting for a reply and filling the 'reply' field with | 510 | * a reply and filling the 'reply' field with the externally visible |
537 | * the externally visible address. | 511 | * address. |
538 | * | 512 | * |
539 | * @param server, the address of the stun server | 513 | * @param server the address of the stun server |
540 | * @param port, port of the stun server | 514 | * @param port port of the stun server |
541 | * @param sock the socket used to send the request | 515 | * @param sock the socket used to send the request |
542 | * @param cb, callback in case of error | 516 | * @param cb callback in case of error |
517 | * @param cb_cls closure for @a cb | ||
543 | * @return #GNUNET_OK success, #GNUNET_NO on error. | 518 | * @return #GNUNET_OK success, #GNUNET_NO on error. |
544 | */ | 519 | */ |
545 | int | 520 | int |
546 | GNUNET_NAT_stun_make_request(char * server, | 521 | GNUNET_NAT_stun_make_request (const char *server, |
547 | int port, | 522 | uint16_t port, |
548 | struct GNUNET_NETWORK_Handle * sock, | 523 | struct GNUNET_NETWORK_Handle *sock, |
549 | GNUNET_NAT_STUN_ErrorCallback cb, | 524 | GNUNET_NAT_STUN_ErrorCallback cb, |
550 | void *cb_cls) | 525 | void *cb_cls) |
551 | { | 526 | { |
552 | 527 | struct GNUNET_NAT_STUN_Handle *rh; | |
553 | struct GNUNET_NAT_STUN_Handle *rh; | 528 | |
554 | 529 | rh = GNUNET_new (struct GNUNET_NAT_STUN_Handle); | |
555 | rh = GNUNET_malloc (sizeof (struct GNUNET_NAT_STUN_Handle)); | 530 | rh->sock = sock; |
556 | rh->sock = sock; | 531 | rh->cb = cb; |
557 | 532 | rh->cb_cls = cb_cls; | |
558 | char * server_copy = GNUNET_strdup (server); | 533 | rh->stun_server = GNUNET_strdup (server); |
559 | 534 | rh->stun_port = port; | |
560 | rh->cb = cb; | 535 | rh->dns_success = GNUNET_NO; |
561 | rh->cb_cls = cb_cls; | 536 | rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server, |
562 | rh->stun_server = server_copy; | 537 | AF_INET, |
563 | rh->stun_port = port; | 538 | TIMEOUT, |
564 | rh->dns_success = GNUNET_NO; | 539 | &stun_dns_callback, rh); |
565 | 540 | if (NULL == rh->dns_active) | |
566 | rh->dns_active = GNUNET_RESOLVER_ip_get (server_copy, AF_INET, | 541 | { |
567 | TIMEOUT, | 542 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, |
568 | &stun_dns_callback, rh); | 543 | "Failed DNS"); |
569 | 544 | clean (rh); | |
570 | if (rh->dns_active == NULL) | 545 | return GNUNET_NO; |
571 | { | 546 | } |
572 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Failed DNS"); | 547 | return GNUNET_OK; |
573 | GNUNET_free(rh); | ||
574 | GNUNET_free(server_copy); | ||
575 | |||
576 | return GNUNET_NO; | ||
577 | } | ||
578 | |||
579 | return GNUNET_OK; | ||
580 | } | 548 | } |
diff --git a/src/nat/nat_stun.h b/src/nat/nat_stun.h index 1dbb2a6ac..d79fd9ad2 100644 --- a/src/nat/nat_stun.h +++ b/src/nat/nat_stun.h | |||
@@ -36,76 +36,75 @@ | |||
36 | 36 | ||
37 | typedef struct { uint32_t id[3]; } GNUNET_PACKED stun_trans_id; | 37 | typedef struct { uint32_t id[3]; } GNUNET_PACKED stun_trans_id; |
38 | 38 | ||
39 | struct stun_header { | 39 | struct stun_header |
40 | uint16_t msgtype; | 40 | { |
41 | uint16_t msglen; | 41 | uint16_t msgtype; |
42 | uint32_t magic; | 42 | uint16_t msglen; |
43 | stun_trans_id id; | 43 | uint32_t magic; |
44 | 44 | stun_trans_id id; | |
45 | } GNUNET_PACKED; | 45 | } GNUNET_PACKED; |
46 | 46 | ||
47 | struct stun_attr { | 47 | struct stun_attr |
48 | uint16_t attr; | 48 | { |
49 | uint16_t len; | 49 | uint16_t attr; |
50 | 50 | uint16_t len; | |
51 | } GNUNET_PACKED; | 51 | } GNUNET_PACKED; |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * The format normally used for addresses carried by STUN messages. | 54 | * The format normally used for addresses carried by STUN messages. |
55 | */ | 55 | */ |
56 | struct stun_addr { | 56 | struct stun_addr |
57 | uint8_t unused; | 57 | { |
58 | uint8_t family; | 58 | uint8_t unused; |
59 | uint16_t port; | 59 | uint8_t family; |
60 | uint32_t addr; | 60 | uint16_t port; |
61 | uint32_t addr; | ||
61 | } GNUNET_PACKED; | 62 | } GNUNET_PACKED; |
62 | 63 | ||
63 | 64 | ||
64 | 65 | ||
65 | /* STUN message classes */ | 66 | /* STUN message classes */ |
66 | typedef enum StunClasses { | 67 | enum StunClasses { |
67 | INVALID_CLASS = 0, | 68 | INVALID_CLASS = 0, |
68 | STUN_REQUEST = 0x0000, | 69 | STUN_REQUEST = 0x0000, |
69 | STUN_INDICATION = 0x0001, | 70 | STUN_INDICATION = 0x0001, |
70 | STUN_RESPONSE = 0x0002, | 71 | STUN_RESPONSE = 0x0002, |
71 | STUN_ERROR_RESPONSE = 0x0003 | 72 | STUN_ERROR_RESPONSE = 0x0003 |
72 | } StunClasses; | 73 | }; |
73 | 74 | ||
74 | typedef enum StunMethods { | 75 | enum StunMethods { |
75 | INVALID_METHOD = 0, | 76 | INVALID_METHOD = 0, |
76 | STUN_BINDING = 0x0001, | 77 | STUN_BINDING = 0x0001, |
77 | STUN_SHARED_SECRET = 0x0002, | 78 | STUN_SHARED_SECRET = 0x0002, |
78 | STUN_ALLOCATE = 0x0003, | 79 | STUN_ALLOCATE = 0x0003, |
79 | STUN_REFRESH = 0x0004, | 80 | STUN_REFRESH = 0x0004, |
80 | STUN_SEND = 0x0006, | 81 | STUN_SEND = 0x0006, |
81 | STUN_DATA = 0x0007, | 82 | STUN_DATA = 0x0007, |
82 | STUN_CREATE_PERMISSION = 0x0008, | 83 | STUN_CREATE_PERMISSION = 0x0008, |
83 | STUN_CHANNEL_BIND = 0x0009 | 84 | STUN_CHANNEL_BIND = 0x0009 |
84 | } StunMethods; | 85 | }; |
85 | 86 | ||
86 | /* Basic attribute types in stun messages. | 87 | /* Basic attribute types in stun messages. |
87 | * Messages can also contain custom attributes (codes above 0x7fff) | 88 | * Messages can also contain custom attributes (codes above 0x7fff) |
88 | */ | 89 | */ |
89 | 90 | enum StunAttributes { | |
90 | typedef enum StunAttributes { | 91 | STUN_MAPPED_ADDRESS = 0x0001, |
91 | STUN_MAPPED_ADDRESS = 0x0001, | 92 | STUN_RESPONSE_ADDRESS = 0x0002, |
92 | STUN_RESPONSE_ADDRESS = 0x0002, | 93 | STUN_CHANGE_ADDRESS = 0x0003, |
93 | STUN_CHANGE_ADDRESS = 0x0003, | 94 | STUN_SOURCE_ADDRESS = 0x0004, |
94 | STUN_SOURCE_ADDRESS = 0x0004, | 95 | STUN_CHANGED_ADDRESS = 0x0005, |
95 | STUN_CHANGED_ADDRESS = 0x0005, | 96 | STUN_USERNAME = 0x0006, |
96 | STUN_USERNAME = 0x0006, | 97 | STUN_PASSWORD = 0x0007, |
97 | STUN_PASSWORD = 0x0007, | 98 | STUN_MESSAGE_INTEGRITY = 0x0008, |
98 | STUN_MESSAGE_INTEGRITY = 0x0008, | 99 | STUN_ERROR_CODE = 0x0009, |
99 | STUN_ERROR_CODE = 0x0009, | 100 | STUN_UNKNOWN_ATTRIBUTES = 0x000a, |
100 | STUN_UNKNOWN_ATTRIBUTES = 0x000a, | 101 | STUN_REFLECTED_FROM = 0x000b, |
101 | STUN_REFLECTED_FROM = 0x000b, | 102 | STUN_REALM = 0x0014, |
102 | STUN_REALM = 0x0014, | 103 | STUN_NONCE = 0x0015, |
103 | STUN_NONCE = 0x0015, | 104 | STUN_XOR_MAPPED_ADDRESS = 0x0020, |
104 | STUN_XOR_MAPPED_ADDRESS = 0x0020, | 105 | STUN_MS_VERSION = 0x8008, |
105 | STUN_MS_VERSION = 0x8008, | 106 | STUN_MS_XOR_MAPPED_ADDRESS = 0x8020, |
106 | STUN_MS_XOR_MAPPED_ADDRESS = 0x8020, | 107 | STUN_SOFTWARE = 0x8022, |
107 | STUN_SOFTWARE = 0x8022, | 108 | STUN_ALTERNATE_SERVER = 0x8023, |
108 | STUN_ALTERNATE_SERVER = 0x8023, | 109 | STUN_FINGERPRINT = 0x8028 |
109 | STUN_FINGERPRINT = 0x8028 | 110 | }; |
110 | } StunAttributes; | ||
111 | |||