reSIProcate/rutil  9694
Stun.cxx
Go to the documentation of this file.
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