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

Generated on Mon Apr 23 10:09:13 2007 for oRTP by  doxygen 1.5.2