|
reSIProcate/rutil
9694
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #include <cassert> 00006 #include <cstring> 00007 #include <iostream> 00008 #include <cstdlib> 00009 #include <errno.h> 00010 00011 #ifdef WIN32 00012 #include <winsock2.h> 00013 #include <stdlib.h> 00014 #include <io.h> 00015 #include <time.h> 00016 #else 00017 00018 #include <stdlib.h> 00019 #include <unistd.h> 00020 #include <string.h> 00021 #include <sys/ioctl.h> 00022 #include <sys/socket.h> 00023 #include <sys/time.h> 00024 #include <sys/types.h> 00025 #include <arpa/inet.h> 00026 #include <fcntl.h> 00027 #include <netdb.h> 00028 #include <netinet/in.h> 00029 00030 #ifndef __CYGWIN__ 00031 #include <arpa/nameser.h> 00032 #include <resolv.h> 00033 #endif 00034 00035 #include <net/if.h> 00036 00037 #if defined (__SUNPRO_CC) || defined (__sun__) 00038 #include <sys/sockio.h> // solaris only? 00039 #endif 00040 00041 #endif 00042 00043 #include "Udp.hxx" 00044 #include "Stun.hxx" 00045 #include "rutil/Socket.hxx" 00046 #include "rutil/WinLeakCheck.hxx" 00047 00048 using namespace std; 00049 using namespace resip; 00050 00051 static bool 00052 stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4& result ) 00053 { 00054 if ( hdrLen != 8 ) 00055 { 00056 // clog << "hdrLen wrong for Address" <<endl; 00057 return false; 00058 } 00059 result.pad = *body++; 00060 result.family = *body++; 00061 if (result.family == IPv4Family) 00062 { 00063 UInt16 nport; 00064 memcpy(&nport, body, 2); body+=2; 00065 result.ipv4.port = ntohs(nport); 00066 00067 UInt32 naddr; 00068 memcpy(&naddr, body, 4); body+=4; 00069 result.ipv4.addr = ntohl(naddr); 00070 return true; 00071 } 00072 else if (result.family == IPv6Family) 00073 { 00074 //clog << "ipv6 not supported" << endl; 00075 } 00076 else 00077 { 00078 //clog << "bad address family: " << result.family << endl; 00079 } 00080 00081 return false; 00082 } 00083 00084 static bool 00085 stunParseUInt32( char* body, unsigned int hdrLen, UInt32& result ) 00086 { 00087 if ( hdrLen != 4 ) 00088 { 00089 return false; 00090 } 00091 else 00092 { 00093 UInt32 tmp; 00094 memcpy(&tmp, body, 4); 00095 result = ntohl(tmp); 00096 return true; 00097 } 00098 } 00099 00100 static bool 00101 stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest& result ) 00102 { 00103 if ( hdrLen != 4 ) 00104 { 00105 //clog << "hdr length = " << hdrLen << " expecting " << sizeof(result) << endl; 00106 00107 //clog << "Incorrect size for ChangeRequest" << endl; 00108 return false; 00109 } 00110 else 00111 { 00112 memcpy(&result.value, body, 4); 00113 result.value = ntohl(result.value); 00114 return true; 00115 } 00116 } 00117 00118 static bool 00119 stunParseAtrError( char* body, unsigned int hdrLen, StunAtrError& result ) 00120 { 00121 if ( hdrLen >= (sizeof(result)-sizeof(result.sizeReason)) ) // Note: result.sizeReason is extra info in StunAtrError that is not on the wire 00122 { 00123 //clog << "head on Error too large" << endl; 00124 return false; 00125 } 00126 else 00127 { 00128 memcpy(&result.pad, body, 2); body+=2; 00129 result.pad = ntohs(result.pad); 00130 result.errorClass = *body++; 00131 result.number = *body++; 00132 00133 result.sizeReason = hdrLen - 4; 00134 memcpy(&result.reason, body, result.sizeReason); 00135 result.reason[result.sizeReason] = 0; 00136 return true; 00137 } 00138 } 00139 00140 static bool 00141 stunParseAtrUnknown( char* body, unsigned int hdrLen, StunAtrUnknown& result ) 00142 { 00143 if ( hdrLen >= sizeof(result) ) 00144 { 00145 return false; 00146 } 00147 else 00148 { 00149 if (hdrLen % 4 != 0) return false; 00150 result.numAttributes = hdrLen / 4; 00151 for (int i=0; i<result.numAttributes; i++) 00152 { 00153 memcpy(&result.attrType[i], body, 2); body+=2; 00154 result.attrType[i] = ntohs(result.attrType[i]); 00155 } 00156 return true; 00157 } 00158 } 00159 00160 00161 static bool 00162 stunParseAtrString( char* body, unsigned int hdrLen, StunAtrString& result ) 00163 { 00164 if ( hdrLen >= STUN_MAX_STRING ) 00165 { 00166 //clog << "String is too large" << endl; 00167 return false; 00168 } 00169 else 00170 { 00171 if (hdrLen % 4 != 0) 00172 { 00173 //clog << "Bad length string " << hdrLen << endl; 00174 return false; 00175 } 00176 00177 result.sizeValue = hdrLen; 00178 memcpy(&result.value, body, hdrLen); 00179 result.value[hdrLen] = 0; 00180 return true; 00181 } 00182 } 00183 00184 00185 static bool 00186 stunParseAtrIntegrity( char* body, unsigned int hdrLen, StunAtrIntegrity& result ) 00187 { 00188 if ( hdrLen != 20) 00189 { 00190 //clog << "MessageIntegrity must be 20 bytes" << endl; 00191 return false; 00192 } 00193 else 00194 { 00195 memcpy(&result.hash, body, hdrLen); 00196 return true; 00197 } 00198 } 00199 00200 00201 00202 bool 00203 stunParseMessage( char* buf, unsigned int bufLen, StunMessage& msg, bool verbose) 00204 { 00205 if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl; 00206 memset(&msg, 0, sizeof(msg)); 00207 00208 if (sizeof(StunMsgHdr) > bufLen) 00209 { 00210 clog << "Bad message" << endl; 00211 return false; 00212 } 00213 00214 memcpy(&msg.msgHdr, buf, sizeof(StunMsgHdr)); 00215 msg.msgHdr.msgType = ntohs(msg.msgHdr.msgType); 00216 msg.msgHdr.msgLength = ntohs(msg.msgHdr.msgLength); 00217 00218 if (msg.msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen) 00219 { 00220 clog << "Message header length doesn't match message size: " << msg.msgHdr.msgLength << " - " << bufLen << endl; 00221 return false; 00222 } 00223 00224 char* body = buf + sizeof(StunMsgHdr); 00225 unsigned int size = msg.msgHdr.msgLength; 00226 00227 if (verbose) clog << "bytes after header = " << size << endl; 00228 00229 while ( size > 0 ) 00230 { 00231 // !jf! should check that there are enough bytes left in the buffer 00232 00233 StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body); 00234 00235 unsigned int attrLen = ntohs(attr->length); 00236 int atrType = ntohs(attr->type); 00237 00238 if (verbose) clog << "Found attribute type=" << atrType << " length=" << attrLen << endl; 00239 if ( attrLen+4 > size ) 00240 { 00241 clog << "claims attribute is larger than size of message " <<"(attribute type="<<atrType<<")"<< endl; 00242 return false; 00243 } 00244 00245 body += 4; // skip the length and type in attribute header 00246 size -= 4; 00247 00248 switch ( atrType ) 00249 { 00250 case MappedAddress: 00251 msg.hasMappedAddress = true; 00252 if ( stunParseAtrAddress( body, attrLen, msg.mappedAddress )== false ) 00253 { 00254 clog << "problem parsing MappedAddress" << endl; 00255 return false; 00256 } 00257 else 00258 { 00259 if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl; 00260 } 00261 00262 break; 00263 00264 case ResponseAddress: 00265 msg.hasResponseAddress = true; 00266 if ( stunParseAtrAddress( body, attrLen, msg.responseAddress )== false ) 00267 { 00268 if (verbose) clog << "problem parsing ResponseAddress" << endl; 00269 return false; 00270 } 00271 else 00272 { 00273 if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl; 00274 } 00275 break; 00276 00277 case ChangeRequest: 00278 msg.hasChangeRequest = true; 00279 if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false) 00280 { 00281 if (verbose) clog << "problem parsing ChangeRequest" << endl; 00282 return false; 00283 } 00284 else 00285 { 00286 if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl; 00287 } 00288 break; 00289 00290 case SourceAddress: 00291 msg.hasSourceAddress = true; 00292 if ( stunParseAtrAddress( body, attrLen, msg.sourceAddress )== false ) 00293 { 00294 if (verbose) clog << "problem parsing SourceAddress" << endl; 00295 return false; 00296 } 00297 else 00298 { 00299 if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl; 00300 } 00301 break; 00302 00303 case ChangedAddress: 00304 msg.hasChangedAddress = true; 00305 if ( stunParseAtrAddress( body, attrLen, msg.changedAddress )== false ) 00306 { 00307 if (verbose) clog << "problem parsing ChangedAddress" << endl; 00308 return false; 00309 } 00310 else 00311 { 00312 if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl; 00313 } 00314 break; 00315 00316 case Username: 00317 msg.hasUsername = true; 00318 if (stunParseAtrString( body, attrLen, msg.username) == false) 00319 { 00320 if (verbose) clog << "problem parsing Username" << endl; 00321 return false; 00322 } 00323 else 00324 { 00325 if (verbose) clog << "Username = " << msg.username.value << endl; 00326 } 00327 00328 break; 00329 00330 case Password: 00331 msg.hasPassword = true; 00332 if (stunParseAtrString( body, attrLen, msg.password) == false) 00333 { 00334 if (verbose) clog << "problem parsing Password" << endl; 00335 return false; 00336 } 00337 else 00338 { 00339 if (verbose) clog << "Password = " << msg.password.value << endl; 00340 } 00341 break; 00342 00343 case MessageIntegrity: 00344 msg.hasMessageIntegrity = true; 00345 if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false) 00346 { 00347 if (verbose) clog << "problem parsing MessageIntegrity" << endl; 00348 return false; 00349 } 00350 else 00351 { 00352 if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl; 00353 } 00354 00355 // read the current HMAC 00356 // look up the password given the user of given the transaction id 00357 // compute the HMAC on the buffer 00358 // decide if they match or not 00359 break; 00360 00361 case ErrorCode: 00362 msg.hasErrorCode = true; 00363 if (stunParseAtrError(body, attrLen, msg.errorCode) == false) 00364 { 00365 if (verbose) clog << "problem parsing ErrorCode" << endl; 00366 return false; 00367 } 00368 else 00369 { 00370 if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass) 00371 << " " << int(msg.errorCode.number) 00372 << " " << msg.errorCode.reason << endl; 00373 } 00374 00375 break; 00376 00377 case UnknownAttribute: 00378 msg.hasUnknownAttributes = true; 00379 if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false) 00380 { 00381 if (verbose) clog << "problem parsing UnknownAttribute" << endl; 00382 return false; 00383 } 00384 break; 00385 00386 case ReflectedFrom: 00387 msg.hasReflectedFrom = true; 00388 if ( stunParseAtrAddress( body, attrLen, msg.reflectedFrom ) == false ) 00389 { 00390 if (verbose) clog << "problem parsing ReflectedFrom" << endl; 00391 return false; 00392 } 00393 break; 00394 00395 case XorMappedAddress: 00396 msg.hasXorMappedAddress = true; 00397 if ( stunParseAtrAddress( body, attrLen, msg.xorMappedAddress ) == false ) 00398 { 00399 if (verbose) clog << "problem parsing XorMappedAddress" << endl; 00400 return false; 00401 } 00402 else 00403 { 00404 if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl; 00405 } 00406 break; 00407 00408 case XorOnly: 00409 msg.xorOnly = true; 00410 if (verbose) 00411 { 00412 if (verbose) clog << "xorOnly = true" << endl; 00413 } 00414 break; 00415 00416 case ServerName: 00417 msg.hasServerName = true; 00418 if (stunParseAtrString( body, attrLen, msg.serverName) == false) 00419 { 00420 if (verbose) clog << "problem parsing ServerName" << endl; 00421 return false; 00422 } 00423 else 00424 { 00425 if (verbose) clog << "ServerName = " << msg.serverName.value << endl; 00426 } 00427 break; 00428 00429 case SecondaryAddress: 00430 msg.hasSecondaryAddress = true; 00431 if ( stunParseAtrAddress( body, attrLen, msg.secondaryAddress ) == false ) 00432 { 00433 if (verbose) clog << "problem parsing secondaryAddress" << endl; 00434 return false; 00435 } 00436 else 00437 { 00438 if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl; 00439 } 00440 break; 00441 00442 // TURN attributes 00443 00444 case TurnLifetime: 00445 msg.hasTurnLifetime = true; 00446 if (stunParseUInt32( body, attrLen, msg.turnLifetime) == false) 00447 { 00448 return false; 00449 } 00450 break; 00451 00452 case TurnAlternateServer: 00453 msg.hasTurnAlternateServer = true; 00454 if ( stunParseAtrAddress( body, attrLen, msg.turnAlternateServer ) == false ) 00455 { 00456 return false; 00457 } 00458 break; 00459 00460 case TurnMagicCookie: 00461 msg.hasTurnMagicCookie = true; 00462 if (stunParseUInt32( body, attrLen, msg.turnMagicCookie) == false) 00463 { 00464 return false; 00465 } 00466 break; 00467 00468 case TurnBandwidth: 00469 msg.hasTurnBandwidth = true; 00470 if (stunParseUInt32( body, attrLen, msg.turnBandwidth) == false) 00471 { 00472 return false; 00473 } 00474 break; 00475 00476 case TurnDestinationAddress: 00477 msg.hasTurnDestinationAddress = true; 00478 if ( stunParseAtrAddress( body, attrLen, msg.turnDestinationAddress ) == false ) 00479 { 00480 return false; 00481 } 00482 break; 00483 00484 case TurnRemoteAddress: 00485 msg.hasTurnRemoteAddress = true; 00486 if ( stunParseAtrAddress( body, attrLen, msg.turnRemoteAddress ) == false ) 00487 { 00488 return false; 00489 } 00490 break; 00491 00492 //overlay on parse, ownership is buffer parsed from 00493 case TurnData: 00494 msg.hasTurnData = true; 00495 msg.turnData = new resip::Data(resip::Data::Share, body, attrLen); 00496 break; 00497 00498 //case TurnNonce: 00499 //break; 00500 //case TurnRealm: 00501 //break; 00502 00503 default: 00504 if (verbose) clog << "Unknown attribute: " << atrType << endl; 00505 if ( atrType <= 0x7FFF ) 00506 { 00507 return false; 00508 } 00509 } 00510 00511 body += attrLen; 00512 size -= attrLen; 00513 } 00514 00515 return true; 00516 } 00517 00518 static char* 00519 encode16(char* buf, UInt16 data) 00520 { 00521 UInt16 ndata = htons(data); 00522 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16)); 00523 return buf + sizeof(UInt16); 00524 } 00525 00526 static char* 00527 encode32(char* buf, UInt32 data) 00528 { 00529 UInt32 ndata = htonl(data); 00530 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt32)); 00531 return buf + sizeof(UInt32); 00532 } 00533 00534 00535 static char* 00536 encode(char* buf, const char* data, unsigned int length) 00537 { 00538 memcpy(buf, data, length); 00539 return buf + length; 00540 } 00541 00542 static char* 00543 encodeTurnData(char *ptr, const resip::Data* td) 00544 { 00545 ptr = encode16(ptr, TurnData); 00546 ptr = encode16(ptr, (UInt16)td->size()); 00547 memcpy(ptr, td->data(), td->size()); 00548 ptr += td->size(); 00549 00550 return ptr; 00551 } 00552 00553 static char* 00554 encodeAtrUInt32(char* ptr, UInt16 type, UInt32 value) 00555 { 00556 ptr = encode16(ptr, type); 00557 ptr = encode16(ptr, 4); 00558 ptr = encode32(ptr, value); 00559 return ptr; 00560 } 00561 00562 static char* 00563 encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4& atr) 00564 { 00565 ptr = encode16(ptr, type); 00566 ptr = encode16(ptr, 8); 00567 *ptr++ = atr.pad; 00568 *ptr++ = IPv4Family; 00569 ptr = encode16(ptr, atr.ipv4.port); 00570 ptr = encode32(ptr, atr.ipv4.addr); 00571 00572 return ptr; 00573 } 00574 00575 static char* 00576 encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest& atr) 00577 { 00578 ptr = encode16(ptr, ChangeRequest); 00579 ptr = encode16(ptr, 4); 00580 ptr = encode32(ptr, atr.value); 00581 return ptr; 00582 } 00583 00584 static char* 00585 encodeMagicCookie(char* ptr, const UInt32& cookie) 00586 { 00587 ptr = encode16(ptr, TurnMagicCookie); 00588 ptr = encode16(ptr, 4); 00589 ptr = encode32(ptr, cookie); 00590 return ptr; 00591 } 00592 00593 00594 static char* 00595 encodeAtrError(char* ptr, const StunAtrError& atr) 00596 { 00597 ptr = encode16(ptr, ErrorCode); 00598 ptr = encode16(ptr, 4 + atr.sizeReason); 00599 ptr = encode16(ptr, atr.pad); 00600 *ptr++ = atr.errorClass; 00601 *ptr++ = atr.number; 00602 ptr = encode(ptr, atr.reason, atr.sizeReason); 00603 return ptr; 00604 } 00605 00606 00607 static char* 00608 encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr) 00609 { 00610 ptr = encode16(ptr, UnknownAttribute); 00611 ptr = encode16(ptr, 2+2*atr.numAttributes); 00612 for (int i=0; i<atr.numAttributes; i++) 00613 { 00614 ptr = encode16(ptr, atr.attrType[i]); 00615 } 00616 return ptr; 00617 } 00618 00619 00620 static char* 00621 encodeXorOnly(char* ptr) 00622 { 00623 ptr = encode16(ptr, XorOnly ); 00624 return ptr; 00625 } 00626 00627 00628 static char* 00629 encodeAtrString(char* ptr, UInt16 type, const StunAtrString& atr) 00630 { 00631 assert(atr.sizeValue % 4 == 0); 00632 00633 ptr = encode16(ptr, type); 00634 ptr = encode16(ptr, atr.sizeValue); 00635 ptr = encode(ptr, atr.value, atr.sizeValue); 00636 return ptr; 00637 } 00638 00639 00640 static char* 00641 encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr) 00642 { 00643 ptr = encode16(ptr, MessageIntegrity); 00644 ptr = encode16(ptr, 20); 00645 ptr = encode(ptr, atr.hash, sizeof(atr.hash)); 00646 return ptr; 00647 } 00648 00649 00650 unsigned int 00651 stunEncodeMessage( const StunMessage& msg, 00652 char* buf, 00653 unsigned int bufLen, 00654 const StunAtrString& password, 00655 bool verbose) 00656 { 00657 assert(bufLen >= sizeof(StunMsgHdr)); 00658 char* ptr = buf; 00659 00660 if (verbose) clog << "Encoding stun message: " << endl; 00661 00662 ptr = encode16(ptr, msg.msgHdr.msgType); 00663 char* lengthp = ptr; 00664 ptr = encode16(ptr, 0); 00665 ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id)); 00666 00667 if (msg.hasTurnMagicCookie) 00668 { 00669 if (verbose) clog << "Encoding TurnMagicCookie: " << msg.turnMagicCookie << endl; 00670 ptr = encodeMagicCookie(ptr, msg.turnMagicCookie); 00671 } 00672 if (msg.hasTurnDestinationAddress) 00673 { 00674 if (verbose) clog << "Encoding TurnDestinationAddress: " << msg.turnDestinationAddress.ipv4 << endl; 00675 ptr = encodeAtrAddress4 (ptr, TurnDestinationAddress, msg.turnDestinationAddress); 00676 } 00677 if (msg.hasMappedAddress) 00678 { 00679 if (verbose) clog << "Encoding MappedAddress: " << msg.mappedAddress.ipv4 << endl; 00680 ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress); 00681 } 00682 if (msg.hasResponseAddress) 00683 { 00684 if (verbose) clog << "Encoding ResponseAddress: " << msg.responseAddress.ipv4 << endl; 00685 ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress); 00686 } 00687 if (msg.hasTurnAlternateServer ) 00688 { 00689 if (verbose) clog << "Encoding AlternateServer: " << msg.turnAlternateServer.ipv4 << endl; 00690 ptr = encodeAtrAddress4 (ptr, TurnAlternateServer, msg.turnAlternateServer); 00691 } 00692 if (msg.hasChangeRequest) 00693 { 00694 if (verbose) clog << "Encoding ChangeRequest: " << msg.changeRequest.value << endl; 00695 ptr = encodeAtrChangeRequest(ptr, msg.changeRequest); 00696 } 00697 if (msg.hasSourceAddress) 00698 { 00699 if (verbose) clog << "Encoding SourceAddress: " << msg.sourceAddress.ipv4 << endl; 00700 ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress); 00701 } 00702 if (msg.hasChangedAddress) 00703 { 00704 if (verbose) clog << "Encoding ChangedAddress: " << msg.changedAddress.ipv4 << endl; 00705 ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress); 00706 } 00707 if (msg.hasUsername) 00708 { 00709 if (verbose) clog << "Encoding Username: " << msg.username.value << endl; 00710 ptr = encodeAtrString(ptr, Username, msg.username); 00711 } 00712 if (msg.hasPassword) 00713 { 00714 if (verbose) clog << "Encoding Password: " << msg.password.value << endl; 00715 ptr = encodeAtrString(ptr, Password, msg.password); 00716 } 00717 if (msg.hasErrorCode) 00718 { 00719 if (verbose) clog << "Encoding ErrorCode: class=" 00720 << int(msg.errorCode.errorClass) 00721 << " number=" << int(msg.errorCode.number) 00722 << " reason=" 00723 << msg.errorCode.reason 00724 << endl; 00725 00726 ptr = encodeAtrError(ptr, msg.errorCode); 00727 } 00728 if (msg.hasUnknownAttributes) 00729 { 00730 if (verbose) clog << "Encoding UnknownAttribute: ???" << endl; 00731 ptr = encodeAtrUnknown(ptr, msg.unknownAttributes); 00732 } 00733 if (msg.hasReflectedFrom) 00734 { 00735 if (verbose) clog << "Encoding ReflectedFrom: " << msg.reflectedFrom.ipv4 << endl; 00736 ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom); 00737 } 00738 if (msg.hasXorMappedAddress) 00739 { 00740 if (verbose) clog << "Encoding XorMappedAddress: " << msg.xorMappedAddress.ipv4 << endl; 00741 ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress); 00742 } 00743 if (msg.xorOnly) 00744 { 00745 if (verbose) clog << "Encoding xorOnly: " << endl; 00746 ptr = encodeXorOnly( ptr ); 00747 } 00748 if (msg.hasServerName) 00749 { 00750 if (verbose) clog << "Encoding ServerName: " << msg.serverName.value << endl; 00751 ptr = encodeAtrString(ptr, ServerName, msg.serverName); 00752 } 00753 if (msg.hasSecondaryAddress) 00754 { 00755 if (verbose) clog << "Encoding SecondaryAddress: " << msg.secondaryAddress.ipv4 << endl; 00756 ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress); 00757 } 00758 if (msg.hasTurnLifetime) 00759 { 00760 if (verbose) clog << "Encoding Turn Lifetime: " << msg.turnLifetime << endl; 00761 ptr = encodeAtrUInt32(ptr, TurnLifetime, msg.turnLifetime); 00762 } 00763 if (msg.hasTurnBandwidth) 00764 { 00765 if (verbose) clog << "Encoding Turn Bandwidth: " << msg.turnBandwidth << endl; 00766 ptr = encodeAtrUInt32(ptr, TurnBandwidth, msg.turnBandwidth); 00767 } 00768 if (msg.hasTurnData) 00769 { 00770 if (verbose) clog << "Encoding TurnData (not shown)" << endl; 00771 ptr = encodeTurnData (ptr, msg.turnData); 00772 } 00773 if (password.sizeValue > 0) 00774 { 00775 if (verbose) clog << "HMAC with password: " << password.value << endl; 00776 00777 // allocate space for message integrity attribute (hash + attribute type + size) 00778 char* ptrMessageIntegrity = ptr; 00779 ptr += 20 + sizeof(MessageIntegrity) + sizeof(UInt16); 00780 encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr))); 00781 00782 StunAtrIntegrity integrity; 00783 // pad with zeros prior to calculating message integrity attribute 00784 int padding = 0; 00785 int len = int(ptrMessageIntegrity - buf); 00786 if (len % 64) 00787 { 00788 padding = 64 - (len % 64); 00789 memset(ptrMessageIntegrity, 0, padding); 00790 } 00791 computeHmac(integrity.hash, buf, len + padding, password.value, password.sizeValue); 00792 encodeAtrIntegrity(ptrMessageIntegrity, integrity); 00793 } 00794 00795 if (verbose) clog << endl; 00796 encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr))); 00797 return int(ptr - buf); 00798 } 00799 00800 int 00801 stunRand() 00802 { 00803 // return 32 bits of random stuff 00804 assert( sizeof(int) == 4 ); 00805 static bool init=false; 00806 if ( !init ) 00807 { 00808 init = true; 00809 00810 UInt64 tick; 00811 00812 #if defined(WIN32) 00813 #if !defined(UNDER_CE) && !defined(__GNUC__) && !defined(_WIN64) 00814 volatile unsigned int lowtick=0,hightick=0; 00815 __asm 00816 { 00817 rdtsc 00818 mov lowtick, eax 00819 mov hightick, edx 00820 } 00821 tick = hightick; 00822 tick <<= 32; 00823 tick |= lowtick; 00824 #else 00825 tick = GetTickCount(); 00826 #endif 00827 #elif defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) || defined(__x86_64__) ) 00828 asm("rdtsc" : "=A" (tick)); 00829 #elif defined (__SUNPRO_CC) || defined( __sparc__ ) 00830 tick = gethrtime(); 00831 #elif defined(__APPLE__) || defined(__MACH__) 00832 int fd=open("/dev/random",O_RDONLY); 00833 read(fd,&tick,sizeof(tick)); 00834 closeSocket(fd); 00835 #elif defined(__linux__) 00836 int fd=open("/dev/urandom",O_RDONLY); 00837 read(fd,&tick,sizeof(tick)); 00838 closeSocket(fd); 00839 #else 00840 # error Need some way to seed the random number generator 00841 #endif 00842 int seed = int(tick); 00843 #ifdef WIN32 00844 srand(seed); 00845 #else 00846 srandom(seed); 00847 #endif 00848 } 00849 00850 #ifdef WIN32 00851 assert( RAND_MAX == 0x7fff ); 00852 int r1 = rand(); 00853 int r2 = rand(); 00854 00855 int ret = (r1<<16) + r2; 00856 00857 return ret; 00858 #else 00859 return random(); 00860 #endif 00861 } 00862 00863 00865 int 00866 stunRandomPort() 00867 { 00868 int min=0x4000; 00869 int max=0x7FFF; 00870 00871 int ret = stunRand(); 00872 ret = ret|min; 00873 ret = ret&max; 00874 00875 return ret; 00876 } 00877 00878 00879 #ifndef USE_SSL 00880 void 00881 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey) 00882 { 00883 strncpy(hmac,"hmac-not-implemented",20); 00884 } 00885 #else 00886 #ifdef WIN32 00887 //hack for name collision of OCSP_RESPONSE and wincrypt.h in latest openssl release 0.9.8h 00888 //http://www.google.com/search?q=OCSP%5fRESPONSE+wincrypt%2eh 00889 //continue to watch this issue for a real fix. 00890 #undef OCSP_RESPONSE 00891 #endif 00892 #include <openssl/hmac.h> 00893 00894 void 00895 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey) 00896 { 00897 unsigned int resultSize=0; 00898 HMAC(EVP_sha1(), 00899 key, sizeKey, 00900 reinterpret_cast<const unsigned char*>(input), length, 00901 reinterpret_cast<unsigned char*>(hmac), &resultSize); 00902 assert(resultSize == 20); 00903 } 00904 #endif 00905 00906 00907 static void 00908 toHex(const char* buffer, int bufferSize, char* output) 00909 { 00910 static char hexmap[] = "0123456789abcdef"; 00911 00912 const char* p = buffer; 00913 char* r = output; 00914 for (int i=0; i < bufferSize; i++) 00915 { 00916 unsigned char temp = *p++; 00917 00918 int hi = (temp & 0xf0)>>4; 00919 int low = (temp & 0xf); 00920 00921 *r++ = hexmap[hi]; 00922 *r++ = hexmap[low]; 00923 } 00924 *r = 0; 00925 } 00926 00927 void 00928 stunCreateUserName(const StunAddress4& source, StunAtrString* username) 00929 { 00930 UInt64 time = stunGetSystemTimeSecs(); 00931 time -= (time % 20*60); 00932 //UInt64 hitime = time >> 32; 00933 UInt64 lotime = time & 0xFFFFFFFF; 00934 00935 char buffer[1024]; 00936 sprintf(buffer, 00937 "%08x:%08x:%08x:", 00938 UInt32(source.addr), 00939 UInt32(stunRand()), 00940 UInt32(lotime)); 00941 assert( strlen(buffer) < 1024 ); 00942 00943 assert(strlen(buffer) + 41 < STUN_MAX_STRING); 00944 00945 char hmac[20]; 00946 char key[] = "Jason"; 00947 computeHmac(hmac, buffer, (int)strlen(buffer), key, (int)strlen(key) ); 00948 char hmacHex[41]; 00949 toHex(hmac, 20, hmacHex ); 00950 hmacHex[40] =0; 00951 00952 strcat(buffer,hmacHex); 00953 00954 int l = (int)strlen(buffer); 00955 assert( l+1 < STUN_MAX_STRING ); 00956 assert( l%4 == 0 ); 00957 00958 username->sizeValue = l; 00959 memcpy(username->value,buffer,l); 00960 username->value[l]=0; 00961 00962 //if (verbose) clog << "computed username=" << username.value << endl; 00963 } 00964 00965 void 00966 stunCreatePassword(const StunAtrString& username, StunAtrString* password) 00967 { 00968 char hmac[20]; 00969 char key[] = "Fluffy"; 00970 //char buffer[STUN_MAX_STRING]; 00971 computeHmac(hmac, username.value, (int)strlen(username.value), key, (int)strlen(key)); 00972 toHex(hmac, 20, password->value); 00973 password->sizeValue = 40; 00974 password->value[40]=0; 00975 00976 //clog << "password=" << password->value << endl; 00977 } 00978 00979 00980 UInt64 00981 stunGetSystemTimeSecs() 00982 { 00983 UInt64 time=0; 00984 #if defined(WIN32) 00985 SYSTEMTIME t; 00986 // CJ TODO - this probably has bug on wrap around every 24 hours 00987 GetSystemTime( &t ); 00988 time = (t.wHour*60+t.wMinute)*60+t.wSecond; 00989 #else 00990 struct timeval now; 00991 gettimeofday( &now , NULL ); 00992 //assert( now ); 00993 time = now.tv_sec; 00994 #endif 00995 return time; 00996 } 00997 00998 00999 ostream& operator<< ( ostream& strm, const UInt128& r ) 01000 { 01001 strm << int(r.octet[0]); 01002 for ( int i=1; i<16; i++ ) 01003 { 01004 strm << ':' << int(r.octet[i]); 01005 } 01006 01007 return strm; 01008 } 01009 01010 ostream& 01011 operator<<( ostream& strm, const StunAddress4& addr) 01012 { 01013 UInt32 ip = addr.addr; 01014 strm << ((int)(ip>>24)&0xFF) << "."; 01015 strm << ((int)(ip>>16)&0xFF) << "."; 01016 strm << ((int)(ip>> 8)&0xFF) << "."; 01017 strm << ((int)(ip>> 0)&0xFF) ; 01018 01019 strm << ":" << addr.port; 01020 01021 return strm; 01022 } 01023 01024 ostream& 01025 operator<<(ostream& os, const StunMsgHdr& h) 01026 { 01027 os << "STUN: "; 01028 switch (h.msgType) { 01029 case BindRequestMsg: 01030 os << "BindingRequest"; 01031 break; 01032 case BindResponseMsg: 01033 os << "BindingResponse"; 01034 break; 01035 case BindErrorResponseMsg: 01036 os << "BindingErrorResponse"; 01037 break; 01038 case TurnAllocateRequest: 01039 os << "TurnAllocateRequest"; 01040 break; 01041 case TurnAllocateResponse: 01042 os << "TurnAllocateResponse"; 01043 break; 01044 case TurnAllocateErrorResponse: 01045 os << "TurnAllocateErrorResponse"; 01046 break; 01047 case TurnSendRequest: 01048 os << "TurnSendRequest"; 01049 break; 01050 case TurnSendResponse: 01051 os << "TurnSendResponse"; 01052 break; 01053 case TurnSendErrorResponse: 01054 os << "TurnSendErrorResponse"; 01055 break; 01056 case TurnDataIndication: 01057 os << "TurnDataIndication"; 01058 break; 01059 case TurnSetActiveDestinationRequest: 01060 os << "TurnSetActiveDestinationRequest"; 01061 break; 01062 case TurnSetActiveDestinationResponse: 01063 os << "TurnSetActiveDestinationResponse"; 01064 break; 01065 case TurnSetActiveDestinationErrorResponse: 01066 os << "TurnSetActiveDestinationErrorResponse"; 01067 break; 01068 } 01069 01070 os << ", id "; 01071 01072 os << std::hex; 01073 for (unsigned int i = 0; i < sizeof(UInt128); i++) { 01074 os << static_cast<int>(h.id.octet[i]); 01075 } 01076 os << std::dec; 01077 01078 return os; 01079 } 01080 01081 01082 // returns true if it scucceeded 01083 bool 01084 stunParseHostName( char* peerName, 01085 UInt32& ip, 01086 UInt16& portVal, 01087 UInt16 defaultPort ) 01088 { 01089 in_addr sin_addr; 01090 01091 char host[512]; 01092 strncpy(host,peerName,512); 01093 host[512-1]='\0'; 01094 char* port = NULL; 01095 01096 int portNum = defaultPort; 01097 01098 // pull out the port part if present. 01099 char* sep = strchr(host,':'); 01100 01101 if ( sep == NULL ) 01102 { 01103 portNum = defaultPort; 01104 } 01105 else 01106 { 01107 *sep = '\0'; 01108 port = sep + 1; 01109 // set port part 01110 01111 char* endPtr=NULL; 01112 01113 portNum = strtol(port,&endPtr,10); 01114 01115 if ( endPtr != NULL ) 01116 { 01117 if ( *endPtr != '\0' ) 01118 { 01119 portNum = defaultPort; 01120 } 01121 } 01122 } 01123 01124 if ( portNum < 1024 ) return false; 01125 if ( portNum >= 0xFFFF ) return false; 01126 01127 // figure out the host part 01128 struct hostent* h; 01129 01130 #ifdef WIN32 01131 assert( strlen(host) >= 1 ); 01132 if ( isdigit( host[0] ) ) 01133 { 01134 // assume it is a ip address 01135 unsigned long a = inet_addr(host); 01136 //cerr << "a=0x" << hex << a << dec << endl; 01137 01138 ip = ntohl( a ); 01139 } 01140 else 01141 { 01142 // assume it is a host name 01143 h = gethostbyname( host ); 01144 01145 if ( h == NULL ) 01146 { 01147 int err = getErrno(); 01148 std::cerr << "error was " << err << std::endl; 01149 assert( err != WSANOTINITIALISED ); 01150 01151 ip = ntohl( 0x7F000001L ); 01152 01153 return false; 01154 } 01155 else 01156 { 01157 sin_addr = *(struct in_addr*)h->h_addr; 01158 ip = ntohl( sin_addr.s_addr ); 01159 } 01160 } 01161 01162 #else 01163 h = gethostbyname( host ); 01164 if ( h == NULL ) 01165 { 01166 int err = getErrno(); 01167 std::cerr << "error was " << err << std::endl; 01168 ip = ntohl( 0x7F000001L ); 01169 return false; 01170 } 01171 else 01172 { 01173 sin_addr = *(struct in_addr*)h->h_addr; 01174 ip = ntohl( sin_addr.s_addr ); 01175 } 01176 #endif 01177 01178 portVal = portNum; 01179 01180 return true; 01181 } 01182 01183 01184 bool 01185 stunParseServerName( char* name, StunAddress4& addr) 01186 { 01187 assert(name); 01188 01189 // TODO - put in DNS SRV stuff. 01190 01191 bool ret = stunParseHostName( name, addr.addr, addr.port, 3478); 01192 if ( ret != true ) 01193 { 01194 addr.port=0xFFFF; 01195 } 01196 return ret; 01197 } 01198 01199 static void 01200 stunCreateErrorResponse(StunMessage& response, int cl, int number, const char* msg) 01201 { 01202 response.msgHdr.msgType = BindErrorResponseMsg; 01203 response.hasErrorCode = true; 01204 response.errorCode.errorClass = cl; 01205 response.errorCode.number = number; 01206 strcpy(response.errorCode.reason, msg); 01207 response.errorCode.sizeReason = (UInt16)strlen(msg); 01208 } 01209 01210 #if 0 01211 static void 01212 stunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg) 01213 { 01214 response.msgHdr.msgType = SharedSecretErrorResponseMsg; 01215 response.hasErrorCode = true; 01216 response.errorCode.errorClass = cl; 01217 response.errorCode.number = number; 01218 strcpy(response.errorCode.reason, msg); 01219 } 01220 #endif 01221 01222 static void 01223 stunCreateSharedSecretResponse(const StunMessage& request, const StunAddress4& source, StunMessage& response) 01224 { 01225 response.msgHdr.msgType = SharedSecretResponseMsg; 01226 response.msgHdr.id = request.msgHdr.id; 01227 01228 response.hasUsername = true; 01229 stunCreateUserName( source, &response.username); 01230 01231 response.hasPassword = true; 01232 stunCreatePassword( response.username, &response.password); 01233 } 01234 01235 01236 // This funtion takes a single message sent to a stun server, parses 01237 // and constructs an apropriate repsonse - returns true if message is 01238 // valid 01239 bool 01240 stunServerProcessMsg( char* buf, 01241 unsigned int bufLen, 01242 StunAddress4& from, 01243 StunAddress4& secondary, 01244 StunAddress4& myAddr, 01245 StunAddress4& altAddr, 01246 StunMessage* resp, 01247 StunAddress4* destination, 01248 StunAtrString* hmacPassword, 01249 bool* changePort, 01250 bool* changeIp, 01251 bool verbose) 01252 { 01253 01254 // set up information for default response 01255 01256 memset( resp, 0 , sizeof(*resp) ); 01257 01258 *changeIp = false; 01259 *changePort = false; 01260 01261 StunMessage req; 01262 bool ok = stunParseMessage( buf,bufLen, req, verbose); 01263 01264 if (!ok) // Complete garbage, drop it on the floor 01265 { 01266 if (verbose) clog << "Request did not parse" << endl; 01267 return false; 01268 } 01269 if (verbose) clog << "Request parsed ok" << endl; 01270 01271 StunAddress4 mapped = req.mappedAddress.ipv4; 01272 StunAddress4 respondTo = req.responseAddress.ipv4; 01273 UInt32 flags = req.changeRequest.value; 01274 01275 switch (req.msgHdr.msgType) 01276 { 01277 case SharedSecretRequestMsg: 01278 if(verbose) clog << "Received SharedSecretRequestMsg on udp. send error 433." << endl; 01279 // !cj! - should fix so you know if this came over TLS or UDP 01280 stunCreateSharedSecretResponse(req, from, *resp); 01281 //stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS"); 01282 return true; 01283 01284 case BindRequestMsg: 01285 if (!req.hasMessageIntegrity) 01286 { 01287 if (verbose) clog << "BindRequest does not contain MessageIntegrity" << endl; 01288 01289 if (0) // !jf! mustAuthenticate 01290 { 01291 if(verbose) clog << "Received BindRequest with no MessageIntegrity. Sending 401." << endl; 01292 stunCreateErrorResponse(*resp, 4, 1, "Missing MessageIntegrity"); 01293 return true; 01294 } 01295 } 01296 else 01297 { 01298 if (!req.hasUsername) 01299 { 01300 if (verbose) clog << "No UserName. Send 432." << endl; 01301 stunCreateErrorResponse(*resp, 4, 32, "No UserName and contains MessageIntegrity"); 01302 return true; 01303 } 01304 else 01305 { 01306 if (verbose) clog << "Validating username: " << req.username.value << endl; 01307 // !jf! could retrieve associated password from provisioning here 01308 if (strcmp(req.username.value, "test") == 0) 01309 { 01310 if (0) 01311 { 01312 // !jf! if the credentials are stale 01313 stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest"); 01314 return true; 01315 } 01316 else 01317 { 01318 if (verbose) clog << "Validating MessageIntegrity" << endl; 01319 // need access to shared secret 01320 01321 unsigned char hmac[20]; 01322 #ifdef USE_SSL 01323 unsigned int hmacSize=20; 01324 01325 HMAC(EVP_sha1(), 01326 "1234", 4, 01327 reinterpret_cast<const unsigned char*>(buf), bufLen-20-4, 01328 hmac, &hmacSize); 01329 assert(hmacSize == 20); 01330 #endif 01331 01332 if (memcmp(buf, hmac, 20) != 0) 01333 { 01334 if (verbose) clog << "MessageIntegrity is bad. Sending " << endl; 01335 stunCreateErrorResponse(*resp, 4, 3, "Unknown username. Try test with password 1234"); 01336 return true; 01337 } 01338 01339 // need to compute this later after message is filled in 01340 resp->hasMessageIntegrity = true; 01341 assert(req.hasUsername); 01342 resp->hasUsername = true; 01343 resp->username = req.username; // copy username in 01344 } 01345 } 01346 else 01347 { 01348 if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl; 01349 } 01350 } 01351 } 01352 01353 // TODO !jf! should check for unknown attributes here and send 420 listing the 01354 // unknown attributes. 01355 01356 if ( respondTo.port == 0 ) respondTo = from; 01357 if ( mapped.port == 0 ) mapped = from; 01358 01359 *changeIp = ( flags & ChangeIpFlag )?true:false; 01360 *changePort = ( flags & ChangePortFlag )?true:false; 01361 01362 if (verbose) 01363 { 01364 clog << "Request is valid:" << endl; 01365 clog << "\t flags=" << flags << endl; 01366 clog << "\t changeIp=" << *changeIp << endl; 01367 clog << "\t changePort=" << *changePort << endl; 01368 clog << "\t from = " << from << endl; 01369 clog << "\t respond to = " << respondTo << endl; 01370 clog << "\t mapped = " << mapped << endl; 01371 } 01372 01373 // form the outgoing message 01374 resp->msgHdr.msgType = BindResponseMsg; 01375 for ( int i=0; i<16; i++ ) 01376 { 01377 resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i]; 01378 } 01379 01380 if ( req.xorOnly == false ) 01381 { 01382 resp->hasMappedAddress = true; 01383 resp->mappedAddress.ipv4.port = mapped.port; 01384 resp->mappedAddress.ipv4.addr = mapped.addr; 01385 } 01386 01387 if (1) // do xorMapped address or not 01388 { 01389 resp->hasXorMappedAddress = true; 01390 UInt16 id16 = req.msgHdr.id.octet[0]<<8 01391 | req.msgHdr.id.octet[1]; 01392 UInt32 id32 = req.msgHdr.id.octet[0]<<24 01393 | req.msgHdr.id.octet[1]<<16 01394 | req.msgHdr.id.octet[2]<<8 01395 | req.msgHdr.id.octet[3]; 01396 resp->xorMappedAddress.ipv4.port = mapped.port^id16; 01397 resp->xorMappedAddress.ipv4.addr = mapped.addr^id32; 01398 } 01399 01400 resp->hasSourceAddress = true; 01401 resp->sourceAddress.ipv4.port = (*changePort) ? altAddr.port : myAddr.port; 01402 resp->sourceAddress.ipv4.addr = (*changeIp) ? altAddr.addr : myAddr.addr; 01403 01404 resp->hasChangedAddress = true; 01405 resp->changedAddress.ipv4.port = altAddr.port; 01406 resp->changedAddress.ipv4.addr = altAddr.addr; 01407 01408 if ( secondary.port != 0 ) 01409 { 01410 resp->hasSecondaryAddress = true; 01411 resp->secondaryAddress.ipv4.port = secondary.port; 01412 resp->secondaryAddress.ipv4.addr = secondary.addr; 01413 } 01414 01415 if ( req.hasUsername && req.username.sizeValue > 0 ) 01416 { 01417 // copy username in 01418 resp->hasUsername = true; 01419 assert( req.username.sizeValue % 4 == 0 ); 01420 assert( req.username.sizeValue < STUN_MAX_STRING ); 01421 memcpy( resp->username.value, req.username.value, req.username.sizeValue ); 01422 resp->username.sizeValue = req.username.sizeValue; 01423 } 01424 01425 if (1) // add ServerName 01426 { 01427 resp->hasServerName = true; 01428 const char serverName[] = "Vovida.org " STUN_VERSION; // must pad to mult of 4 01429 01430 assert( sizeof(serverName) < STUN_MAX_STRING ); 01431 //cerr << "sizeof serverName is " << sizeof(serverName) << endl; 01432 assert( sizeof(serverName)%4 == 0 ); 01433 memcpy( resp->serverName.value, serverName, sizeof(serverName)); 01434 resp->serverName.sizeValue = sizeof(serverName); 01435 } 01436 01437 if ( req.hasMessageIntegrity & req.hasUsername ) 01438 { 01439 // this creates the password that will be used in the HMAC when then 01440 // messages is sent 01441 stunCreatePassword( req.username, hmacPassword ); 01442 } 01443 01444 if (req.hasUsername && (req.username.sizeValue > 64 ) ) 01445 { 01446 UInt32 source; 01447 assert( sizeof(int) == sizeof(UInt32) ); 01448 01449 sscanf(req.username.value, "%x", &source); 01450 resp->hasReflectedFrom = true; 01451 resp->reflectedFrom.ipv4.port = 0; 01452 resp->reflectedFrom.ipv4.addr = source; 01453 } 01454 01455 destination->port = respondTo.port; 01456 destination->addr = respondTo.addr; 01457 01458 return true; 01459 01460 default: 01461 if (verbose) clog << "Unknown or unsupported request " << endl; 01462 return false; 01463 } 01464 01465 assert(0); 01466 return false; 01467 } 01468 01469 bool 01470 stunInitServer(StunServerInfo& info, const StunAddress4& myAddr, 01471 const StunAddress4& altAddr, int startMediaPort, bool verbose ) 01472 { 01473 assert( myAddr.port != 0 ); 01474 assert( altAddr.port!= 0 ); 01475 assert( myAddr.addr != 0 ); 01476 //assert( altAddr.addr != 0 ); 01477 01478 info.myAddr = myAddr; 01479 info.altAddr = altAddr; 01480 01481 info.myFd = INVALID_SOCKET; 01482 info.altPortFd = INVALID_SOCKET; 01483 info.altIpFd = INVALID_SOCKET; 01484 info.altIpPortFd = INVALID_SOCKET; 01485 01486 memset(info.relays, 0, sizeof(info.relays)); 01487 if (startMediaPort > 0) 01488 { 01489 info.relay = true; 01490 01491 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01492 { 01493 StunMediaRelay* relay = &info.relays[i]; 01494 relay->relayPort = startMediaPort+i; 01495 relay->fd = 0; 01496 relay->expireTime = 0; 01497 } 01498 } 01499 else 01500 { 01501 info.relay = false; 01502 } 01503 01504 if ((info.myFd = openPort(myAddr.port, myAddr.addr,verbose)) == INVALID_SOCKET) 01505 { 01506 if (verbose) clog << "Can't open " << myAddr << endl; 01507 stunStopServer(info); 01508 01509 return false; 01510 } 01511 //if (verbose) clog << "Opened " << myAddr.addr << ":" << myAddr.port << " --> " << info.myFd << endl; 01512 01513 if ((info.altPortFd = openPort(altAddr.port,myAddr.addr,verbose)) == INVALID_SOCKET) 01514 { 01515 if (verbose) clog << "Can't open " << myAddr << endl; 01516 stunStopServer(info); 01517 return false; 01518 } 01519 //if (verbose) clog << "Opened " << myAddr.addr << ":" << altAddr.port << " --> " << info.altPortFd << endl; 01520 01521 01522 info.altIpFd = INVALID_SOCKET; 01523 if ( altAddr.addr != 0 ) 01524 { 01525 if ((info.altIpFd = openPort( myAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET) 01526 { 01527 if (verbose) clog << "Can't open " << altAddr << endl; 01528 stunStopServer(info); 01529 return false; 01530 } 01531 //if (verbose) clog << "Opened " << altAddr.addr << ":" << myAddr.port << " --> " << info.altIpFd << endl;; 01532 } 01533 01534 info.altIpPortFd = INVALID_SOCKET; 01535 if ( altAddr.addr != 0 ) 01536 { if ((info.altIpPortFd = openPort(altAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET) 01537 { 01538 if (verbose) clog << "Can't open " << altAddr << endl; 01539 stunStopServer(info); 01540 return false; 01541 } 01542 //if (verbose) clog << "Opened " << altAddr.addr << ":" << altAddr.port << " --> " << info.altIpPortFd << endl;; 01543 } 01544 01545 return true; 01546 } 01547 01548 void 01549 stunStopServer(StunServerInfo& info) 01550 { 01551 if (info.myFd > 0) closeSocket(info.myFd); 01552 if (info.altPortFd > 0) closeSocket(info.altPortFd); 01553 if (info.altIpFd > 0) closeSocket(info.altIpFd); 01554 if (info.altIpPortFd > 0) closeSocket(info.altIpPortFd); 01555 01556 if (info.relay) 01557 { 01558 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01559 { 01560 StunMediaRelay* relay = &info.relays[i]; 01561 if (relay->fd) 01562 { 01563 closeSocket(relay->fd); 01564 relay->fd = 0; 01565 } 01566 } 01567 } 01568 } 01569 01570 bool 01571 stunServerProcess(StunServerInfo& info, bool verbose) 01572 { 01573 char msg[STUN_MAX_MESSAGE_SIZE]; 01574 int msgLen = sizeof(msg); 01575 01576 bool ok = false; 01577 bool recvAltIp =false; 01578 bool recvAltPort = false; 01579 01580 fd_set fdSet; 01581 resip::Socket maxFd=0; 01582 01583 FD_ZERO(&fdSet); 01584 FD_SET(info.myFd,&fdSet); 01585 if ( info.myFd >= maxFd ) maxFd=info.myFd+1; 01586 FD_SET(info.altPortFd,&fdSet); 01587 if ( info.altPortFd >= maxFd ) maxFd=info.altPortFd+1; 01588 01589 if ( info.altIpFd != INVALID_SOCKET ) 01590 { 01591 FD_SET(info.altIpFd,&fdSet); 01592 if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1; 01593 } 01594 if ( info.altIpPortFd != INVALID_SOCKET ) 01595 { 01596 FD_SET(info.altIpPortFd,&fdSet); 01597 if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1; 01598 } 01599 01600 if (info.relay) 01601 { 01602 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01603 { 01604 StunMediaRelay* relay = &info.relays[i]; 01605 if (relay->fd) 01606 { 01607 FD_SET(relay->fd, &fdSet); 01608 if ((resip::Socket)relay->fd >= maxFd) 01609 { 01610 maxFd=relay->fd+1; 01611 } 01612 } 01613 } 01614 } 01615 01616 if ( info.altIpFd != INVALID_SOCKET ) 01617 { 01618 FD_SET(info.altIpFd,&fdSet); 01619 if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1; 01620 } 01621 if ( info.altIpPortFd != INVALID_SOCKET ) 01622 { 01623 FD_SET(info.altIpPortFd,&fdSet); 01624 if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1; 01625 } 01626 01627 struct timeval tv; 01628 tv.tv_sec = 0; 01629 tv.tv_usec = 1000; 01630 01631 int e = (int)select( (int)maxFd, &fdSet, NULL,NULL, &tv ); 01632 if (e < 0) 01633 { 01634 int err = getErrno(); 01635 if (verbose) clog << "Error on select: " << strerror(err) << endl; 01636 } 01637 else if (e >= 0) 01638 { 01639 StunAddress4 from; 01640 01641 // do the media relaying 01642 if (info.relay) 01643 { 01644 time_t now = time(0); 01645 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01646 { 01647 StunMediaRelay* relay = &info.relays[i]; 01648 if (relay->fd) 01649 { 01650 if (FD_ISSET(relay->fd, &fdSet)) 01651 { 01652 char msg[MAX_RTP_MSG_SIZE]; 01653 int msgLen = sizeof(msg); 01654 01655 StunAddress4 rtpFrom; 01656 ok = getMessage( relay->fd, msg, &msgLen, &rtpFrom.addr, &rtpFrom.port ,verbose); 01657 if (ok) 01658 { 01659 sendMessage(info.myFd, msg, msgLen, relay->destination.addr, relay->destination.port, verbose); 01660 relay->expireTime = now + MEDIA_RELAY_TIMEOUT; 01661 if ( verbose ) clog << "Relay packet on " 01662 << relay->fd 01663 << " from " << rtpFrom 01664 << " -> " << relay->destination 01665 << endl; 01666 } 01667 } 01668 else if (now > relay->expireTime) 01669 { 01670 closeSocket(relay->fd); 01671 relay->fd = 0; 01672 } 01673 } 01674 } 01675 } 01676 01677 01678 if (FD_ISSET(info.myFd,&fdSet)) 01679 { 01680 if (verbose) clog << "received on A1:P1" << endl; 01681 recvAltIp = false; 01682 recvAltPort = false; 01683 ok = getMessage( info.myFd, msg, &msgLen, &from.addr, &from.port,verbose ); 01684 } 01685 else if (FD_ISSET(info.altPortFd, &fdSet)) 01686 { 01687 if (verbose) clog << "received on A1:P2" << endl; 01688 recvAltIp = false; 01689 recvAltPort = true; 01690 ok = getMessage( info.altPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); 01691 } 01692 else if ( (info.altIpFd!=INVALID_SOCKET) && FD_ISSET(info.altIpFd,&fdSet)) 01693 { 01694 if (verbose) clog << "received on A2:P1" << endl; 01695 recvAltIp = true; 01696 recvAltPort = false; 01697 ok = getMessage( info.altIpFd, msg, &msgLen, &from.addr, &from.port ,verbose); 01698 } 01699 else if ( (info.altIpPortFd!=INVALID_SOCKET) && FD_ISSET(info.altIpPortFd, &fdSet)) 01700 { 01701 if (verbose) clog << "received on A2:P2" << endl; 01702 recvAltIp = true; 01703 recvAltPort = true; 01704 ok = getMessage( info.altIpPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); 01705 } 01706 else 01707 { 01708 return true; 01709 } 01710 01711 int relayPort = 0; 01712 if (info.relay) 01713 { 01714 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01715 { 01716 StunMediaRelay* relay = &info.relays[i]; 01717 if (relay->destination.addr == from.addr && 01718 relay->destination.port == from.port) 01719 { 01720 relayPort = relay->relayPort; 01721 relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; 01722 break; 01723 } 01724 } 01725 01726 if (relayPort == 0) 01727 { 01728 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01729 { 01730 StunMediaRelay* relay = &info.relays[i]; 01731 if (relay->fd == 0) 01732 { 01733 if ( verbose ) clog << "Open relay port " << relay->relayPort << endl; 01734 01735 relay->fd = (int)openPort(relay->relayPort, info.myAddr.addr, verbose); 01736 relay->destination.addr = from.addr; 01737 relay->destination.port = from.port; 01738 relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; 01739 relayPort = relay->relayPort; 01740 break; 01741 } 01742 } 01743 } 01744 } 01745 01746 if ( !ok ) 01747 { 01748 if ( verbose ) clog << "Get message did not return a valid message" <<endl; 01749 return true; 01750 } 01751 01752 if ( verbose ) clog << "Got a request (len=" << msgLen << ") from " << from << endl; 01753 01754 if ( msgLen <= 0 ) 01755 { 01756 return true; 01757 } 01758 01759 bool changePort = false; 01760 bool changeIp = false; 01761 01762 StunMessage resp; 01763 StunAddress4 dest; 01764 StunAtrString hmacPassword; 01765 hmacPassword.sizeValue = 0; 01766 01767 StunAddress4 secondary; 01768 secondary.port = 0; 01769 secondary.addr = 0; 01770 01771 if (info.relay && relayPort) 01772 { 01773 secondary = from; 01774 01775 from.addr = info.myAddr.addr; 01776 from.port = relayPort; 01777 } 01778 01779 ok = stunServerProcessMsg( msg, msgLen, from, secondary, 01780 recvAltIp ? info.altAddr : info.myAddr, 01781 recvAltIp ? info.myAddr : info.altAddr, 01782 &resp, 01783 &dest, 01784 &hmacPassword, 01785 &changePort, 01786 &changeIp, 01787 verbose ); 01788 01789 if ( !ok ) 01790 { 01791 if ( verbose ) clog << "Failed to parse message" << endl; 01792 return true; 01793 } 01794 01795 char buf[STUN_MAX_MESSAGE_SIZE]; 01796 int len = sizeof(buf); 01797 01798 len = stunEncodeMessage( resp, buf, len, hmacPassword,verbose ); 01799 01800 if ( dest.addr == 0 ) ok=false; 01801 if ( dest.port == 0 ) ok=false; 01802 01803 if ( ok ) 01804 { 01805 assert( dest.addr != 0 ); 01806 assert( dest.port != 0 ); 01807 01808 resip::Socket sendFd; 01809 01810 bool sendAltIp = recvAltIp; // send on the received IP address 01811 bool sendAltPort = recvAltPort; // send on the received port 01812 01813 if ( changeIp ) sendAltIp = !sendAltIp; // if need to change IP, then flip logic 01814 if ( changePort ) sendAltPort = !sendAltPort; // if need to change port, then flip logic 01815 01816 if ( !sendAltPort ) 01817 { 01818 if ( !sendAltIp ) 01819 { 01820 sendFd = info.myFd; 01821 } 01822 else 01823 { 01824 sendFd = info.altIpFd; 01825 } 01826 } 01827 else 01828 { 01829 if ( !sendAltIp ) 01830 { 01831 sendFd = info.altPortFd; 01832 } 01833 else 01834 { 01835 sendFd = info.altIpPortFd; 01836 } 01837 } 01838 01839 if ( sendFd != INVALID_SOCKET ) 01840 { 01841 sendMessage( sendFd, buf, len, dest.addr, dest.port, verbose ); 01842 } 01843 } 01844 } 01845 01846 return true; 01847 } 01848 01849 int 01850 stunFindLocalInterfaces(UInt32* addresses,int maxRet) 01851 { 01852 #if defined(WIN32) || defined(__sparc__) 01853 return 0; 01854 #else 01855 struct ifconf ifc; 01856 01857 int s = socket( AF_INET, SOCK_DGRAM, 0 ); 01858 const int len = 100 * sizeof(struct ifreq); 01859 01860 char buf[ len ]; 01861 01862 ifc.ifc_len = len; 01863 ifc.ifc_buf = buf; 01864 01865 int e = ioctl(s,SIOCGIFCONF,&ifc); 01866 char *ptr = buf; 01867 int tl = ifc.ifc_len; 01868 int count=0; 01869 01870 while ( (tl > 0) && ( count < maxRet) ) 01871 { 01872 struct ifreq* ifr = (struct ifreq *)ptr; 01873 01874 int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr); 01875 tl -= si; 01876 ptr += si; 01877 //char* name = ifr->ifr_ifrn.ifrn_name; 01878 //cerr << "name = " << name << endl; 01879 01880 struct ifreq ifr2; 01881 ifr2 = *ifr; 01882 01883 e = ioctl(s,SIOCGIFADDR,&ifr2); 01884 if ( e == -1 ) 01885 { 01886 break; 01887 } 01888 01889 //cerr << "ioctl addr e = " << e << endl; 01890 01891 struct sockaddr a = ifr2.ifr_addr; 01892 struct sockaddr_in* addr = (struct sockaddr_in*) &a; 01893 01894 UInt32 ai = ntohl( addr->sin_addr.s_addr ); 01895 if (int((ai>>24)&0xFF) != 127) 01896 { 01897 addresses[count++] = ai; 01898 } 01899 01900 #if 0 01901 cerr << "Detected interface " 01902 << int((ai>>24)&0xFF) << "." 01903 << int((ai>>16)&0xFF) << "." 01904 << int((ai>> 8)&0xFF) << "." 01905 << int((ai )&0xFF) << endl; 01906 #endif 01907 } 01908 01909 closeSocket(s); 01910 01911 return count; 01912 #endif 01913 } 01914 01915 void 01916 stunBuildReqSimple( StunMessage* msg, 01917 const StunAtrString& username, 01918 bool changePort, bool changeIp, unsigned int id ) 01919 { 01920 assert( msg ); 01921 memset( msg , 0 , sizeof(*msg) ); 01922 01923 msg->msgHdr.msgType = BindRequestMsg; 01924 01925 for ( int i=0; i<16; i=i+4 ) 01926 { 01927 assert(i+3<16); 01928 int r = stunRand(); 01929 msg->msgHdr.id.octet[i+0]= r>>0; 01930 msg->msgHdr.id.octet[i+1]= r>>8; 01931 msg->msgHdr.id.octet[i+2]= r>>16; 01932 msg->msgHdr.id.octet[i+3]= r>>24; 01933 } 01934 01935 if ( id != 0 ) 01936 { 01937 msg->msgHdr.id.octet[0] = id; 01938 } 01939 01940 msg->hasChangeRequest = true; 01941 msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | 01942 (changePort?ChangePortFlag:0); 01943 01944 if ( username.sizeValue > 0 ) 01945 { 01946 msg->hasUsername = true; 01947 msg->username = username; 01948 } 01949 } 01950 01951 01952 static void 01953 stunSendTest( resip::Socket myFd, StunAddress4& dest, 01954 const StunAtrString& username, const StunAtrString& password, 01955 int testNum, bool verbose ) 01956 { 01957 assert( dest.addr != 0 ); 01958 assert( dest.port != 0 ); 01959 01960 bool changePort=false; 01961 bool changeIP=false; 01962 bool discard=false; 01963 01964 switch (testNum) 01965 { 01966 case 1: 01967 case 10: 01968 case 11: 01969 break; 01970 case 2: 01971 //changePort=true; 01972 changeIP=true; 01973 break; 01974 case 3: 01975 changePort=true; 01976 break; 01977 case 4: 01978 changeIP=true; 01979 break; 01980 case 5: 01981 discard=true; 01982 break; 01983 default: 01984 cerr << "Test " << testNum <<" is unknown\n"; 01985 assert(0); 01986 } 01987 01988 StunMessage req; 01989 memset(&req, 0, sizeof(StunMessage)); 01990 01991 stunBuildReqSimple( &req, username, 01992 changePort , changeIP , 01993 testNum ); 01994 01995 char buf[STUN_MAX_MESSAGE_SIZE]; 01996 int len = STUN_MAX_MESSAGE_SIZE; 01997 01998 len = stunEncodeMessage( req, buf, len, password,verbose ); 01999 02000 if ( verbose ) 02001 { 02002 clog << "About to send msg of len " << len << " to " << dest << endl; 02003 } 02004 02005 sendMessage( myFd, buf, len, dest.addr, dest.port, verbose ); 02006 02007 } 02008 02009 02010 void 02011 stunGetUserNameAndPassword( const StunAddress4& dest, 02012 StunAtrString* username, 02013 StunAtrString* password) 02014 { 02015 // !cj! This is totally bogus - need to make TLS connection to dest and get a 02016 // username and password to use 02017 stunCreateUserName(dest, username); 02018 stunCreatePassword(*username, password); 02019 } 02020 02021 02022 bool 02023 stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* sAddr, unsigned long timeoutMs ) 02024 { 02025 assert( dest.addr != 0 ); 02026 assert( dest.port != 0 ); 02027 02028 int port = stunRandomPort(); 02029 UInt32 interfaceIp=0; 02030 if (sAddr) 02031 { 02032 interfaceIp = sAddr->addr; 02033 if ( sAddr->port != 0 ) 02034 { 02035 port = sAddr->port; 02036 } 02037 } 02038 resip::Socket myFd = openPort(port,interfaceIp,verbose); 02039 02040 if (myFd == INVALID_SOCKET) 02041 { 02042 return false; 02043 } 02044 02045 // make socket non-blocking 02046 if (!makeSocketNonBlocking(myFd)) 02047 { 02048 return false; 02049 } 02050 02051 StunAtrString username; 02052 StunAtrString password; 02053 02054 username.sizeValue = 0; 02055 password.sizeValue = 0; 02056 02057 #ifdef USE_TLS 02058 stunGetUserNameAndPassword( dest, username, password ); 02059 #endif 02060 02061 stunSendTest( myFd, dest, username, password, testNum, verbose ); 02062 02063 char msg[STUN_MAX_MESSAGE_SIZE]; 02064 int msgLen = STUN_MAX_MESSAGE_SIZE; 02065 02066 // Wait to receive a packet 02067 resip::FdSet myFdSet; 02068 myFdSet.setRead(myFd); 02069 if (myFdSet.selectMilliSeconds(timeoutMs) < 1) 02070 { 02071 // no packet received or an error occured 02072 return false; 02073 } 02074 02075 StunAddress4 from; 02076 if (!getMessage(myFd, msg, &msgLen, &from.addr, &from.port, verbose)) 02077 { 02078 closeSocket(myFd); 02079 return false; 02080 } 02081 02082 StunMessage resp; 02083 memset(&resp, 0, sizeof(StunMessage)); 02084 02085 if ( verbose ) clog << "Got a response" << endl; 02086 02087 bool ok = stunParseMessage( msg,msgLen, resp,verbose ); 02088 02089 if ( verbose ) 02090 { 02091 clog << "\t ok=" << ok << endl; 02092 clog << "\t id=" << resp.msgHdr.id << endl; 02093 clog << "\t mappedAddr=" << resp.mappedAddress.ipv4 << endl; 02094 clog << "\t changedAddr=" << resp.changedAddress.ipv4 << endl; 02095 clog << endl; 02096 } 02097 02098 if (sAddr) 02099 { 02100 sAddr->port = resp.mappedAddress.ipv4.port; 02101 sAddr->addr = resp.mappedAddress.ipv4.addr; 02102 } 02103 02104 closeSocket(myFd); 02105 return ok; 02106 } 02107 02108 02109 NatType 02110 stunNatType( StunAddress4& dest, 02111 bool verbose, 02112 bool* preservePort, // if set, is return for if NAT preservers ports or not 02113 bool* hairpin, // if set, is the return for if NAT will hairpin packets 02114 int port, // port to use for the test, 0 to choose random port 02115 StunAddress4* sAddr // NIC to use 02116 ) 02117 { 02118 assert( dest.addr != 0 ); 02119 assert( dest.port != 0 ); 02120 02121 if ( hairpin ) 02122 { 02123 *hairpin = false; 02124 } 02125 02126 if ( port == 0 ) 02127 { 02128 port = stunRandomPort(); 02129 } 02130 UInt32 interfaceIp=0; 02131 if (sAddr) 02132 { 02133 interfaceIp = sAddr->addr; 02134 } 02135 resip::Socket myFd1 = openPort(port,interfaceIp,verbose); 02136 resip::Socket myFd2 = openPort(port+1,interfaceIp,verbose); 02137 02138 if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) ) 02139 { 02140 cerr << "Some problem opening port/interface to send on" << endl; 02141 return StunTypeFailure; 02142 } 02143 02144 assert( myFd1 != INVALID_SOCKET ); 02145 assert( myFd2 != INVALID_SOCKET ); 02146 02147 bool respTestI=false; 02148 bool isNat=true; 02149 StunAddress4 testIchangedAddr; 02150 StunAddress4 testImappedAddr; 02151 bool respTestI2=false; 02152 bool mappedIpSame = true; 02153 StunAddress4 testI2mappedAddr; 02154 StunAddress4 testI2dest=dest; 02155 bool respTestII=false; 02156 bool respTestIII=false; 02157 02158 bool respTestHairpin=false; 02159 bool respTestPreservePort=false; 02160 02161 memset(&testImappedAddr,0,sizeof(testImappedAddr)); 02162 02163 StunAtrString username; 02164 StunAtrString password; 02165 02166 username.sizeValue = 0; 02167 password.sizeValue = 0; 02168 02169 #ifdef USE_TLS 02170 stunGetUserNameAndPassword( dest, username, password ); 02171 #endif 02172 02173 int count=0; 02174 while ( count < 7 ) 02175 { 02176 struct timeval tv; 02177 fd_set fdSet; 02178 #ifdef WIN32 02179 typedef unsigned int FdSetSize; 02180 #else 02181 typedef int FdSetSize; 02182 #endif 02183 FdSetSize fdSetSize; 02184 FD_ZERO(&fdSet); fdSetSize=0; 02185 FD_SET(myFd1,&fdSet); fdSetSize = ((FdSetSize)myFd1+1>fdSetSize) ? (FdSetSize)myFd1+1 : fdSetSize; 02186 FD_SET(myFd2,&fdSet); fdSetSize = ((FdSetSize)myFd2+1>fdSetSize) ? (FdSetSize)myFd2+1 : fdSetSize; 02187 tv.tv_sec=0; 02188 tv.tv_usec=150*1000; // 150 ms 02189 if ( count == 0 ) tv.tv_usec=0; 02190 02191 int err = select(fdSetSize, &fdSet, NULL, NULL, &tv); 02192 int e = getErrno(); 02193 if ( err == SOCKET_ERROR ) 02194 { 02195 // error occured 02196 cerr << "Error " << e << " " << strerror(e) << " in select" << endl; 02197 return StunTypeFailure; 02198 } 02199 else if ( err == 0 ) 02200 { 02201 // timeout occured 02202 count++; 02203 02204 if ( !respTestI ) 02205 { 02206 stunSendTest( myFd1, dest, username, password, 1 ,verbose ); 02207 } 02208 02209 if ( (!respTestI2) && respTestI ) 02210 { 02211 // check the address to send to if valid 02212 if ( ( testI2dest.addr != 0 ) && 02213 ( testI2dest.port != 0 ) ) 02214 { 02215 stunSendTest( myFd1, testI2dest, username, password, 10 ,verbose); 02216 } 02217 } 02218 02219 if ( !respTestII ) 02220 { 02221 stunSendTest( myFd2, dest, username, password, 2 ,verbose ); 02222 } 02223 02224 if ( !respTestIII ) 02225 { 02226 stunSendTest( myFd2, dest, username, password, 3 ,verbose ); 02227 } 02228 02229 if ( respTestI && (!respTestHairpin) ) 02230 { 02231 if ( ( testImappedAddr.addr != 0 ) && 02232 ( testImappedAddr.port != 0 ) ) 02233 { 02234 stunSendTest( myFd1, testImappedAddr, username, password, 11 ,verbose ); 02235 } 02236 } 02237 } 02238 else 02239 { 02240 //if (verbose) clog << "-----------------------------------------" << endl; 02241 assert( err>0 ); 02242 // data is avialbe on some fd 02243 02244 for ( int i=0; i<2; i++) 02245 { 02246 resip::Socket myFd; 02247 if ( i==0 ) 02248 { 02249 myFd=myFd1; 02250 } 02251 else 02252 { 02253 myFd=myFd2; 02254 } 02255 02256 if ( myFd!=INVALID_SOCKET ) 02257 { 02258 if ( FD_ISSET(myFd,&fdSet) ) 02259 { 02260 char msg[STUN_MAX_MESSAGE_SIZE]; 02261 int msgLen = sizeof(msg); 02262 02263 StunAddress4 from; 02264 02265 getMessage( myFd, 02266 msg, 02267 &msgLen, 02268 &from.addr, 02269 &from.port,verbose ); 02270 02271 StunMessage resp; 02272 memset(&resp, 0, sizeof(StunMessage)); 02273 02274 stunParseMessage( msg,msgLen, resp,verbose ); 02275 02276 if ( verbose ) 02277 { 02278 clog << "Received message of type " << resp.msgHdr.msgType 02279 << " id=" << (int)(resp.msgHdr.id.octet[0]) << endl; 02280 } 02281 02282 switch( resp.msgHdr.id.octet[0] ) 02283 { 02284 case 1: 02285 { 02286 if ( !respTestI ) 02287 { 02288 02289 testIchangedAddr.addr = resp.changedAddress.ipv4.addr; 02290 testIchangedAddr.port = resp.changedAddress.ipv4.port; 02291 testImappedAddr.addr = resp.mappedAddress.ipv4.addr; 02292 testImappedAddr.port = resp.mappedAddress.ipv4.port; 02293 02294 respTestPreservePort = ( testImappedAddr.port == port ); 02295 if ( preservePort ) 02296 { 02297 *preservePort = respTestPreservePort; 02298 } 02299 02300 testI2dest.addr = resp.changedAddress.ipv4.addr; 02301 02302 if (sAddr) 02303 { 02304 sAddr->port = testImappedAddr.port; 02305 sAddr->addr = testImappedAddr.addr; 02306 } 02307 02308 count = 0; 02309 } 02310 respTestI=true; 02311 } 02312 break; 02313 case 2: 02314 { 02315 respTestII=true; 02316 } 02317 break; 02318 case 3: 02319 { 02320 respTestIII=true; 02321 } 02322 break; 02323 case 10: 02324 { 02325 if ( !respTestI2 ) 02326 { 02327 testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr; 02328 testI2mappedAddr.port = resp.mappedAddress.ipv4.port; 02329 02330 mappedIpSame = false; 02331 if ( (testI2mappedAddr.addr == testImappedAddr.addr ) && 02332 (testI2mappedAddr.port == testImappedAddr.port )) 02333 { 02334 mappedIpSame = true; 02335 } 02336 02337 02338 } 02339 respTestI2=true; 02340 } 02341 break; 02342 case 11: 02343 { 02344 02345 if ( hairpin ) 02346 { 02347 *hairpin = true; 02348 } 02349 respTestHairpin = true; 02350 } 02351 break; 02352 } 02353 } 02354 } 02355 } 02356 } 02357 } 02358 02359 closeSocket(myFd1); 02360 closeSocket(myFd2); 02361 02362 // see if we can bind to this address 02363 //cerr << "try binding to " << testImappedAddr << endl; 02364 resip::Socket s = openPort( 0/*use ephemeral*/, testImappedAddr.addr, false ); 02365 if ( s != INVALID_SOCKET ) 02366 { 02367 closeSocket(s); 02368 isNat = false; 02369 //cerr << "binding worked" << endl; 02370 } 02371 else 02372 { 02373 isNat = true; 02374 //cerr << "binding failed" << endl; 02375 } 02376 02377 if (verbose) 02378 { 02379 clog << "test I = " << respTestI << endl; 02380 clog << "test II = " << respTestII << endl; 02381 clog << "test III = " << respTestIII << endl; 02382 clog << "test I(2) = " << respTestI2 << endl; 02383 clog << "is nat = " << isNat <<endl; 02384 clog << "mapped IP same = " << mappedIpSame << endl; 02385 clog << "hairpin = " << respTestHairpin << endl; 02386 clog << "preserver port = " << respTestPreservePort << endl; 02387 } 02388 02389 #if 0 02390 // implement logic flow chart from draft RFC 02391 if ( respTestI ) 02392 { 02393 if ( isNat ) 02394 { 02395 if (respTestII) 02396 { 02397 return StunTypeConeNat; 02398 } 02399 else 02400 { 02401 if ( mappedIpSame ) 02402 { 02403 if ( respTestIII ) 02404 { 02405 return StunTypeRestrictedNat; 02406 } 02407 else 02408 { 02409 return StunTypePortRestrictedNat; 02410 } 02411 } 02412 else 02413 { 02414 return StunTypeSymNat; 02415 } 02416 } 02417 } 02418 else 02419 { 02420 if (respTestII) 02421 { 02422 return StunTypeOpen; 02423 } 02424 else 02425 { 02426 return StunTypeSymFirewall; 02427 } 02428 } 02429 } 02430 else 02431 { 02432 return StunTypeBlocked; 02433 } 02434 #else 02435 if ( respTestI ) // not blocked 02436 { 02437 if ( isNat ) 02438 { 02439 if ( mappedIpSame ) 02440 { 02441 if (respTestII) 02442 { 02443 return StunTypeIndependentFilter; 02444 } 02445 else 02446 { 02447 if ( respTestIII ) 02448 { 02449 return StunTypeDependentFilter; 02450 } 02451 else 02452 { 02453 return StunTypePortDependedFilter; 02454 } 02455 } 02456 } 02457 else // mappedIp is not same 02458 { 02459 return StunTypeDependentMapping; 02460 } 02461 } 02462 else // isNat is false 02463 { 02464 if (respTestII) 02465 { 02466 return StunTypeOpen; 02467 } 02468 else 02469 { 02470 return StunTypeFirewall; 02471 } 02472 } 02473 } 02474 else 02475 { 02476 return StunTypeBlocked; 02477 } 02478 #endif 02479 02480 return StunTypeUnknown; 02481 } 02482 02483 02484 int 02485 stunOpenSocket( StunAddress4& dest, StunAddress4* mapAddr, 02486 int port, StunAddress4* srcAddr, 02487 bool verbose ) 02488 { 02489 assert( dest.addr != 0 ); 02490 assert( dest.port != 0 ); 02491 assert( mapAddr ); 02492 02493 if ( port == 0 ) 02494 { 02495 port = stunRandomPort(); 02496 } 02497 unsigned int interfaceIp = 0; 02498 if ( srcAddr ) 02499 { 02500 interfaceIp = srcAddr->addr; 02501 } 02502 02503 resip::Socket myFd = openPort(port,interfaceIp,verbose); 02504 if (myFd == INVALID_SOCKET) 02505 { 02506 return (int)myFd; 02507 } 02508 02509 char msg[STUN_MAX_MESSAGE_SIZE]; 02510 int msgLen = sizeof(msg); 02511 02512 StunAtrString username; 02513 StunAtrString password; 02514 02515 username.sizeValue = 0; 02516 password.sizeValue = 0; 02517 02518 #ifdef USE_TLS 02519 stunGetUserNameAndPassword( dest, username, password ); 02520 #endif 02521 02522 stunSendTest(myFd, dest, username, password, 1, 0/*false*/ ); 02523 02524 StunAddress4 from; 02525 02526 getMessage( myFd, msg, &msgLen, &from.addr, &from.port,verbose ); 02527 02528 StunMessage resp; 02529 memset(&resp, 0, sizeof(StunMessage)); 02530 02531 bool ok = stunParseMessage( msg, msgLen, resp,verbose ); 02532 if (!ok) 02533 { 02534 return -1; 02535 } 02536 02537 StunAddress4 mappedAddr = resp.mappedAddress.ipv4; 02538 StunAddress4 changedAddr = resp.changedAddress.ipv4; 02539 02540 //clog << "--- stunOpenSocket --- " << endl; 02541 //clog << "\treq id=" << req.id << endl; 02542 //clog << "\tresp id=" << id << endl; 02543 //clog << "\tmappedAddr=" << mappedAddr << endl; 02544 02545 *mapAddr = mappedAddr; 02546 02547 return (int)myFd; 02548 } 02549 02550 02551 bool 02552 stunOpenSocketPair( StunAddress4& dest, StunAddress4* mapAddr, 02553 int* fd1, int* fd2, 02554 int port, StunAddress4* srcAddr, 02555 bool verbose ) 02556 { 02557 assert( dest.addr!= 0 ); 02558 assert( dest.port != 0 ); 02559 assert( mapAddr ); 02560 02561 const int NUM=3; 02562 02563 if ( port == 0 ) 02564 { 02565 port = stunRandomPort(); 02566 } 02567 02568 *fd1=-1; 02569 *fd2=-1; 02570 02571 char msg[STUN_MAX_MESSAGE_SIZE]; 02572 int msgLen =sizeof(msg); 02573 02574 StunAddress4 from; 02575 int fd[NUM]; 02576 int i; 02577 02578 unsigned int interfaceIp = 0; 02579 if ( srcAddr ) 02580 { 02581 interfaceIp = srcAddr->addr; 02582 } 02583 02584 for( i=0; i<NUM; i++) 02585 { 02586 fd[i] = (int)openPort( (port == 0) ? 0 : (port + i), 02587 interfaceIp, verbose); 02588 if (fd[i] < 0) 02589 { 02590 while (i > 0) 02591 { 02592 closeSocket(fd[--i]); 02593 } 02594 return false; 02595 } 02596 } 02597 02598 StunAtrString username; 02599 StunAtrString password; 02600 02601 username.sizeValue = 0; 02602 password.sizeValue = 0; 02603 02604 #ifdef USE_TLS 02605 stunGetUserNameAndPassword( dest, username, password ); 02606 #endif 02607 02608 for( i=0; i<NUM; i++) 02609 { 02610 stunSendTest(fd[i], dest, username, password, 1/*testNum*/, verbose ); 02611 } 02612 02613 StunAddress4 mappedAddr[NUM]; 02614 for( i=0; i<NUM; i++) 02615 { 02616 msgLen = sizeof(msg)/sizeof(*msg); 02617 getMessage( fd[i], 02618 msg, 02619 &msgLen, 02620 &from.addr, 02621 &from.port ,verbose); 02622 02623 StunMessage resp; 02624 memset(&resp, 0, sizeof(StunMessage)); 02625 02626 bool ok = stunParseMessage( msg, msgLen, resp, verbose ); 02627 if (!ok) 02628 { 02629 return false; 02630 } 02631 02632 mappedAddr[i] = resp.mappedAddress.ipv4; 02633 StunAddress4 changedAddr = resp.changedAddress.ipv4; 02634 } 02635 02636 if (verbose) 02637 { 02638 clog << "--- stunOpenSocketPair --- " << endl; 02639 for( i=0; i<NUM; i++) 02640 { 02641 clog << "\t mappedAddr=" << mappedAddr[i] << endl; 02642 } 02643 } 02644 02645 if ( mappedAddr[0].port %2 == 0 ) 02646 { 02647 if ( mappedAddr[0].port+1 == mappedAddr[1].port ) 02648 { 02649 *mapAddr = mappedAddr[0]; 02650 *fd1 = fd[0]; 02651 *fd2 = fd[1]; 02652 closeSocket( fd[2] ); 02653 return true; 02654 } 02655 } 02656 else 02657 { 02658 if (( mappedAddr[1].port %2 == 0 ) 02659 && ( mappedAddr[1].port+1 == mappedAddr[2].port )) 02660 { 02661 *mapAddr = mappedAddr[1]; 02662 *fd1 = fd[1]; 02663 *fd2 = fd[2]; 02664 closeSocket( fd[0] ); 02665 return true; 02666 } 02667 } 02668 02669 // something failed, close all and return error 02670 for( i=0; i<NUM; i++) 02671 { 02672 closeSocket( fd[i] ); 02673 } 02674 02675 return false; 02676 } 02677 02678 bool 02679 operator<(const UInt128& lhs, const UInt128& rhs) 02680 { 02681 return memcmp(&lhs, &rhs, sizeof(lhs)) < 0; 02682 } 02683 02684 bool operator==(const UInt128& lhs, const UInt128& rhs) 02685 { 02686 return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; 02687 } 02688 02689 bool 02690 operator<(const StunMsgHdr& lhs, const StunMsgHdr& rhs) 02691 { 02692 return lhs.id < rhs.id; 02693 } 02694 02695 /* ==================================================================== 02696 * The Vovida Software License, Version 1.0 02697 * 02698 * Redistribution and use in source and binary forms, with or without 02699 * modification, are permitted provided that the following conditions 02700 * are met: 02701 * 02702 * 1. Redistributions of source code must retain the above copyright 02703 * notice, this list of conditions and the following disclaimer. 02704 * 02705 * 2. Redistributions in binary form must reproduce the above copyright 02706 * notice, this list of conditions and the following disclaimer in 02707 * the documentation and/or other materials provided with the 02708 * distribution. 02709 * 02710 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 02711 * and "Vovida Open Communication Application Library (VOCAL)" must 02712 * not be used to endorse or promote products derived from this 02713 * software without prior written permission. For written 02714 * permission, please contact vocal@vovida.org. 02715 * 02716 * 4. Products derived from this software may not be called "VOCAL", nor 02717 * may "VOCAL" appear in their name, without prior written 02718 * permission of Vovida Networks, Inc. 02719 * 02720 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 02721 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 02722 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 02723 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 02724 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 02725 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 02726 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 02727 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 02728 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 02729 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 02730 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 02731 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 02732 * DAMAGE. 02733 * 02734 */ 02735 02736 // Local Variables: 02737 // mode:c++ 02738 // c-file-style:"ellemtel" 02739 // c-file-offsets:((case-label . +)) 02740 // indent-tabs-mode:nil 02741 // End: 02742 02743
1.7.5.1