diff options
author | Bruno Cabral <bcabral@uw.edu> | 2015-08-21 04:15:24 +0000 |
---|---|---|
committer | Bruno Cabral <bcabral@uw.edu> | 2015-08-21 04:15:24 +0000 |
commit | ecc90530eb2b3f4d0d5037d8d8b69722dda2a2cb (patch) | |
tree | e43497b563f2d7ee7856fb8f2f57bb8f2598b371 /src/nat/nat_stun.c | |
parent | 946e39d3696847334b5316902c1eeb84d4c34cb0 (diff) | |
download | gnunet-ecc90530eb2b3f4d0d5037d8d8b69722dda2a2cb.tar.gz gnunet-ecc90530eb2b3f4d0d5037d8d8b69722dda2a2cb.zip |
Fix crashes and memory leaks.
Diffstat (limited to 'src/nat/nat_stun.c')
-rw-r--r-- | src/nat/nat_stun.c | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c index 5fff40656..4d1afb3bb 100644 --- a/src/nat/nat_stun.c +++ b/src/nat/nat_stun.c | |||
@@ -111,8 +111,10 @@ struct StunState { | |||
111 | * @param msg the received message | 111 | * @param msg the received message |
112 | * @return the converted StunClass | 112 | * @return the converted StunClass |
113 | */ | 113 | */ |
114 | static int decode_class(int msg) | 114 | static int |
115 | decode_class(int msg) | ||
115 | { | 116 | { |
117 | /* Sorry for the magic, but this maps the class according to rfc5245 */ | ||
116 | return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); | 118 | return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); |
117 | } | 119 | } |
118 | 120 | ||
@@ -122,7 +124,8 @@ static int decode_class(int msg) | |||
122 | * @param msg the received message | 124 | * @param msg the received message |
123 | * @return the converted StunMethod | 125 | * @return the converted StunMethod |
124 | */ | 126 | */ |
125 | static int decode_method(int msg) | 127 | static int |
128 | decode_method(int msg) | ||
126 | { | 129 | { |
127 | return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); | 130 | return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); |
128 | } | 131 | } |
@@ -134,7 +137,8 @@ static int decode_method(int msg) | |||
134 | * @param method method to be converted | 137 | * @param method method to be converted |
135 | * @return message in a STUN compatible format | 138 | * @return message in a STUN compatible format |
136 | */ | 139 | */ |
137 | static int encode_message(StunClasses msg_class, StunMethods method) | 140 | static int |
141 | encode_message(StunClasses msg_class, StunMethods method) | ||
138 | { | 142 | { |
139 | return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | | 143 | return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | |
140 | (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); | 144 | (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); |
@@ -146,7 +150,8 @@ static int encode_message(StunClasses msg_class, StunMethods method) | |||
146 | * @param msg | 150 | * @param msg |
147 | * @return string with the message class and method | 151 | * @return string with the message class and method |
148 | */ | 152 | */ |
149 | static const char *stun_msg2str(int msg) | 153 | static const char * |
154 | stun_msg2str(int msg) | ||
150 | { | 155 | { |
151 | 156 | ||
152 | const struct { enum StunClasses value; const char *name; } classes[] = { | 157 | const struct { enum StunClasses value; const char *name; } classes[] = { |
@@ -180,7 +185,7 @@ static const char *stun_msg2str(int msg) | |||
180 | if (methods[i].value == value) | 185 | if (methods[i].value == value) |
181 | break; | 186 | break; |
182 | } | 187 | } |
183 | snprintf(result, sizeof(result), "%s %s", | 188 | GNUNET_snprintf(result, sizeof(result), "%s %s", |
184 | method ? : "Unknown Method", | 189 | method ? : "Unknown Method", |
185 | msg_class ? : "Unknown Class Message"); | 190 | msg_class ? : "Unknown Class Message"); |
186 | return result; | 191 | return result; |
@@ -192,7 +197,8 @@ static const char *stun_msg2str(int msg) | |||
192 | * @param msg with a attribute type | 197 | * @param msg with a attribute type |
193 | * @return string with the attribute name | 198 | * @return string with the attribute name |
194 | */ | 199 | */ |
195 | static const char *stun_attr2str(int msg) | 200 | static const char * |
201 | stun_attr2str(int msg) | ||
196 | { | 202 | { |
197 | const struct { enum StunAttributes value; const char *name; } attrs[] = { | 203 | const struct { enum StunAttributes value; const char *name; } attrs[] = { |
198 | { STUN_MAPPED_ADDRESS, "Mapped Address" }, | 204 | { STUN_MAPPED_ADDRESS, "Mapped Address" }, |
@@ -234,7 +240,8 @@ static const char *stun_attr2str(int msg) | |||
234 | * | 240 | * |
235 | * @param req, stun header to be filled | 241 | * @param req, stun header to be filled |
236 | */ | 242 | */ |
237 | static int stun_process_attr(struct StunState *state, struct stun_attr *attr) | 243 | static int |
244 | stun_process_attr(struct StunState *state, struct stun_attr *attr) | ||
238 | { | 245 | { |
239 | LOG (GNUNET_ERROR_TYPE_INFO, | 246 | LOG (GNUNET_ERROR_TYPE_INFO, |
240 | "Found STUN Attribute %s (%04x), length %d\n", | 247 | "Found STUN Attribute %s (%04x), length %d\n", |
@@ -264,7 +271,7 @@ static int stun_process_attr(struct StunState *state, struct stun_attr *attr) | |||
264 | static void | 271 | static void |
265 | generate_request_id(struct stun_header *req) | 272 | generate_request_id(struct stun_header *req) |
266 | { | 273 | { |
267 | int x; | 274 | unsigned int x; |
268 | req->magic = htonl(STUN_MAGIC_COOKIE); | 275 | req->magic = htonl(STUN_MAGIC_COOKIE); |
269 | for (x = 0; x < 3; x++) | 276 | for (x = 0; x < 3; x++) |
270 | req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | 277 | req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, |
@@ -282,7 +289,7 @@ generate_request_id(struct stun_header *req) | |||
282 | * @param arg , pointer to a sockaddr_in where we will set the reported IP and port | 289 | * @param arg , pointer to a sockaddr_in where we will set the reported IP and port |
283 | * @param magic , Magic cookie | 290 | * @param magic , Magic cookie |
284 | * | 291 | * |
285 | * @return 0 on sucess, other value otherwise | 292 | * @return 0 on success, other value otherwise |
286 | */ | 293 | */ |
287 | static int | 294 | static int |
288 | stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in *arg, unsigned int magic) | 295 | stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in *arg, unsigned int magic) |
@@ -312,7 +319,7 @@ stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in | |||
312 | } | 319 | } |
313 | 320 | ||
314 | st->attr = type; | 321 | st->attr = type; |
315 | /*TODO: Detect Family*/ | 322 | |
316 | sa->sin_family = AF_INET; | 323 | sa->sin_family = AF_INET; |
317 | sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); | 324 | sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); |
318 | sa->sin_addr.s_addr = returned_addr->addr ^ magic; | 325 | sa->sin_addr.s_addr = returned_addr->addr ^ magic; |
@@ -331,12 +338,12 @@ stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in | |||
331 | * @param len, the length of the packet | 338 | * @param len, the length of the packet |
332 | * @param arg, sockaddr_in where we will set our discovered packet | 339 | * @param arg, sockaddr_in where we will set our discovered packet |
333 | * | 340 | * |
334 | * @return, GNUNET_OK on OK, GNUNET_NO if the packet is invalid ( not a stun packet) | 341 | * @return, #GNUNET_OK on OK, #GNUNET_NO if the packet is invalid ( not a stun packet) |
335 | */ | 342 | */ |
336 | int | 343 | int |
337 | GNUNET_NAT_stun_handle_packet(const void *data, size_t len, struct sockaddr_in *arg) | 344 | GNUNET_NAT_stun_handle_packet(const void *data, size_t len, struct sockaddr_in *arg) |
338 | { | 345 | { |
339 | struct stun_header *hdr = (struct stun_header *)data; | 346 | const struct stun_header *hdr = (const struct stun_header *)data; |
340 | struct stun_attr *attr; | 347 | struct stun_attr *attr; |
341 | struct StunState st; | 348 | struct StunState st; |
342 | int ret = GNUNET_OK; | 349 | int ret = GNUNET_OK; |
@@ -367,28 +374,29 @@ GNUNET_NAT_stun_handle_packet(const void *data, size_t len, struct sockaddr_in * | |||
367 | if(STUN_MAGIC_COOKIE != message_magic_cookie){ | 374 | if(STUN_MAGIC_COOKIE != message_magic_cookie){ |
368 | LOG (GNUNET_ERROR_TYPE_INFO, | 375 | LOG (GNUNET_ERROR_TYPE_INFO, |
369 | "Invalid magic cookie \n"); | 376 | "Invalid magic cookie \n"); |
370 | GNUNET_break_op (0); | ||
371 | return GNUNET_NO; | 377 | return GNUNET_NO; |
372 | } | 378 | } |
373 | 379 | ||
374 | 380 | ||
375 | LOG (GNUNET_ERROR_TYPE_INFO, "STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), advertised_message_size); | 381 | LOG (GNUNET_ERROR_TYPE_INFO, "STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), |
382 | ntohs(hdr->msgtype), | ||
383 | advertised_message_size); | ||
376 | 384 | ||
377 | 385 | ||
378 | if (advertised_message_size > len) { | 386 | if (advertised_message_size > len) { |
379 | LOG (GNUNET_ERROR_TYPE_INFO, "Scrambled STUN packet length (got %d, expecting %d)\n", advertised_message_size, (int)len); | 387 | LOG (GNUNET_ERROR_TYPE_INFO, "Scrambled STUN packet length (got %d, expecting %d)\n", advertised_message_size, |
380 | GNUNET_break_op (0); | 388 | (int)len); |
381 | return GNUNET_NO; | 389 | return GNUNET_NO; |
382 | } else { | 390 | } else { |
383 | len = advertised_message_size; | 391 | len = advertised_message_size; |
384 | } | 392 | } |
385 | /* Zero the struct */ | 393 | |
386 | memset(&st,0, sizeof(st)); | 394 | memset(&st,0, sizeof(st)); |
387 | 395 | ||
388 | while (len > 0) { | 396 | while (len > 0) { |
389 | if (len < sizeof(struct stun_attr)) { | 397 | if (len < sizeof(struct stun_attr)) { |
390 | LOG (GNUNET_ERROR_TYPE_INFO, "Attribute too short (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr)); | 398 | LOG (GNUNET_ERROR_TYPE_INFO, "Attribute too short (got %d, expecting %d)\n", (int)len, |
391 | GNUNET_break_op (0); | 399 | (int) sizeof(struct stun_attr)); |
392 | break; | 400 | break; |
393 | } | 401 | } |
394 | attr = (struct stun_attr *)data; | 402 | attr = (struct stun_attr *)data; |
@@ -398,8 +406,8 @@ GNUNET_NAT_stun_handle_packet(const void *data, size_t len, struct sockaddr_in * | |||
398 | 406 | ||
399 | /* Check if we still have space in our buffer */ | 407 | /* Check if we still have space in our buffer */ |
400 | if (advertised_message_size > len ) { | 408 | if (advertised_message_size > len ) { |
401 | LOG (GNUNET_ERROR_TYPE_INFO, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", advertised_message_size, (int)len); | 409 | LOG (GNUNET_ERROR_TYPE_INFO, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", advertised_message_size, |
402 | GNUNET_break_op (0); | 410 | (int)len); |
403 | break; | 411 | break; |
404 | } | 412 | } |
405 | 413 | ||
@@ -407,7 +415,8 @@ GNUNET_NAT_stun_handle_packet(const void *data, size_t len, struct sockaddr_in * | |||
407 | stun_get_mapped(&st, attr, arg, hdr->magic); | 415 | stun_get_mapped(&st, attr, arg, hdr->magic); |
408 | 416 | ||
409 | if (stun_process_attr(&st, attr)) { | 417 | if (stun_process_attr(&st, attr)) { |
410 | LOG (GNUNET_ERROR_TYPE_INFO, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); | 418 | LOG (GNUNET_ERROR_TYPE_INFO, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), |
419 | ntohs(attr->attr)); | ||
411 | break; | 420 | break; |
412 | } | 421 | } |
413 | /** Clear attribute id: in case previous entry was a string, | 422 | /** Clear attribute id: in case previous entry was a string, |
@@ -429,7 +438,8 @@ GNUNET_NAT_stun_handle_packet(const void *data, size_t len, struct sockaddr_in * | |||
429 | * | 438 | * |
430 | * @param cls our `struct GNUNET_NAT_STUN_Handle *` | 439 | * @param cls our `struct GNUNET_NAT_STUN_Handle *` |
431 | */ | 440 | */ |
432 | void clean(struct GNUNET_NAT_STUN_Handle * handle) | 441 | static void |
442 | clean(struct GNUNET_NAT_STUN_Handle * handle) | ||
433 | { | 443 | { |
434 | GNUNET_free(handle->stun_server); | 444 | GNUNET_free(handle->stun_server); |
435 | GNUNET_free(handle); | 445 | GNUNET_free(handle); |
@@ -526,9 +536,9 @@ stun_dns_callback (void *cls, | |||
526 | * @param server, the address of the stun server | 536 | * @param server, the address of the stun server |
527 | * @param port, port of the stun server | 537 | * @param port, port of the stun server |
528 | * @param sock the socket used to send the request | 538 | * @param sock the socket used to send the request |
529 | * @return GNUNET_NAT_STUN_Handle on success, NULL on error. | 539 | * @return #GNUNET_OK success, #GNUNET_NO on error. |
530 | */ | 540 | */ |
531 | struct GNUNET_NAT_STUN_Handle * | 541 | int |
532 | GNUNET_NAT_stun_make_request(char * server, int port, | 542 | GNUNET_NAT_stun_make_request(char * server, int port, |
533 | struct GNUNET_NETWORK_Handle * sock,GNUNET_NAT_stun_RequestCallback cb, | 543 | struct GNUNET_NETWORK_Handle * sock,GNUNET_NAT_stun_RequestCallback cb, |
534 | void *cb_cls) | 544 | void *cb_cls) |
@@ -554,9 +564,10 @@ GNUNET_NAT_stun_make_request(char * server, int port, | |||
554 | if(rh->dns_active == NULL) | 564 | if(rh->dns_active == NULL) |
555 | { | 565 | { |
556 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Failed DNS"); | 566 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Failed DNS"); |
557 | return NULL; | 567 | GNUNET_free(rh); |
568 | return GNUNET_NO; | ||
558 | } | 569 | } |
559 | 570 | ||
560 | 571 | ||
561 | return rh; | 572 | return GNUNET_OK; |
562 | } | 573 | } |