src/stun.c

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

Generated on Thu Feb 14 16:10:27 2008 for oRTP by  doxygen 1.5.4