ml / util / stun.c @ 11fce711
History | View | Annotate | Download (25.9 KB)
1 |
/*
|
---|---|
2 |
* Policy Management
|
3 |
*
|
4 |
* NEC Europe Ltd. PROPRIETARY INFORMATION
|
5 |
*
|
6 |
* This software is supplied under the terms of a license agreement
|
7 |
* or nondisclosure agreement with NEC Europe Ltd. and may not be
|
8 |
* copied or disclosed except in accordance with the terms of that
|
9 |
* agreement.
|
10 |
*
|
11 |
* Copyright (c) 2009 NEC Europe Ltd. All Rights Reserved.
|
12 |
*
|
13 |
* Authors: Kristian Beckers <beckers@nw.neclab.eu>
|
14 |
* Sebastian Kiesel <kiesel@nw.neclab.eu>
|
15 |
*
|
16 |
*
|
17 |
* NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
|
18 |
* INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
|
19 |
* AND FITNESS FOR A PARTICULAR PURPOSE AND THE WARRANTY AGAINST LATENT
|
20 |
* DEFECTS, WITH RESPECT TO THE PROGRAM AND THE ACCOMPANYING
|
21 |
* DOCUMENTATION.
|
22 |
*
|
23 |
* No Liability For Consequential Damages IN NO EVENT SHALL NEC Europe
|
24 |
* Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY
|
25 |
* DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
|
26 |
* OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR
|
27 |
* OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL, INCIDENTAL,
|
28 |
* ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF OR INABILITY
|
29 |
* TO USE THIS PROGRAM, EVEN IF NEC Europe Ltd. HAS BEEN ADVISED OF THE
|
30 |
* POSSIBILITY OF SUCH DAMAGES.
|
31 |
*
|
32 |
* THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
|
33 |
*/
|
34 |
|
35 |
#include <assert.h> |
36 |
#include <stdlib.h> |
37 |
#include <unistd.h> |
38 |
#include <errno.h> |
39 |
#include <string.h> |
40 |
|
41 |
#include <stdio.h> |
42 |
#include <unistd.h> |
43 |
|
44 |
#include <sys/ioctl.h> |
45 |
#include <sys/socket.h> |
46 |
#include <sys/time.h> |
47 |
#include <sys/types.h> |
48 |
#include <arpa/inet.h> |
49 |
|
50 |
#include <fcntl.h> |
51 |
#include <netdb.h> |
52 |
#include <netinet/in.h> |
53 |
//#include <arpa/nameser.h>
|
54 |
//#include <resolv.h>
|
55 |
#include <net/if.h> |
56 |
|
57 |
#include "ml_log.h" |
58 |
#include "stun.h" |
59 |
#include "udpSocket.h" |
60 |
|
61 |
/// define a structure to hold a stun address
|
62 |
const UInt8 IPv4Family = 0x01; |
63 |
const UInt8 IPv6Family = 0x02; |
64 |
// define flags
|
65 |
const UInt32 ChangeIpFlag = 0x04; |
66 |
const UInt32 ChangePortFlag = 0x02; |
67 |
// define stun attributes
|
68 |
const UInt16 MappedAddress = 0x0001; |
69 |
const UInt16 ResponseAddress = 0x0002; |
70 |
const UInt16 ChangeRequest = 0x0003; |
71 |
const UInt16 SourceAddress = 0x0004; |
72 |
const UInt16 ChangedAddress = 0x0005; |
73 |
const UInt16 Username = 0x0006; |
74 |
const UInt16 Password = 0x0007; |
75 |
const UInt16 MessageIntegrity = 0x0008; |
76 |
const UInt16 ErrorCode = 0x0009; |
77 |
const UInt16 UnknownAttribute = 0x000A; |
78 |
const UInt16 ReflectedFrom = 0x000B; |
79 |
const UInt16 XorMappedAddress = 0x8020; |
80 |
const UInt16 XorOnly = 0x0021; |
81 |
const UInt16 ServerName = 0x8022; |
82 |
const UInt16 SecondaryAddress = 0x8050; // Non standard extention |
83 |
// define types for a stun message
|
84 |
const UInt16 BindRequestMsg = 0x0001; |
85 |
const UInt16 BindResponseMsg = 0x0101; |
86 |
const UInt16 BindErrorResponseMsg = 0x0111; |
87 |
const UInt16 SharedSecretRequestMsg = 0x0002; |
88 |
const UInt16 SharedSecretResponseMsg = 0x0102; |
89 |
const UInt16 SharedSecretErrorResponseMsg = 0x0112; |
90 |
|
91 |
void pmtu_error_cb_stun(char *buf,int bufsize){ |
92 |
|
93 |
printf("error: MTU size of stun message too big !");
|
94 |
|
95 |
} |
96 |
|
97 |
/* sends a request to a stun server */
|
98 |
int send_stun_request(const int udpSocket,struct sockaddr_in *stunServ) |
99 |
{ |
100 |
|
101 |
assert( sizeof(UInt8 ) == 1 ); |
102 |
assert( sizeof(UInt16) == 2 ); |
103 |
assert( sizeof(UInt32) == 4 ); |
104 |
|
105 |
bool verbose = false; |
106 |
|
107 |
//set the verbose mode
|
108 |
verbose = true;
|
109 |
|
110 |
StunMessage req; |
111 |
memset(&req, 0, sizeof(StunMessage)); |
112 |
|
113 |
StunAtrString username; |
114 |
StunAtrString password; |
115 |
username.sizeValue = 0;
|
116 |
password.sizeValue = 0;
|
117 |
|
118 |
/* build a stun request message */
|
119 |
/* creates a stun message struct with the given atributes */
|
120 |
stunBuildReqSimple( &req, username, |
121 |
false , false , |
122 |
0x0c );
|
123 |
|
124 |
/* buffer for the stun request */
|
125 |
char buf[STUN_MAX_MESSAGE_SIZE];
|
126 |
int len = STUN_MAX_MESSAGE_SIZE;
|
127 |
|
128 |
/* encode the stun message */
|
129 |
len = stunEncodeMessage( req, buf, len, password, verbose); |
130 |
|
131 |
struct iovec iov;
|
132 |
iov.iov_len = len; |
133 |
iov.iov_base = buf; |
134 |
sendPacket(udpSocket,&iov,1,stunServ);
|
135 |
|
136 |
return 0; |
137 |
|
138 |
} |
139 |
|
140 |
/* sends a keep alive to a server */
|
141 |
int send_stun_keep_alive(const int udpSocket,struct sockaddr_in *stunServ) |
142 |
{ |
143 |
|
144 |
send_stun_request(udpSocket,stunServ); |
145 |
|
146 |
return 0; |
147 |
} |
148 |
|
149 |
/* parses a given stun message and sets the refelxive address */
|
150 |
int recv_stun_message(char *msgbuf,int msgLen,StunMessage *response){ |
151 |
|
152 |
//StunMessage resp;
|
153 |
//memset(&resp, 0, sizeof(StunMessage));
|
154 |
int returnValue = 0; |
155 |
//bool verbose = true;
|
156 |
bool verbose = false; |
157 |
|
158 |
//printf("still alive 4 \n ");
|
159 |
//if ( verbose ) printf("Got a response \n");
|
160 |
|
161 |
bool ok = stunParseMessage(msgbuf, msgLen, response, verbose );
|
162 |
|
163 |
if (!ok){
|
164 |
|
165 |
returnValue = 1;
|
166 |
error("parse STUN message failed \n");
|
167 |
|
168 |
} |
169 |
|
170 |
UInt32 ip_addr = response->mappedAddress.ipv4.addr; |
171 |
char mapped_addr[16]; |
172 |
int length;
|
173 |
length = sprintf(mapped_addr,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16) & 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff); |
174 |
|
175 |
ip_addr = response->changedAddress.ipv4.addr; |
176 |
char changed_addr[16]; |
177 |
length = sprintf(changed_addr,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16)\ |
178 |
& 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff); |
179 |
|
180 |
if ( verbose )
|
181 |
{ |
182 |
|
183 |
info( "\t mappedAddr= ipv4 %s port %d \n \t changedAddr= ipv4 %s port %d \n",
|
184 |
mapped_addr , |
185 |
response->mappedAddress.ipv4.port, |
186 |
changed_addr, |
187 |
response->changedAddress.ipv4.port); |
188 |
|
189 |
} |
190 |
debug("still here");
|
191 |
|
192 |
//reflexiveAddr.sin_addr.s_addr = inet_addr(changed_addr);
|
193 |
//reflexiveAddr->sin_addr.s_addr = inet_addr("1.1.1.1");
|
194 |
//reflexiveAddr->sin_port = htons(resp.mappedAddress.ipv4.port);
|
195 |
|
196 |
return returnValue;
|
197 |
} |
198 |
|
199 |
bool
|
200 |
stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4 *result, bool verbose ) |
201 |
{ |
202 |
if ( hdrLen != 8 ) |
203 |
{ |
204 |
error("hdrlen is not 8 \n ");
|
205 |
return false; |
206 |
} |
207 |
result->pad = *body++; |
208 |
result->family = *body++; |
209 |
|
210 |
if (result->family == IPv4Family)
|
211 |
{ |
212 |
|
213 |
UInt16 nport; |
214 |
memcpy(&nport, body, 2); body+=2; |
215 |
|
216 |
if (verbose) info("port %i \n",ntohs(nport)); |
217 |
|
218 |
result->ipv4.port = ntohs(nport); |
219 |
|
220 |
|
221 |
UInt32 naddr; |
222 |
memcpy(&naddr, body, 4); body+=4; |
223 |
//printf("port %d \n",ntohl(naddr));
|
224 |
|
225 |
if (verbose)
|
226 |
{ |
227 |
UInt32 ip_addr = ntohl(naddr); |
228 |
char str_p[20]; |
229 |
|
230 |
sprintf(str_p,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16) & 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff); |
231 |
|
232 |
info(" ipv4 as str %s \n ",str_p);
|
233 |
} |
234 |
|
235 |
result->ipv4.addr = ntohl(naddr); |
236 |
|
237 |
return true; |
238 |
} |
239 |
|
240 |
else if (result->family == IPv6Family) |
241 |
|
242 |
{ |
243 |
warn("ipv6 not supported \n");
|
244 |
} |
245 |
else
|
246 |
{ |
247 |
error("bad address family: %i \n ",result->family );
|
248 |
} |
249 |
|
250 |
return false; |
251 |
} |
252 |
|
253 |
|
254 |
|
255 |
bool
|
256 |
stunParseMessage( char* buf, unsigned int bufLen, StunMessage *msg, bool verbose) |
257 |
{ |
258 |
if (verbose) info("Received stun message: %d bytes \n",bufLen); |
259 |
memset(msg, 0, sizeof(msg)); |
260 |
|
261 |
if (sizeof(StunMsgHdr) > bufLen) |
262 |
{ |
263 |
error("Bad message \n");
|
264 |
return false; |
265 |
} |
266 |
|
267 |
memcpy(&msg->msgHdr, buf, sizeof(StunMsgHdr));
|
268 |
msg->msgHdr.msgType = ntohs(msg->msgHdr.msgType); |
269 |
msg->msgHdr.msgLength = ntohs(msg->msgHdr.msgLength); |
270 |
|
271 |
if (msg->msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen) |
272 |
{ |
273 |
error("Message header length doesn't match message size: %d - %d \n"
|
274 |
,msg->msgHdr.msgLength,bufLen); |
275 |
return false; |
276 |
} |
277 |
|
278 |
char* body = buf + sizeof(StunMsgHdr); |
279 |
unsigned int size = msg->msgHdr.msgLength; |
280 |
|
281 |
debug("bytes after header = %d",size);
|
282 |
|
283 |
while ( size > 0 ) |
284 |
{ |
285 |
// !jf! should check that there are enough bytes left in the buffer
|
286 |
|
287 |
StunAtrHdr* attr = (StunAtrHdr*)(body); |
288 |
|
289 |
unsigned int attrLen = ntohs(attr->length); |
290 |
int atrType = ntohs(attr->type);
|
291 |
|
292 |
//if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl;
|
293 |
if ( attrLen+4 > size ) |
294 |
{ |
295 |
debug( "claims attribute is larger than size of message " \
|
296 |
"(attribute type= %d \n" ,atrType);
|
297 |
return false; |
298 |
} |
299 |
|
300 |
body += 4; // skip the length and type in attribute header |
301 |
size -= 4;
|
302 |
|
303 |
if( atrType == MappedAddress)
|
304 |
{ |
305 |
msg->hasMappedAddress = true;
|
306 |
//printf("has mapped address \n");
|
307 |
if ( stunParseAtrAddress(body, attrLen, &msg->mappedAddress, verbose) == false) |
308 |
{ |
309 |
debug("problem parsing MappedAddress \n");
|
310 |
return false; |
311 |
} |
312 |
else
|
313 |
{ |
314 |
if (verbose) {info("MappedAddress -------------------\n");} |
315 |
} |
316 |
|
317 |
}else
|
318 |
if (atrType == ResponseAddress)
|
319 |
{ |
320 |
msg->hasResponseAddress = true;
|
321 |
if ( stunParseAtrAddress( body, attrLen, &msg->responseAddress, verbose )== false ) |
322 |
{ |
323 |
debug("problem parsing ResponseAddress \n");
|
324 |
return false; |
325 |
} |
326 |
else
|
327 |
{ |
328 |
if (verbose) {info("ResponseAddress ---------------------\n");} |
329 |
} |
330 |
|
331 |
}else if(atrType == ChangeRequest) |
332 |
{ |
333 |
msg->hasChangeRequest = true;
|
334 |
if (stunParseAtrChangeRequest( body, attrLen, &msg->changeRequest) == false) |
335 |
{ |
336 |
debug("problem parsing ChangeRequest \n");
|
337 |
return false; |
338 |
} |
339 |
else
|
340 |
{ |
341 |
if (verbose) info("ChangeRequest = %i \n",(int)&msg->changeRequest.value); |
342 |
} |
343 |
|
344 |
} else if (atrType == SourceAddress) |
345 |
{ |
346 |
msg->hasSourceAddress = true;
|
347 |
if ( stunParseAtrAddress( body, attrLen, &msg->sourceAddress, verbose )== false ) |
348 |
{ |
349 |
debug("problem parsing SourceAddress \n");
|
350 |
return false; |
351 |
} |
352 |
else
|
353 |
{ |
354 |
if (verbose) info("SourceAddress ------------------\n"); |
355 |
} |
356 |
} else if (atrType == ChangedAddress) |
357 |
{ |
358 |
msg->hasChangedAddress = true;
|
359 |
if ( stunParseAtrAddress( body, attrLen, &msg->changedAddress, verbose )== false ) |
360 |
{ |
361 |
debug("problem parsing ChangedAddress \n");
|
362 |
return false; |
363 |
} |
364 |
else
|
365 |
{ |
366 |
if (verbose) info("ChangedAddress = ---------------------\n"); |
367 |
} |
368 |
} else if (atrType == Username) |
369 |
{ |
370 |
msg->hasUsername = true;
|
371 |
if (stunParseAtrString( body, attrLen, &msg->username) == false) |
372 |
{ |
373 |
debug("problem parsing Username \n");
|
374 |
return false; |
375 |
} |
376 |
else
|
377 |
{ |
378 |
if (verbose) info("Username = %s \n",msg->username.value); |
379 |
} |
380 |
}else if (atrType == Password) |
381 |
{ |
382 |
msg->hasPassword = true;
|
383 |
if (stunParseAtrString( body, attrLen, &msg->password) == false) |
384 |
{ |
385 |
debug("problem parsing Password \n");
|
386 |
return false; |
387 |
} |
388 |
else
|
389 |
{ |
390 |
if (verbose) info("Password = %s \n",(char *)&msg->password.value); |
391 |
} |
392 |
}else if (atrType == MessageIntegrity) |
393 |
{ |
394 |
msg->hasMessageIntegrity = true;
|
395 |
if (stunParseAtrIntegrity( body, attrLen,&msg->messageIntegrity) == false) |
396 |
{ |
397 |
debug("problem parsing MessageIntegrity \n");
|
398 |
return false; |
399 |
} |
400 |
else
|
401 |
{ |
402 |
//if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl;
|
403 |
} |
404 |
|
405 |
// read the current HMAC
|
406 |
// look up the password given the user of given the transaction id
|
407 |
// compute the HMAC on the buffer
|
408 |
// decide if they match or not
|
409 |
|
410 |
} else if (atrType == ErrorCode) |
411 |
{ |
412 |
msg->hasErrorCode = true;
|
413 |
if (stunParseAtrError(body, attrLen, &msg->errorCode) == false) |
414 |
{ |
415 |
debug("problem parsing ErrorCode \n");
|
416 |
return false; |
417 |
} |
418 |
else
|
419 |
{ |
420 |
if (verbose) info("ErrorCode = %d %d %s \n",(int)(msg->errorCode.errorClass) ,(int)(msg->errorCode.number) |
421 |
,msg->errorCode.reason); |
422 |
} |
423 |
|
424 |
} else if (atrType == UnknownAttribute) |
425 |
{ |
426 |
msg->hasUnknownAttributes = true;
|
427 |
if (stunParseAtrUnknown(body, attrLen,&msg->unknownAttributes) == false) |
428 |
{ |
429 |
debug("problem parsing UnknownAttribute \n");
|
430 |
return false; |
431 |
} |
432 |
} else if (atrType == ReflectedFrom) |
433 |
{ |
434 |
msg->hasReflectedFrom = true;
|
435 |
if ( stunParseAtrAddress( body, attrLen, &msg->reflectedFrom, verbose ) == false ) |
436 |
{ |
437 |
debug("problem parsing ReflectedFrom \n");
|
438 |
return false; |
439 |
} |
440 |
} else if (atrType == XorMappedAddress) |
441 |
{ |
442 |
msg->hasXorMappedAddress = true;
|
443 |
if ( stunParseAtrAddress( body, attrLen, &msg->xorMappedAddress, verbose ) == false ) |
444 |
{ |
445 |
debug("problem parsing XorMappedAddress \n");
|
446 |
return false; |
447 |
} |
448 |
else
|
449 |
{ |
450 |
if (verbose) info("XorMappedAddress ------------------- \n"); |
451 |
} |
452 |
} else if (atrType == XorOnly) |
453 |
{ |
454 |
msg->xorOnly = true;
|
455 |
if (verbose)
|
456 |
{ |
457 |
debug("xorOnly = true \n");
|
458 |
} |
459 |
} else if (atrType == ServerName) |
460 |
{ |
461 |
msg->hasServerName = true;
|
462 |
if (stunParseAtrString( body, attrLen, &msg->serverName) == false) |
463 |
{ |
464 |
debug("problem parsing ServerName \n");
|
465 |
return false; |
466 |
} |
467 |
else
|
468 |
{ |
469 |
if (verbose) info("ServerName = %s \n",(char *)&msg->serverName.value); |
470 |
} |
471 |
} else if (atrType == SecondaryAddress) |
472 |
{ |
473 |
msg->hasSecondaryAddress = true;
|
474 |
if ( stunParseAtrAddress( body, attrLen, &msg->secondaryAddress, verbose ) == false ) |
475 |
{ |
476 |
debug("problem parsing secondaryAddress \n");
|
477 |
return false; |
478 |
} |
479 |
else
|
480 |
{ |
481 |
if (verbose) info("SecondaryAddress ---------------- \n"); |
482 |
} |
483 |
} else
|
484 |
{ |
485 |
|
486 |
if (verbose) info("Unknown attribute: %i \n",atrType); |
487 |
if ( atrType <= 0x7FFF ) |
488 |
{ |
489 |
return false; |
490 |
} |
491 |
} |
492 |
|
493 |
|
494 |
body += attrLen; |
495 |
size -= attrLen; |
496 |
} |
497 |
|
498 |
return true; |
499 |
} |
500 |
|
501 |
|
502 |
void
|
503 |
stunBuildReqSimple(StunMessage* msg, |
504 |
const StunAtrString username,
|
505 |
bool changePort, bool changeIp, unsigned int id ) |
506 |
{ |
507 |
assert( msg ); |
508 |
memset( msg , 0 , sizeof(*msg) ); |
509 |
|
510 |
msg->msgHdr.msgType = BindRequestMsg; |
511 |
|
512 |
int i;
|
513 |
for (i=0; i<16; i=i+4 ) |
514 |
{ |
515 |
assert(i+3<16); |
516 |
int r = stunRand();
|
517 |
msg->msgHdr.id.octet[i+0]= r>>0; |
518 |
msg->msgHdr.id.octet[i+1]= r>>8; |
519 |
msg->msgHdr.id.octet[i+2]= r>>16; |
520 |
msg->msgHdr.id.octet[i+3]= r>>24; |
521 |
} |
522 |
|
523 |
if ( id != 0 ) |
524 |
{ |
525 |
msg->msgHdr.id.octet[0] = id;
|
526 |
} |
527 |
|
528 |
msg->hasChangeRequest = true;
|
529 |
msg->changeRequest.value =(changeIp?ChangeIpFlag:0) |
|
530 |
(changePort?ChangePortFlag:0);
|
531 |
|
532 |
if ( username.sizeValue > 0 ) |
533 |
{ |
534 |
msg->hasUsername = true;
|
535 |
msg->username = username; |
536 |
} |
537 |
} |
538 |
|
539 |
|
540 |
unsigned int |
541 |
stunEncodeMessage( const StunMessage msg,
|
542 |
char* buf,
|
543 |
unsigned int bufLen, |
544 |
const StunAtrString password,
|
545 |
bool verbose)
|
546 |
{ |
547 |
assert(bufLen >= sizeof(StunMsgHdr));
|
548 |
char* ptr = buf;
|
549 |
|
550 |
ptr = encode16(ptr, msg.msgHdr.msgType); |
551 |
char* lengthp = ptr;
|
552 |
ptr = encode16(ptr, 0);
|
553 |
ptr = encode(ptr, (const char*)(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id)); |
554 |
|
555 |
if (verbose) debug("Encoding stun message: "); |
556 |
|
557 |
if (msg.hasMappedAddress)
|
558 |
{ |
559 |
//if (verbose) info("Encoding MappedAddress: %s \n",msg.mappedAddress.ipv4);
|
560 |
ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress); |
561 |
} |
562 |
if (msg.hasResponseAddress)
|
563 |
{ |
564 |
//if (verbose) info("Encoding ResponseAddress: %s \n",msg.responseAddress.ipv4);
|
565 |
ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress); |
566 |
} |
567 |
if (msg.hasChangeRequest)
|
568 |
{ |
569 |
//if (verbose) info("Encoding ChangeRequest: %s \n",msg.changeRequest.value);
|
570 |
ptr = encodeAtrChangeRequest(ptr, msg.changeRequest); |
571 |
} |
572 |
if (msg.hasSourceAddress)
|
573 |
{ |
574 |
//if (verbose) info("Encoding SourceAddress: %s \n ",msg.sourceAddress.ipv4);
|
575 |
ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress); |
576 |
} |
577 |
if (msg.hasChangedAddress)
|
578 |
{ |
579 |
//if (verbose) info("Encoding ChangedAddress: %s \n ",msg.changedAddress.ipv4);
|
580 |
ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress); |
581 |
} |
582 |
if (msg.hasUsername)
|
583 |
{ |
584 |
if (verbose) info("Encoding Username: %s \n", msg.username.value); |
585 |
ptr = encodeAtrString(ptr, Username, msg.username); |
586 |
} |
587 |
if (msg.hasPassword)
|
588 |
{ |
589 |
if (verbose) info("Encoding Password: %s \n ",msg.password.value); |
590 |
ptr = encodeAtrString(ptr, Password, msg.password); |
591 |
} |
592 |
if (msg.hasErrorCode)
|
593 |
{ |
594 |
if (verbose) info("Encoding ErrorCode: class= %d number= %d reason= %s \n" |
595 |
,(int)msg.errorCode.errorClass
|
596 |
,(int)msg.errorCode.number
|
597 |
,msg.errorCode.reason |
598 |
); |
599 |
|
600 |
ptr = encodeAtrError(ptr, msg.errorCode); |
601 |
} |
602 |
if (msg.hasUnknownAttributes)
|
603 |
{ |
604 |
if (verbose) info("Encoding UnknownAttribute: ??? \n"); |
605 |
ptr = encodeAtrUnknown(ptr, msg.unknownAttributes); |
606 |
} |
607 |
if (msg.hasReflectedFrom)
|
608 |
{ |
609 |
//if (verbose) info("Encoding ReflectedFrom: %s \n ",msg.reflectedFrom.ipv4);
|
610 |
ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom); |
611 |
} |
612 |
if (msg.hasXorMappedAddress)
|
613 |
{ |
614 |
//if (verbose) info("Encoding XorMappedAddress: %s \n ",msg.xorMappedAddress.ipv4 );
|
615 |
ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress); |
616 |
} |
617 |
if (msg.xorOnly)
|
618 |
{ |
619 |
if (verbose) info("Encoding xorOnly: \n"); |
620 |
ptr = encodeXorOnly( ptr ); |
621 |
} |
622 |
if (msg.hasServerName)
|
623 |
{ |
624 |
if (verbose) info("Encoding ServerName: %s \n ",msg.serverName.value); |
625 |
ptr = encodeAtrString(ptr, ServerName, msg.serverName); |
626 |
} |
627 |
if (msg.hasSecondaryAddress)
|
628 |
{ |
629 |
//if (verbose) info("Encoding SecondaryAddress: %s \n", msg.secondaryAddress.ipv4);
|
630 |
ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress); |
631 |
} |
632 |
|
633 |
if (password.sizeValue > 0) |
634 |
{ |
635 |
if (verbose) info("HMAC with password: %s \n ",password.value); |
636 |
|
637 |
StunAtrIntegrity integrity; |
638 |
//computeHmac(integrity.hash, buf, (int)(ptr-buf) , password.value, password.sizeValue);
|
639 |
ptr = encodeAtrIntegrity(ptr, integrity); |
640 |
} |
641 |
|
642 |
encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)));
|
643 |
return (int)(ptr - buf); |
644 |
} |
645 |
|
646 |
|
647 |
int
|
648 |
stunRand() |
649 |
{ |
650 |
// return 32 bits of random stuff
|
651 |
assert( sizeof(int) == 4 ); |
652 |
static bool init=false; |
653 |
if ( !init )
|
654 |
{ |
655 |
init = true;
|
656 |
|
657 |
UInt64 tick; |
658 |
|
659 |
#if defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) || defined(__amd64__) )
|
660 |
asm("rdtsc" : "=A" (tick)); |
661 |
#elif defined (__SUNPRO_CC) || defined( __sparc__ )
|
662 |
tick = gethrtime(); |
663 |
#elif defined(__MACH__)
|
664 |
int fd=open("/dev/random",O_RDONLY); |
665 |
read(fd,&tick,sizeof(tick));
|
666 |
closesocket(fd); |
667 |
#else
|
668 |
# error Need some way to seed the random number generator
|
669 |
#endif
|
670 |
int seed = (int)(tick); |
671 |
#ifdef WIN32
|
672 |
srand(seed); |
673 |
#else
|
674 |
srandom(seed); |
675 |
#endif
|
676 |
} |
677 |
|
678 |
|
679 |
return random();
|
680 |
|
681 |
} |
682 |
|
683 |
|
684 |
UInt64 |
685 |
stunGetSystemTimeSecs() |
686 |
{ |
687 |
UInt64 time=0;
|
688 |
#if defined(WIN32)
|
689 |
SYSTEMTIME t; |
690 |
// CJ TODO - this probably has bug on wrap around every 24 hours
|
691 |
GetSystemTime( &t ); |
692 |
time = (t.wHour*60+t.wMinute)*60+t.wSecond; |
693 |
#else
|
694 |
struct timeval now;
|
695 |
gettimeofday( &now , NULL );
|
696 |
//assert( now );
|
697 |
time = now.tv_sec; |
698 |
#endif
|
699 |
return time;
|
700 |
} |
701 |
|
702 |
|
703 |
bool
|
704 |
stunParseServerName( char* name, StunAddress4 addr)
|
705 |
{ |
706 |
assert(name); |
707 |
|
708 |
// TODO - put in DNS SRV stuff.
|
709 |
|
710 |
bool ret = stunParseHostName( name, addr.addr, addr.port, 3478); |
711 |
if ( ret != true ) |
712 |
{ |
713 |
addr.port=0xFFFF;
|
714 |
} |
715 |
return ret;
|
716 |
} |
717 |
|
718 |
|
719 |
// returns true if it scucceeded
|
720 |
bool
|
721 |
stunParseHostName( char* peerName,
|
722 |
UInt32 ip, |
723 |
UInt16 portVal, |
724 |
UInt16 defaultPort ) |
725 |
{ |
726 |
struct in_addr sin_addr;
|
727 |
|
728 |
char host[512]; |
729 |
strncpy(host,peerName,512);
|
730 |
host[512-1]='\0'; |
731 |
char* port = NULL; |
732 |
|
733 |
int portNum = defaultPort;
|
734 |
|
735 |
// pull out the port part if present.
|
736 |
char* sep = strchr(host,':'); |
737 |
|
738 |
if ( sep == NULL ) |
739 |
{ |
740 |
portNum = defaultPort; |
741 |
} |
742 |
else
|
743 |
{ |
744 |
*sep = '\0';
|
745 |
port = sep + 1;
|
746 |
// set port part
|
747 |
|
748 |
char* endPtr=NULL; |
749 |
|
750 |
portNum = strtol(port,&endPtr,10);
|
751 |
|
752 |
if ( endPtr != NULL ) |
753 |
{ |
754 |
if ( *endPtr != '\0' ) |
755 |
{ |
756 |
portNum = defaultPort; |
757 |
} |
758 |
} |
759 |
} |
760 |
|
761 |
if ( portNum < 1024 ) return false; |
762 |
if ( portNum >= 0xFFFF ) return false; |
763 |
|
764 |
// figure out the host part
|
765 |
struct hostent* h;
|
766 |
|
767 |
h = gethostbyname( host ); |
768 |
if ( h == NULL ) |
769 |
{ |
770 |
//int err = getErrno();
|
771 |
error("error was %d \n",errno);
|
772 |
ip = ntohl( 0x7F000001L );
|
773 |
return false; |
774 |
} |
775 |
else
|
776 |
{ |
777 |
sin_addr = *(struct in_addr*)h->h_addr;
|
778 |
ip = ntohl( sin_addr.s_addr ); |
779 |
} |
780 |
|
781 |
|
782 |
portVal = portNum; |
783 |
|
784 |
return true; |
785 |
} |
786 |
|
787 |
|
788 |
|
789 |
bool
|
790 |
stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest *result ) |
791 |
{ |
792 |
if ( hdrLen != 4 ) |
793 |
{ |
794 |
error("hdr length = %d excepcting %d \n ",hdrLen,sizeof(result)); |
795 |
|
796 |
error("Incorrect size for ChangeRequest \n ");
|
797 |
|
798 |
return false; |
799 |
} |
800 |
else
|
801 |
{ |
802 |
memcpy(&result->value, body, 4);
|
803 |
result->value = ntohl(result->value); |
804 |
return true; |
805 |
} |
806 |
} |
807 |
|
808 |
|
809 |
|
810 |
|
811 |
bool
|
812 |
stunParseAtrUnknown( char* body, unsigned int hdrLen, StunAtrUnknown *result) |
813 |
{ |
814 |
if ( hdrLen >= sizeof(StunAtrUnknown) ) |
815 |
{ |
816 |
return false; |
817 |
} |
818 |
else
|
819 |
{ |
820 |
if (hdrLen % 4 != 0) return false; |
821 |
result->numAttributes = hdrLen / 4;
|
822 |
int i;
|
823 |
for (i=0; i<result->numAttributes; i++) |
824 |
{ |
825 |
memcpy(&result->attrType[i], body, 2); body+=2; |
826 |
result->attrType[i] = ntohs(result->attrType[i]); |
827 |
} |
828 |
return true; |
829 |
} |
830 |
} |
831 |
|
832 |
|
833 |
|
834 |
bool
|
835 |
stunParseAtrString( char* body, unsigned int hdrLen, StunAtrString *result ) |
836 |
{ |
837 |
if ( hdrLen >= STUN_MAX_STRING )
|
838 |
{ |
839 |
debug( "String is too large \n");
|
840 |
return false; |
841 |
} |
842 |
else
|
843 |
{ |
844 |
if (hdrLen % 4 != 0) |
845 |
{ |
846 |
debug("Bad length string %d \n ",hdrLen);
|
847 |
return false; |
848 |
} |
849 |
|
850 |
result->sizeValue = hdrLen; |
851 |
memcpy(&result->value, body, hdrLen); |
852 |
result->value[hdrLen] = 0;
|
853 |
return true; |
854 |
} |
855 |
} |
856 |
|
857 |
|
858 |
bool
|
859 |
stunParseAtrIntegrity( char* body, unsigned int hdrLen,StunAtrIntegrity *result ) |
860 |
{ |
861 |
if ( hdrLen != 20) |
862 |
{ |
863 |
debug("MessageIntegrity must be 20 bytes \n");
|
864 |
return false; |
865 |
} |
866 |
else
|
867 |
{ |
868 |
memcpy(&result->hash, body, hdrLen); |
869 |
return true; |
870 |
} |
871 |
} |
872 |
|
873 |
|
874 |
void
|
875 |
stunCreateErrorResponse(StunMessage response, int cl, int number, const char* msg) |
876 |
{ |
877 |
response.msgHdr.msgType = BindErrorResponseMsg; |
878 |
response.hasErrorCode = true;
|
879 |
response.errorCode.errorClass = cl; |
880 |
response.errorCode.number = number; |
881 |
strcpy(response.errorCode.reason, msg); |
882 |
} |
883 |
|
884 |
bool
|
885 |
stunParseAtrError(char* body,unsigned int hdrLen,StunAtrError *result) |
886 |
{ |
887 |
if ( hdrLen >= sizeof(StunAtrError) ) |
888 |
{ |
889 |
debug("head on Error too large \n ");
|
890 |
return false; |
891 |
} |
892 |
else
|
893 |
{ |
894 |
memcpy(&result->pad, body, 2); body+=2; |
895 |
result->pad = ntohs(result->pad); |
896 |
result->errorClass = *body++; |
897 |
result->number = *body++; |
898 |
|
899 |
result->sizeReason = hdrLen - 4;
|
900 |
memcpy(&result->reason, body, result->sizeReason); |
901 |
result->reason[result->sizeReason] = 0;
|
902 |
return true; |
903 |
} |
904 |
} |
905 |
|
906 |
|
907 |
char*
|
908 |
encodeAtrString(char* ptr, UInt16 type, const StunAtrString atr) |
909 |
{ |
910 |
assert(atr.sizeValue % 4 == 0); |
911 |
|
912 |
ptr = encode16(ptr, type); |
913 |
ptr = encode16(ptr, atr.sizeValue); |
914 |
ptr = encode(ptr, atr.value, atr.sizeValue); |
915 |
return ptr;
|
916 |
} |
917 |
|
918 |
|
919 |
char*
|
920 |
encodeAtrIntegrity(char* ptr, const StunAtrIntegrity atr) |
921 |
{ |
922 |
ptr = encode16(ptr, MessageIntegrity); |
923 |
ptr = encode16(ptr, 20);
|
924 |
ptr = encode(ptr, atr.hash, sizeof(atr.hash));
|
925 |
return ptr;
|
926 |
} |
927 |
|
928 |
char*
|
929 |
encodeAtrError(char* ptr, const StunAtrError atr) |
930 |
{ |
931 |
ptr = encode16(ptr, ErrorCode); |
932 |
ptr = encode16(ptr, 6 + atr.sizeReason);
|
933 |
ptr = encode16(ptr, atr.pad); |
934 |
*ptr++ = atr.errorClass; |
935 |
*ptr++ = atr.number; |
936 |
ptr = encode(ptr, atr.reason, atr.sizeReason); |
937 |
return ptr;
|
938 |
} |
939 |
|
940 |
|
941 |
char*
|
942 |
encodeAtrUnknown(char* ptr, const StunAtrUnknown atr) |
943 |
{ |
944 |
ptr = encode16(ptr, UnknownAttribute); |
945 |
ptr = encode16(ptr, 2+2*atr.numAttributes); |
946 |
int i;
|
947 |
for (i=0; i<atr.numAttributes; i++) |
948 |
{ |
949 |
ptr = encode16(ptr, atr.attrType[i]); |
950 |
} |
951 |
return ptr;
|
952 |
} |
953 |
|
954 |
|
955 |
char*
|
956 |
encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4 atr) |
957 |
{ |
958 |
ptr = encode16(ptr, type); |
959 |
ptr = encode16(ptr, 8);
|
960 |
*ptr++ = atr.pad; |
961 |
*ptr++ = IPv4Family; |
962 |
ptr = encode16(ptr, atr.ipv4.port); |
963 |
ptr = encode32(ptr, atr.ipv4.addr); |
964 |
|
965 |
return ptr;
|
966 |
} |
967 |
|
968 |
|
969 |
char*
|
970 |
encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest atr) |
971 |
{ |
972 |
ptr = encode16(ptr, ChangeRequest); |
973 |
ptr = encode16(ptr, 4);
|
974 |
ptr = encode32(ptr, atr.value); |
975 |
return ptr;
|
976 |
} |
977 |
|
978 |
char*
|
979 |
encodeXorOnly(char* ptr)
|
980 |
{ |
981 |
ptr = encode16(ptr, XorOnly ); |
982 |
return ptr;
|
983 |
} |
984 |
|
985 |
char*
|
986 |
encode(char* buf, const char* data, unsigned int length) |
987 |
{ |
988 |
memcpy(buf, data, length); |
989 |
return buf + length;
|
990 |
} |
991 |
|
992 |
char*
|
993 |
encode16(char* buf, UInt16 data)
|
994 |
{ |
995 |
UInt16 ndata = htons(data); |
996 |
memcpy(buf, (void*)(&ndata), sizeof(UInt16)); |
997 |
return buf + sizeof(UInt16); |
998 |
} |
999 |
|
1000 |
char*
|
1001 |
encode32(char* buf, UInt32 data)
|
1002 |
{ |
1003 |
UInt32 ndata = htonl(data); |
1004 |
memcpy(buf, (void*)(&ndata), sizeof(UInt32)); |
1005 |
return buf + sizeof(UInt32); |
1006 |
} |
1007 |
|
1008 |
/// return a random number to use as a port
|
1009 |
int
|
1010 |
stunRandomPort() |
1011 |
{ |
1012 |
int min=0x4000; |
1013 |
int max=0x7FFF; |
1014 |
|
1015 |
int ret = stunRand();
|
1016 |
ret = ret|min; |
1017 |
ret = ret&max; |
1018 |
|
1019 |
return ret;
|
1020 |
} |
1021 |
|
1022 |
|
1023 |
void
|
1024 |
toHex(const char* buffer, int bufferSize, char* output) |
1025 |
{ |
1026 |
static char hexmap[] = "0123456789abcdef"; |
1027 |
|
1028 |
const char* p = buffer; |
1029 |
char* r = output;
|
1030 |
int i;
|
1031 |
for (i=0; i < bufferSize; i++) |
1032 |
{ |
1033 |
unsigned char temp = *p++; |
1034 |
|
1035 |
int hi = (temp & 0xf0)>>4; |
1036 |
int low = (temp & 0xf); |
1037 |
|
1038 |
*r++ = hexmap[hi]; |
1039 |
*r++ = hexmap[low]; |
1040 |
} |
1041 |
*r = 0;
|
1042 |
} |
1043 |
|
1044 |
|
1045 |
|