diff --git a/sflphone-common/libs/stund/COPYING b/sflphone-common/libs/stund/COPYING deleted file mode 100644 index bce8e8623fb6040913df4b5597679e5f86337cf3..0000000000000000000000000000000000000000 --- a/sflphone-common/libs/stund/COPYING +++ /dev/null @@ -1,50 +0,0 @@ -/* ==================================================================== - * The Vovida Software License, Version 1.0 - * - * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The names "VOCAL", "Vovida Open Communication Application Library", - * and "Vovida Open Communication Application Library (VOCAL)" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact vocal@vovida.org. - * - * 4. Products derived from this software may not be called "VOCAL", nor - * may "VOCAL" appear in their name, without prior written - * permission of Vovida Networks, Inc. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA - * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES - * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * ==================================================================== - * - * This software consists of voluntary contributions made by Vovida - * Networks, Inc. and many individuals on behalf of Vovida Networks, - * Inc. For more information on Vovida Networks, Inc., please see - * <http://www.vovida.org/>. - * - */ - - diff --git a/sflphone-common/libs/stund/Makefile.am b/sflphone-common/libs/stund/Makefile.am deleted file mode 100644 index 56ffb3375780934416e07d3a4f4bc80ef2581360..0000000000000000000000000000000000000000 --- a/sflphone-common/libs/stund/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -noinst_LTLIBRARIES = libstun.la - -libstun_la_SOURCES = \ - stun.cxx stun.h \ - udp.cxx udp.h \ No newline at end of file diff --git a/sflphone-common/libs/stund/stun.cxx b/sflphone-common/libs/stund/stun.cxx deleted file mode 100644 index 33cb2e79cc6153bed7772f7495bdb10c52c3dd6c..0000000000000000000000000000000000000000 --- a/sflphone-common/libs/stund/stun.cxx +++ /dev/null @@ -1,2447 +0,0 @@ -/* ==================================================================== - * The Vovida Software License, Version 1.0 - * - * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The names "VOCAL", "Vovida Open Communication Application Library", - * and "Vovida Open Communication Application Library (VOCAL)" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact vocal@vovida.org. - * - * 4. Products derived from this software may not be called "VOCAL", nor - * may "VOCAL" appear in their name, without prior written - * permission of Vovida Networks, Inc. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA - * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES - * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * ==================================================================== - * - * This software consists of voluntary contributions made by Vovida - * Networks, Inc. and many individuals on behalf of Vovida Networks, - * Inc. For more information on Vovida Networks, Inc., please see - * <http://www.vovida.org/>. - * - */ - - -#include <cassert> -#include <cstring> -#include <iostream> -#include <cstdlib> -#include <errno.h> - -#ifdef WIN32 -#include <winsock2.h> -#include <stdlib.h> -#include <io.h> -#include <time.h> -#else - -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/types.h> -#include <arpa/inet.h> -#include <fcntl.h> -#include <netdb.h> -#include <netinet/in.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include <net/if.h> - -#endif - - -#if defined(__sparc__) || defined(WIN32) -#define NOSSL -#endif -#define NOSSL - -#include "udp.h" -#include "stun.h" - - -using namespace std; - - -static void -computeHmac(char* hmac, const char* input, int length, const char* key, int keySize); - -static bool -stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4& result ) -{ - if ( hdrLen != 8 ) - { - clog << "hdrLen wrong for Address" <<endl; - return false; - } - result.pad = *body++; - result.family = *body++; - if (result.family == IPv4Family) - { - UInt16 nport; - memcpy(&nport, body, 2); body+=2; - result.ipv4.port = ntohs(nport); - - UInt32 naddr; - memcpy(&naddr, body, 4); body+=4; - result.ipv4.addr = ntohl(naddr); - return true; - } - else if (result.family == IPv6Family) - { - clog << "ipv6 not supported" << endl; - } - else - { - clog << "bad address family: " << result.family << endl; - } - - return false; -} - -static bool -stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest& result ) -{ - if ( hdrLen != 4 ) - { - clog << "hdr length = " << hdrLen << " expecting " << sizeof(result) << endl; - - clog << "Incorrect size for ChangeRequest" << endl; - return false; - } - else - { - memcpy(&result.value, body, 4); - result.value = ntohl(result.value); - return true; - } -} - -static bool -stunParseAtrError( char* body, unsigned int hdrLen, StunAtrError& result ) -{ - if ( hdrLen >= sizeof(result) ) - { - clog << "head on Error too large" << endl; - return false; - } - else - { - memcpy(&result.pad, body, 2); body+=2; - result.pad = ntohs(result.pad); - result.errorClass = *body++; - result.number = *body++; - - result.sizeReason = hdrLen - 4; - memcpy(&result.reason, body, result.sizeReason); - result.reason[result.sizeReason] = 0; - return true; - } -} - -static bool -stunParseAtrUnknown( char* body, unsigned int hdrLen, StunAtrUnknown& result ) -{ - if ( hdrLen >= sizeof(result) ) - { - return false; - } - else - { - if (hdrLen % 4 != 0) return false; - result.numAttributes = hdrLen / 4; - for (int i=0; i<result.numAttributes; i++) - { - memcpy(&result.attrType[i], body, 2); body+=2; - result.attrType[i] = ntohs(result.attrType[i]); - } - return true; - } -} - - -static bool -stunParseAtrString( char* body, unsigned int hdrLen, StunAtrString& result ) -{ - if ( hdrLen >= STUN_MAX_STRING ) - { - clog << "String is too large" << endl; - return false; - } - else - { - if (hdrLen % 4 != 0) - { - clog << "Bad length string " << hdrLen << endl; - return false; - } - - result.sizeValue = hdrLen; - memcpy(&result.value, body, hdrLen); - result.value[hdrLen] = 0; - return true; - } -} - - -static bool -stunParseAtrIntegrity( char* body, unsigned int hdrLen, StunAtrIntegrity& result ) -{ - if ( hdrLen != 20) - { - clog << "MessageIntegrity must be 20 bytes" << endl; - return false; - } - else - { - memcpy(&result.hash, body, hdrLen); - return true; - } -} - - -bool -stunParseMessage( char* buf, unsigned int bufLen, StunMessage& msg, bool verbose) -{ - if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl; - memset(&msg, 0, sizeof(msg)); - - if (sizeof(StunMsgHdr) > bufLen) - { - clog << "Bad message" << endl; - return false; - } - - memcpy(&msg.msgHdr, buf, sizeof(StunMsgHdr)); - msg.msgHdr.msgType = ntohs(msg.msgHdr.msgType); - msg.msgHdr.msgLength = ntohs(msg.msgHdr.msgLength); - - if (msg.msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen) - { - clog << "Message header length doesn't match message size: " << msg.msgHdr.msgLength << " - " << bufLen << endl; - return false; - } - - char* body = buf + sizeof(StunMsgHdr); - unsigned int size = msg.msgHdr.msgLength; - - //clog << "bytes after header = " << size << endl; - - while ( size > 0 ) - { - // !jf! should check that there are enough bytes left in the buffer - - StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body); - - unsigned int attrLen = ntohs(attr->length); - int atrType = ntohs(attr->type); - - //if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl; - if ( attrLen+4 > size ) - { - clog << "claims attribute is larger than size of message " <<"(attribute type="<<atrType<<")"<< endl; - return false; - } - - body += 4; // skip the length and type in attribute header - size -= 4; - - switch ( atrType ) - { - case MappedAddress: - msg.hasMappedAddress = true; - if ( stunParseAtrAddress( body, attrLen, msg.mappedAddress )== false ) - { - clog << "problem parsing MappedAddress" << endl; - return false; - } - else - { - if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl; - } - - break; - - case ResponseAddress: - msg.hasResponseAddress = true; - if ( stunParseAtrAddress( body, attrLen, msg.responseAddress )== false ) - { - clog << "problem parsing ResponseAddress" << endl; - return false; - } - else - { - if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl; - } - break; - - case ChangeRequest: - msg.hasChangeRequest = true; - if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false) - { - clog << "problem parsing ChangeRequest" << endl; - return false; - } - else - { - if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl; - } - break; - - case SourceAddress: - msg.hasSourceAddress = true; - if ( stunParseAtrAddress( body, attrLen, msg.sourceAddress )== false ) - { - clog << "problem parsing SourceAddress" << endl; - return false; - } - else - { - if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl; - } - break; - - case ChangedAddress: - msg.hasChangedAddress = true; - if ( stunParseAtrAddress( body, attrLen, msg.changedAddress )== false ) - { - clog << "problem parsing ChangedAddress" << endl; - return false; - } - else - { - if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl; - } - break; - - case Username: - msg.hasUsername = true; - if (stunParseAtrString( body, attrLen, msg.username) == false) - { - clog << "problem parsing Username" << endl; - return false; - } - else - { - if (verbose) clog << "Username = " << msg.username.value << endl; - } - - break; - - case Password: - msg.hasPassword = true; - if (stunParseAtrString( body, attrLen, msg.password) == false) - { - clog << "problem parsing Password" << endl; - return false; - } - else - { - if (verbose) clog << "Password = " << msg.password.value << endl; - } - break; - - case MessageIntegrity: - msg.hasMessageIntegrity = true; - if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false) - { - clog << "problem parsing MessageIntegrity" << endl; - return false; - } - else - { - //if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl; - } - - // read the current HMAC - // look up the password given the user of given the transaction id - // compute the HMAC on the buffer - // decide if they match or not - break; - - case ErrorCode: - msg.hasErrorCode = true; - if (stunParseAtrError(body, attrLen, msg.errorCode) == false) - { - clog << "problem parsing ErrorCode" << endl; - return false; - } - else - { - if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass) - << " " << int(msg.errorCode.number) - << " " << msg.errorCode.reason << endl; - } - - break; - - case UnknownAttribute: - msg.hasUnknownAttributes = true; - if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false) - { - clog << "problem parsing UnknownAttribute" << endl; - return false; - } - break; - - case ReflectedFrom: - msg.hasReflectedFrom = true; - if ( stunParseAtrAddress( body, attrLen, msg.reflectedFrom ) == false ) - { - clog << "problem parsing ReflectedFrom" << endl; - return false; - } - break; - - case XorMappedAddress: - msg.hasXorMappedAddress = true; - if ( stunParseAtrAddress( body, attrLen, msg.xorMappedAddress ) == false ) - { - clog << "problem parsing XorMappedAddress" << endl; - return false; - } - else - { - if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl; - } - break; - - case XorOnly: - msg.xorOnly = true; - if (verbose) - { - clog << "xorOnly = true" << endl; - } - break; - - case ServerName: - msg.hasServerName = true; - if (stunParseAtrString( body, attrLen, msg.serverName) == false) - { - clog << "problem parsing ServerName" << endl; - return false; - } - else - { - if (verbose) clog << "ServerName = " << msg.serverName.value << endl; - } - break; - - case SecondaryAddress: - msg.hasSecondaryAddress = true; - if ( stunParseAtrAddress( body, attrLen, msg.secondaryAddress ) == false ) - { - clog << "problem parsing secondaryAddress" << endl; - return false; - } - else - { - if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl; - } - break; - - default: - if (verbose) clog << "Unknown attribute: " << atrType << endl; - if ( atrType <= 0x7FFF ) - { - return false; - } - } - - body += attrLen; - size -= attrLen; - } - - return true; -} - - -static char* -encode16(char* buf, UInt16 data) -{ - UInt16 ndata = htons(data); - memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16)); - return buf + sizeof(UInt16); -} - -static char* -encode32(char* buf, UInt32 data) -{ - UInt32 ndata = htonl(data); - memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt32)); - return buf + sizeof(UInt32); -} - - -static char* -encode(char* buf, const char* data, unsigned int length) -{ - memcpy(buf, data, length); - return buf + length; -} - - -static char* -encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4& atr) -{ - ptr = encode16(ptr, type); - ptr = encode16(ptr, 8); - *ptr++ = atr.pad; - *ptr++ = IPv4Family; - ptr = encode16(ptr, atr.ipv4.port); - ptr = encode32(ptr, atr.ipv4.addr); - - return ptr; -} - -static char* -encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest& atr) -{ - ptr = encode16(ptr, ChangeRequest); - ptr = encode16(ptr, 4); - ptr = encode32(ptr, atr.value); - return ptr; -} - -static char* -encodeAtrError(char* ptr, const StunAtrError& atr) -{ - ptr = encode16(ptr, ErrorCode); - ptr = encode16(ptr, 6 + atr.sizeReason); - ptr = encode16(ptr, atr.pad); - *ptr++ = atr.errorClass; - *ptr++ = atr.number; - ptr = encode(ptr, atr.reason, atr.sizeReason); - return ptr; -} - - -static char* -encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr) -{ - ptr = encode16(ptr, UnknownAttribute); - ptr = encode16(ptr, 2+2*atr.numAttributes); - for (int i=0; i<atr.numAttributes; i++) - { - ptr = encode16(ptr, atr.attrType[i]); - } - return ptr; -} - - -static char* -encodeXorOnly(char* ptr) -{ - ptr = encode16(ptr, XorOnly ); - return ptr; -} - - -static char* -encodeAtrString(char* ptr, UInt16 type, const StunAtrString& atr) -{ - assert(atr.sizeValue % 4 == 0); - - ptr = encode16(ptr, type); - ptr = encode16(ptr, atr.sizeValue); - ptr = encode(ptr, atr.value, atr.sizeValue); - return ptr; -} - - -static char* -encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr) -{ - ptr = encode16(ptr, MessageIntegrity); - ptr = encode16(ptr, 20); - ptr = encode(ptr, atr.hash, sizeof(atr.hash)); - return ptr; -} - - -unsigned int -stunEncodeMessage( const StunMessage& msg, - char* buf, - unsigned int bufLen, - const StunAtrString& password, - bool verbose) -{ - assert(bufLen >= sizeof(StunMsgHdr)); - char* ptr = buf; - - ptr = encode16(ptr, msg.msgHdr.msgType); - char* lengthp = ptr; - ptr = encode16(ptr, 0); - ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id)); - - if (verbose) clog << "Encoding stun message: " << endl; - if (msg.hasMappedAddress) - { - if (verbose) clog << "Encoding MappedAddress: " << msg.mappedAddress.ipv4 << endl; - ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress); - } - if (msg.hasResponseAddress) - { - if (verbose) clog << "Encoding ResponseAddress: " << msg.responseAddress.ipv4 << endl; - ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress); - } - if (msg.hasChangeRequest) - { - if (verbose) clog << "Encoding ChangeRequest: " << msg.changeRequest.value << endl; - ptr = encodeAtrChangeRequest(ptr, msg.changeRequest); - } - if (msg.hasSourceAddress) - { - if (verbose) clog << "Encoding SourceAddress: " << msg.sourceAddress.ipv4 << endl; - ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress); - } - if (msg.hasChangedAddress) - { - if (verbose) clog << "Encoding ChangedAddress: " << msg.changedAddress.ipv4 << endl; - ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress); - } - if (msg.hasUsername) - { - if (verbose) clog << "Encoding Username: " << msg.username.value << endl; - ptr = encodeAtrString(ptr, Username, msg.username); - } - if (msg.hasPassword) - { - if (verbose) clog << "Encoding Password: " << msg.password.value << endl; - ptr = encodeAtrString(ptr, Password, msg.password); - } - if (msg.hasErrorCode) - { - if (verbose) clog << "Encoding ErrorCode: class=" - << int(msg.errorCode.errorClass) - << " number=" << int(msg.errorCode.number) - << " reason=" - << msg.errorCode.reason - << endl; - - ptr = encodeAtrError(ptr, msg.errorCode); - } - if (msg.hasUnknownAttributes) - { - if (verbose) clog << "Encoding UnknownAttribute: ???" << endl; - ptr = encodeAtrUnknown(ptr, msg.unknownAttributes); - } - if (msg.hasReflectedFrom) - { - if (verbose) clog << "Encoding ReflectedFrom: " << msg.reflectedFrom.ipv4 << endl; - ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom); - } - if (msg.hasXorMappedAddress) - { - if (verbose) clog << "Encoding XorMappedAddress: " << msg.xorMappedAddress.ipv4 << endl; - ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress); - } - if (msg.xorOnly) - { - if (verbose) clog << "Encoding xorOnly: " << endl; - ptr = encodeXorOnly( ptr ); - } - if (msg.hasServerName) - { - if (verbose) clog << "Encoding ServerName: " << msg.serverName.value << endl; - ptr = encodeAtrString(ptr, ServerName, msg.serverName); - } - if (msg.hasSecondaryAddress) - { - if (verbose) clog << "Encoding SecondaryAddress: " << msg.secondaryAddress.ipv4 << endl; - ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress); - } - - if (password.sizeValue > 0) - { - if (verbose) clog << "HMAC with password: " << password.value << endl; - - StunAtrIntegrity integrity; - computeHmac(integrity.hash, buf, int(ptr-buf) , password.value, password.sizeValue); - ptr = encodeAtrIntegrity(ptr, integrity); - } - if (verbose) clog << endl; - - encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr))); - return int(ptr - buf); -} - -int -stunRand() -{ - // return 32 bits of random stuff - assert( sizeof(int) == 4 ); - static bool init=false; - if ( !init ) - { - init = true; - - UInt64 tick; - -#if defined(WIN32) - volatile unsigned int lowtick=0,hightick=0; - __asm - { - rdtsc - mov lowtick, eax - mov hightick, edx - } - tick = hightick; - tick <<= 32; - tick |= lowtick; -#elif defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) || defined(__x86_64__)) - asm("rdtsc" : "=A" (tick)); -#elif defined (__SUNPRO_CC) || defined( __sparc__ ) - tick = gethrtime(); -#elif defined(__MACH__) || defined(__powerpc__) - int fd=open("/dev/random",O_RDONLY); - read(fd,&tick,sizeof(tick)); - closesocket(fd); -#else -# error Need some way to seed the random number generator -#endif - int seed = int(tick); -#ifdef WIN32 - srand(seed); -#else - srandom(seed); -#endif - } - -#ifdef WIN32 - assert( RAND_MAX == 0x7fff ); - int r1 = rand(); - int r2 = rand(); - - int ret = (r1<<16) + r2; - - return ret; -#else - return random(); -#endif -} - - -/// return a random number to use as a port -static int -randomPort() -{ - int min=0x4000; - int max=0x7FFF; - - int ret = stunRand(); - ret = ret|min; - ret = ret&max; - - return ret; -} - - -#ifdef NOSSL -static void -computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey) -{ - (void)input; - (void)length; - (void)key; - (void)sizeKey; - strncpy(hmac,"hmac-not-implemented",20); -} -#else -#include <openssl/hmac.h> - -static void -computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey) -{ - unsigned int resultSize=0; - HMAC(EVP_sha1(), - key, sizeKey, - reinterpret_cast<const unsigned char*>(input), length, - reinterpret_cast<unsigned char*>(hmac), &resultSize); - assert(resultSize == 20); -} -#endif - - -static void -toHex(const char* buffer, int bufferSize, char* output) -{ - static char hexmap[] = "0123456789abcdef"; - - const char* p = buffer; - char* r = output; - for (int i=0; i < bufferSize; i++) - { - unsigned char temp = *p++; - - int hi = (temp & 0xf0)>>4; - int low = (temp & 0xf); - - *r++ = hexmap[hi]; - *r++ = hexmap[low]; - } - *r = 0; -} - -void -stunCreateUserName(const StunAddress4& source, StunAtrString* username) -{ - UInt64 time = stunGetSystemTimeSecs(); - time -= (time % 20*60); - //UInt64 hitime = time >> 32; - UInt64 lotime = time & 0xFFFFFFFF; - - char buffer[1024]; - sprintf(buffer, - "%08x:%08x:%08x:", - UInt32(source.addr), - UInt32(stunRand()), - UInt32(lotime)); - assert( strlen(buffer) < 1024 ); - - assert(strlen(buffer) + 41 < STUN_MAX_STRING); - - char hmac[20]; - char key[] = "Jason"; - computeHmac(hmac, buffer, strlen(buffer), key, strlen(key) ); - char hmacHex[41]; - toHex(hmac, 20, hmacHex ); - hmacHex[40] =0; - - strcat(buffer,hmacHex); - - int l = strlen(buffer); - assert( l+1 < STUN_MAX_STRING ); - assert( l%4 == 0 ); - - username->sizeValue = l; - memcpy(username->value,buffer,l); - username->value[l]=0; - - //if (verbose) clog << "computed username=" << username.value << endl; -} - -void -stunCreatePassword(const StunAtrString& username, StunAtrString* password) -{ - char hmac[20]; - char key[] = "Fluffy"; - //char buffer[STUN_MAX_STRING]; - computeHmac(hmac, username.value, strlen(username.value), key, strlen(key)); - toHex(hmac, 20, password->value); - password->sizeValue = 40; - password->value[40]=0; - - //clog << "password=" << password->value << endl; -} - - -UInt64 -stunGetSystemTimeSecs() -{ - UInt64 time=0; -#if defined(WIN32) - SYSTEMTIME t; - // CJ TODO - this probably has bug on wrap around every 24 hours - GetSystemTime( &t ); - time = (t.wHour*60+t.wMinute)*60+t.wSecond; -#else - struct timeval now; - gettimeofday( &now , NULL ); - //assert( now ); - time = now.tv_sec; -#endif - return time; -} - - -ostream& operator<< ( ostream& strm, const UInt128& r ) -{ - strm << int(r.octet[0]); - for ( int i=1; i<16; i++ ) - { - strm << ':' << int(r.octet[i]); - } - - return strm; -} - -ostream& -operator<<( ostream& strm, const StunAddress4& addr) -{ - UInt32 ip = addr.addr; - strm << ((int)(ip>>24)&0xFF) << "."; - strm << ((int)(ip>>16)&0xFF) << "."; - strm << ((int)(ip>> 8)&0xFF) << "."; - strm << ((int)(ip>> 0)&0xFF) ; - - strm << ":" << addr.port; - - return strm; -} - - -// returns true if it scucceeded -bool -stunParseHostName( char* peerName, - UInt32& ip, - UInt16& portVal, - UInt16 defaultPort ) -{ - in_addr sin_addr; - - char host[512]; - strncpy(host,peerName,512); - host[512-1]='\0'; - char* port = NULL; - - int portNum = defaultPort; - - // pull out the port part if present. - char* sep = strchr(host,':'); - - if ( sep == NULL ) - { - portNum = defaultPort; - } - else - { - *sep = '\0'; - port = sep + 1; - // set port part - - char* endPtr=NULL; - - portNum = strtol(port,&endPtr,10); - - if ( endPtr != NULL ) - { - if ( *endPtr != '\0' ) - { - portNum = defaultPort; - } - } - } - - if ( portNum < 1024 ) return false; - if ( portNum >= 0xFFFF ) return false; - - // figure out the host part - struct hostent* h; - -#ifdef WIN32 - assert( strlen(host) >= 1 ); - if ( isdigit( host[0] ) ) - { - // assume it is a ip address - unsigned long a = inet_addr(host); - //cerr << "a=0x" << hex << a << dec << endl; - - ip = ntohl( a ); - } - else - { - // assume it is a host name - h = gethostbyname( host ); - - if ( h == NULL ) - { - int err = getErrno(); - std::cerr << "error was " << err << std::endl; - assert( err != WSANOTINITIALISED ); - - ip = ntohl( 0x7F000001L ); - - return false; - } - else - { - sin_addr = *(struct in_addr*)h->h_addr; - ip = ntohl( sin_addr.s_addr ); - } - } - -#else - h = gethostbyname( host ); - if ( h == NULL ) - { - int err = getErrno(); - std::cerr << "error was " << err << std::endl; - ip = ntohl( 0x7F000001L ); - return false; - } - else - { - sin_addr = *(struct in_addr*)h->h_addr; - ip = ntohl( sin_addr.s_addr ); - } -#endif - - portVal = portNum; - - return true; -} - - -bool -stunParseServerName( char* name, StunAddress4& addr) -{ - assert(name); - - // TODO - put in DNS SRV stuff. - - bool ret = stunParseHostName( name, addr.addr, addr.port, 3478); - if ( ret != true ) - { - addr.port=0xFFFF; - } - return ret; -} - - -static void -stunCreateErrorResponse(StunMessage& response, int cl, int number, const char* msg) -{ - response.msgHdr.msgType = BindErrorResponseMsg; - response.hasErrorCode = true; - response.errorCode.errorClass = cl; - response.errorCode.number = number; - strcpy(response.errorCode.reason, msg); -} - -#if 0 -static void -stunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg) -{ - response.msgHdr.msgType = SharedSecretErrorResponseMsg; - response.hasErrorCode = true; - response.errorCode.errorClass = cl; - response.errorCode.number = number; - strcpy(response.errorCode.reason, msg); -} -#endif - -static void -stunCreateSharedSecretResponse(const StunMessage& request, const StunAddress4& source, StunMessage& response) -{ - response.msgHdr.msgType = SharedSecretResponseMsg; - response.msgHdr.id = request.msgHdr.id; - - response.hasUsername = true; - stunCreateUserName( source, &response.username); - - response.hasPassword = true; - stunCreatePassword( response.username, &response.password); -} - - -// This funtion takes a single message sent to a stun server, parses -// and constructs an apropriate repsonse - returns true if message is -// valid -bool -stunServerProcessMsg( char* buf, - unsigned int bufLen, - StunAddress4& from, - StunAddress4& secondary, - StunAddress4& myAddr, - StunAddress4& altAddr, - StunMessage* resp, - StunAddress4* destination, - StunAtrString* hmacPassword, - bool* changePort, - bool* changeIp, - bool verbose) -{ - - // set up information for default response - - memset( resp, 0 , sizeof(*resp) ); - - *changeIp = false; - *changePort = false; - - StunMessage req; - bool ok = stunParseMessage( buf,bufLen, req, verbose); - - if (!ok) // Complete garbage, drop it on the floor - { - if (verbose) clog << "Request did not parse" << endl; - return false; - } - if (verbose) clog << "Request parsed ok" << endl; - - StunAddress4 mapped = req.mappedAddress.ipv4; - StunAddress4 respondTo = req.responseAddress.ipv4; - UInt32 flags = req.changeRequest.value; - - switch (req.msgHdr.msgType) - { - case SharedSecretRequestMsg: - if(verbose) clog << "Received SharedSecretRequestMsg on udp. send error 433." << endl; - // !cj! - should fix so you know if this came over TLS or UDP - stunCreateSharedSecretResponse(req, from, *resp); - //stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS"); - return true; - - case BindRequestMsg: - if (!req.hasMessageIntegrity) - { - if (verbose) clog << "BindRequest does not contain MessageIntegrity" << endl; - - if (0) // !jf! mustAuthenticate - { - if(verbose) clog << "Received BindRequest with no MessageIntegrity. Sending 401." << endl; - stunCreateErrorResponse(*resp, 4, 1, "Missing MessageIntegrity"); - return true; - } - } - else - { - if (!req.hasUsername) - { - if (verbose) clog << "No UserName. Send 432." << endl; - stunCreateErrorResponse(*resp, 4, 32, "No UserName and contains MessageIntegrity"); - return true; - } - else - { - if (verbose) clog << "Validating username: " << req.username.value << endl; - // !jf! could retrieve associated password from provisioning here - if (strcmp(req.username.value, "test") == 0) - { - if (0) - { - // !jf! if the credentials are stale - stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest"); - return true; - } - else - { - if (verbose) clog << "Validating MessageIntegrity" << endl; - // need access to shared secret - - unsigned char hmac[20]; -#ifndef NOSSL - unsigned int hmacSize=20; - - HMAC(EVP_sha1(), - "1234", 4, - reinterpret_cast<const unsigned char*>(buf), bufLen-20-4, - hmac, &hmacSize); - assert(hmacSize == 20); -#endif - - if (memcmp(buf, hmac, 20) != 0) - { - if (verbose) clog << "MessageIntegrity is bad. Sending " << endl; - stunCreateErrorResponse(*resp, 4, 3, "Unknown username. Try test with password 1234"); - return true; - } - - // need to compute this later after message is filled in - resp->hasMessageIntegrity = true; - assert(req.hasUsername); - resp->hasUsername = true; - resp->username = req.username; // copy username in - } - } - else - { - if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl; - } - } - } - - // TODO !jf! should check for unknown attributes here and send 420 listing the - // unknown attributes. - - if ( respondTo.port == 0 ) respondTo = from; - if ( mapped.port == 0 ) mapped = from; - - *changeIp = ( flags & ChangeIpFlag )?true:false; - *changePort = ( flags & ChangePortFlag )?true:false; - - if (verbose) - { - clog << "Request is valid:" << endl; - clog << "\t flags=" << flags << endl; - clog << "\t changeIp=" << *changeIp << endl; - clog << "\t changePort=" << *changePort << endl; - clog << "\t from = " << from << endl; - clog << "\t respond to = " << respondTo << endl; - clog << "\t mapped = " << mapped << endl; - } - - // form the outgoing message - resp->msgHdr.msgType = BindResponseMsg; - for ( int i=0; i<16; i++ ) - { - resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i]; - } - - if ( req.xorOnly == false ) - { - resp->hasMappedAddress = true; - resp->mappedAddress.ipv4.port = mapped.port; - resp->mappedAddress.ipv4.addr = mapped.addr; - } - - if (1) // do xorMapped address or not - { - resp->hasXorMappedAddress = true; - UInt16 id16 = req.msgHdr.id.octet[7]<<8 - | req.msgHdr.id.octet[6]; - UInt32 id32 = req.msgHdr.id.octet[7]<<24 - | req.msgHdr.id.octet[6]<<16 - | req.msgHdr.id.octet[5]<<8 - | req.msgHdr.id.octet[4];; - resp->xorMappedAddress.ipv4.port = mapped.port^id16; - resp->xorMappedAddress.ipv4.addr = mapped.addr^id32; - } - - resp->hasSourceAddress = true; - resp->sourceAddress.ipv4.port = (*changePort) ? altAddr.port : myAddr.port; - resp->sourceAddress.ipv4.addr = (*changeIp) ? altAddr.addr : myAddr.addr; - - resp->hasChangedAddress = true; - resp->changedAddress.ipv4.port = altAddr.port; - resp->changedAddress.ipv4.addr = altAddr.addr; - - if ( secondary.port != 0 ) - { - resp->hasSecondaryAddress = true; - resp->secondaryAddress.ipv4.port = secondary.port; - resp->secondaryAddress.ipv4.addr = secondary.addr; - } - - if ( req.hasUsername && req.username.sizeValue > 0 ) - { - // copy username in - resp->hasUsername = true; - assert( req.username.sizeValue % 4 == 0 ); - assert( req.username.sizeValue < STUN_MAX_STRING ); - memcpy( resp->username.value, req.username.value, req.username.sizeValue ); - resp->username.sizeValue = req.username.sizeValue; - } - - if (1) // add ServerName - { - resp->hasServerName = true; - const char serverName[] = "Vovida.org " STUN_VERSION; // must pad to mult of 4 - - assert( sizeof(serverName) < STUN_MAX_STRING ); - //cerr << "sizeof serverName is " << sizeof(serverName) << endl; - assert( sizeof(serverName)%4 == 0 ); - memcpy( resp->serverName.value, serverName, sizeof(serverName)); - resp->serverName.sizeValue = sizeof(serverName); - } - - if ( req.hasMessageIntegrity & req.hasUsername ) - { - // this creates the password that will be used in the HMAC when then - // messages is sent - stunCreatePassword( req.username, hmacPassword ); - } - - if (req.hasUsername && (req.username.sizeValue > 64 ) ) - { - UInt32 source; - assert( sizeof(int) == sizeof(UInt32) ); - - sscanf(req.username.value, "%x", &source); - resp->hasReflectedFrom = true; - resp->reflectedFrom.ipv4.port = 0; - resp->reflectedFrom.ipv4.addr = source; - } - - destination->port = respondTo.port; - destination->addr = respondTo.addr; - - return true; - - default: - if (verbose) clog << "Unknown or unsupported request " << endl; - return false; - } - - assert(0); - return false; -} - -bool -stunInitServer(StunServerInfo& info, const StunAddress4& myAddr, const StunAddress4& altAddr, int startMediaPort, bool verbose ) -{ - assert( myAddr.port != 0 ); - assert( altAddr.port!= 0 ); - assert( myAddr.addr != 0 ); - //assert( altAddr.addr != 0 ); - - info.myAddr = myAddr; - info.altAddr = altAddr; - - info.myFd = INVALID_SOCKET; - info.altPortFd = INVALID_SOCKET; - info.altIpFd = INVALID_SOCKET; - info.altIpPortFd = INVALID_SOCKET; - - memset(info.relays, 0, sizeof(info.relays)); - if (startMediaPort > 0) - { - info.relay = true; - - for (int i=0; i<MAX_MEDIA_RELAYS; ++i) - { - StunMediaRelay* relay = &info.relays[i]; - relay->relayPort = startMediaPort+i; - relay->fd = 0; - relay->expireTime = 0; - } - } - else - { - info.relay = false; - } - - if ((info.myFd = openPort(myAddr.port, myAddr.addr,verbose)) == INVALID_SOCKET) - { - clog << "Can't open " << myAddr << endl; - stunStopServer(info); - - return false; - } - //if (verbose) clog << "Opened " << myAddr.addr << ":" << myAddr.port << " --> " << info.myFd << endl; - - if ((info.altPortFd = openPort(altAddr.port,myAddr.addr,verbose)) == INVALID_SOCKET) - { - clog << "Can't open " << myAddr << endl; - stunStopServer(info); - return false; - } - //if (verbose) clog << "Opened " << myAddr.addr << ":" << altAddr.port << " --> " << info.altPortFd << endl; - - - info.altIpFd = INVALID_SOCKET; - if ( altAddr.addr != 0 ) - { - if ((info.altIpFd = openPort( myAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET) - { - clog << "Can't open " << altAddr << endl; - stunStopServer(info); - return false; - } - //if (verbose) clog << "Opened " << altAddr.addr << ":" << myAddr.port << " --> " << info.altIpFd << endl;; - } - - info.altIpPortFd = INVALID_SOCKET; - if ( altAddr.addr != 0 ) - { if ((info.altIpPortFd = openPort(altAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET) - { - clog << "Can't open " << altAddr << endl; - stunStopServer(info); - return false; - } - //if (verbose) clog << "Opened " << altAddr.addr << ":" << altAddr.port << " --> " << info.altIpPortFd << endl;; - } - - return true; -} - -void -stunStopServer(StunServerInfo& info) -{ - if (info.myFd > 0) closesocket(info.myFd); - if (info.altPortFd > 0) closesocket(info.altPortFd); - if (info.altIpFd > 0) closesocket(info.altIpFd); - if (info.altIpPortFd > 0) closesocket(info.altIpPortFd); - - if (info.relay) - { - for (int i=0; i<MAX_MEDIA_RELAYS; ++i) - { - StunMediaRelay* relay = &info.relays[i]; - if (relay->fd) - { - closesocket(relay->fd); - relay->fd = 0; - } - } - } -} - - -bool -stunServerProcess(StunServerInfo& info, bool verbose) -{ - char msg[STUN_MAX_MESSAGE_SIZE]; - int msgLen = sizeof(msg); - - bool ok = false; - bool recvAltIp =false; - bool recvAltPort = false; - - fd_set fdSet; -#ifdef WIN32 - unsigned int maxFd=0; -#else - int maxFd=0; -#endif - FD_ZERO(&fdSet); - FD_SET(info.myFd,&fdSet); - if ( info.myFd >= maxFd ) maxFd=info.myFd+1; - FD_SET(info.altPortFd,&fdSet); - if ( info.altPortFd >= maxFd ) maxFd=info.altPortFd+1; - - if ( info.altIpFd != INVALID_SOCKET ) - { - FD_SET(info.altIpFd,&fdSet); - if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1; - } - if ( info.altIpPortFd != INVALID_SOCKET ) - { - FD_SET(info.altIpPortFd,&fdSet); - if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1; - } - - if (info.relay) - { - for (int i=0; i<MAX_MEDIA_RELAYS; ++i) - { - StunMediaRelay* relay = &info.relays[i]; - if (relay->fd) - { - FD_SET(relay->fd, &fdSet); - if (relay->fd >= maxFd) maxFd=relay->fd+1; - } - } - } - - if ( info.altIpFd != INVALID_SOCKET ) - { - FD_SET(info.altIpFd,&fdSet); - if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1; - } - if ( info.altIpPortFd != INVALID_SOCKET ) - { - FD_SET(info.altIpPortFd,&fdSet); - if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1; - } - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 1000; - - int e = select( maxFd, &fdSet, NULL,NULL, &tv ); - if (e < 0) - { - int err = getErrno(); - clog << "Error on select: " << strerror(err) << endl; - } - else if (e >= 0) - { - StunAddress4 from; - - // do the media relaying - if (info.relay) - { - time_t now = time(0); - for (int i=0; i<MAX_MEDIA_RELAYS; ++i) - { - StunMediaRelay* relay = &info.relays[i]; - if (relay->fd) - { - if (FD_ISSET(relay->fd, &fdSet)) - { - char msg[MAX_RTP_MSG_SIZE]; - int msgLen = sizeof(msg); - - StunAddress4 rtpFrom; - ok = getMessage( relay->fd, msg, &msgLen, &rtpFrom.addr, &rtpFrom.port ,verbose); - if (ok) - { - sendMessage(info.myFd, msg, msgLen, relay->destination.addr, relay->destination.port, verbose); - relay->expireTime = now + MEDIA_RELAY_TIMEOUT; - if ( verbose ) clog << "Relay packet on " - << relay->fd - << " from " << rtpFrom - << " -> " << relay->destination - << endl; - } - } - else if (now > relay->expireTime) - { - closesocket(relay->fd); - relay->fd = 0; - } - } - } - } - - - if (FD_ISSET(info.myFd,&fdSet)) - { - if (verbose) clog << "received on A1:P1" << endl; - recvAltIp = false; - recvAltPort = false; - ok = getMessage( info.myFd, msg, &msgLen, &from.addr, &from.port,verbose ); - } - else if (FD_ISSET(info.altPortFd, &fdSet)) - { - if (verbose) clog << "received on A1:P2" << endl; - recvAltIp = false; - recvAltPort = true; - ok = getMessage( info.altPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); - } - else if ( (info.altIpFd!=INVALID_SOCKET) && FD_ISSET(info.altIpFd,&fdSet)) - { - if (verbose) clog << "received on A2:P1" << endl; - recvAltIp = true; - recvAltPort = false; - ok = getMessage( info.altIpFd, msg, &msgLen, &from.addr, &from.port ,verbose); - } - else if ( (info.altIpPortFd!=INVALID_SOCKET) && FD_ISSET(info.altIpPortFd, &fdSet)) - { - if (verbose) clog << "received on A2:P2" << endl; - recvAltIp = true; - recvAltPort = true; - ok = getMessage( info.altIpPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); - } - else - { - return true; - } - - int relayPort = 0; - if (info.relay) - { - for (int i=0; i<MAX_MEDIA_RELAYS; ++i) - { - StunMediaRelay* relay = &info.relays[i]; - if (relay->destination.addr == from.addr && - relay->destination.port == from.port) - { - relayPort = relay->relayPort; - relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; - break; - } - } - - if (relayPort == 0) - { - for (int i=0; i<MAX_MEDIA_RELAYS; ++i) - { - StunMediaRelay* relay = &info.relays[i]; - if (relay->fd == 0) - { - if ( verbose ) clog << "Open relay port " << relay->relayPort << endl; - - relay->fd = openPort(relay->relayPort, info.myAddr.addr, verbose); - relay->destination.addr = from.addr; - relay->destination.port = from.port; - relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; - relayPort = relay->relayPort; - break; - } - } - } - } - - if ( !ok ) - { - if ( verbose ) clog << "Get message did not return a valid message" <<endl; - return true; - } - - if ( verbose ) clog << "Got a request (len=" << msgLen << ") from " << from << endl; - - if ( msgLen <= 0 ) - { - return true; - } - - bool changePort = false; - bool changeIp = false; - - StunMessage resp; - StunAddress4 dest; - StunAtrString hmacPassword; - hmacPassword.sizeValue = 0; - - StunAddress4 secondary; - secondary.port = 0; - secondary.addr = 0; - - if (info.relay && relayPort) - { - secondary = from; - - from.addr = info.myAddr.addr; - from.port = relayPort; - } - - ok = stunServerProcessMsg( msg, msgLen, from, secondary, - recvAltIp ? info.altAddr : info.myAddr, - recvAltIp ? info.myAddr : info.altAddr, - &resp, - &dest, - &hmacPassword, - &changePort, - &changeIp, - verbose ); - - if ( !ok ) - { - if ( verbose ) clog << "Failed to parse message" << endl; - return true; - } - - char buf[STUN_MAX_MESSAGE_SIZE]; - int len = sizeof(buf); - - len = stunEncodeMessage( resp, buf, len, hmacPassword,verbose ); - - if ( dest.addr == 0 ) ok=false; - if ( dest.port == 0 ) ok=false; - - if ( ok ) - { - assert( dest.addr != 0 ); - assert( dest.port != 0 ); - - Socket sendFd; - - bool sendAltIp = recvAltIp; // send on the received IP address - bool sendAltPort = recvAltPort; // send on the received port - - if ( changeIp ) sendAltIp = !sendAltIp; // if need to change IP, then flip logic - if ( changePort ) sendAltPort = !sendAltPort; // if need to change port, then flip logic - - if ( !sendAltPort ) - { - if ( !sendAltIp ) - { - sendFd = info.myFd; - } - else - { - sendFd = info.altIpFd; - } - } - else - { - if ( !sendAltIp ) - { - sendFd = info.altPortFd; - } - else - { - sendFd = info.altIpPortFd; - } - } - - if ( sendFd != INVALID_SOCKET ) - { - sendMessage( sendFd, buf, len, dest.addr, dest.port, verbose ); - } - } - } - - return true; -} - -int -stunFindLocalInterfaces(UInt32* addresses,int maxRet) -{ -#if defined(WIN32) || defined(__sparc__) - return 0; -#else - struct ifconf ifc; - - int s = socket( AF_INET, SOCK_DGRAM, 0 ); - int len = 100 * sizeof(struct ifreq); - - char buf[ len ]; - - ifc.ifc_len = len; - ifc.ifc_buf = buf; - - int e = ioctl(s,SIOCGIFCONF,&ifc); - char *ptr = buf; - int tl = ifc.ifc_len; - int count=0; - - while ( (tl > 0) && ( count < maxRet) ) - { - struct ifreq* ifr = (struct ifreq *)ptr; - - int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr); - tl -= si; - ptr += si; - //char* name = ifr->ifr_ifrn.ifrn_name; - //cerr << "name = " << name << endl; - - struct ifreq ifr2; - ifr2 = *ifr; - - e = ioctl(s,SIOCGIFADDR,&ifr2); - if ( e == -1 ) - { - break; - } - - //cerr << "ioctl addr e = " << e << endl; - - struct sockaddr a = ifr2.ifr_addr; - struct sockaddr_in* addr = (struct sockaddr_in*) &a; - - UInt32 ai = ntohl( addr->sin_addr.s_addr ); - if (int((ai>>24)&0xFF) != 127) - { - addresses[count++] = ai; - } - -#if 0 - cerr << "Detected interface " - << int((ai>>24)&0xFF) << "." - << int((ai>>16)&0xFF) << "." - << int((ai>> 8)&0xFF) << "." - << int((ai )&0xFF) << endl; -#endif - } - - closesocket(s); - - return count; -#endif -} - - -void -stunBuildReqSimple( StunMessage* msg, - const StunAtrString& username, - bool changePort, bool changeIp, unsigned int id ) -{ - assert( msg ); - memset( msg , 0 , sizeof(*msg) ); - - msg->msgHdr.msgType = BindRequestMsg; - - for ( int i=0; i<16; i=i+4 ) - { - assert(i+3<16); - int r = stunRand(); - msg->msgHdr.id.octet[i+0]= r>>0; - msg->msgHdr.id.octet[i+1]= r>>8; - msg->msgHdr.id.octet[i+2]= r>>16; - msg->msgHdr.id.octet[i+3]= r>>24; - } - - if ( id != 0 ) - { - msg->msgHdr.id.octet[0] = id; - } - - msg->hasChangeRequest = true; - msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | - (changePort?ChangePortFlag:0); - - if ( username.sizeValue > 0 ) - { - msg->hasUsername = true; - msg->username = username; - } -} - - -static void -stunSendTest( Socket myFd, StunAddress4& dest, - const StunAtrString& username, const StunAtrString& password, - int testNum, bool verbose ) -{ - assert( dest.addr != 0 ); - assert( dest.port != 0 ); - - bool changePort=false; - bool changeIP=false; - bool discard=false; - - switch (testNum) - { - case 1: - case 10: - case 11: - break; - case 2: - //changePort=true; - changeIP=true; - break; - case 3: - changePort=true; - break; - case 4: - changeIP=true; - break; - case 5: - discard=true; - break; - default: - cerr << "Test " << testNum <<" is unkown\n"; - assert(0); - } - - StunMessage req; - memset(&req, 0, sizeof(StunMessage)); - - stunBuildReqSimple( &req, username, - changePort , changeIP , - testNum ); - - char buf[STUN_MAX_MESSAGE_SIZE]; - int len = STUN_MAX_MESSAGE_SIZE; - - len = stunEncodeMessage( req, buf, len, password,verbose ); - - if ( verbose ) - { - clog << "About to send msg of len " << len << " to " << dest << endl; - } - - sendMessage( myFd, buf, len, dest.addr, dest.port, verbose ); - - // add some delay so the packets don't get sent too quickly -#ifdef WIN32 // !cj! TODO - should fix this up in windows - clock_t now = clock(); - assert( CLOCKS_PER_SEC == 1000 ); - while ( clock() <= now+10 ) { }; -#else - usleep(10*1000); -#endif - -} - - -void -stunGetUserNameAndPassword( const StunAddress4& dest, - StunAtrString* username, - StunAtrString* password) -{ - // !cj! This is totally bogus - need to make TLS connection to dest and get a - // username and password to use - stunCreateUserName(dest, username); - stunCreatePassword(*username, password); -} - - -void -stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* sAddr ) -{ - assert( dest.addr != 0 ); - assert( dest.port != 0 ); - - int port = randomPort(); - UInt32 interfaceIp=0; - if (sAddr) - { - interfaceIp = sAddr->addr; - if ( sAddr->port != 0 ) - { - port = sAddr->port; - } - } - Socket myFd = openPort(port,interfaceIp,verbose); - - StunAtrString username; - StunAtrString password; - - username.sizeValue = 0; - password.sizeValue = 0; - -#ifdef USE_TLS - stunGetUserNameAndPassword( dest, username, password ); -#endif - - stunSendTest( myFd, dest, username, password, testNum, verbose ); - - char msg[STUN_MAX_MESSAGE_SIZE]; - int msgLen = STUN_MAX_MESSAGE_SIZE; - - StunAddress4 from; - getMessage( myFd, - msg, - &msgLen, - &from.addr, - &from.port,verbose ); - - StunMessage resp; - memset(&resp, 0, sizeof(StunMessage)); - - if ( verbose ) clog << "Got a response" << endl; - bool ok = stunParseMessage( msg,msgLen, resp,verbose ); - - if ( verbose ) - { - clog << "\t ok=" << ok << endl; - clog << "\t id=" << resp.msgHdr.id << endl; - clog << "\t mappedAddr=" << resp.mappedAddress.ipv4 << endl; - clog << "\t changedAddr=" << resp.changedAddress.ipv4 << endl; - clog << endl; - } - - if (sAddr) - { - sAddr->port = resp.mappedAddress.ipv4.port; - sAddr->addr = resp.mappedAddress.ipv4.addr; - } -} - - -NatType -stunNatType( StunAddress4& dest, - bool verbose, - bool* preservePort, // if set, is return for if NAT preservers ports or not - bool* hairpin, // if set, is the return for if NAT will hairpin packets - int port, // port to use for the test, 0 to choose random port - StunAddress4* sAddr // NIC to use - ) -{ - assert( dest.addr != 0 ); - assert( dest.port != 0 ); - - if ( hairpin ) - { - *hairpin = false; - } - - if ( port == 0 ) - { - port = randomPort(); - } - UInt32 interfaceIp=0; - if (sAddr) - { - interfaceIp = sAddr->addr; - } - Socket myFd1 = openPort(port,interfaceIp,verbose); - Socket myFd2 = openPort(port+1,interfaceIp,verbose); - - if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) ) - { - cerr << "Some problem opening port/interface to send on" << endl; - return StunTypeFailure; - } - - assert( myFd1 != INVALID_SOCKET ); - assert( myFd2 != INVALID_SOCKET ); - - bool respTestI=false; - bool isNat=true; - StunAddress4 testIchangedAddr; - StunAddress4 testImappedAddr; - bool respTestI2=false; - bool mappedIpSame = true; - StunAddress4 testI2mappedAddr; - StunAddress4 testI2dest=dest; - bool respTestII=false; - bool respTestIII=false; - - bool respTestHairpin=false; - - memset(&testImappedAddr,0,sizeof(testImappedAddr)); - - StunAtrString username; - StunAtrString password; - - username.sizeValue = 0; - password.sizeValue = 0; - -#ifdef USE_TLS - stunGetUserNameAndPassword( dest, username, password ); -#endif - - //stunSendTest( myFd1, dest, username, password, 1, verbose ); - int count=0; - while ( count < 7 ) - { - struct timeval tv; - fd_set fdSet; -#ifdef WIN32 - unsigned int fdSetSize; -#else - int fdSetSize; -#endif - FD_ZERO(&fdSet); fdSetSize=0; - FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize; - FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize; - tv.tv_sec=0; - tv.tv_usec=150*1000; // 150 ms - if ( count == 0 ) tv.tv_usec=0; - - int err = select(fdSetSize, &fdSet, NULL, NULL, &tv); - int e = getErrno(); - if ( err == SOCKET_ERROR ) - { - // error occured - cerr << "Error " << e << " " << strerror(e) << " in select" << endl; - return StunTypeFailure; - } - else if ( err == 0 ) - { - // timeout occured - count++; - - if ( !respTestI ) - { - stunSendTest( myFd1, dest, username, password, 1 ,verbose ); - } - - if ( (!respTestI2) && respTestI ) - { - // check the address to send to if valid - if ( ( testI2dest.addr != 0 ) && - ( testI2dest.port != 0 ) ) - { - stunSendTest( myFd1, testI2dest, username, password, 10 ,verbose); - } - } - - if ( !respTestII ) - { - stunSendTest( myFd2, dest, username, password, 2 ,verbose ); - } - - if ( !respTestIII ) - { - stunSendTest( myFd2, dest, username, password, 3 ,verbose ); - } - - if ( respTestI && (!respTestHairpin) ) - { - if ( ( testImappedAddr.addr != 0 ) && - ( testImappedAddr.port != 0 ) ) - { - stunSendTest( myFd1, testImappedAddr, username, password, 11 ,verbose ); - } - } - } - else - { - //if (verbose) clog << "-----------------------------------------" << endl; - assert( err>0 ); - // data is avialbe on some fd - - for ( int i=0; i<2; i++) - { - Socket myFd; - if ( i==0 ) - { - myFd=myFd1; - } - else - { - myFd=myFd2; - } - - if ( myFd!=INVALID_SOCKET ) - { - if ( FD_ISSET(myFd,&fdSet) ) - { - char msg[STUN_MAX_MESSAGE_SIZE]; - int msgLen = sizeof(msg); - - StunAddress4 from; - - getMessage( myFd, - msg, - &msgLen, - &from.addr, - &from.port,verbose ); - - StunMessage resp; - memset(&resp, 0, sizeof(StunMessage)); - - stunParseMessage( msg,msgLen, resp,verbose ); - - if ( verbose ) - { - clog << "Received message of type " << resp.msgHdr.msgType - << " id=" << (int)(resp.msgHdr.id.octet[0]) << endl; - } - - switch( resp.msgHdr.id.octet[0] ) - { - case 1: - { - if ( !respTestI ) - { - - testIchangedAddr.addr = resp.changedAddress.ipv4.addr; - testIchangedAddr.port = resp.changedAddress.ipv4.port; - testImappedAddr.addr = resp.mappedAddress.ipv4.addr; - testImappedAddr.port = resp.mappedAddress.ipv4.port; - - if ( preservePort ) - { - *preservePort = ( testImappedAddr.port == port ); - } - - testI2dest.addr = resp.changedAddress.ipv4.addr; - - if (sAddr) - { - sAddr->port = testImappedAddr.port; - sAddr->addr = testImappedAddr.addr; - } - - count = 0; - } - respTestI=true; - } - break; - case 2: - { - respTestII=true; - } - break; - case 3: - { - respTestIII=true; - } - break; - case 10: - { - if ( !respTestI2 ) - { - testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr; - testI2mappedAddr.port = resp.mappedAddress.ipv4.port; - - mappedIpSame = false; - if ( (testI2mappedAddr.addr == testImappedAddr.addr ) && - (testI2mappedAddr.port == testImappedAddr.port )) - { - mappedIpSame = true; - } - - - } - respTestI2=true; - } - break; - case 11: - { - - if ( hairpin ) - { - *hairpin = true; - } - respTestHairpin = true; - } - break; - } - } - } - } - } - } - - // see if we can bind to this address - //cerr << "try binding to " << testImappedAddr << endl; - Socket s = openPort( 0/*use ephemeral*/, testImappedAddr.addr, false ); - if ( s != INVALID_SOCKET ) - { - closesocket(s); - isNat = false; - //cerr << "binding worked" << endl; - } - else - { - isNat = true; - //cerr << "binding failed" << endl; - } - - if (verbose) - { - clog << "test I = " << respTestI << endl; - clog << "test II = " << respTestII << endl; - clog << "test III = " << respTestIII << endl; - clog << "test I(2) = " << respTestI2 << endl; - clog << "is nat = " << isNat <<endl; - clog << "mapped IP same = " << mappedIpSame << endl; - } - - // implement logic flow chart from draft RFC - if ( respTestI ) - { - if ( isNat ) - { - if (respTestII) - { - return StunTypeConeNat; - } - else - { - if ( mappedIpSame ) - { - if ( respTestIII ) - { - return StunTypeRestrictedNat; - } - else - { - return StunTypePortRestrictedNat; - } - } - else - { - return StunTypeSymNat; - } - } - } - else - { - if (respTestII) - { - return StunTypeOpen; - } - else - { - return StunTypeSymFirewall; - } - } - } - else - { - return StunTypeBlocked; - } - - return StunTypeUnknown; -} - - -int -stunOpenSocket( StunAddress4& dest, StunAddress4* mapAddr, - int port, StunAddress4* srcAddr, - bool verbose ) -{ - assert( dest.addr != 0 ); - assert( dest.port != 0 ); - assert( mapAddr ); - - if ( port == 0 ) - { - port = randomPort(); - } - unsigned int interfaceIp = 0; - if ( srcAddr ) - { - interfaceIp = srcAddr->addr; - } - - Socket myFd = openPort(port,interfaceIp,verbose); - if (myFd == INVALID_SOCKET) - { - return myFd; - } - - char msg[STUN_MAX_MESSAGE_SIZE]; - int msgLen = sizeof(msg); - - StunAtrString username; - StunAtrString password; - - username.sizeValue = 0; - password.sizeValue = 0; - -#ifdef USE_TLS - stunGetUserNameAndPassword( dest, username, password ); -#endif - - stunSendTest(myFd, dest, username, password, 1, 0/*false*/ ); - - StunAddress4 from; - - getMessage( myFd, msg, &msgLen, &from.addr, &from.port,verbose ); - - StunMessage resp; - memset(&resp, 0, sizeof(StunMessage)); - - bool ok = stunParseMessage( msg, msgLen, resp,verbose ); - if (!ok) - { - return -1; - } - - StunAddress4 mappedAddr = resp.mappedAddress.ipv4; - StunAddress4 changedAddr = resp.changedAddress.ipv4; - - //clog << "--- stunOpenSocket --- " << endl; - //clog << "\treq id=" << req.id << endl; - //clog << "\tresp id=" << id << endl; - //clog << "\tmappedAddr=" << mappedAddr << endl; - - *mapAddr = mappedAddr; - - return myFd; -} - - -bool -stunOpenSocketPair( StunAddress4& dest, StunAddress4* mapAddr, - int* fd1, int* fd2, - int port, StunAddress4* srcAddr, - bool verbose ) -{ - assert( dest.addr!= 0 ); - assert( dest.port != 0 ); - assert( mapAddr ); - - const int NUM=3; - - if ( port == 0 ) - { - port = randomPort(); - } - - *fd1=-1; - *fd2=-1; - - char msg[STUN_MAX_MESSAGE_SIZE]; - int msgLen =sizeof(msg); - - StunAddress4 from; - int fd[NUM]; - int i; - - unsigned int interfaceIp = 0; - if ( srcAddr ) - { - interfaceIp = srcAddr->addr; - } - - for( i=0; i<NUM; i++) - { - fd[i] = openPort( (port == 0) ? 0 : (port + i), - interfaceIp, verbose); - if (fd[i] < 0) - { - while (i > 0) - { - closesocket(fd[--i]); - } - return false; - } - } - - StunAtrString username; - StunAtrString password; - - username.sizeValue = 0; - password.sizeValue = 0; - -#ifdef USE_TLS - stunGetUserNameAndPassword( dest, username, password ); -#endif - - for( i=0; i<NUM; i++) - { - stunSendTest(fd[i], dest, username, password, 1/*testNum*/, verbose ); - } - - StunAddress4 mappedAddr[NUM]; - for( i=0; i<NUM; i++) - { - msgLen = sizeof(msg)/sizeof(*msg); - getMessage( fd[i], - msg, - &msgLen, - &from.addr, - &from.port ,verbose); - - StunMessage resp; - memset(&resp, 0, sizeof(StunMessage)); - - bool ok = stunParseMessage( msg, msgLen, resp, verbose ); - if (!ok) - { - return false; - } - - mappedAddr[i] = resp.mappedAddress.ipv4; - StunAddress4 changedAddr = resp.changedAddress.ipv4; - } - - if (verbose) - { - clog << "--- stunOpenSocketPair --- " << endl; - for( i=0; i<NUM; i++) - { - clog << "\t mappedAddr=" << mappedAddr[i] << endl; - } - } - - if ( mappedAddr[0].port %2 == 0 ) - { - if ( mappedAddr[0].port+1 == mappedAddr[1].port ) - { - *mapAddr = mappedAddr[0]; - *fd1 = fd[0]; - *fd2 = fd[1]; - closesocket( fd[2] ); - return true; - } - } - else - { - if (( mappedAddr[1].port %2 == 0 ) - && ( mappedAddr[1].port+1 == mappedAddr[2].port )) - { - *mapAddr = mappedAddr[1]; - *fd1 = fd[1]; - *fd2 = fd[2]; - closesocket( fd[0] ); - return true; - } - } - - // something failed, close all and return error - for( i=0; i<NUM; i++) - { - closesocket( fd[i] ); - } - - return false; -} -// Local Variables: -// mode:c++ -// c-file-style:"ellemtel" -// c-file-offsets:((case-label . +)) -// indent-tabs-mode:nil -// End: - - diff --git a/sflphone-common/libs/stund/stun.h b/sflphone-common/libs/stund/stun.h deleted file mode 100644 index c67b7014f57ff4f340e92dc70cd83bf62b1b1776..0000000000000000000000000000000000000000 --- a/sflphone-common/libs/stund/stun.h +++ /dev/null @@ -1,390 +0,0 @@ -/* ==================================================================== - * The Vovida Software License, Version 1.0 - * - * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The names "VOCAL", "Vovida Open Communication Application Library", - * and "Vovida Open Communication Application Library (VOCAL)" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact vocal@vovida.org. - * - * 4. Products derived from this software may not be called "VOCAL", nor - * may "VOCAL" appear in their name, without prior written - * permission of Vovida Networks, Inc. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA - * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES - * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * ==================================================================== - * - * This software consists of voluntary contributions made by Vovida - * Networks, Inc. and many individuals on behalf of Vovida Networks, - * Inc. For more information on Vovida Networks, Inc., please see - * <http://www.vovida.org/>. - * - */ - - - -#ifndef STUN_H -#define STUN_H - -#include <iostream> -#include <time.h> -#include "udp.h" -// if you change this version, change in makefile too -#define STUN_VERSION "0.94" - -#define STUN_MAX_STRING 256 -#define STUN_MAX_UNKNOWN_ATTRIBUTES 8 -#define STUN_MAX_MESSAGE_SIZE 2048 - -#define STUN_PORT 3478 - -// define some basic types -typedef unsigned char UInt8; -typedef unsigned short UInt16; -typedef unsigned int UInt32; -#if defined( WIN32 ) -typedef unsigned __int64 UInt64; -#else -typedef unsigned long long UInt64; -#endif -typedef struct { unsigned char octet[16]; } UInt128; - -/// define a structure to hold a stun address -const UInt8 IPv4Family = 0x01; -const UInt8 IPv6Family = 0x02; - -// define flags -const UInt32 ChangeIpFlag = 0x04; -const UInt32 ChangePortFlag = 0x02; - -// define stun attribute -const UInt16 MappedAddress = 0x0001; -const UInt16 ResponseAddress = 0x0002; -const UInt16 ChangeRequest = 0x0003; -const UInt16 SourceAddress = 0x0004; -const UInt16 ChangedAddress = 0x0005; -const UInt16 Username = 0x0006; -const UInt16 Password = 0x0007; -const UInt16 MessageIntegrity = 0x0008; -const UInt16 ErrorCode = 0x0009; -const UInt16 UnknownAttribute = 0x000A; -const UInt16 ReflectedFrom = 0x000B; -const UInt16 XorMappedAddress = 0x0020; -const UInt16 XorOnly = 0x0021; -const UInt16 ServerName = 0x0022; -const UInt16 SecondaryAddress = 0x0050; // Non standard extention - -// define types for a stun message -const UInt16 BindRequestMsg = 0x0001; -const UInt16 BindResponseMsg = 0x0101; -const UInt16 BindErrorResponseMsg = 0x0111; -const UInt16 SharedSecretRequestMsg = 0x0002; -const UInt16 SharedSecretResponseMsg = 0x0102; -const UInt16 SharedSecretErrorResponseMsg = 0x0112; - -typedef struct -{ - UInt16 msgType; - UInt16 msgLength; - UInt128 id; -} StunMsgHdr; - - -typedef struct -{ - UInt16 type; - UInt16 length; -} StunAtrHdr; - -typedef struct -{ - UInt16 port; - UInt32 addr; -} StunAddress4; - -typedef struct -{ - UInt8 pad; - UInt8 family; - StunAddress4 ipv4; -} StunAtrAddress4; - -typedef struct -{ - UInt32 value; -} StunAtrChangeRequest; - -typedef struct -{ - UInt16 pad; // all 0 - UInt8 errorClass; - UInt8 number; - char reason[STUN_MAX_STRING]; - UInt16 sizeReason; -} StunAtrError; - -typedef struct -{ - UInt16 attrType[STUN_MAX_UNKNOWN_ATTRIBUTES]; - UInt16 numAttributes; -} StunAtrUnknown; - -typedef struct -{ - char value[STUN_MAX_STRING]; - UInt16 sizeValue; -} StunAtrString; - -typedef struct -{ - char hash[20]; -} StunAtrIntegrity; - -typedef enum -{ - HmacUnkown=0, - HmacOK, - HmacBadUserName, - HmacUnkownUserName, - HmacFailed, -} StunHmacStatus; - -typedef struct -{ - StunMsgHdr msgHdr; - - bool hasMappedAddress; - StunAtrAddress4 mappedAddress; - - bool hasResponseAddress; - StunAtrAddress4 responseAddress; - - bool hasChangeRequest; - StunAtrChangeRequest changeRequest; - - bool hasSourceAddress; - StunAtrAddress4 sourceAddress; - - bool hasChangedAddress; - StunAtrAddress4 changedAddress; - - bool hasUsername; - StunAtrString username; - - bool hasPassword; - StunAtrString password; - - bool hasMessageIntegrity; - StunAtrIntegrity messageIntegrity; - - bool hasErrorCode; - StunAtrError errorCode; - - bool hasUnknownAttributes; - StunAtrUnknown unknownAttributes; - - bool hasReflectedFrom; - StunAtrAddress4 reflectedFrom; - - bool hasXorMappedAddress; - StunAtrAddress4 xorMappedAddress; - - bool xorOnly; - - bool hasServerName; - StunAtrString serverName; - - bool hasSecondaryAddress; - StunAtrAddress4 secondaryAddress; -} StunMessage; - - -// Define enum with different types of NAT -typedef enum -{ - StunTypeUnknown=0, - StunTypeOpen, - StunTypeConeNat, - StunTypeRestrictedNat, - StunTypePortRestrictedNat, - StunTypeSymNat, - StunTypeSymFirewall, - StunTypeBlocked, - StunTypeFailure -} NatType; - -#ifdef WIN32 -typedef SOCKET Socket; -#else -#endif - -#define MAX_MEDIA_RELAYS 500 -#define MAX_RTP_MSG_SIZE 1500 -#define MEDIA_RELAY_TIMEOUT 3*60 - -typedef struct -{ - int relayPort; // media relay port - int fd; // media relay file descriptor - StunAddress4 destination; // NAT IP:port - time_t expireTime; // if no activity after time, close the socket -} StunMediaRelay; - -typedef struct -{ - StunAddress4 myAddr; - StunAddress4 altAddr; - Socket myFd; - Socket altPortFd; - Socket altIpFd; - Socket altIpPortFd; - bool relay; // true if media relaying is to be done - StunMediaRelay relays[MAX_MEDIA_RELAYS]; -} StunServerInfo; - -bool -stunParseMessage( char* buf, - unsigned int bufLen, - StunMessage& message, - bool verbose ); - -void -stunBuildReqSimple( StunMessage* msg, - const StunAtrString& username, - bool changePort, bool changeIp, unsigned int id=0 ); - -unsigned int -stunEncodeMessage( const StunMessage& message, - char* buf, - unsigned int bufLen, - const StunAtrString& password, - bool verbose); - -void -stunCreateUserName(const StunAddress4& addr, StunAtrString* username); - -void -stunGetUserNameAndPassword( const StunAddress4& dest, - StunAtrString* username, - StunAtrString* password); - -void -stunCreatePassword(const StunAtrString& username, StunAtrString* password); - -int -stunRand(); - -UInt64 -stunGetSystemTimeSecs(); - -/// find the IP address of a the specified stun server - return false is fails parse -bool -stunParseServerName( char* serverName, StunAddress4& stunServerAddr); - -bool -stunParseHostName( char* peerName, - UInt32& ip, - UInt16& portVal, - UInt16 defaultPort ); - -/// return true if all is OK -/// Create a media relay and do the STERN thing if startMediaPort is non-zero -bool -stunInitServer(StunServerInfo& info, - const StunAddress4& myAddr, - const StunAddress4& altAddr, - int startMediaPort, - bool verbose); - -void -stunStopServer(StunServerInfo& info); - -/// return true if all is OK -bool -stunServerProcess(StunServerInfo& info, bool verbose); - -/// returns number of address found - take array or addres -int -stunFindLocalInterfaces(UInt32* addresses, int maxSize ); - -void -stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* srcAddr=0 ); - -NatType -stunNatType( StunAddress4& dest, bool verbose, - bool* preservePort=0, // if set, is return for if NAT preservers ports or not - bool* hairpin=0 , // if set, is the return for if NAT will hairpin packets - int port=0, // port to use for the test, 0 to choose random port - StunAddress4* sAddr=0 // NIC to use - ); - -/// prints a StunAddress -std::ostream& -operator<<( std::ostream& strm, const StunAddress4& addr); - -std::ostream& -operator<< ( std::ostream& strm, const UInt128& ); - - -bool -stunServerProcessMsg( char* buf, - unsigned int bufLen, - StunAddress4& from, - StunAddress4& myAddr, - StunAddress4& altAddr, - StunMessage* resp, - StunAddress4* destination, - StunAtrString* hmacPassword, - bool* changePort, - bool* changeIp, - bool verbose); - -int -stunOpenSocket( StunAddress4& dest, - StunAddress4* mappedAddr, - int port=0, - StunAddress4* srcAddr=0, - bool verbose=false ); - -bool -stunOpenSocketPair( StunAddress4& dest, StunAddress4* mappedAddr, - int* fd1, int* fd2, - int srcPort=0, StunAddress4* srcAddr=0, - bool verbose=false); - -#endif - - -// Local Variables: -// mode:c++ -// c-file-style:"ellemtel" -// c-file-offsets:((case-label . +)) -// indent-tabs-mode:nil -// End: - diff --git a/sflphone-common/libs/stund/udp.cxx b/sflphone-common/libs/stund/udp.cxx deleted file mode 100644 index 23f3aaadc6d8b567189b855e74a69fa70d2661d3..0000000000000000000000000000000000000000 --- a/sflphone-common/libs/stund/udp.cxx +++ /dev/null @@ -1,350 +0,0 @@ -/* ==================================================================== - * The Vovida Software License, Version 1.0 - * - * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The names "VOCAL", "Vovida Open Communication Application Library", - * and "Vovida Open Communication Application Library (VOCAL)" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact vocal@vovida.org. - * - * 4. Products derived from this software may not be called "VOCAL", nor - * may "VOCAL" appear in their name, without prior written - * permission of Vovida Networks, Inc. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA - * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES - * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * ==================================================================== - * - * This software consists of voluntary contributions made by Vovida - * Networks, Inc. and many individuals on behalf of Vovida Networks, - * Inc. For more information on Vovida Networks, Inc., please see - * <http://www.vovida.org/>. - * - */ - - - -#include <cassert> -#include <cstdio> -#include <cstring> -#include <errno.h> -#include <iostream> -#include <cstdlib> -#include <time.h> - -#ifdef WIN32 - -#include <winsock2.h> -#include <stdlib.h> -#include <io.h> - -#else - -#include <arpa/inet.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <netdb.h> -#include <string.h> -#include <unistd.h> - -#endif - -#include <string.h> - -#include "udp.h" - -using namespace std; - - -Socket -openPort( unsigned short port, unsigned int interfaceIp, bool verbose ) -{ - Socket fd; - - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if ( fd == INVALID_SOCKET ) - { - int err = getErrno(); - cerr << "Could not create a UDP socket:" << err << endl; - return INVALID_SOCKET; - } - - struct sockaddr_in addr; - memset((char*) &(addr),0, sizeof((addr))); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(port); - - if ( (interfaceIp != 0) && - ( interfaceIp != 0x100007f ) ) - { - addr.sin_addr.s_addr = htonl(interfaceIp); - if (verbose ) - { - clog << "Binding to interface " - << hex << "0x" << htonl(interfaceIp) << dec << endl; - } - } - - if ( bind( fd,(struct sockaddr*)&addr, sizeof(addr)) != 0 ) - { - int e = getErrno(); - - switch (e) - { - case 0: - { - cerr << "Could not bind socket" << endl; - return INVALID_SOCKET; - } - case EADDRINUSE: - { - cerr << "Port " << port << " for receiving UDP is in use" << endl; - return INVALID_SOCKET; - } - break; - case EADDRNOTAVAIL: - { - if ( verbose ) - { - cerr << "Cannot assign requested address" << endl; - } - return INVALID_SOCKET; - } - break; - default: - { - cerr << "Could not bind UDP receive port" - << "Error=" << e << " " << strerror(e) << endl; - return INVALID_SOCKET; - } - break; - } - } - if ( verbose ) - { - clog << "Opened port " << port << " with fd " << fd << endl; - } - - assert( fd != INVALID_SOCKET ); - - return fd; -} - - -bool -getMessage( Socket fd, char* buf, int* len, - unsigned int* srcIp, unsigned short* srcPort, - bool verbose) -{ - assert( fd != INVALID_SOCKET ); - - int originalSize = *len; - assert( originalSize > 0 ); - - struct sockaddr_in from; - int fromLen = sizeof(from); - - *len = recvfrom(fd, - buf, - originalSize, - 0, - (struct sockaddr *)&from, - (socklen_t*)&fromLen); - - if ( *len == SOCKET_ERROR ) - { - int err = getErrno(); - - switch (err) - { - case ENOTSOCK: - cerr << "Error fd not a socket" << endl; - break; - case ECONNRESET: - cerr << "Error connection reset - host not reachable" << endl; - break; - - default: - cerr << "Socket Error=" << err << endl; - } - - return false; - } - - if ( *len < 0 ) - { - clog << "socket closed? negative len" << endl; - return false; - } - - if ( *len == 0 ) - { - clog << "socket closed? zero len" << endl; - return false; - } - - *srcPort = ntohs(from.sin_port); - *srcIp = ntohl(from.sin_addr.s_addr); - - if ( (*len)+1 >= originalSize ) - { - if (verbose) - { - clog << "Received a message that was too large" << endl; - } - return false; - } - buf[*len]=0; - - return true; -} - - -bool -sendMessage( Socket fd, char* buf, int l, - unsigned int dstIp, unsigned short dstPort, - bool verbose) -{ - assert( fd != INVALID_SOCKET ); - - int s; - if ( dstPort == 0 ) - { - // sending on a connected port - assert( dstIp == 0 ); - - s = send(fd,buf,l,0); - } - else - { - assert( dstIp != 0 ); - assert( dstPort != 0 ); - - struct sockaddr_in to; - int toLen = sizeof(to); - memset(&to,0,toLen); - - to.sin_family = AF_INET; - to.sin_port = htons(dstPort); - to.sin_addr.s_addr = htonl(dstIp); - - s = sendto(fd, buf, l, 0,(sockaddr*)&to, toLen); - } - - if ( s == SOCKET_ERROR ) - { - int e = getErrno(); - switch (e) - { - case ECONNREFUSED: - case EHOSTDOWN: - case EHOSTUNREACH: - { - // quietly ignore this - } - break; - case EAFNOSUPPORT: - { - cerr << "err EAFNOSUPPORT in send" << endl; - } - break; - default: - { - cerr << "err " << e << " " << strerror(e) << " in send" << endl; - } - } - return false; - } - - if ( s == 0 ) - { - cerr << "no data sent in send" << endl; - return false; - } - - if ( s != l ) - { - if (verbose) - { - cerr << "only " << s << " out of " << l << " bytes sent" << endl; - } - return false; - } - - return true; -} - - -void -initNetwork() -{ -#ifdef WIN32 - WORD wVersionRequested = MAKEWORD( 2, 2 ); - WSADATA wsaData; - int err; - - err = WSAStartup( wVersionRequested, &wsaData ); - if ( err != 0 ) - { - // could not find a usable WinSock DLL - cerr << "Could not load winsock" << endl; - assert(0); // is this is failing, try a different version that 2.2, 1.0 or later will likely work - exit(1); - } - - /* Confirm that the WinSock DLL supports 2.2.*/ - /* Note that if the DLL supports versions greater */ - /* than 2.2 in addition to 2.2, it will still return */ - /* 2.2 in wVersion since that is the version we */ - /* requested. */ - - if ( LOBYTE( wsaData.wVersion ) != 2 || - HIBYTE( wsaData.wVersion ) != 2 ) - { - /* Tell the user that we could not find a usable */ - /* WinSock DLL. */ - WSACleanup( ); - cerr << "Bad winsock verion" << endl; - assert(0); // is this is failing, try a different version that 2.2, 1.0 or later will likely work - exit(1); - } -#endif -} - -// Local Variables: -// mode:c++ -// c-file-style:"ellemtel" -// c-file-offsets:((case-label . +)) -// indent-tabs-mode:nil -// End: diff --git a/sflphone-common/libs/stund/udp.h b/sflphone-common/libs/stund/udp.h deleted file mode 100644 index 8eeb8fb88d4dcceee3ac7abddb4e8359e789ffdd..0000000000000000000000000000000000000000 --- a/sflphone-common/libs/stund/udp.h +++ /dev/null @@ -1,158 +0,0 @@ -/* ==================================================================== - * The Vovida Software License, Version 1.0 - * - * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The names "VOCAL", "Vovida Open Communication Application Library", - * and "Vovida Open Communication Application Library (VOCAL)" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact vocal@vovida.org. - * - * 4. Products derived from this software may not be called "VOCAL", nor - * may "VOCAL" appear in their name, without prior written - * permission of Vovida Networks, Inc. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA - * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES - * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * ==================================================================== - * - * This software consists of voluntary contributions made by Vovida - * Networks, Inc. and many individuals on behalf of Vovida Networks, - * Inc. For more information on Vovida Networks, Inc., please see - * <http://www.vovida.org/>. - * - */ - - - -#ifndef udp_h -#define udp_h - - -#ifdef __MACH__ -typedef int socklen_t; -#endif - -#include <errno.h> - -#ifdef WIN32 - -#include <winsock2.h> -#include <io.h> - -typedef int socklen_t; -typedef SOCKET Socket; - -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EINPROGRESS WSAEINPROGRESS -#define EALREADY WSAEALREADY -#define ENOTSOCK WSAENOTSOCK -#define EDESTADDRREQ WSAEDESTADDRREQ -#define EMSGSIZE WSAEMSGSIZE -#define EPROTOTYPE WSAEPROTOTYPE -#define ENOPROTOOPT WSAENOPROTOOPT -#define EPROTONOSUPPORT WSAEPROTONOSUPPORT -#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT -#define EOPNOTSUPP WSAEOPNOTSUPP -#define EPFNOSUPPORT WSAEPFNOSUPPORT -#define EAFNOSUPPORT WSAEAFNOSUPPORT -#define EADDRINUSE WSAEADDRINUSE -#define EADDRNOTAVAIL WSAEADDRNOTAVAIL -#define ENETDOWN WSAENETDOWN -#define ENETUNREACH WSAENETUNREACH -#define ENETRESET WSAENETRESET -#define ECONNABORTED WSAECONNABORTED -#define ECONNRESET WSAECONNRESET -#define ENOBUFS WSAENOBUFS -#define EISCONN WSAEISCONN -#define ENOTCONN WSAENOTCONN -#define ESHUTDOWN WSAESHUTDOWN -#define ETOOMANYREFS WSAETOOMANYREFS -#define ETIMEDOUT WSAETIMEDOUT -#define ECONNREFUSED WSAECONNREFUSED -#define ELOOP WSAELOOP -#define EHOSTDOWN WSAEHOSTDOWN -#define EHOSTUNREACH WSAEHOSTUNREACH -#define EPROCLIM WSAEPROCLIM -#define EUSERS WSAEUSERS -#define EDQUOT WSAEDQUOT -#define ESTALE WSAESTALE -#define EREMOTE WSAEREMOTE - -typedef LONGLONG Int64; -inline int getErrno() { return WSAGetLastError(); } - -#else - -//typedef int Socket; -#define Socket int -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 - -inline int closesocket( int fd ) { return close(fd); }; - -inline int getErrno() { return errno; } - -#define WSANOTINITIALISED EPROTONOSUPPORT - -#endif - -/// Open a UDP socket to receive on the given port - if port is 0, pick a a -/// port, if interfaceIp!=0 then use ONLY the interface specified instead of -/// all of them -int -openPort( unsigned short port, unsigned int interfaceIp, - bool verbose); - - -/// recive a UDP message -bool -getMessage( int fd, char* buf, int* len, - unsigned int* srcIp, unsigned short* srcPort, - bool verbose); - - -/// send a UDP message -bool -sendMessage( int fd, char* msg, int len, - unsigned int dstIp, unsigned short dstPort, - bool verbose); - - -/// set up network - does nothing in unix but needed for windows -void -initNetwork(); - -// Local Variables: -// mode:c++ -// c-file-style:"ellemtel" -// c-file-offsets:((case-label . +)) -// indent-tabs-mode:nil -// End: - -#endif