aboutsummaryrefslogtreecommitdiff
path: root/src/nat/nat_stun.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/nat_stun.c')
-rw-r--r--src/nat/nat_stun.c553
1 files changed, 305 insertions, 248 deletions
diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c
index 9419074a7..5e502c29e 100644
--- a/src/nat/nat_stun.c
+++ b/src/nat/nat_stun.c
@@ -48,6 +48,7 @@
48 48
49#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__) 49#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__)
50 50
51#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
51 52
52 53
53/** 54/**
@@ -55,28 +56,44 @@
55 * the request prior to the timeout or successful execution. Also 56 * the request prior to the timeout or successful execution. Also
56 * used to track our internal state for the request. 57 * used to track our internal state for the request.
57 */ 58 */
58struct GNUNET_NAT_StunRequestHandle { 59struct GNUNET_NAT_STUN_Handle {
59 60
60 /** 61 /**
61 * Handle to a pending DNS lookup request. 62 * Handle to a pending DNS lookup request.
62 */ 63 */
63 struct GNUNET_RESOLVER_RequestHandle *dns_active; 64 struct GNUNET_RESOLVER_RequestHandle *dns_active;
64 65
65 66
66 /** 67 /**
67 * Handle to the listen socket 68 * Handle to the listen socket
68 */ 69 */
69 struct GNUNET_NETWORK_Handle * sock; 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;
70 81
71 /** 82 /**
72 * Stun server address 83 * Function to call when a error occours
84 */
85 GNUNET_NAT_stun_RequestCallback cb;
86
87 /**
88 * Closure for @e cb.
73 */ 89 */
74 char *stun_server ; 90 void *cb_cls;
75 91
76 /** 92 /**
77 * STUN port 93 * Do we got a DNS resolution successfully ?
78 */ 94 */
79 int stun_port; 95 int dns_success;
96
80 97
81}; 98};
82 99
@@ -84,7 +101,7 @@ struct GNUNET_NAT_StunRequestHandle {
84 101
85/* here we store credentials extracted from a message */ 102/* here we store credentials extracted from a message */
86struct StunState { 103struct StunState {
87 uint16_t attr; 104 uint16_t attr;
88}; 105};
89 106
90 107
@@ -96,7 +113,7 @@ struct StunState {
96 */ 113 */
97static int decode_class(int msg) 114static int decode_class(int msg)
98{ 115{
99 return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); 116 return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7);
100} 117}
101 118
102/** 119/**
@@ -107,7 +124,7 @@ static int decode_class(int msg)
107 */ 124 */
108static int decode_method(int msg) 125static int decode_method(int msg)
109{ 126{
110 return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); 127 return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2);
111} 128}
112 129
113/** 130/**
@@ -119,8 +136,8 @@ static int decode_method(int msg)
119 */ 136 */
120static int encode_message(StunClasses msg_class, StunMethods method) 137static int encode_message(StunClasses msg_class, StunMethods method)
121{ 138{
122 return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | 139 return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) |
123 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); 140 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2);
124} 141}
125 142
126/** 143/**
@@ -132,41 +149,41 @@ static int encode_message(StunClasses msg_class, StunMethods method)
132static const char *stun_msg2str(int msg) 149static const char *stun_msg2str(int msg)
133{ 150{
134 151
135 const struct { enum StunClasses value; const char *name; } classes[] = { 152 const struct { enum StunClasses value; const char *name; } classes[] = {
136 { STUN_REQUEST, "Request" }, 153 { STUN_REQUEST, "Request" },
137 { STUN_INDICATION, "Indication" }, 154 { STUN_INDICATION, "Indication" },
138 { STUN_RESPONSE, "Response" }, 155 { STUN_RESPONSE, "Response" },
139 { STUN_ERROR_RESPONSE, "Error Response" }, 156 { STUN_ERROR_RESPONSE, "Error Response" },
140 { 0, NULL } 157 { 0, NULL }
141 }; 158 };
142 159
143 const struct { enum StunMethods value; const char *name; } methods[] = { 160 const struct { enum StunMethods value; const char *name; } methods[] = {
144 { STUN_BINDING, "Binding" }, 161 { STUN_BINDING, "Binding" },
145 { 0, NULL } 162 { 0, NULL }
146 }; 163 };
147 164
148 static char result[32]; 165 static char result[32];
149 const char *msg_class = NULL; 166 const char *msg_class = NULL;
150 const char *method = NULL; 167 const char *method = NULL;
151 int i; 168 int i;
152 int value; 169 int value;
153 170
154 value = decode_class(msg); 171 value = decode_class(msg);
155 for (i = 0; classes[i].name; i++) { 172 for (i = 0; classes[i].name; i++) {
156 msg_class = classes[i].name; 173 msg_class = classes[i].name;
157 if (classes[i].value == value) 174 if (classes[i].value == value)
158 break; 175 break;
159 } 176 }
160 value = decode_method(msg); 177 value = decode_method(msg);
161 for (i = 0; methods[i].name; i++) { 178 for (i = 0; methods[i].name; i++) {
162 method = methods[i].name; 179 method = methods[i].name;
163 if (methods[i].value == value) 180 if (methods[i].value == value)
164 break; 181 break;
165 } 182 }
166 snprintf(result, sizeof(result), "%s %s", 183 snprintf(result, sizeof(result), "%s %s",
167 method ? : "Unknown Method", 184 method ? : "Unknown Method",
168 msg_class ? : "Unknown Class Message"); 185 msg_class ? : "Unknown Class Message");
169 return result; 186 return result;
170} 187}
171 188
172/** 189/**
@@ -177,35 +194,35 @@ static const char *stun_msg2str(int msg)
177 */ 194 */
178static const char *stun_attr2str(int msg) 195static const char *stun_attr2str(int msg)
179{ 196{
180 const struct { enum StunAttributes value; const char *name; } attrs[] = { 197 const struct { enum StunAttributes value; const char *name; } attrs[] = {
181 { STUN_MAPPED_ADDRESS, "Mapped Address" }, 198 { STUN_MAPPED_ADDRESS, "Mapped Address" },
182 { STUN_RESPONSE_ADDRESS, "Response Address" }, 199 { STUN_RESPONSE_ADDRESS, "Response Address" },
183 { STUN_CHANGE_ADDRESS, "Change Address" }, 200 { STUN_CHANGE_ADDRESS, "Change Address" },
184 { STUN_SOURCE_ADDRESS, "Source Address" }, 201 { STUN_SOURCE_ADDRESS, "Source Address" },
185 { STUN_CHANGED_ADDRESS, "Changed Address" }, 202 { STUN_CHANGED_ADDRESS, "Changed Address" },
186 { STUN_USERNAME, "Username" }, 203 { STUN_USERNAME, "Username" },
187 { STUN_PASSWORD, "Password" }, 204 { STUN_PASSWORD, "Password" },
188 { STUN_MESSAGE_INTEGRITY, "Message Integrity" }, 205 { STUN_MESSAGE_INTEGRITY, "Message Integrity" },
189 { STUN_ERROR_CODE, "Error Code" }, 206 { STUN_ERROR_CODE, "Error Code" },
190 { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" }, 207 { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" },
191 { STUN_REFLECTED_FROM, "Reflected From" }, 208 { STUN_REFLECTED_FROM, "Reflected From" },
192 { STUN_REALM, "Realm" }, 209 { STUN_REALM, "Realm" },
193 { STUN_NONCE, "Nonce" }, 210 { STUN_NONCE, "Nonce" },
194 { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" }, 211 { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" },
195 { STUN_MS_VERSION, "MS Version" }, 212 { STUN_MS_VERSION, "MS Version" },
196 { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" }, 213 { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" },
197 { STUN_SOFTWARE, "Software" }, 214 { STUN_SOFTWARE, "Software" },
198 { STUN_ALTERNATE_SERVER, "Alternate Server" }, 215 { STUN_ALTERNATE_SERVER, "Alternate Server" },
199 { STUN_FINGERPRINT, "Fingerprint" }, 216 { STUN_FINGERPRINT, "Fingerprint" },
200 { 0, NULL } 217 { 0, NULL }
201 }; 218 };
202 int i; 219 int i;
203 220
204 for (i = 0; attrs[i].name; i++) { 221 for (i = 0; attrs[i].name; i++) {
205 if (attrs[i].value == msg) 222 if (attrs[i].value == msg)
206 return attrs[i].name; 223 return attrs[i].name;
207 } 224 }
208 return "Unknown Attribute"; 225 return "Unknown Attribute";
209} 226}
210 227
211 228
@@ -219,22 +236,22 @@ static const char *stun_attr2str(int msg)
219 */ 236 */
220static int stun_process_attr(struct StunState *state, struct stun_attr *attr) 237static int stun_process_attr(struct StunState *state, struct stun_attr *attr)
221{ 238{
222 LOG (GNUNET_ERROR_TYPE_INFO, 239 LOG (GNUNET_ERROR_TYPE_INFO,
223 "Found STUN Attribute %s (%04x), length %d\n", 240 "Found STUN Attribute %s (%04x), length %d\n",
224 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 241 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
225 242
226 switch (ntohs(attr->attr)) { 243 switch (ntohs(attr->attr)) {
227 case STUN_MAPPED_ADDRESS: 244 case STUN_MAPPED_ADDRESS:
228 case STUN_XOR_MAPPED_ADDRESS: 245 case STUN_XOR_MAPPED_ADDRESS:
229 case STUN_MS_XOR_MAPPED_ADDRESS: 246 case STUN_MS_XOR_MAPPED_ADDRESS:
230 break; 247 break;
231 default: 248 default:
232 LOG (GNUNET_ERROR_TYPE_INFO, 249 LOG (GNUNET_ERROR_TYPE_INFO,
233 "Ignoring STUN Attribute %s (%04x), length %d\n", 250 "Ignoring STUN Attribute %s (%04x), length %d\n",
234 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 251 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
235 252
236 } 253 }
237 return 0; 254 return 0;
238} 255}
239 256
240 257
@@ -247,11 +264,11 @@ static int stun_process_attr(struct StunState *state, struct stun_attr *attr)
247static void 264static void
248generate_request_id(struct stun_header *req) 265generate_request_id(struct stun_header *req)
249{ 266{
250 int x; 267 int x;
251 req->magic = htonl(STUN_MAGIC_COOKIE); 268 req->magic = htonl(STUN_MAGIC_COOKIE);
252 for (x = 0; x < 3; x++) 269 for (x = 0; x < 3; x++)
253 req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 270 req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
254 UINT32_MAX); 271 UINT32_MAX);
255} 272}
256 273
257 274
@@ -295,6 +312,8 @@ stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in
295 } 312 }
296 313
297 st->attr = type; 314 st->attr = type;
315 /*TODO: Detect Family*/
316 sa->sin_family = AF_INET;
298 sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); 317 sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16);
299 sa->sin_addr.s_addr = returned_addr->addr ^ magic; 318 sa->sin_addr.s_addr = returned_addr->addr ^ magic;
300 return 0; 319 return 0;
@@ -312,94 +331,109 @@ stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in
312 * @param len, the length of the packet 331 * @param len, the length of the packet
313 * @param arg, sockaddr_in where we will set our discovered packet 332 * @param arg, sockaddr_in where we will set our discovered packet
314 * 333 *
315 * @return, 0 on OK, -1 if the packet is invalid ( not a stun packet) 334 * @return, GNUNET_OK on OK, GNUNET_NO if the packet is invalid ( not a stun packet)
316 */ 335 */
317int 336int
318GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in *arg) 337GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in *arg)
319{ 338{
320 struct stun_header *hdr = (struct stun_header *)data; 339 struct stun_header *hdr = (struct stun_header *)data;
321 struct stun_attr *attr; 340 struct stun_attr *attr;
322 struct StunState st; 341 struct StunState st;
323 int ret = STUN_IGNORE; 342 int ret = GNUNET_OK;
324 343
325 uint32_t advertised_message_size; 344 uint32_t advertised_message_size;
326 uint32_t message_magic_cookie; 345 uint32_t message_magic_cookie;
327 346
328 347
329 /* On entry, 'len' is the length of the udp payload. After the 348 /* On entry, 'len' is the length of the udp payload. After the
330 * initial checks it becomes the size of unprocessed options, 349 * initial checks it becomes the size of unprocessed options,
331 * while 'data' is advanced accordingly. 350 * while 'data' is advanced accordingly.
332 */ 351 */
333 if (len < sizeof(struct stun_header)) { 352 if (len < sizeof(struct stun_header)) {
334 LOG (GNUNET_ERROR_TYPE_INFO, 353 LOG (GNUNET_ERROR_TYPE_INFO,
335 "STUN packet too short (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header)); 354 "STUN packet too short (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
336 GNUNET_break_op (0); 355 GNUNET_break_op (0);
337 return -1; 356 return GNUNET_NO;
338 } 357 }
339 /* Skip header as it is already in hdr */ 358 /* Skip header as it is already in hdr */
340 len -= sizeof(struct stun_header); 359 len -= sizeof(struct stun_header);
341 data += sizeof(struct stun_header); 360 data += sizeof(struct stun_header);
342 361
343 /* len as advertised in the message */ 362 /* len as advertised in the message */
344 advertised_message_size = ntohs(hdr->msglen); 363 advertised_message_size = ntohs(hdr->msglen);
345 364
346 message_magic_cookie = ntohl(hdr->magic); 365 message_magic_cookie = ntohl(hdr->magic);
347 /* Compare if the cookie match */ 366 /* Compare if the cookie match */
348 if(STUN_MAGIC_COOKIE != message_magic_cookie){ 367 if(STUN_MAGIC_COOKIE != message_magic_cookie){
349 LOG (GNUNET_ERROR_TYPE_INFO, 368 LOG (GNUNET_ERROR_TYPE_INFO,
350 "Invalid magic cookie \n"); 369 "Invalid magic cookie \n");
351 GNUNET_break_op (0); 370 GNUNET_break_op (0);
352 return -1; 371 return GNUNET_NO;
353 } 372 }
354 373
355 374
356 LOG (GNUNET_ERROR_TYPE_INFO, "STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), advertised_message_size); 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);
357 376
358 377
359 if (advertised_message_size > len) { 378 if (advertised_message_size > len) {
360 LOG (GNUNET_ERROR_TYPE_INFO, "Scrambled STUN packet length (got %d, expecting %d)\n", advertised_message_size, (int)len); 379 LOG (GNUNET_ERROR_TYPE_INFO, "Scrambled STUN packet length (got %d, expecting %d)\n", advertised_message_size, (int)len);
361 GNUNET_break_op (0); 380 GNUNET_break_op (0);
362 return -1; 381 return GNUNET_NO;
363 } else { 382 } else {
364 len = advertised_message_size; 383 len = advertised_message_size;
365 } 384 }
366 /* Zero the struct */ 385 /* Zero the struct */
367 memset(&st,0, sizeof(st)); 386 memset(&st,0, sizeof(st));
368 387
369 while (len > 0) { 388 while (len > 0) {
370 if (len < sizeof(struct stun_attr)) { 389 if (len < sizeof(struct stun_attr)) {
371 LOG (GNUNET_ERROR_TYPE_INFO, "Attribute too short (got %d, expecting %d)\n", (int)len, (int) 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));
372 GNUNET_break_op (0); 391 GNUNET_break_op (0);
373 break; 392 break;
374 } 393 }
375 attr = (struct stun_attr *)data; 394 attr = (struct stun_attr *)data;
376 395
377 /* compute total attribute length */ 396 /* compute total attribute length */
378 advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr); 397 advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr);
379 398
380 /* Check if we still have space in our buffer */ 399 /* Check if we still have space in our buffer */
381 if (advertised_message_size > len ) { 400 if (advertised_message_size > len ) {
382 LOG (GNUNET_ERROR_TYPE_INFO, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", advertised_message_size, (int)len); 401 LOG (GNUNET_ERROR_TYPE_INFO, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", advertised_message_size, (int)len);
383 GNUNET_break_op (0); 402 GNUNET_break_op (0);
384 break; 403 break;
385 } 404 }
386 405
387 406
388 stun_get_mapped(&st, attr, arg, hdr->magic); 407 stun_get_mapped(&st, attr, arg, hdr->magic);
389 408
390 if (stun_process_attr(&st, attr)) { 409 if (stun_process_attr(&st, attr)) {
391 LOG (GNUNET_ERROR_TYPE_INFO, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 410 LOG (GNUNET_ERROR_TYPE_INFO, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
392 break; 411 break;
393 } 412 }
394 /* Clear attribute id: in case previous entry was a string, 413 /** Clear attribute id: in case previous entry was a string,
395 * this will act as the terminator for the string. 414 * this will act as the terminator for the string.
396 */ 415 **/
397 attr->attr = 0; 416 attr->attr = 0;
398 data += advertised_message_size; 417 data += advertised_message_size;
399 len -= advertised_message_size; 418 len -= advertised_message_size;
400 } 419 ret = GNUNET_OK;
401 420 }
402 return ret; 421
422 return ret;
423}
424
425
426
427/**
428 * Clean-up used memory
429 *
430 * @param cls our `struct GNUNET_NAT_STUN_Handle *`
431 */
432void clean(struct GNUNET_NAT_STUN_Handle * handle)
433{
434 GNUNET_free(handle->stun_server);
435 GNUNET_free(handle);
436
403} 437}
404 438
405 439
@@ -407,97 +441,120 @@ GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in
407/** 441/**
408 * Try to establish a connection given the specified address. 442 * Try to establish a connection given the specified address.
409 * 443 *
410 * @param cls our `struct GNUNET_NAT_StunRequestHandle *` 444 * @param cls our `struct GNUNET_NAT_STUN_Handle *`
411 * @param addr address to try, NULL for "last call" 445 * @param addr address to try, NULL for "last call"
412 * @param addrlen length of @a addr 446 * @param addrlen length of @a addr
413 */ 447 */
414static void 448static void
415stun_dns_callback (void *cls, 449stun_dns_callback (void *cls,
416 const struct sockaddr *addr, 450 const struct sockaddr *addr,
417 socklen_t addrlen) { 451 socklen_t addrlen) {
452
453
454 struct GNUNET_NAT_STUN_Handle *request = cls;
418 455
456 struct stun_header *req;
457 uint8_t reqdata[1024];
458 int reqlen;
459 struct sockaddr_in server;
419 460
420 struct GNUNET_NAT_StunRequestHandle *request = cls;
421 461
422 struct stun_header *req; 462 if(NULL == request) {
423 uint8_t reqdata[1024];
424 int reqlen;
425 struct sockaddr_in server;
426 463
427 if(NULL == request) { 464 if( GNUNET_NO == request->dns_success){
428 LOG (GNUNET_ERROR_TYPE_INFO, "Empty request\n"); 465 LOG (GNUNET_ERROR_TYPE_INFO, "Empty request\n");
429 /* FIXME clean up ? */ 466 clean(request);
430 return; 467 request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
431 } 468 }
469 return;
470 }
432 471
433 if (NULL == addr) { 472 if (NULL == addr) {
434 request->dns_active = NULL; 473 request->dns_active = NULL;
435 LOG (GNUNET_ERROR_TYPE_INFO, "Error resolving host %s\n", request->stun_server);
436 /* FIXME clean up? */
437 return;
438 }
439 474
475 if( GNUNET_NO == request->dns_success){
476 LOG (GNUNET_ERROR_TYPE_INFO, "Error resolving host %s\n", request->stun_server);
477 clean(request);
478 request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
479 }
440 480
441 memset(&server,0, sizeof(server)); 481 return;
442 server.sin_family = AF_INET; 482 }
443 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
444 server.sin_port = htons(request->stun_port);
445 483
446 484
447 /*Craft the simplest possible STUN packet. A request binding*/ 485 request->dns_success= GNUNET_YES;
448 req = (struct stun_header *)reqdata; 486 memset(&server,0, sizeof(server));
449 generate_request_id(req); 487 server.sin_family = AF_INET;
450 reqlen = 0; 488 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
451 req->msgtype = 0; 489 server.sin_port = htons(request->stun_port);
452 req->msglen = 0; 490
453 req->msglen = htons(reqlen); 491
454 req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING)); 492 /*Craft the simplest possible STUN packet. A request binding*/
493 req = (struct stun_header *)reqdata;
494 generate_request_id(req);
495 reqlen = 0;
496 req->msgtype = 0;
497 req->msglen = 0;
498 req->msglen = htons(reqlen);
499 req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING));
500
501 /* Send the packet */
502 if (-1 == GNUNET_NETWORK_socket_sendto (request->sock, req, ntohs(req->msglen) + sizeof(*req),
503 (const struct sockaddr *) &server, sizeof (server)))
504 {
505 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Fail to sendto");
506 clean(request);
507 request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
508 return;
509 }
455 510
456 /* Send the packet */
457 if (-1 == GNUNET_NETWORK_socket_sendto (request->sock, req, ntohs(req->msglen) + sizeof(*req),
458 (const struct sockaddr *) &server, sizeof (server)))
459 {
460 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "Fail to sendto");
461 }
462 511
463} 512}
464 513
465 514
515
516
517
466/** 518/**
467 * Make Generic STUN request and 519 * Make Generic STUN request and
468 * Send a generic stun request to the server specified using the specified socket. 520 * Send a generic stun request to the server specified using the specified socket.
469 * possibly waiting for a reply and filling the 'reply' field with 521 * possibly waiting for a reply and filling the 'reply' field with
470 * the externally visible address. 522 * the externally visible address.
471 *c 523 *
472 * @param server, the address of the stun server 524 * @param server, the address of the stun server
473 * @param port, port of the stun server 525 * @param port, port of the stun server
474 * @param sock the socket used to send the request 526 * @param sock the socket used to send the request
475 * @return GNUNET_NAT_StunRequestHandle on success, NULL on error. 527 * @return GNUNET_NAT_STUN_Handle on success, NULL on error.
476 */ 528 */
477struct GNUNET_NAT_StunRequestHandle * 529struct GNUNET_NAT_STUN_Handle *
478GNUNET_NAT_stun_make_request(char * server, int port, struct GNUNET_NETWORK_Handle * sock) 530GNUNET_NAT_stun_make_request(char * server, int port,
531 struct GNUNET_NETWORK_Handle * sock,GNUNET_NAT_stun_RequestCallback cb,
532 void *cb_cls)
479{ 533{
480 534
481 struct GNUNET_NAT_StunRequestHandle *rh; 535 struct GNUNET_NAT_STUN_Handle *rh;
536
537 rh = GNUNET_malloc (sizeof (struct GNUNET_NAT_STUN_Handle));
538 rh->sock = sock;
482 539
483 rh = GNUNET_malloc (sizeof (struct GNUNET_NAT_StunRequestHandle)); 540 char * server_copy = GNUNET_strdup (server);
484 rh->sock = sock;
485 541
486 char * server_copy = GNUNET_malloc (1 + strlen (server)); 542 rh->cb = cb;
487 if (server_copy) { 543 rh->cb_cls = cb_cls;
488 strcpy (server_copy, server); 544 rh->stun_server = server_copy;
489 }else{ 545 rh->stun_port = port;
490 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "Failed to allocate string"); 546 rh->dns_success = GNUNET_NO;
491 /* FIXME: cleanup rh? */ 547
492 return NULL; 548 rh->dns_active = GNUNET_RESOLVER_ip_get (server_copy, AF_INET,
493 } 549 TIMEOUT,
550 &stun_dns_callback, rh);
551
552 if(rh->dns_active == NULL)
553 {
554 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Failed DNS");
555 return NULL;
556 }
494 557
495 rh->stun_server = server_copy;
496 rh->stun_port = port;
497 rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server, AF_INET,
498 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
499 &stun_dns_callback, rh);
500 /* FIXME: error handling NULL==dns_active, callback function? */
501 558
502 return rh; 559 return rh;
503} 560}