1 #include <cassert>
2 #include <cstring>
3 #include <iostream>
4 #include <cstdlib>
5 #include <errno.h>
6
7 #ifdef WIN32
8 #include <winsock2.h>
9 #include <stdlib.h>
10 #include <io.h>
11 #include <time.h>
12 #else
13
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <sys/ioctl.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <arpa/inet.h>
22 #include <fcntl.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #include <arpa/nameser.h>
26 #include <resolv.h>
27 #include <net/if.h>
28
29 #endif
30
31
32 #if defined(__sparc__) || defined(WIN32)
33 #define NOSSL
34 #endif
35 #define NOSSL
36
37 #include "udp.h"
38 #include "stun.h"
39
40
41 using namespace std;
42
43
44 static void
45 computeHmac(char* hmac, const char* input, int length, const char* key, int keySize);
46
47 static bool
stunParseAtrAddress(char * body,unsigned int hdrLen,StunAtrAddress4 & result)48 stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4& result )
49 {
50 if ( hdrLen != 8 )
51 {
52 clog << "hdrLen wrong for Address" <<endl;
53 return false;
54 }
55 result.pad = *body++;
56 result.family = *body++;
57 if (result.family == IPv4Family)
58 {
59 UInt16 nport;
60 memcpy(&nport, body, 2); body+=2;
61 result.ipv4.port = ntohs(nport);
62
63 UInt32 naddr;
64 memcpy(&naddr, body, 4); body+=4;
65 result.ipv4.addr = ntohl(naddr);
66 return true;
67 }
68 else if (result.family == IPv6Family)
69 {
70 clog << "ipv6 not supported" << endl;
71 }
72 else
73 {
74 clog << "bad address family: " << result.family << endl;
75 }
76
77 return false;
78 }
79
80 static bool
stunParseAtrChangeRequest(char * body,unsigned int hdrLen,StunAtrChangeRequest & result)81 stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest& result )
82 {
83 if ( hdrLen != 4 )
84 {
85 clog << "hdr length = " << hdrLen << " expecting " << sizeof(result) << endl;
86
87 clog << "Incorrect size for ChangeRequest" << endl;
88 return false;
89 }
90 else
91 {
92 memcpy(&result.value, body, 4);
93 result.value = ntohl(result.value);
94 return true;
95 }
96 }
97
98 static bool
stunParseAtrError(char * body,unsigned int hdrLen,StunAtrError & result)99 stunParseAtrError( char* body, unsigned int hdrLen, StunAtrError& result )
100 {
101 if ( hdrLen >= sizeof(result) )
102 {
103 clog << "head on Error too large" << endl;
104 return false;
105 }
106 else
107 {
108 memcpy(&result.pad, body, 2); body+=2;
109 result.pad = ntohs(result.pad);
110 result.errorClass = *body++;
111 result.number = *body++;
112
113 result.sizeReason = hdrLen - 4;
114 memcpy(&result.reason, body, result.sizeReason);
115 result.reason[result.sizeReason] = 0;
116 return true;
117 }
118 }
119
120 static bool
stunParseAtrUnknown(char * body,unsigned int hdrLen,StunAtrUnknown & result)121 stunParseAtrUnknown( char* body, unsigned int hdrLen, StunAtrUnknown& result )
122 {
123 if ( hdrLen >= sizeof(result) )
124 {
125 return false;
126 }
127 else
128 {
129 if (hdrLen % 4 != 0) return false;
130 result.numAttributes = hdrLen / 4;
131 for (int i=0; i<result.numAttributes; i++)
132 {
133 memcpy(&result.attrType[i], body, 2); body+=2;
134 result.attrType[i] = ntohs(result.attrType[i]);
135 }
136 return true;
137 }
138 }
139
140
141 static bool
stunParseAtrString(char * body,unsigned int hdrLen,StunAtrString & result)142 stunParseAtrString( char* body, unsigned int hdrLen, StunAtrString& result )
143 {
144 if ( hdrLen >= STUN_MAX_STRING )
145 {
146 clog << "String is too large" << endl;
147 return false;
148 }
149 else
150 {
151 if (hdrLen % 4 != 0)
152 {
153 clog << "Bad length string " << hdrLen << endl;
154 return false;
155 }
156
157 result.sizeValue = hdrLen;
158 memcpy(&result.value, body, hdrLen);
159 result.value[hdrLen] = 0;
160 return true;
161 }
162 }
163
164
165 static bool
stunParseAtrIntegrity(char * body,unsigned int hdrLen,StunAtrIntegrity & result)166 stunParseAtrIntegrity( char* body, unsigned int hdrLen, StunAtrIntegrity& result )
167 {
168 if ( hdrLen != 20)
169 {
170 clog << "MessageIntegrity must be 20 bytes" << endl;
171 return false;
172 }
173 else
174 {
175 memcpy(&result.hash, body, hdrLen);
176 return true;
177 }
178 }
179
180
181 bool
stunParseMessage(char * buf,unsigned int bufLen,StunMessage & msg,bool verbose)182 stunParseMessage( char* buf, unsigned int bufLen, StunMessage& msg, bool verbose)
183 {
184 if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl;
185 memset(&msg, 0, sizeof(msg));
186
187 if (sizeof(StunMsgHdr) > bufLen)
188 {
189 clog << "Bad message" << endl;
190 return false;
191 }
192
193 memcpy(&msg.msgHdr, buf, sizeof(StunMsgHdr));
194 msg.msgHdr.msgType = ntohs(msg.msgHdr.msgType);
195 msg.msgHdr.msgLength = ntohs(msg.msgHdr.msgLength);
196
197 if (msg.msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen)
198 {
199 clog << "Message header length doesn't match message size: "
200 << msg.msgHdr.msgLength << " - " << bufLen << endl;
201 return false;
202 }
203
204 char* body = buf + sizeof(StunMsgHdr);
205 unsigned int size = msg.msgHdr.msgLength;
206
207 //clog << "bytes after header = " << size << endl;
208
209 while ( size > 0 )
210 {
211 // !jf! should check that there are enough bytes left in the buffer
212
213 StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body);
214
215 unsigned int attrLen = ntohs(attr->length);
216 int atrType = ntohs(attr->type);
217
218 //if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl;
219 if ( attrLen+4 > size )
220 {
221 clog << "claims attribute is larger than size of message "
222 <<"(attribute type="<<atrType<<")"<< endl;
223 return false;
224 }
225
226 body += 4; // skip the length and type in attribute header
227 size -= 4;
228
229 switch ( atrType )
230 {
231 case MappedAddress:
232 msg.hasMappedAddress = true;
233 if ( stunParseAtrAddress( body, attrLen, msg.mappedAddress )== false )
234 {
235 clog << "problem parsing MappedAddress" << endl;
236 return false;
237 }
238 else
239 {
240 if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl;
241 }
242
243 break;
244
245 case ResponseAddress:
246 msg.hasResponseAddress = true;
247 if ( stunParseAtrAddress( body, attrLen, msg.responseAddress )== false )
248 {
249 clog << "problem parsing ResponseAddress" << endl;
250 return false;
251 }
252 else
253 {
254 if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl;
255 }
256 break;
257
258 case ChangeRequest:
259 msg.hasChangeRequest = true;
260 if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false)
261 {
262 clog << "problem parsing ChangeRequest" << endl;
263 return false;
264 }
265 else
266 {
267 if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl;
268 }
269 break;
270
271 case SourceAddress:
272 msg.hasSourceAddress = true;
273 if ( stunParseAtrAddress( body, attrLen, msg.sourceAddress )== false )
274 {
275 clog << "problem parsing SourceAddress" << endl;
276 return false;
277 }
278 else
279 {
280 if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl;
281 }
282 break;
283
284 case ChangedAddress:
285 msg.hasChangedAddress = true;
286 if ( stunParseAtrAddress( body, attrLen, msg.changedAddress )== false )
287 {
288 clog << "problem parsing ChangedAddress" << endl;
289 return false;
290 }
291 else
292 {
293 if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl;
294 }
295 break;
296
297 case Username:
298 msg.hasUsername = true;
299 if (stunParseAtrString( body, attrLen, msg.username) == false)
300 {
301 clog << "problem parsing Username" << endl;
302 return false;
303 }
304 else
305 {
306 if (verbose) clog << "Username = " << msg.username.value << endl;
307 }
308
309 break;
310
311 case Password:
312 msg.hasPassword = true;
313 if (stunParseAtrString( body, attrLen, msg.password) == false)
314 {
315 clog << "problem parsing Password" << endl;
316 return false;
317 }
318 else
319 {
320 if (verbose) clog << "Password = " << msg.password.value << endl;
321 }
322 break;
323
324 case MessageIntegrity:
325 msg.hasMessageIntegrity = true;
326 if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false)
327 {
328 clog << "problem parsing MessageIntegrity" << endl;
329 return false;
330 }
331 else
332 {
333 //if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl;
334 }
335
336 // read the current HMAC
337 // look up the password given the user of given the transaction id
338 // compute the HMAC on the buffer
339 // decide if they match or not
340 break;
341
342 case ErrorCode:
343 msg.hasErrorCode = true;
344 if (stunParseAtrError(body, attrLen, msg.errorCode) == false)
345 {
346 clog << "problem parsing ErrorCode" << endl;
347 return false;
348 }
349 else
350 {
351 if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass)
352 << " " << int(msg.errorCode.number)
353 << " " << msg.errorCode.reason << endl;
354 }
355
356 break;
357
358 case UnknownAttribute:
359 msg.hasUnknownAttributes = true;
360 if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false)
361 {
362 clog << "problem parsing UnknownAttribute" << endl;
363 return false;
364 }
365 break;
366
367 case ReflectedFrom:
368 msg.hasReflectedFrom = true;
369 if ( stunParseAtrAddress( body, attrLen, msg.reflectedFrom ) == false )
370 {
371 clog << "problem parsing ReflectedFrom" << endl;
372 return false;
373 }
374 break;
375
376 case XorMappedAddress:
377 msg.hasXorMappedAddress = true;
378 if ( stunParseAtrAddress( body, attrLen, msg.xorMappedAddress ) == false )
379 {
380 clog << "problem parsing XorMappedAddress" << endl;
381 return false;
382 }
383 else
384 {
385 if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl;
386 }
387 break;
388
389 case XorOnly:
390 msg.xorOnly = true;
391 if (verbose)
392 {
393 clog << "xorOnly = true" << endl;
394 }
395 break;
396
397 case ServerName:
398 msg.hasServerName = true;
399 if (stunParseAtrString( body, attrLen, msg.serverName) == false)
400 {
401 clog << "problem parsing ServerName" << endl;
402 return false;
403 }
404 else
405 {
406 if (verbose) clog << "ServerName = " << msg.serverName.value << endl;
407 }
408 break;
409
410 case SecondaryAddress:
411 msg.hasSecondaryAddress = true;
412 if ( stunParseAtrAddress( body, attrLen, msg.secondaryAddress ) == false )
413 {
414 clog << "problem parsing secondaryAddress" << endl;
415 return false;
416 }
417 else
418 {
419 if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl;
420 }
421 break;
422
423 default:
424 if (verbose) clog << "Unknown attribute: " << atrType << endl;
425 if ( atrType <= 0x7FFF )
426 {
427 return false;
428 }
429 }
430
431 body += attrLen;
432 size -= attrLen;
433 }
434
435 return true;
436 }
437
438
439 static char*
encode16(char * buf,UInt16 data)440 encode16(char* buf, UInt16 data)
441 {
442 UInt16 ndata = htons(data);
443 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16));
444 return buf + sizeof(UInt16);
445 }
446
447 static char*
encode32(char * buf,UInt32 data)448 encode32(char* buf, UInt32 data)
449 {
450 UInt32 ndata = htonl(data);
451 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt32));
452 return buf + sizeof(UInt32);
453 }
454
455
456 static char*
encode(char * buf,const char * data,unsigned int length)457 encode(char* buf, const char* data, unsigned int length)
458 {
459 memcpy(buf, data, length);
460 return buf + length;
461 }
462
463
464 static char*
encodeAtrAddress4(char * ptr,UInt16 type,const StunAtrAddress4 & atr)465 encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4& atr)
466 {
467 ptr = encode16(ptr, type);
468 ptr = encode16(ptr, 8);
469 *ptr++ = atr.pad;
470 *ptr++ = IPv4Family;
471 ptr = encode16(ptr, atr.ipv4.port);
472 ptr = encode32(ptr, atr.ipv4.addr);
473
474 return ptr;
475 }
476
477 static char*
encodeAtrChangeRequest(char * ptr,const StunAtrChangeRequest & atr)478 encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest& atr)
479 {
480 ptr = encode16(ptr, ChangeRequest);
481 ptr = encode16(ptr, 4);
482 ptr = encode32(ptr, atr.value);
483 return ptr;
484 }
485
486 static char*
encodeAtrError(char * ptr,const StunAtrError & atr)487 encodeAtrError(char* ptr, const StunAtrError& atr)
488 {
489 ptr = encode16(ptr, ErrorCode);
490 ptr = encode16(ptr, 6 + atr.sizeReason);
491 ptr = encode16(ptr, atr.pad);
492 *ptr++ = atr.errorClass;
493 *ptr++ = atr.number;
494 ptr = encode(ptr, atr.reason, atr.sizeReason);
495 return ptr;
496 }
497
498
499 static char*
encodeAtrUnknown(char * ptr,const StunAtrUnknown & atr)500 encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr)
501 {
502 ptr = encode16(ptr, UnknownAttribute);
503 ptr = encode16(ptr, 2+2*atr.numAttributes);
504 for (int i=0; i<atr.numAttributes; i++)
505 {
506 ptr = encode16(ptr, atr.attrType[i]);
507 }
508 return ptr;
509 }
510
511
512 static char*
encodeXorOnly(char * ptr)513 encodeXorOnly(char* ptr)
514 {
515 ptr = encode16(ptr, XorOnly );
516 return ptr;
517 }
518
519
520 static char*
encodeAtrString(char * ptr,UInt16 type,const StunAtrString & atr)521 encodeAtrString(char* ptr, UInt16 type, const StunAtrString& atr)
522 {
523 assert(atr.sizeValue % 4 == 0);
524
525 ptr = encode16(ptr, type);
526 ptr = encode16(ptr, atr.sizeValue);
527 ptr = encode(ptr, atr.value, atr.sizeValue);
528 return ptr;
529 }
530
531
532 static char*
encodeAtrIntegrity(char * ptr,const StunAtrIntegrity & atr)533 encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr)
534 {
535 ptr = encode16(ptr, MessageIntegrity);
536 ptr = encode16(ptr, 20);
537 ptr = encode(ptr, atr.hash, sizeof(atr.hash));
538 return ptr;
539 }
540
541
542 unsigned int
stunEncodeMessage(const StunMessage & msg,char * buf,unsigned int bufLen,const StunAtrString & password,bool verbose)543 stunEncodeMessage( const StunMessage& msg,
544 char* buf,
545 unsigned int bufLen,
546 const StunAtrString& password,
547 bool verbose)
548 {
549 assert(bufLen >= sizeof(StunMsgHdr));
550 char* ptr = buf;
551
552 ptr = encode16(ptr, msg.msgHdr.msgType);
553 char* lengthp = ptr;
554 ptr = encode16(ptr, 0);
555 ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id));
556
557 if (verbose) clog << "Encoding stun message: " << endl;
558 if (msg.hasMappedAddress)
559 {
560 if (verbose) clog << "Encoding MappedAddress: " << msg.mappedAddress.ipv4 << endl;
561 ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress);
562 }
563 if (msg.hasResponseAddress)
564 {
565 if (verbose) clog << "Encoding ResponseAddress: " << msg.responseAddress.ipv4 << endl;
566 ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress);
567 }
568 if (msg.hasChangeRequest)
569 {
570 if (verbose) clog << "Encoding ChangeRequest: " << msg.changeRequest.value << endl;
571 ptr = encodeAtrChangeRequest(ptr, msg.changeRequest);
572 }
573 if (msg.hasSourceAddress)
574 {
575 if (verbose) clog << "Encoding SourceAddress: " << msg.sourceAddress.ipv4 << endl;
576 ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress);
577 }
578 if (msg.hasChangedAddress)
579 {
580 if (verbose) clog << "Encoding ChangedAddress: " << msg.changedAddress.ipv4 << endl;
581 ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress);
582 }
583 if (msg.hasUsername)
584 {
585 if (verbose) clog << "Encoding Username: " << msg.username.value << endl;
586 ptr = encodeAtrString(ptr, Username, msg.username);
587 }
588 if (msg.hasPassword)
589 {
590 if (verbose) clog << "Encoding Password: " << msg.password.value << endl;
591 ptr = encodeAtrString(ptr, Password, msg.password);
592 }
593 if (msg.hasErrorCode)
594 {
595 if (verbose) clog << "Encoding ErrorCode: class="
596 << int(msg.errorCode.errorClass)
597 << " number=" << int(msg.errorCode.number)
598 << " reason="
599 << msg.errorCode.reason
600 << endl;
601
602 ptr = encodeAtrError(ptr, msg.errorCode);
603 }
604 if (msg.hasUnknownAttributes)
605 {
606 if (verbose) clog << "Encoding UnknownAttribute: ???" << endl;
607 ptr = encodeAtrUnknown(ptr, msg.unknownAttributes);
608 }
609 if (msg.hasReflectedFrom)
610 {
611 if (verbose) clog << "Encoding ReflectedFrom: " << msg.reflectedFrom.ipv4 << endl;
612 ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom);
613 }
614 if (msg.hasXorMappedAddress)
615 {
616 if (verbose) clog << "Encoding XorMappedAddress: " << msg.xorMappedAddress.ipv4 << endl;
617 ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress);
618 }
619 if (msg.xorOnly)
620 {
621 if (verbose) clog << "Encoding xorOnly: " << endl;
622 ptr = encodeXorOnly( ptr );
623 }
624 if (msg.hasServerName)
625 {
626 if (verbose) clog << "Encoding ServerName: " << msg.serverName.value << endl;
627 ptr = encodeAtrString(ptr, ServerName, msg.serverName);
628 }
629 if (msg.hasSecondaryAddress)
630 {
631 if (verbose) clog << "Encoding SecondaryAddress: " << msg.secondaryAddress.ipv4 << endl;
632 ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress);
633 }
634
635 if (password.sizeValue > 0)
636 {
637 if (verbose) clog << "HMAC with password: " << password.value << endl;
638
639 StunAtrIntegrity integrity;
640 computeHmac(integrity.hash, buf, int(ptr-buf) , password.value, password.sizeValue);
641 ptr = encodeAtrIntegrity(ptr, integrity);
642 }
643 if (verbose) clog << endl;
644
645 encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr)));
646 return int(ptr - buf);
647 }
648
649 int
stunRand()650 stunRand()
651 {
652 // return 32 bits of random stuff
653 static bool init=false;
654 if ( !init ) {
655 srandomdev();
656 init = true;
657 }
658 /* random() is described as returning 0...2**31-1 */
659 return 0xffffffff & ( ( random() << 31 ) | random() );
660 }
661
662
663 /// return a random number to use as a port
664 int
stunRandomPort()665 stunRandomPort()
666 {
667 int min=0x4000;
668 int max=0x7FFF;
669
670 int ret = stunRand();
671 ret = ret|min;
672 ret = ret&max;
673
674 return ret;
675 }
676
677
678 #ifdef NOSSL
679 static void
computeHmac(char * hmac,const char * input,int length,const char * key,int sizeKey)680 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
681 {
682 strncpy(hmac,"hmac-not-implemented",20);
683 }
684 #else
685 #include <openssl/hmac.h>
686
687 static void
computeHmac(char * hmac,const char * input,int length,const char * key,int sizeKey)688 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
689 {
690 unsigned int resultSize=0;
691 HMAC(EVP_sha1(),
692 key, sizeKey,
693 reinterpret_cast<const unsigned char*>(input), length,
694 reinterpret_cast<unsigned char*>(hmac), &resultSize);
695 assert(resultSize == 20);
696 }
697 #endif
698
699
700 static void
toHex(const char * buffer,int bufferSize,char * output)701 toHex(const char* buffer, int bufferSize, char* output)
702 {
703 static char hexmap[] = "0123456789abcdef";
704
705 const char* p = buffer;
706 char* r = output;
707 for (int i=0; i < bufferSize; i++)
708 {
709 unsigned char temp = *p++;
710
711 int hi = (temp & 0xf0)>>4;
712 int low = (temp & 0xf);
713
714 *r++ = hexmap[hi];
715 *r++ = hexmap[low];
716 }
717 *r = 0;
718 }
719
720 void
stunCreateUserName(const StunAddress4 & source,StunAtrString * username)721 stunCreateUserName(const StunAddress4& source, StunAtrString* username)
722 {
723 UInt64 time = stunGetSystemTimeSecs();
724 time -= (time % 20*60);
725 //UInt64 hitime = time >> 32;
726 UInt64 lotime = time & 0xFFFFFFFF;
727
728 char buffer[1024];
729 sprintf(buffer,
730 "%08x:%08x:%08x:",
731 UInt32(source.addr),
732 UInt32(stunRand()),
733 UInt32(lotime));
734 assert( strlen(buffer) < 1024 );
735
736 assert(strlen(buffer) + 41 < STUN_MAX_STRING);
737
738 char hmac[20];
739 char key[] = "Jason";
740 computeHmac(hmac, buffer, strlen(buffer), key, strlen(key) );
741 char hmacHex[41];
742 toHex(hmac, 20, hmacHex );
743 hmacHex[40] =0;
744
745 strcat(buffer,hmacHex);
746
747 int l = strlen(buffer);
748 assert( l+1 < STUN_MAX_STRING );
749 assert( l%4 == 0 );
750
751 username->sizeValue = l;
752 memcpy(username->value,buffer,l);
753 username->value[l]=0;
754
755 //if (verbose) clog << "computed username=" << username.value << endl;
756 }
757
758 void
stunCreatePassword(const StunAtrString & username,StunAtrString * password)759 stunCreatePassword(const StunAtrString& username, StunAtrString* password)
760 {
761 char hmac[20];
762 char key[] = "Fluffy";
763 //char buffer[STUN_MAX_STRING];
764 computeHmac(hmac, username.value, strlen(username.value), key, strlen(key));
765 toHex(hmac, 20, password->value);
766 password->sizeValue = 40;
767 password->value[40]=0;
768
769 //clog << "password=" << password->value << endl;
770 }
771
772
773 UInt64
stunGetSystemTimeSecs()774 stunGetSystemTimeSecs()
775 {
776 UInt64 time=0;
777 #if defined(WIN32)
778 SYSTEMTIME t;
779 // CJ TODO - this probably has bug on wrap around every 24 hours
780 GetSystemTime( &t );
781 time = (t.wHour*60+t.wMinute)*60+t.wSecond;
782 #else
783 struct timeval now;
784 gettimeofday( &now , NULL );
785 //assert( now );
786 time = now.tv_sec;
787 #endif
788 return time;
789 }
790
791
operator <<(ostream & strm,const UInt128 & r)792 ostream& operator<< ( ostream& strm, const UInt128& r )
793 {
794 strm << int(r.octet[0]);
795 for ( int i=1; i<16; i++ )
796 {
797 strm << ':' << int(r.octet[i]);
798 }
799
800 return strm;
801 }
802
803 ostream&
operator <<(ostream & strm,const StunAddress4 & addr)804 operator<<( ostream& strm, const StunAddress4& addr)
805 {
806 UInt32 ip = addr.addr;
807 strm << ((int)(ip>>24)&0xFF) << ".";
808 strm << ((int)(ip>>16)&0xFF) << ".";
809 strm << ((int)(ip>> 8)&0xFF) << ".";
810 strm << ((int)(ip>> 0)&0xFF) ;
811
812 strm << ":" << addr.port;
813
814 return strm;
815 }
816
817
818 // returns true if it scucceeded
819 bool
stunParseHostName(char * peerName,UInt32 & ip,UInt16 & portVal,UInt16 defaultPort)820 stunParseHostName( char* peerName,
821 UInt32& ip,
822 UInt16& portVal,
823 UInt16 defaultPort )
824 {
825 in_addr sin_addr;
826
827 char host[512];
828 strncpy(host,peerName,512);
829 host[512-1]='\0';
830 char* port = NULL;
831
832 int portNum = defaultPort;
833
834 // pull out the port part if present.
835 char* sep = strchr(host,':');
836
837 if ( sep == NULL )
838 {
839 portNum = defaultPort;
840 }
841 else
842 {
843 *sep = '\0';
844 port = sep + 1;
845 // set port part
846
847 char* endPtr=NULL;
848
849 portNum = strtol(port,&endPtr,10);
850
851 if ( endPtr != NULL )
852 {
853 if ( *endPtr != '\0' )
854 {
855 portNum = defaultPort;
856 }
857 }
858 }
859
860 if ( portNum < 1024 ) return false;
861 if ( portNum >= 0xFFFF ) return false;
862
863 // figure out the host part
864 struct hostent* h;
865
866 #ifdef WIN32
867 assert( strlen(host) >= 1 );
868 if ( isdigit( host[0] ) )
869 {
870 // assume it is a ip address
871 unsigned long a = inet_addr(host);
872 //cerr << "a=0x" << hex << a << dec << endl;
873
874 ip = ntohl( a );
875 }
876 else
877 {
878 // assume it is a host name
879 h = gethostbyname( host );
880
881 if ( h == NULL )
882 {
883 int err = getErrno();
884 std::cerr << "error was " << err << std::endl;
885 assert( err != WSANOTINITIALISED );
886
887 ip = ntohl( 0x7F000001L );
888
889 return false;
890 }
891 else
892 {
893 sin_addr = *(struct in_addr*)h->h_addr;
894 ip = ntohl( sin_addr.s_addr );
895 }
896 }
897
898 #else
899 h = gethostbyname( host );
900 if ( h == NULL )
901 {
902 int err = getErrno();
903 std::cerr << "error was " << err << std::endl;
904 ip = ntohl( 0x7F000001L );
905 return false;
906 }
907 else
908 {
909 sin_addr = *(struct in_addr*)h->h_addr;
910 ip = ntohl( sin_addr.s_addr );
911 }
912 #endif
913
914 portVal = portNum;
915
916 return true;
917 }
918
919
920 bool
stunParseServerName(char * name,StunAddress4 & addr)921 stunParseServerName( char* name, StunAddress4& addr)
922 {
923 assert(name);
924
925 // TODO - put in DNS SRV stuff.
926
927 bool ret = stunParseHostName( name, addr.addr, addr.port, 3478);
928 if ( ret != true )
929 {
930 addr.port=0xFFFF;
931 }
932 return ret;
933 }
934
935
936 static void
stunCreateErrorResponse(StunMessage & response,int cl,int number,const char * msg)937 stunCreateErrorResponse(StunMessage& response, int cl, int number, const char* msg)
938 {
939 response.msgHdr.msgType = BindErrorResponseMsg;
940 response.hasErrorCode = true;
941 response.errorCode.errorClass = cl;
942 response.errorCode.number = number;
943 strcpy(response.errorCode.reason, msg);
944 }
945
946 #if 0
947 static void
948 stunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg)
949 {
950 response.msgHdr.msgType = SharedSecretErrorResponseMsg;
951 response.hasErrorCode = true;
952 response.errorCode.errorClass = cl;
953 response.errorCode.number = number;
954 strcpy(response.errorCode.reason, msg);
955 }
956 #endif
957
958 static void
stunCreateSharedSecretResponse(const StunMessage & request,const StunAddress4 & source,StunMessage & response)959 stunCreateSharedSecretResponse(const StunMessage& request, const StunAddress4& source, StunMessage& response)
960 {
961 response.msgHdr.msgType = SharedSecretResponseMsg;
962 response.msgHdr.id = request.msgHdr.id;
963
964 response.hasUsername = true;
965 stunCreateUserName( source, &response.username);
966
967 response.hasPassword = true;
968 stunCreatePassword( response.username, &response.password);
969 }
970
971
972 // This funtion takes a single message sent to a stun server, parses
973 // and constructs an apropriate repsonse - returns true if message is
974 // valid
975 bool
stunServerProcessMsg(char * buf,unsigned int bufLen,StunAddress4 & from,StunAddress4 & secondary,StunAddress4 & myAddr,StunAddress4 & altAddr,StunMessage * resp,StunAddress4 * destination,StunAtrString * hmacPassword,bool * changePort,bool * changeIp,bool verbose)976 stunServerProcessMsg( char* buf,
977 unsigned int bufLen,
978 StunAddress4& from,
979 StunAddress4& secondary,
980 StunAddress4& myAddr,
981 StunAddress4& altAddr,
982 StunMessage* resp,
983 StunAddress4* destination,
984 StunAtrString* hmacPassword,
985 bool* changePort,
986 bool* changeIp,
987 bool verbose)
988 {
989
990 // set up information for default response
991
992 memset( resp, 0 , sizeof(*resp) );
993
994 *changeIp = false;
995 *changePort = false;
996
997 StunMessage req;
998 bool ok = stunParseMessage( buf,bufLen, req, verbose);
999
1000 if (!ok) // Complete garbage, drop it on the floor
1001 {
1002 if (verbose) clog << "Request did not parse" << endl;
1003 return false;
1004 }
1005 if (verbose) clog << "Request parsed ok" << endl;
1006
1007 StunAddress4 mapped = req.mappedAddress.ipv4;
1008 StunAddress4 respondTo = req.responseAddress.ipv4;
1009 UInt32 flags = req.changeRequest.value;
1010
1011 switch (req.msgHdr.msgType)
1012 {
1013 case SharedSecretRequestMsg:
1014 if(verbose) clog << "Received SharedSecretRequestMsg on udp. send error 433." << endl;
1015 // !cj! - should fix so you know if this came over TLS or UDP
1016 stunCreateSharedSecretResponse(req, from, *resp);
1017 //stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS");
1018 return true;
1019
1020 case BindRequestMsg:
1021 if (!req.hasMessageIntegrity)
1022 {
1023 if (verbose) clog << "BindRequest does not contain MessageIntegrity" << endl;
1024
1025 if (0) // !jf! mustAuthenticate
1026 {
1027 if(verbose) clog << "Received BindRequest with no MessageIntegrity. Sending 401." << endl;
1028 stunCreateErrorResponse(*resp, 4, 1, "Missing MessageIntegrity");
1029 return true;
1030 }
1031 }
1032 else
1033 {
1034 if (!req.hasUsername)
1035 {
1036 if (verbose) clog << "No UserName. Send 432." << endl;
1037 stunCreateErrorResponse(*resp, 4, 32, "No UserName and contains MessageIntegrity");
1038 return true;
1039 }
1040 else
1041 {
1042 if (verbose) clog << "Validating username: " << req.username.value << endl;
1043 // !jf! could retrieve associated password from provisioning here
1044 if (strcmp(req.username.value, "test") == 0)
1045 {
1046 if (0)
1047 {
1048 // !jf! if the credentials are stale
1049 stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest");
1050 return true;
1051 }
1052 else
1053 {
1054 if (verbose) clog << "Validating MessageIntegrity" << endl;
1055 // need access to shared secret
1056
1057 unsigned char hmac[20];
1058 #ifndef NOSSL
1059 unsigned int hmacSize=20;
1060
1061 HMAC(EVP_sha1(),
1062 "1234", 4,
1063 reinterpret_cast<const unsigned char*>(buf), bufLen-20-4,
1064 hmac, &hmacSize);
1065 assert(hmacSize == 20);
1066 #endif
1067
1068 if (memcmp(buf, hmac, 20) != 0)
1069 {
1070 if (verbose) clog << "MessageIntegrity is bad. Sending " << endl;
1071 stunCreateErrorResponse(*resp, 4, 3, "Unknown username. Try test with password 1234");
1072 return true;
1073 }
1074
1075 // need to compute this later after message is filled in
1076 resp->hasMessageIntegrity = true;
1077 assert(req.hasUsername);
1078 resp->hasUsername = true;
1079 resp->username = req.username; // copy username in
1080 }
1081 }
1082 else
1083 {
1084 if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl;
1085 }
1086 }
1087 }
1088
1089 // TODO !jf! should check for unknown attributes here and send 420 listing the
1090 // unknown attributes.
1091
1092 if ( respondTo.port == 0 ) respondTo = from;
1093 if ( mapped.port == 0 ) mapped = from;
1094
1095 *changeIp = ( flags & ChangeIpFlag )?true:false;
1096 *changePort = ( flags & ChangePortFlag )?true:false;
1097
1098 if (verbose)
1099 {
1100 clog << "Request is valid:" << endl;
1101 clog << "\t flags=" << flags << endl;
1102 clog << "\t changeIp=" << *changeIp << endl;
1103 clog << "\t changePort=" << *changePort << endl;
1104 clog << "\t from = " << from << endl;
1105 clog << "\t respond to = " << respondTo << endl;
1106 clog << "\t mapped = " << mapped << endl;
1107 }
1108
1109 // form the outgoing message
1110 resp->msgHdr.msgType = BindResponseMsg;
1111 for ( int i=0; i<16; i++ )
1112 {
1113 resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i];
1114 }
1115
1116 if ( req.xorOnly == false )
1117 {
1118 resp->hasMappedAddress = true;
1119 resp->mappedAddress.ipv4.port = mapped.port;
1120 resp->mappedAddress.ipv4.addr = mapped.addr;
1121 }
1122
1123 if (1) // do xorMapped address or not
1124 {
1125 resp->hasXorMappedAddress = true;
1126 UInt16 id16 = req.msgHdr.id.octet[0]<<8
1127 | req.msgHdr.id.octet[1];
1128 UInt32 id32 = req.msgHdr.id.octet[0]<<24
1129 | req.msgHdr.id.octet[1]<<16
1130 | req.msgHdr.id.octet[2]<<8
1131 | req.msgHdr.id.octet[3];
1132 resp->xorMappedAddress.ipv4.port = mapped.port^id16;
1133 resp->xorMappedAddress.ipv4.addr = mapped.addr^id32;
1134 }
1135
1136 resp->hasSourceAddress = true;
1137 resp->sourceAddress.ipv4.port = (*changePort) ? altAddr.port : myAddr.port;
1138 resp->sourceAddress.ipv4.addr = (*changeIp) ? altAddr.addr : myAddr.addr;
1139
1140 resp->hasChangedAddress = true;
1141 resp->changedAddress.ipv4.port = altAddr.port;
1142 resp->changedAddress.ipv4.addr = altAddr.addr;
1143
1144 if ( secondary.port != 0 )
1145 {
1146 resp->hasSecondaryAddress = true;
1147 resp->secondaryAddress.ipv4.port = secondary.port;
1148 resp->secondaryAddress.ipv4.addr = secondary.addr;
1149 }
1150
1151 if ( req.hasUsername && req.username.sizeValue > 0 )
1152 {
1153 // copy username in
1154 resp->hasUsername = true;
1155 assert( req.username.sizeValue % 4 == 0 );
1156 assert( req.username.sizeValue < STUN_MAX_STRING );
1157 memcpy( resp->username.value, req.username.value, req.username.sizeValue );
1158 resp->username.sizeValue = req.username.sizeValue;
1159 }
1160
1161 if (1) // add ServerName
1162 {
1163 resp->hasServerName = true;
1164 const char serverName[] = "Vovida.org " STUN_VERSION; // must pad to mult of 4
1165
1166 assert( sizeof(serverName) < STUN_MAX_STRING );
1167 //cerr << "sizeof serverName is " << sizeof(serverName) << endl;
1168 assert( sizeof(serverName)%4 == 0 );
1169 memcpy( resp->serverName.value, serverName, sizeof(serverName));
1170 resp->serverName.sizeValue = sizeof(serverName);
1171 }
1172
1173 if ( req.hasMessageIntegrity & req.hasUsername )
1174 {
1175 // this creates the password that will be used in the HMAC when then
1176 // messages is sent
1177 stunCreatePassword( req.username, hmacPassword );
1178 }
1179
1180 if (req.hasUsername && (req.username.sizeValue > 64 ) )
1181 {
1182 UInt32 source;
1183 assert( sizeof(int) == sizeof(UInt32) );
1184
1185 sscanf(req.username.value, "%x", &source);
1186 resp->hasReflectedFrom = true;
1187 resp->reflectedFrom.ipv4.port = 0;
1188 resp->reflectedFrom.ipv4.addr = source;
1189 }
1190
1191 destination->port = respondTo.port;
1192 destination->addr = respondTo.addr;
1193
1194 return true;
1195
1196 default:
1197 if (verbose) clog << "Unknown or unsupported request " << endl;
1198 return false;
1199 }
1200
1201 assert(0);
1202 return false;
1203 }
1204
1205 bool
stunInitServer(StunServerInfo & info,const StunAddress4 & myAddr,const StunAddress4 & altAddr,int startMediaPort,bool verbose)1206 stunInitServer(StunServerInfo& info, const StunAddress4& myAddr,
1207 const StunAddress4& altAddr, int startMediaPort, bool verbose )
1208 {
1209 assert( myAddr.port != 0 );
1210 assert( altAddr.port!= 0 );
1211 assert( myAddr.addr != 0 );
1212 //assert( altAddr.addr != 0 );
1213
1214 info.myAddr = myAddr;
1215 info.altAddr = altAddr;
1216
1217 info.myFd = INVALID_SOCKET;
1218 info.altPortFd = INVALID_SOCKET;
1219 info.altIpFd = INVALID_SOCKET;
1220 info.altIpPortFd = INVALID_SOCKET;
1221
1222 memset(info.relays, 0, sizeof(info.relays));
1223 if (startMediaPort > 0)
1224 {
1225 info.relay = true;
1226
1227 for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1228 {
1229 StunMediaRelay* relay = &info.relays[i];
1230 relay->relayPort = startMediaPort+i;
1231 relay->fd = 0;
1232 relay->expireTime = 0;
1233 }
1234 }
1235 else
1236 {
1237 info.relay = false;
1238 }
1239
1240 if ((info.myFd = openPort(myAddr.port, myAddr.addr,verbose)) == INVALID_SOCKET)
1241 {
1242 clog << "Can't open " << myAddr << endl;
1243 stunStopServer(info);
1244
1245 return false;
1246 }
1247 //if (verbose) clog << "Opened " << myAddr.addr << ":" << myAddr.port << " --> " << info.myFd << endl;
1248
1249 if ((info.altPortFd = openPort(altAddr.port,myAddr.addr,verbose)) == INVALID_SOCKET)
1250 {
1251 clog << "Can't open " << myAddr << endl;
1252 stunStopServer(info);
1253 return false;
1254 }
1255 //if (verbose) clog << "Opened " << myAddr.addr << ":" << altAddr.port << " --> " << info.altPortFd << endl;
1256
1257
1258 info.altIpFd = INVALID_SOCKET;
1259 if ( altAddr.addr != 0 )
1260 {
1261 if ((info.altIpFd = openPort( myAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET)
1262 {
1263 clog << "Can't open " << altAddr << endl;
1264 stunStopServer(info);
1265 return false;
1266 }
1267 //if (verbose) clog << "Opened " << altAddr.addr << ":" << myAddr.port << " --> " << info.altIpFd << endl;;
1268 }
1269
1270 info.altIpPortFd = INVALID_SOCKET;
1271 if ( altAddr.addr != 0 )
1272 { if ((info.altIpPortFd = openPort(altAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET)
1273 {
1274 clog << "Can't open " << altAddr << endl;
1275 stunStopServer(info);
1276 return false;
1277 }
1278 //if (verbose) clog << "Opened " << altAddr.addr << ":" << altAddr.port << " --> " << info.altIpPortFd << endl;;
1279 }
1280
1281 return true;
1282 }
1283
1284 void
stunStopServer(StunServerInfo & info)1285 stunStopServer(StunServerInfo& info)
1286 {
1287 if (info.myFd > 0) closesocket(info.myFd);
1288 if (info.altPortFd > 0) closesocket(info.altPortFd);
1289 if (info.altIpFd > 0) closesocket(info.altIpFd);
1290 if (info.altIpPortFd > 0) closesocket(info.altIpPortFd);
1291
1292 if (info.relay)
1293 {
1294 for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1295 {
1296 StunMediaRelay* relay = &info.relays[i];
1297 if (relay->fd)
1298 {
1299 closesocket(relay->fd);
1300 relay->fd = 0;
1301 }
1302 }
1303 }
1304 }
1305
1306
1307 bool
stunServerProcess(StunServerInfo & info,bool verbose)1308 stunServerProcess(StunServerInfo& info, bool verbose)
1309 {
1310 char msg[STUN_MAX_MESSAGE_SIZE];
1311 int msgLen = sizeof(msg);
1312
1313 bool ok = false;
1314 bool recvAltIp =false;
1315 bool recvAltPort = false;
1316
1317 fd_set fdSet;
1318 Socket maxFd=0;
1319
1320 FD_ZERO(&fdSet);
1321 FD_SET(info.myFd,&fdSet);
1322 if ( info.myFd >= maxFd ) maxFd=info.myFd+1;
1323 FD_SET(info.altPortFd,&fdSet);
1324 if ( info.altPortFd >= maxFd ) maxFd=info.altPortFd+1;
1325
1326 if ( info.altIpFd != INVALID_SOCKET )
1327 {
1328 FD_SET(info.altIpFd,&fdSet);
1329 if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1;
1330 }
1331 if ( info.altIpPortFd != INVALID_SOCKET )
1332 {
1333 FD_SET(info.altIpPortFd,&fdSet);
1334 if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1;
1335 }
1336
1337 if (info.relay)
1338 {
1339 for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1340 {
1341 StunMediaRelay* relay = &info.relays[i];
1342 if (relay->fd)
1343 {
1344 FD_SET(relay->fd, &fdSet);
1345 if (relay->fd >= maxFd)
1346 {
1347 maxFd=relay->fd+1;
1348 }
1349 }
1350 }
1351 }
1352
1353 if ( info.altIpFd != INVALID_SOCKET )
1354 {
1355 FD_SET(info.altIpFd,&fdSet);
1356 if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1;
1357 }
1358 if ( info.altIpPortFd != INVALID_SOCKET )
1359 {
1360 FD_SET(info.altIpPortFd,&fdSet);
1361 if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1;
1362 }
1363
1364 struct timeval tv;
1365 tv.tv_sec = 0;
1366 tv.tv_usec = 1000;
1367
1368 int e = select( maxFd, &fdSet, NULL,NULL, &tv );
1369 if (e < 0)
1370 {
1371 int err = getErrno();
1372 clog << "Error on select: " << strerror(err) << endl;
1373 }
1374 else if (e >= 0)
1375 {
1376 StunAddress4 from;
1377
1378 // do the media relaying
1379 if (info.relay)
1380 {
1381 time_t now = time(0);
1382 for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1383 {
1384 StunMediaRelay* relay = &info.relays[i];
1385 if (relay->fd)
1386 {
1387 if (FD_ISSET(relay->fd, &fdSet))
1388 {
1389 char msg[MAX_RTP_MSG_SIZE];
1390 int msgLen = sizeof(msg);
1391
1392 StunAddress4 rtpFrom;
1393 ok = getMessage( relay->fd, msg, &msgLen, &rtpFrom.addr, &rtpFrom.port ,verbose);
1394 if (ok)
1395 {
1396 sendMessage(info.myFd, msg, msgLen, relay->destination.addr, relay->destination.port, verbose);
1397 relay->expireTime = now + MEDIA_RELAY_TIMEOUT;
1398 if ( verbose ) clog << "Relay packet on "
1399 << relay->fd
1400 << " from " << rtpFrom
1401 << " -> " << relay->destination
1402 << endl;
1403 }
1404 }
1405 else if (now > relay->expireTime)
1406 {
1407 closesocket(relay->fd);
1408 relay->fd = 0;
1409 }
1410 }
1411 }
1412 }
1413
1414
1415 if (FD_ISSET(info.myFd,&fdSet))
1416 {
1417 if (verbose) clog << "received on A1:P1" << endl;
1418 recvAltIp = false;
1419 recvAltPort = false;
1420 ok = getMessage( info.myFd, msg, &msgLen, &from.addr, &from.port,verbose );
1421 }
1422 else if (FD_ISSET(info.altPortFd, &fdSet))
1423 {
1424 if (verbose) clog << "received on A1:P2" << endl;
1425 recvAltIp = false;
1426 recvAltPort = true;
1427 ok = getMessage( info.altPortFd, msg, &msgLen, &from.addr, &from.port,verbose );
1428 }
1429 else if ( (info.altIpFd!=INVALID_SOCKET) && FD_ISSET(info.altIpFd,&fdSet))
1430 {
1431 if (verbose) clog << "received on A2:P1" << endl;
1432 recvAltIp = true;
1433 recvAltPort = false;
1434 ok = getMessage( info.altIpFd, msg, &msgLen, &from.addr, &from.port ,verbose);
1435 }
1436 else if ( (info.altIpPortFd!=INVALID_SOCKET) && FD_ISSET(info.altIpPortFd, &fdSet))
1437 {
1438 if (verbose) clog << "received on A2:P2" << endl;
1439 recvAltIp = true;
1440 recvAltPort = true;
1441 ok = getMessage( info.altIpPortFd, msg, &msgLen, &from.addr, &from.port,verbose );
1442 }
1443 else
1444 {
1445 return true;
1446 }
1447
1448 int relayPort = 0;
1449 if (info.relay)
1450 {
1451 for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1452 {
1453 StunMediaRelay* relay = &info.relays[i];
1454 if (relay->destination.addr == from.addr &&
1455 relay->destination.port == from.port)
1456 {
1457 relayPort = relay->relayPort;
1458 relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT;
1459 break;
1460 }
1461 }
1462
1463 if (relayPort == 0)
1464 {
1465 for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1466 {
1467 StunMediaRelay* relay = &info.relays[i];
1468 if (relay->fd == 0)
1469 {
1470 if ( verbose ) clog << "Open relay port " << relay->relayPort << endl;
1471
1472 relay->fd = openPort(relay->relayPort, info.myAddr.addr, verbose);
1473 relay->destination.addr = from.addr;
1474 relay->destination.port = from.port;
1475 relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT;
1476 relayPort = relay->relayPort;
1477 break;
1478 }
1479 }
1480 }
1481 }
1482
1483 if ( !ok )
1484 {
1485 if ( verbose ) clog << "Get message did not return a valid message" <<endl;
1486 return true;
1487 }
1488
1489 if ( verbose ) clog << "Got a request (len=" << msgLen << ") from " << from << endl;
1490
1491 if ( msgLen <= 0 )
1492 {
1493 return true;
1494 }
1495
1496 bool changePort = false;
1497 bool changeIp = false;
1498
1499 StunMessage resp;
1500 StunAddress4 dest;
1501 StunAtrString hmacPassword;
1502 hmacPassword.sizeValue = 0;
1503
1504 StunAddress4 secondary;
1505 secondary.port = 0;
1506 secondary.addr = 0;
1507
1508 if (info.relay && relayPort)
1509 {
1510 secondary = from;
1511
1512 from.addr = info.myAddr.addr;
1513 from.port = relayPort;
1514 }
1515
1516 ok = stunServerProcessMsg( msg, msgLen, from, secondary,
1517 recvAltIp ? info.altAddr : info.myAddr,
1518 recvAltIp ? info.myAddr : info.altAddr,
1519 &resp,
1520 &dest,
1521 &hmacPassword,
1522 &changePort,
1523 &changeIp,
1524 verbose );
1525
1526 if ( !ok )
1527 {
1528 if ( verbose ) clog << "Failed to parse message" << endl;
1529 return true;
1530 }
1531
1532 char buf[STUN_MAX_MESSAGE_SIZE];
1533 int len = sizeof(buf);
1534
1535 len = stunEncodeMessage( resp, buf, len, hmacPassword,verbose );
1536
1537 if ( dest.addr == 0 ) ok=false;
1538 if ( dest.port == 0 ) ok=false;
1539
1540 if ( ok )
1541 {
1542 assert( dest.addr != 0 );
1543 assert( dest.port != 0 );
1544
1545 Socket sendFd;
1546
1547 bool sendAltIp = recvAltIp; // send on the received IP address
1548 bool sendAltPort = recvAltPort; // send on the received port
1549
1550 if ( changeIp ) sendAltIp = !sendAltIp; // if need to change IP, then flip logic
1551 if ( changePort ) sendAltPort = !sendAltPort; // if need to change port, then flip logic
1552
1553 if ( !sendAltPort )
1554 {
1555 if ( !sendAltIp )
1556 {
1557 sendFd = info.myFd;
1558 }
1559 else
1560 {
1561 sendFd = info.altIpFd;
1562 }
1563 }
1564 else
1565 {
1566 if ( !sendAltIp )
1567 {
1568 sendFd = info.altPortFd;
1569 }
1570 else
1571 {
1572 sendFd = info.altIpPortFd;
1573 }
1574 }
1575
1576 if ( sendFd != INVALID_SOCKET )
1577 {
1578 sendMessage( sendFd, buf, len, dest.addr, dest.port, verbose );
1579 }
1580 }
1581 }
1582
1583 return true;
1584 }
1585
1586 int
stunFindLocalInterfaces(UInt32 * addresses,int maxRet)1587 stunFindLocalInterfaces(UInt32* addresses,int maxRet)
1588 {
1589 #if defined(WIN32) || defined(__sparc__)
1590 return 0;
1591 #else
1592 struct ifconf ifc;
1593
1594 int s = socket( AF_INET, SOCK_DGRAM, 0 );
1595 int len = 100 * sizeof(struct ifreq);
1596
1597 char buf[ len ];
1598
1599 ifc.ifc_len = len;
1600 ifc.ifc_buf = buf;
1601
1602 int e = ioctl(s,SIOCGIFCONF,&ifc);
1603 char *ptr = buf;
1604 int tl = ifc.ifc_len;
1605 int count=0;
1606
1607 while ( (tl > 0) && ( count < maxRet) )
1608 {
1609 struct ifreq* ifr = (struct ifreq *)ptr;
1610
1611 int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1612 tl -= si;
1613 ptr += si;
1614 //char* name = ifr->ifr_ifrn.ifrn_name;
1615 //cerr << "name = " << name << endl;
1616
1617 struct ifreq ifr2;
1618 ifr2 = *ifr;
1619
1620 e = ioctl(s,SIOCGIFADDR,&ifr2);
1621 if ( e == -1 )
1622 {
1623 break;
1624 }
1625
1626 //cerr << "ioctl addr e = " << e << endl;
1627
1628 struct sockaddr a = ifr2.ifr_addr;
1629 struct sockaddr_in* addr = (struct sockaddr_in*) &a;
1630
1631 UInt32 ai = ntohl( addr->sin_addr.s_addr );
1632 if (int((ai>>24)&0xFF) != 127)
1633 {
1634 addresses[count++] = ai;
1635 }
1636
1637 #if 0
1638 cerr << "Detected interface "
1639 << int((ai>>24)&0xFF) << "."
1640 << int((ai>>16)&0xFF) << "."
1641 << int((ai>> 8)&0xFF) << "."
1642 << int((ai )&0xFF) << endl;
1643 #endif
1644 }
1645
1646 closesocket(s);
1647
1648 return count;
1649 #endif
1650 }
1651
1652
1653 void
stunBuildReqSimple(StunMessage * msg,const StunAtrString & username,bool changePort,bool changeIp,unsigned int id)1654 stunBuildReqSimple( StunMessage* msg,
1655 const StunAtrString& username,
1656 bool changePort, bool changeIp, unsigned int id )
1657 {
1658 assert( msg );
1659 memset( msg , 0 , sizeof(*msg) );
1660
1661 msg->msgHdr.msgType = BindRequestMsg;
1662
1663 for ( int i=0; i<16; i=i+4 )
1664 {
1665 assert(i+3<16);
1666 int r = stunRand();
1667 msg->msgHdr.id.octet[i+0]= r>>0;
1668 msg->msgHdr.id.octet[i+1]= r>>8;
1669 msg->msgHdr.id.octet[i+2]= r>>16;
1670 msg->msgHdr.id.octet[i+3]= r>>24;
1671 }
1672
1673 if ( id != 0 )
1674 {
1675 msg->msgHdr.id.octet[0] = id;
1676 }
1677
1678 msg->hasChangeRequest = true;
1679 msg->changeRequest.value =(changeIp?ChangeIpFlag:0) |
1680 (changePort?ChangePortFlag:0);
1681
1682 if ( username.sizeValue > 0 )
1683 {
1684 msg->hasUsername = true;
1685 msg->username = username;
1686 }
1687 }
1688
1689
1690 static void
stunSendTest(Socket myFd,StunAddress4 & dest,const StunAtrString & username,const StunAtrString & password,int testNum,bool verbose)1691 stunSendTest( Socket myFd, StunAddress4& dest,
1692 const StunAtrString& username, const StunAtrString& password,
1693 int testNum, bool verbose )
1694 {
1695 assert( dest.addr != 0 );
1696 assert( dest.port != 0 );
1697
1698 bool changePort=false;
1699 bool changeIP=false;
1700 bool discard=false;
1701
1702 switch (testNum)
1703 {
1704 case 1:
1705 case 10:
1706 case 11:
1707 break;
1708 case 2:
1709 //changePort=true;
1710 changeIP=true;
1711 break;
1712 case 3:
1713 changePort=true;
1714 break;
1715 case 4:
1716 changeIP=true;
1717 break;
1718 case 5:
1719 discard=true;
1720 break;
1721 default:
1722 cerr << "Test " << testNum <<" is unkown\n";
1723 assert(0);
1724 }
1725
1726 StunMessage req;
1727 memset(&req, 0, sizeof(StunMessage));
1728
1729 stunBuildReqSimple( &req, username,
1730 changePort , changeIP ,
1731 testNum );
1732
1733 char buf[STUN_MAX_MESSAGE_SIZE];
1734 int len = STUN_MAX_MESSAGE_SIZE;
1735
1736 len = stunEncodeMessage( req, buf, len, password,verbose );
1737
1738 if ( verbose )
1739 {
1740 clog << "About to send msg of len " << len << " to " << dest << endl;
1741 }
1742
1743 sendMessage( myFd, buf, len, dest.addr, dest.port, verbose );
1744
1745 // add some delay so the packets don't get sent too quickly
1746 #ifdef WIN32 // !cj! TODO - should fix this up in windows
1747 clock_t now = clock();
1748 assert( CLOCKS_PER_SEC == 1000 );
1749 while ( clock() <= now+10 ) { };
1750 #else
1751 usleep(10*1000);
1752 #endif
1753
1754 }
1755
1756
1757 void
stunGetUserNameAndPassword(const StunAddress4 & dest,StunAtrString * username,StunAtrString * password)1758 stunGetUserNameAndPassword( const StunAddress4& dest,
1759 StunAtrString* username,
1760 StunAtrString* password)
1761 {
1762 // !cj! This is totally bogus - need to make TLS connection to dest and get a
1763 // username and password to use
1764 stunCreateUserName(dest, username);
1765 stunCreatePassword(*username, password);
1766 }
1767
1768
1769 void
stunTest(StunAddress4 & dest,int testNum,bool verbose,StunAddress4 * sAddr)1770 stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* sAddr )
1771 {
1772 assert( dest.addr != 0 );
1773 assert( dest.port != 0 );
1774
1775 int port = stunRandomPort();
1776 UInt32 interfaceIp=0;
1777 if (sAddr)
1778 {
1779 interfaceIp = sAddr->addr;
1780 if ( sAddr->port != 0 )
1781 {
1782 port = sAddr->port;
1783 }
1784 }
1785 Socket myFd = openPort(port,interfaceIp,verbose);
1786
1787 StunAtrString username;
1788 StunAtrString password;
1789
1790 username.sizeValue = 0;
1791 password.sizeValue = 0;
1792
1793 #ifdef USE_TLS
1794 stunGetUserNameAndPassword( dest, username, password );
1795 #endif
1796
1797 stunSendTest( myFd, dest, username, password, testNum, verbose );
1798
1799 char msg[STUN_MAX_MESSAGE_SIZE];
1800 int msgLen = STUN_MAX_MESSAGE_SIZE;
1801
1802 StunAddress4 from;
1803 getMessage( myFd,
1804 msg,
1805 &msgLen,
1806 &from.addr,
1807 &from.port,verbose );
1808
1809 StunMessage resp;
1810 memset(&resp, 0, sizeof(StunMessage));
1811
1812 if ( verbose ) clog << "Got a response" << endl;
1813 bool ok = stunParseMessage( msg,msgLen, resp,verbose );
1814
1815 if ( verbose )
1816 {
1817 clog << "\t ok=" << ok << endl;
1818 clog << "\t id=" << resp.msgHdr.id << endl;
1819 clog << "\t mappedAddr=" << resp.mappedAddress.ipv4 << endl;
1820 clog << "\t changedAddr=" << resp.changedAddress.ipv4 << endl;
1821 clog << endl;
1822 }
1823
1824 if (sAddr)
1825 {
1826 sAddr->port = resp.mappedAddress.ipv4.port;
1827 sAddr->addr = resp.mappedAddress.ipv4.addr;
1828 }
1829 }
1830
1831
1832 NatType
stunNatType(StunAddress4 & dest,bool verbose,bool * preservePort,bool * hairpin,int port,StunAddress4 * sAddr)1833 stunNatType( StunAddress4& dest,
1834 bool verbose,
1835 bool* preservePort, // if set, is return for if NAT preservers ports or not
1836 bool* hairpin, // if set, is the return for if NAT will hairpin packets
1837 int port, // port to use for the test, 0 to choose random port
1838 StunAddress4* sAddr // NIC to use
1839 )
1840 {
1841 assert( dest.addr != 0 );
1842 assert( dest.port != 0 );
1843
1844 if ( hairpin )
1845 {
1846 *hairpin = false;
1847 }
1848
1849 if ( port == 0 )
1850 {
1851 port = stunRandomPort();
1852 }
1853 UInt32 interfaceIp=0;
1854 if (sAddr)
1855 {
1856 interfaceIp = sAddr->addr;
1857 }
1858 Socket myFd1 = openPort(port,interfaceIp,verbose);
1859 Socket myFd2 = openPort(port+1,interfaceIp,verbose);
1860
1861 if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) )
1862 {
1863 cerr << "Some problem opening port/interface to send on" << endl;
1864 return StunTypeFailure;
1865 }
1866
1867 assert( myFd1 != INVALID_SOCKET );
1868 assert( myFd2 != INVALID_SOCKET );
1869
1870 bool respTestI=false;
1871 bool isNat=true;
1872 StunAddress4 testIchangedAddr;
1873 StunAddress4 testImappedAddr;
1874 bool respTestI2=false;
1875 bool mappedIpSame = true;
1876 StunAddress4 testI2mappedAddr;
1877 StunAddress4 testI2dest=dest;
1878 bool respTestII=false;
1879 bool respTestIII=false;
1880
1881 bool respTestHairpin=false;
1882 bool respTestPreservePort=false;
1883
1884 memset(&testImappedAddr,0,sizeof(testImappedAddr));
1885
1886 StunAtrString username;
1887 StunAtrString password;
1888
1889 username.sizeValue = 0;
1890 password.sizeValue = 0;
1891
1892 #ifdef USE_TLS
1893 stunGetUserNameAndPassword( dest, username, password );
1894 #endif
1895
1896 int count=0;
1897 while ( count < 7 )
1898 {
1899 struct timeval tv;
1900 fd_set fdSet;
1901 #ifdef WIN32
1902 unsigned int fdSetSize;
1903 #else
1904 int fdSetSize;
1905 #endif
1906 FD_ZERO(&fdSet); fdSetSize=0;
1907 FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize;
1908 FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize;
1909 tv.tv_sec=0;
1910 tv.tv_usec=150*1000; // 150 ms
1911 if ( count == 0 ) tv.tv_usec=0;
1912
1913 int err = select(fdSetSize, &fdSet, NULL, NULL, &tv);
1914 int e = getErrno();
1915 if ( err == SOCKET_ERROR )
1916 {
1917 // error occured
1918 cerr << "Error " << e << " " << strerror(e) << " in select" << endl;
1919 return StunTypeFailure;
1920 }
1921 else if ( err == 0 )
1922 {
1923 // timeout occured
1924 count++;
1925
1926 if ( !respTestI )
1927 {
1928 stunSendTest( myFd1, dest, username, password, 1 ,verbose );
1929 }
1930
1931 if ( (!respTestI2) && respTestI )
1932 {
1933 // check the address to send to if valid
1934 if ( ( testI2dest.addr != 0 ) &&
1935 ( testI2dest.port != 0 ) )
1936 {
1937 stunSendTest( myFd1, testI2dest, username, password, 10 ,verbose);
1938 }
1939 }
1940
1941 if ( !respTestII )
1942 {
1943 stunSendTest( myFd2, dest, username, password, 2 ,verbose );
1944 }
1945
1946 if ( !respTestIII )
1947 {
1948 stunSendTest( myFd2, dest, username, password, 3 ,verbose );
1949 }
1950
1951 if ( respTestI && (!respTestHairpin) )
1952 {
1953 if ( ( testImappedAddr.addr != 0 ) &&
1954 ( testImappedAddr.port != 0 ) )
1955 {
1956 stunSendTest( myFd1, testImappedAddr, username, password, 11 ,verbose );
1957 }
1958 }
1959 }
1960 else
1961 {
1962 //if (verbose) clog << "-----------------------------------------" << endl;
1963 assert( err>0 );
1964 // data is avialbe on some fd
1965
1966 for ( int i=0; i<2; i++)
1967 {
1968 Socket myFd;
1969 if ( i==0 )
1970 {
1971 myFd=myFd1;
1972 }
1973 else
1974 {
1975 myFd=myFd2;
1976 }
1977
1978 if ( myFd!=INVALID_SOCKET )
1979 {
1980 if ( FD_ISSET(myFd,&fdSet) )
1981 {
1982 char msg[STUN_MAX_MESSAGE_SIZE];
1983 int msgLen = sizeof(msg);
1984
1985 StunAddress4 from;
1986
1987 getMessage( myFd,
1988 msg,
1989 &msgLen,
1990 &from.addr,
1991 &from.port,verbose );
1992
1993 StunMessage resp;
1994 memset(&resp, 0, sizeof(StunMessage));
1995
1996 stunParseMessage( msg,msgLen, resp,verbose );
1997
1998 if ( verbose )
1999 {
2000 clog << "Received message of type " << resp.msgHdr.msgType
2001 << " id=" << (int)(resp.msgHdr.id.octet[0]) << endl;
2002 }
2003
2004 switch( resp.msgHdr.id.octet[0] )
2005 {
2006 case 1:
2007 {
2008 if ( !respTestI )
2009 {
2010
2011 testIchangedAddr.addr = resp.changedAddress.ipv4.addr;
2012 testIchangedAddr.port = resp.changedAddress.ipv4.port;
2013 testImappedAddr.addr = resp.mappedAddress.ipv4.addr;
2014 testImappedAddr.port = resp.mappedAddress.ipv4.port;
2015
2016 respTestPreservePort = ( testImappedAddr.port == port );
2017 if ( preservePort )
2018 {
2019 *preservePort = respTestPreservePort;
2020 }
2021
2022 testI2dest.addr = resp.changedAddress.ipv4.addr;
2023
2024 if (sAddr)
2025 {
2026 sAddr->port = testImappedAddr.port;
2027 sAddr->addr = testImappedAddr.addr;
2028 }
2029
2030 count = 0;
2031 }
2032 respTestI=true;
2033 }
2034 break;
2035 case 2:
2036 {
2037 respTestII=true;
2038 }
2039 break;
2040 case 3:
2041 {
2042 respTestIII=true;
2043 }
2044 break;
2045 case 10:
2046 {
2047 if ( !respTestI2 )
2048 {
2049 testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr;
2050 testI2mappedAddr.port = resp.mappedAddress.ipv4.port;
2051
2052 mappedIpSame = false;
2053 if ( (testI2mappedAddr.addr == testImappedAddr.addr ) &&
2054 (testI2mappedAddr.port == testImappedAddr.port ))
2055 {
2056 mappedIpSame = true;
2057 }
2058
2059
2060 }
2061 respTestI2=true;
2062 }
2063 break;
2064 case 11:
2065 {
2066
2067 if ( hairpin )
2068 {
2069 *hairpin = true;
2070 }
2071 respTestHairpin = true;
2072 }
2073 break;
2074 }
2075 }
2076 }
2077 }
2078 }
2079 }
2080
2081 // see if we can bind to this address
2082 //cerr << "try binding to " << testImappedAddr << endl;
2083 Socket s = openPort( 0/*use ephemeral*/, testImappedAddr.addr, false );
2084 if ( s != INVALID_SOCKET )
2085 {
2086 closesocket(s);
2087 isNat = false;
2088 //cerr << "binding worked" << endl;
2089 }
2090 else
2091 {
2092 isNat = true;
2093 //cerr << "binding failed" << endl;
2094 }
2095
2096 if (verbose)
2097 {
2098 clog << "test I = " << respTestI << endl;
2099 clog << "test II = " << respTestII << endl;
2100 clog << "test III = " << respTestIII << endl;
2101 clog << "test I(2) = " << respTestI2 << endl;
2102 clog << "is nat = " << isNat <<endl;
2103 clog << "mapped IP same = " << mappedIpSame << endl;
2104 clog << "hairpin = " << respTestHairpin << endl;
2105 clog << "preserver port = " << respTestPreservePort << endl;
2106 }
2107
2108 #if 0
2109 // implement logic flow chart from draft RFC
2110 if ( respTestI )
2111 {
2112 if ( isNat )
2113 {
2114 if (respTestII)
2115 {
2116 return StunTypeConeNat;
2117 }
2118 else
2119 {
2120 if ( mappedIpSame )
2121 {
2122 if ( respTestIII )
2123 {
2124 return StunTypeRestrictedNat;
2125 }
2126 else
2127 {
2128 return StunTypePortRestrictedNat;
2129 }
2130 }
2131 else
2132 {
2133 return StunTypeSymNat;
2134 }
2135 }
2136 }
2137 else
2138 {
2139 if (respTestII)
2140 {
2141 return StunTypeOpen;
2142 }
2143 else
2144 {
2145 return StunTypeSymFirewall;
2146 }
2147 }
2148 }
2149 else
2150 {
2151 return StunTypeBlocked;
2152 }
2153 #else
2154 if ( respTestI ) // not blocked
2155 {
2156 if ( isNat )
2157 {
2158 if ( mappedIpSame )
2159 {
2160 if (respTestII)
2161 {
2162 return StunTypeIndependentFilter;
2163 }
2164 else
2165 {
2166 if ( respTestIII )
2167 {
2168 return StunTypeDependentFilter;
2169 }
2170 else
2171 {
2172 return StunTypePortDependedFilter;
2173 }
2174 }
2175 }
2176 else // mappedIp is not same
2177 {
2178 return StunTypeDependentMapping;
2179 }
2180 }
2181 else // isNat is false
2182 {
2183 if (respTestII)
2184 {
2185 return StunTypeOpen;
2186 }
2187 else
2188 {
2189 return StunTypeFirewall;
2190 }
2191 }
2192 }
2193 else
2194 {
2195 return StunTypeBlocked;
2196 }
2197 #endif
2198
2199 return StunTypeUnknown;
2200 }
2201
2202
2203 int
stunOpenSocket(StunAddress4 & dest,StunAddress4 * mapAddr,int port,StunAddress4 * srcAddr,bool verbose)2204 stunOpenSocket( StunAddress4& dest, StunAddress4* mapAddr,
2205 int port, StunAddress4* srcAddr,
2206 bool verbose )
2207 {
2208 assert( dest.addr != 0 );
2209 assert( dest.port != 0 );
2210 assert( mapAddr );
2211
2212 if ( port == 0 )
2213 {
2214 port = stunRandomPort();
2215 }
2216 unsigned int interfaceIp = 0;
2217 if ( srcAddr )
2218 {
2219 interfaceIp = srcAddr->addr;
2220 }
2221
2222 Socket myFd = openPort(port,interfaceIp,verbose);
2223 if (myFd == INVALID_SOCKET)
2224 {
2225 return myFd;
2226 }
2227
2228 char msg[STUN_MAX_MESSAGE_SIZE];
2229 int msgLen = sizeof(msg);
2230
2231 StunAtrString username;
2232 StunAtrString password;
2233
2234 username.sizeValue = 0;
2235 password.sizeValue = 0;
2236
2237 #ifdef USE_TLS
2238 stunGetUserNameAndPassword( dest, username, password );
2239 #endif
2240
2241 stunSendTest(myFd, dest, username, password, 1, 0/*false*/ );
2242
2243 StunAddress4 from;
2244
2245 getMessage( myFd, msg, &msgLen, &from.addr, &from.port,verbose );
2246
2247 StunMessage resp;
2248 memset(&resp, 0, sizeof(StunMessage));
2249
2250 bool ok = stunParseMessage( msg, msgLen, resp,verbose );
2251 if (!ok)
2252 {
2253 return -1;
2254 }
2255
2256 StunAddress4 mappedAddr = resp.mappedAddress.ipv4;
2257 StunAddress4 changedAddr = resp.changedAddress.ipv4;
2258
2259 //clog << "--- stunOpenSocket --- " << endl;
2260 //clog << "\treq id=" << req.id << endl;
2261 //clog << "\tresp id=" << id << endl;
2262 //clog << "\tmappedAddr=" << mappedAddr << endl;
2263
2264 *mapAddr = mappedAddr;
2265
2266 return myFd;
2267 }
2268
2269
2270 bool
stunOpenSocketPair(StunAddress4 & dest,StunAddress4 * mapAddr,int * fd1,int * fd2,int port,StunAddress4 * srcAddr,bool verbose)2271 stunOpenSocketPair( StunAddress4& dest, StunAddress4* mapAddr,
2272 int* fd1, int* fd2,
2273 int port, StunAddress4* srcAddr,
2274 bool verbose )
2275 {
2276 assert( dest.addr!= 0 );
2277 assert( dest.port != 0 );
2278 assert( mapAddr );
2279
2280 const int NUM=3;
2281
2282 if ( port == 0 )
2283 {
2284 port = stunRandomPort();
2285 }
2286
2287 *fd1=-1;
2288 *fd2=-1;
2289
2290 char msg[STUN_MAX_MESSAGE_SIZE];
2291 int msgLen =sizeof(msg);
2292
2293 StunAddress4 from;
2294 int fd[NUM];
2295 int i;
2296
2297 unsigned int interfaceIp = 0;
2298 if ( srcAddr )
2299 {
2300 interfaceIp = srcAddr->addr;
2301 }
2302
2303 for( i=0; i<NUM; i++)
2304 {
2305 fd[i] = openPort( (port == 0) ? 0 : (port + i),
2306 interfaceIp, verbose);
2307 if (fd[i] < 0)
2308 {
2309 while (i > 0)
2310 {
2311 closesocket(fd[--i]);
2312 }
2313 return false;
2314 }
2315 }
2316
2317 StunAtrString username;
2318 StunAtrString password;
2319
2320 username.sizeValue = 0;
2321 password.sizeValue = 0;
2322
2323 #ifdef USE_TLS
2324 stunGetUserNameAndPassword( dest, username, password );
2325 #endif
2326
2327 for( i=0; i<NUM; i++)
2328 {
2329 stunSendTest(fd[i], dest, username, password, 1/*testNum*/, verbose );
2330 }
2331
2332 StunAddress4 mappedAddr[NUM];
2333 for( i=0; i<NUM; i++)
2334 {
2335 msgLen = sizeof(msg)/sizeof(*msg);
2336 getMessage( fd[i],
2337 msg,
2338 &msgLen,
2339 &from.addr,
2340 &from.port ,verbose);
2341
2342 StunMessage resp;
2343 memset(&resp, 0, sizeof(StunMessage));
2344
2345 bool ok = stunParseMessage( msg, msgLen, resp, verbose );
2346 if (!ok)
2347 {
2348 return false;
2349 }
2350
2351 mappedAddr[i] = resp.mappedAddress.ipv4;
2352 StunAddress4 changedAddr = resp.changedAddress.ipv4;
2353 }
2354
2355 if (verbose)
2356 {
2357 clog << "--- stunOpenSocketPair --- " << endl;
2358 for( i=0; i<NUM; i++)
2359 {
2360 clog << "\t mappedAddr=" << mappedAddr[i] << endl;
2361 }
2362 }
2363
2364 if ( mappedAddr[0].port %2 == 0 )
2365 {
2366 if ( mappedAddr[0].port+1 == mappedAddr[1].port )
2367 {
2368 *mapAddr = mappedAddr[0];
2369 *fd1 = fd[0];
2370 *fd2 = fd[1];
2371 closesocket( fd[2] );
2372 return true;
2373 }
2374 }
2375 else
2376 {
2377 if (( mappedAddr[1].port %2 == 0 )
2378 && ( mappedAddr[1].port+1 == mappedAddr[2].port ))
2379 {
2380 *mapAddr = mappedAddr[1];
2381 *fd1 = fd[1];
2382 *fd2 = fd[2];
2383 closesocket( fd[0] );
2384 return true;
2385 }
2386 }
2387
2388 // something failed, close all and return error
2389 for( i=0; i<NUM; i++)
2390 {
2391 closesocket( fd[i] );
2392 }
2393
2394 return false;
2395 }
2396
2397 /* ====================================================================
2398 * The Vovida Software License, Version 1.0
2399 *
2400 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
2401 *
2402 * Redistribution and use in source and binary forms, with or without
2403 * modification, are permitted provided that the following conditions
2404 * are met:
2405 *
2406 * 1. Redistributions of source code must retain the above copyright
2407 * notice, this list of conditions and the following disclaimer.
2408 *
2409 * 2. Redistributions in binary form must reproduce the above copyright
2410 * notice, this list of conditions and the following disclaimer in
2411 * the documentation and/or other materials provided with the
2412 * distribution.
2413 *
2414 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2415 * and "Vovida Open Communication Application Library (VOCAL)" must
2416 * not be used to endorse or promote products derived from this
2417 * software without prior written permission. For written
2418 * permission, please contact vocal@vovida.org.
2419 *
2420 * 4. Products derived from this software may not be called "VOCAL", nor
2421 * may "VOCAL" appear in their name, without prior written
2422 * permission of Vovida Networks, Inc.
2423 *
2424 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2425 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2426 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2427 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
2428 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2429 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2430 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2431 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2432 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2433 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2434 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2435 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2436 * DAMAGE.
2437 *
2438 * ====================================================================
2439 *
2440 * This software consists of voluntary contributions made by Vovida
2441 * Networks, Inc. and many individuals on behalf of Vovida Networks,
2442 * Inc. For more information on Vovida Networks, Inc., please see
2443 * <http://www.vovida.org/>.
2444 *
2445 */
2446
2447 // Local Variables:
2448 // mode:c++
2449 // c-file-style:"ellemtel"
2450 // c-file-offsets:((case-label . +))
2451 // indent-tabs-mode:nil
2452 // End:
2453
2454
2455