#include <cassert>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <errno.h>
#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>
#include "stun_udp.h"
#include <time.h>
Go to the source code of this file.
Defines | |
#define | NOSSL |
Functions | |
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) |
static bool | stunParseAtrChangeRequest (char *body, unsigned int hdrLen, StunAtrChangeRequest &result) |
static bool | stunParseAtrError (char *body, unsigned int hdrLen, StunAtrError &result) |
static bool | stunParseAtrUnknown (char *body, unsigned int hdrLen, StunAtrUnknown &result) |
static bool | stunParseAtrString (char *body, unsigned int hdrLen, StunAtrString &result) |
static bool | stunParseAtrIntegrity (char *body, unsigned int hdrLen, StunAtrIntegrity &result) |
bool | stunParseMessage (char *buf, unsigned int bufLen, StunMessage &msg, bool verbose) |
static char * | encode16 (char *buf, UInt16 data) |
static char * | encode32 (char *buf, UInt32 data) |
static char * | encode (char *buf, const char *data, unsigned int length) |
static char * | encodeAtrAddress4 (char *ptr, UInt16 type, const StunAtrAddress4 &atr) |
static char * | encodeAtrChangeRequest (char *ptr, const StunAtrChangeRequest &atr) |
static char * | encodeAtrError (char *ptr, const StunAtrError &atr) |
static char * | encodeAtrUnknown (char *ptr, const StunAtrUnknown &atr) |
static char * | encodeXorOnly (char *ptr) |
static char * | encodeAtrString (char *ptr, UInt16 type, const StunAtrString &atr) |
static char * | encodeAtrIntegrity (char *ptr, const StunAtrIntegrity &atr) |
unsigned int | stunEncodeMessage (const StunMessage &msg, char *buf, unsigned int bufLen, const StunAtrString &password, bool verbose) |
int | stunRand () |
int | stunRandomPort () |
return a random number to use as a port | |
static void | toHex (const char *buffer, int bufferSize, char *output) |
void | stunCreateUserName (const StunAddress4 &source, StunAtrString *username) |
void | stunCreatePassword (const StunAtrString &username, StunAtrString *password) |
UInt64 | stunGetSystemTimeSecs () |
ostream & | operator<< (ostream &strm, const UInt128 &r) |
ostream & | operator<< (ostream &strm, const StunAddress4 &addr) |
bool | stunParseHostName (char *peerName, UInt32 &ip, UInt16 &portVal, UInt16 defaultPort) |
bool | stunParseServerName (char *name, StunAddress4 &addr) |
find the IP address of a the specified stun server - return false is fails parse | |
static void | stunCreateErrorResponse (StunMessage &response, int cl, int number, const char *msg) |
static void | stunCreateSharedSecretResponse (const StunMessage &request, const StunAddress4 &source, StunMessage &response) |
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) |
bool | stunInitServer (StunServerInfo &info, const StunAddress4 &myAddr, const StunAddress4 &altAddr, int startMediaPort, bool verbose) |
return true if all is OK Create a media relay and do the STERN thing if startMediaPort is non-zero | |
void | stunStopServer (StunServerInfo &info) |
bool | stunServerProcess (StunServerInfo &info, bool verbose) |
return true if all is OK | |
int | stunFindLocalInterfaces (UInt32 *addresses, int maxRet) |
returns number of address found - take array or addres | |
void | stunBuildReqSimple (StunMessage *msg, const StunAtrString &username, bool changePort, bool changeIp, unsigned int id) |
static void | stunSendTest (Socket myFd, StunAddress4 &dest, const StunAtrString &username, const StunAtrString &password, int testNum, bool verbose) |
void | stunGetUserNameAndPassword (const StunAddress4 &dest, StunAtrString *username, StunAtrString *password) |
void | stunTest (StunAddress4 &dest, int testNum, bool verbose, StunAddress4 *sAddr) |
NatType | stunNatType (StunAddress4 &dest, bool verbose, bool *preservePort, bool *hairpin, int port, StunAddress4 *sAddr) |
int | stunOpenSocket (StunAddress4 &dest, StunAddress4 *mapAddr, int port, StunAddress4 *srcAddr, bool verbose) |
bool | stunOpenSocketPair (StunAddress4 &dest, StunAddress4 *mapAddr, int *fd1, int *fd2, int port, StunAddress4 *srcAddr, bool verbose) |
static void computeHmac | ( | char * | hmac, | |
const char * | input, | |||
int | length, | |||
const char * | key, | |||
int | keySize | |||
) | [static] |
Definition at line 722 of file stun.cc.
Referenced by stunCreatePassword(), stunCreateUserName(), and stunEncodeMessage().
static char* encode | ( | char * | buf, | |
const char * | data, | |||
unsigned int | length | |||
) | [static] |
Definition at line 457 of file stun.cc.
Referenced by encodeAtrError(), encodeAtrIntegrity(), encodeAtrString(), and stunEncodeMessage().
static char* encode16 | ( | char * | buf, | |
UInt16 | data | |||
) | [static] |
Definition at line 440 of file stun.cc.
Referenced by encodeAtrAddress4(), encodeAtrChangeRequest(), encodeAtrError(), encodeAtrIntegrity(), encodeAtrString(), encodeAtrUnknown(), encodeXorOnly(), and stunEncodeMessage().
static char* encode32 | ( | char * | buf, | |
UInt32 | data | |||
) | [static] |
Definition at line 448 of file stun.cc.
Referenced by encodeAtrAddress4(), and encodeAtrChangeRequest().
static char* encodeAtrAddress4 | ( | char * | ptr, | |
UInt16 | type, | |||
const StunAtrAddress4 & | atr | |||
) | [static] |
Definition at line 465 of file stun.cc.
Referenced by stunEncodeMessage().
static char* encodeAtrChangeRequest | ( | char * | ptr, | |
const StunAtrChangeRequest & | atr | |||
) | [static] |
Definition at line 478 of file stun.cc.
Referenced by stunEncodeMessage().
00479 { 00480 ptr = encode16(ptr, ChangeRequest); 00481 ptr = encode16(ptr, 4); 00482 ptr = encode32(ptr, atr.value); 00483 return ptr; 00484 }
static char* encodeAtrError | ( | char * | ptr, | |
const StunAtrError & | atr | |||
) | [static] |
Definition at line 487 of file stun.cc.
Referenced by stunEncodeMessage().
00488 { 00489 ptr = encode16(ptr, ErrorCode); 00490 ptr = encode16(ptr, 6 + atr.sizeReason); 00491 ptr = encode16(ptr, atr.pad); 00492 *ptr++ = atr.errorClass; 00493 *ptr++ = atr.number; 00494 ptr = encode(ptr, atr.reason, atr.sizeReason); 00495 return ptr; 00496 }
static char* encodeAtrIntegrity | ( | char * | ptr, | |
const StunAtrIntegrity & | atr | |||
) | [static] |
Definition at line 533 of file stun.cc.
Referenced by stunEncodeMessage().
static char* encodeAtrString | ( | char * | ptr, | |
UInt16 | type, | |||
const StunAtrString & | atr | |||
) | [static] |
static char* encodeAtrUnknown | ( | char * | ptr, | |
const StunAtrUnknown & | atr | |||
) | [static] |
Definition at line 500 of file stun.cc.
Referenced by stunEncodeMessage().
00501 { 00502 ptr = encode16(ptr, UnknownAttribute); 00503 ptr = encode16(ptr, 2+2*atr.numAttributes); 00504 for (int i=0; i<atr.numAttributes; i++) 00505 { 00506 ptr = encode16(ptr, atr.attrType[i]); 00507 } 00508 return ptr; 00509 }
static char* encodeXorOnly | ( | char * | ptr | ) | [static] |
Definition at line 513 of file stun.cc.
Referenced by stunEncodeMessage().
ostream& operator<< | ( | ostream & | strm, | |
const StunAddress4 & | addr | |||
) |
ostream& operator<< | ( | ostream & | strm, | |
const UInt128 & | r | |||
) |
void stunBuildReqSimple | ( | StunMessage * | msg, | |
const StunAtrString & | username, | |||
bool | changePort, | |||
bool | changeIp, | |||
unsigned int | id | |||
) |
Definition at line 1696 of file stun.cc.
Referenced by stunSendTest().
01699 { 01700 assert( msg ); 01701 memset( msg , 0 , sizeof(*msg) ); 01702 01703 msg->msgHdr.msgType = BindRequestMsg; 01704 01705 for ( int i=0; i<16; i=i+4 ) 01706 { 01707 assert(i+3<16); 01708 int r = stunRand(); 01709 msg->msgHdr.id.octet[i+0]= r>>0; 01710 msg->msgHdr.id.octet[i+1]= r>>8; 01711 msg->msgHdr.id.octet[i+2]= r>>16; 01712 msg->msgHdr.id.octet[i+3]= r>>24; 01713 } 01714 01715 if ( id != 0 ) 01716 { 01717 msg->msgHdr.id.octet[0] = id; 01718 } 01719 01720 msg->hasChangeRequest = true; 01721 msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | 01722 (changePort?ChangePortFlag:0); 01723 01724 if ( username.sizeValue > 0 ) 01725 { 01726 msg->hasUsername = true; 01727 msg->username = username; 01728 } 01729 }
static void stunCreateErrorResponse | ( | StunMessage & | response, | |
int | cl, | |||
int | number, | |||
const char * | msg | |||
) | [static] |
Definition at line 979 of file stun.cc.
Referenced by stunServerProcessMsg().
00980 { 00981 response.msgHdr.msgType = BindErrorResponseMsg; 00982 response.hasErrorCode = true; 00983 response.errorCode.errorClass = cl; 00984 response.errorCode.number = number; 00985 strcpy(response.errorCode.reason, msg); 00986 }
void stunCreatePassword | ( | const StunAtrString & | username, | |
StunAtrString * | password | |||
) |
Definition at line 801 of file stun.cc.
Referenced by stunCreateSharedSecretResponse(), stunGetUserNameAndPassword(), and stunServerProcessMsg().
00802 { 00803 char hmac[20]; 00804 char key[] = "Fluffy"; 00805 //char buffer[STUN_MAX_STRING]; 00806 computeHmac(hmac, username.value, strlen(username.value), key, strlen(key)); 00807 toHex(hmac, 20, password->value); 00808 password->sizeValue = 40; 00809 password->value[40]=0; 00810 00811 //clog << "password=" << password->value << endl; 00812 }
static void stunCreateSharedSecretResponse | ( | const StunMessage & | request, | |
const StunAddress4 & | source, | |||
StunMessage & | response | |||
) | [static] |
Definition at line 1001 of file stun.cc.
Referenced by stunServerProcessMsg().
01002 { 01003 response.msgHdr.msgType = SharedSecretResponseMsg; 01004 response.msgHdr.id = request.msgHdr.id; 01005 01006 response.hasUsername = true; 01007 stunCreateUserName( source, &response.username); 01008 01009 response.hasPassword = true; 01010 stunCreatePassword( response.username, &response.password); 01011 }
void stunCreateUserName | ( | const StunAddress4 & | source, | |
StunAtrString * | username | |||
) |
Definition at line 763 of file stun.cc.
Referenced by stunCreateSharedSecretResponse(), and stunGetUserNameAndPassword().
00764 { 00765 UInt64 time = stunGetSystemTimeSecs(); 00766 time -= (time % 20*60); 00767 //UInt64 hitime = time >> 32; 00768 UInt64 lotime = time & 0xFFFFFFFF; 00769 00770 char buffer[1024]; 00771 sprintf(buffer, 00772 "%08x:%08x:%08x:", 00773 UInt32(source.addr), 00774 UInt32(stunRand()), 00775 UInt32(lotime)); 00776 assert( strlen(buffer) < 1024 ); 00777 00778 assert(strlen(buffer) + 41 < STUN_MAX_STRING); 00779 00780 char hmac[20]; 00781 char key[] = "Jason"; 00782 computeHmac(hmac, buffer, strlen(buffer), key, strlen(key) ); 00783 char hmacHex[41]; 00784 toHex(hmac, 20, hmacHex ); 00785 hmacHex[40] =0; 00786 00787 strcat(buffer,hmacHex); 00788 00789 int l = strlen(buffer); 00790 assert( l+1 < STUN_MAX_STRING ); 00791 assert( l%4 == 0 ); 00792 00793 username->sizeValue = l; 00794 memcpy(username->value,buffer,l); 00795 username->value[l]=0; 00796 00797 //if (verbose) clog << "computed username=" << username.value << endl; 00798 }
unsigned int stunEncodeMessage | ( | const StunMessage & | msg, | |
char * | buf, | |||
unsigned int | bufLen, | |||
const StunAtrString & | password, | |||
bool | verbose | |||
) |
Definition at line 543 of file stun.cc.
Referenced by stunSendTest(), and stunServerProcess().
00548 { 00549 assert(bufLen >= sizeof(StunMsgHdr)); 00550 char* ptr = buf; 00551 00552 ptr = encode16(ptr, msg.msgHdr.msgType); 00553 char* lengthp = ptr; 00554 ptr = encode16(ptr, 0); 00555 ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id)); 00556 00557 if (verbose) clog << "Encoding stun message: " << endl; 00558 if (msg.hasMappedAddress) 00559 { 00560 if (verbose) clog << "Encoding MappedAddress: " << msg.mappedAddress.ipv4 << endl; 00561 ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress); 00562 } 00563 if (msg.hasResponseAddress) 00564 { 00565 if (verbose) clog << "Encoding ResponseAddress: " << msg.responseAddress.ipv4 << endl; 00566 ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress); 00567 } 00568 if (msg.hasChangeRequest) 00569 { 00570 if (verbose) clog << "Encoding ChangeRequest: " << msg.changeRequest.value << endl; 00571 ptr = encodeAtrChangeRequest(ptr, msg.changeRequest); 00572 } 00573 if (msg.hasSourceAddress) 00574 { 00575 if (verbose) clog << "Encoding SourceAddress: " << msg.sourceAddress.ipv4 << endl; 00576 ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress); 00577 } 00578 if (msg.hasChangedAddress) 00579 { 00580 if (verbose) clog << "Encoding ChangedAddress: " << msg.changedAddress.ipv4 << endl; 00581 ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress); 00582 } 00583 if (msg.hasUsername) 00584 { 00585 if (verbose) clog << "Encoding Username: " << msg.username.value << endl; 00586 ptr = encodeAtrString(ptr, Username, msg.username); 00587 } 00588 if (msg.hasPassword) 00589 { 00590 if (verbose) clog << "Encoding Password: " << msg.password.value << endl; 00591 ptr = encodeAtrString(ptr, Password, msg.password); 00592 } 00593 if (msg.hasErrorCode) 00594 { 00595 if (verbose) clog << "Encoding ErrorCode: class=" 00596 << int(msg.errorCode.errorClass) 00597 << " number=" << int(msg.errorCode.number) 00598 << " reason=" 00599 << msg.errorCode.reason 00600 << endl; 00601 00602 ptr = encodeAtrError(ptr, msg.errorCode); 00603 } 00604 if (msg.hasUnknownAttributes) 00605 { 00606 if (verbose) clog << "Encoding UnknownAttribute: ???" << endl; 00607 ptr = encodeAtrUnknown(ptr, msg.unknownAttributes); 00608 } 00609 if (msg.hasReflectedFrom) 00610 { 00611 if (verbose) clog << "Encoding ReflectedFrom: " << msg.reflectedFrom.ipv4 << endl; 00612 ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom); 00613 } 00614 if (msg.hasXorMappedAddress) 00615 { 00616 if (verbose) clog << "Encoding XorMappedAddress: " << msg.xorMappedAddress.ipv4 << endl; 00617 ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress); 00618 } 00619 if (msg.xorOnly) 00620 { 00621 if (verbose) clog << "Encoding xorOnly: " << endl; 00622 ptr = encodeXorOnly( ptr ); 00623 } 00624 if (msg.hasServerName) 00625 { 00626 if (verbose) clog << "Encoding ServerName: " << msg.serverName.value << endl; 00627 ptr = encodeAtrString(ptr, ServerName, msg.serverName); 00628 } 00629 if (msg.hasSecondaryAddress) 00630 { 00631 if (verbose) clog << "Encoding SecondaryAddress: " << msg.secondaryAddress.ipv4 << endl; 00632 ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress); 00633 } 00634 00635 if (password.sizeValue > 0) 00636 { 00637 if (verbose) clog << "HMAC with password: " << password.value << endl; 00638 00639 StunAtrIntegrity integrity; 00640 computeHmac(integrity.hash, buf, int(ptr-buf) , password.value, password.sizeValue); 00641 ptr = encodeAtrIntegrity(ptr, integrity); 00642 } 00643 if (verbose) clog << endl; 00644 00645 encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr))); 00646 return int(ptr - buf); 00647 }
int stunFindLocalInterfaces | ( | UInt32 * | addresses, | |
int | maxRet | |||
) |
returns number of address found - take array or addres
Definition at line 1629 of file stun.cc.
01630 { 01631 #if defined(WIN32) || defined(__sparc__) 01632 return 0; 01633 #else 01634 struct ifconf ifc; 01635 01636 int s = socket( AF_INET, SOCK_DGRAM, 0 ); 01637 int len = 100 * sizeof(struct ifreq); 01638 01639 char buf[ len ]; 01640 01641 ifc.ifc_len = len; 01642 ifc.ifc_buf = buf; 01643 01644 int e = ioctl(s,SIOCGIFCONF,&ifc); 01645 char *ptr = buf; 01646 int tl = ifc.ifc_len; 01647 int count=0; 01648 01649 while ( (tl > 0) && ( count < maxRet) ) 01650 { 01651 struct ifreq* ifr = (struct ifreq *)ptr; 01652 01653 int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr); 01654 tl -= si; 01655 ptr += si; 01656 //char* name = ifr->ifr_ifrn.ifrn_name; 01657 //cerr << "name = " << name << endl; 01658 01659 struct ifreq ifr2; 01660 ifr2 = *ifr; 01661 01662 e = ioctl(s,SIOCGIFADDR,&ifr2); 01663 if ( e == -1 ) 01664 { 01665 break; 01666 } 01667 01668 //cerr << "ioctl addr e = " << e << endl; 01669 01670 struct sockaddr a = ifr2.ifr_addr; 01671 struct sockaddr_in* addr = (struct sockaddr_in*) &a; 01672 01673 UInt32 ai = ntohl( addr->sin_addr.s_addr ); 01674 if (int((ai>>24)&0xFF) != 127) 01675 { 01676 addresses[count++] = ai; 01677 } 01678 01679 #if 0 01680 cerr << "Detected interface " 01681 << int((ai>>24)&0xFF) << "." 01682 << int((ai>>16)&0xFF) << "." 01683 << int((ai>> 8)&0xFF) << "." 01684 << int((ai )&0xFF) << endl; 01685 #endif 01686 } 01687 01688 stunclosesocket(s); 01689 01690 return count; 01691 #endif 01692 }
UInt64 stunGetSystemTimeSecs | ( | ) |
Definition at line 816 of file stun.cc.
Referenced by stunCreateUserName().
00817 { 00818 UInt64 time=0; 00819 #if defined(WIN32) 00820 SYSTEMTIME t; 00821 // CJ TODO - this probably has bug on wrap around every 24 hours 00822 GetSystemTime( &t ); 00823 time = (t.wHour*60+t.wMinute)*60+t.wSecond; 00824 #else 00825 struct timeval now; 00826 gettimeofday( &now , NULL ); 00827 //assert( now ); 00828 time = now.tv_sec; 00829 #endif 00830 return time; 00831 }
void stunGetUserNameAndPassword | ( | const StunAddress4 & | dest, | |
StunAtrString * | username, | |||
StunAtrString * | password | |||
) |
Definition at line 1800 of file stun.cc.
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), and stunTest().
01803 { 01804 // !cj! This is totally bogus - need to make TLS connection to dest and get a 01805 // username and password to use 01806 stunCreateUserName(dest, username); 01807 stunCreatePassword(*username, password); 01808 }
bool stunInitServer | ( | StunServerInfo & | info, | |
const StunAddress4 & | myAddr, | |||
const StunAddress4 & | altAddr, | |||
int | startMediaPort, | |||
bool | verbose | |||
) |
return true if all is OK Create a media relay and do the STERN thing if startMediaPort is non-zero
Definition at line 1248 of file stun.cc.
01250 { 01251 assert( myAddr.port != 0 ); 01252 assert( altAddr.port!= 0 ); 01253 assert( myAddr.addr != 0 ); 01254 //assert( altAddr.addr != 0 ); 01255 01256 info.myAddr = myAddr; 01257 info.altAddr = altAddr; 01258 01259 info.myFd = STUN_INVALID_SOCKET; 01260 info.altPortFd = STUN_INVALID_SOCKET; 01261 info.altIpFd = STUN_INVALID_SOCKET; 01262 info.altIpPortFd = STUN_INVALID_SOCKET; 01263 01264 memset(info.relays, 0, sizeof(info.relays)); 01265 if (startMediaPort > 0) 01266 { 01267 info.relay = true; 01268 01269 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01270 { 01271 StunMediaRelay* relay = &info.relays[i]; 01272 relay->relayPort = startMediaPort+i; 01273 relay->fd = 0; 01274 relay->expireTime = 0; 01275 } 01276 } 01277 else 01278 { 01279 info.relay = false; 01280 } 01281 01282 if ((info.myFd = openPort(myAddr.port, myAddr.addr,verbose)) == STUN_INVALID_SOCKET) 01283 { 01284 clog << "Can't open " << myAddr << endl; 01285 stunStopServer(info); 01286 01287 return false; 01288 } 01289 //if (verbose) clog << "Opened " << myAddr.addr << ":" << myAddr.port << " --> " << info.myFd << endl; 01290 01291 if ((info.altPortFd = openPort(altAddr.port,myAddr.addr,verbose)) == STUN_INVALID_SOCKET) 01292 { 01293 clog << "Can't open " << myAddr << endl; 01294 stunStopServer(info); 01295 return false; 01296 } 01297 //if (verbose) clog << "Opened " << myAddr.addr << ":" << altAddr.port << " --> " << info.altPortFd << endl; 01298 01299 01300 info.altIpFd = STUN_INVALID_SOCKET; 01301 if ( altAddr.addr != 0 ) 01302 { 01303 if ((info.altIpFd = openPort( myAddr.port, altAddr.addr,verbose)) == STUN_INVALID_SOCKET) 01304 { 01305 clog << "Can't open " << altAddr << endl; 01306 stunStopServer(info); 01307 return false; 01308 } 01309 //if (verbose) clog << "Opened " << altAddr.addr << ":" << myAddr.port << " --> " << info.altIpFd << endl;; 01310 } 01311 01312 info.altIpPortFd = STUN_INVALID_SOCKET; 01313 if ( altAddr.addr != 0 ) 01314 { if ((info.altIpPortFd = openPort(altAddr.port, altAddr.addr,verbose)) == STUN_INVALID_SOCKET) 01315 { 01316 clog << "Can't open " << altAddr << endl; 01317 stunStopServer(info); 01318 return false; 01319 } 01320 //if (verbose) clog << "Opened " << altAddr.addr << ":" << altAddr.port << " --> " << info.altIpPortFd << endl;; 01321 } 01322 01323 return true; 01324 }
NatType stunNatType | ( | StunAddress4 & | dest, | |
bool | verbose, | |||
bool * | preservePort, | |||
bool * | hairpin, | |||
int | port, | |||
StunAddress4 * | sAddr | |||
) |
Definition at line 1875 of file stun.cc.
Referenced by SingleHostUnderlayConfigurator::initializeUnderlay().
01882 { 01883 assert( dest.addr != 0 ); 01884 assert( dest.port != 0 ); 01885 01886 if ( hairpin ) 01887 { 01888 *hairpin = false; 01889 } 01890 01891 if ( port == 0 ) 01892 { 01893 port = stunRandomPort(); 01894 } 01895 UInt32 interfaceIp=0; 01896 if (sAddr) 01897 { 01898 interfaceIp = sAddr->addr; 01899 } 01900 Socket myFd1 = openPort(port,interfaceIp,verbose); 01901 Socket myFd2 = openPort(port+1,interfaceIp,verbose); 01902 01903 if ( ( myFd1 == STUN_INVALID_SOCKET) || ( myFd2 == STUN_INVALID_SOCKET) ) 01904 { 01905 cerr << "Some problem opening port/interface to send on" << endl; 01906 return StunTypeFailure; 01907 } 01908 01909 assert( myFd1 != STUN_INVALID_SOCKET ); 01910 assert( myFd2 != STUN_INVALID_SOCKET ); 01911 01912 bool respTestI=false; 01913 bool isNat=true; 01914 StunAddress4 testIchangedAddr; 01915 StunAddress4 testImappedAddr; 01916 bool respTestI2=false; 01917 bool mappedIpSame = true; 01918 StunAddress4 testI2mappedAddr; 01919 StunAddress4 testI2dest=dest; 01920 bool respTestII=false; 01921 bool respTestIII=false; 01922 01923 bool respTestHairpin=false; 01924 bool respTestPreservePort=false; 01925 01926 memset(&testImappedAddr,0,sizeof(testImappedAddr)); 01927 01928 StunAtrString username; 01929 StunAtrString password; 01930 01931 username.sizeValue = 0; 01932 password.sizeValue = 0; 01933 01934 #ifdef USE_TLS 01935 stunGetUserNameAndPassword( dest, username, password ); 01936 #endif 01937 01938 int count=0; 01939 while ( count < 7 ) 01940 { 01941 struct timeval tv; 01942 fd_set fdSet; 01943 #ifdef WIN32 01944 unsigned int fdSetSize; 01945 #else 01946 int fdSetSize; 01947 #endif 01948 FD_ZERO(&fdSet); fdSetSize=0; 01949 FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize; 01950 FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize; 01951 tv.tv_sec=0; 01952 tv.tv_usec=150*1000; // 150 ms 01953 if ( count == 0 ) tv.tv_usec=0; 01954 01955 int err = select(fdSetSize, &fdSet, NULL, NULL, &tv); 01956 int e = getErrno(); 01957 if ( err == STUN_SOCKET_ERROR ) 01958 { 01959 // error occured 01960 cerr << "Error " << e << " " << strerror(e) << " in select" << endl; 01961 return StunTypeFailure; 01962 } 01963 else if ( err == 0 ) 01964 { 01965 // timeout occured 01966 count++; 01967 01968 if ( !respTestI ) 01969 { 01970 stunSendTest( myFd1, dest, username, password, 1 ,verbose ); 01971 } 01972 01973 if ( (!respTestI2) && respTestI ) 01974 { 01975 // check the address to send to if valid 01976 if ( ( testI2dest.addr != 0 ) && 01977 ( testI2dest.port != 0 ) ) 01978 { 01979 stunSendTest( myFd1, testI2dest, username, password, 10 ,verbose); 01980 } 01981 } 01982 01983 if ( !respTestII ) 01984 { 01985 stunSendTest( myFd2, dest, username, password, 2 ,verbose ); 01986 } 01987 01988 if ( !respTestIII ) 01989 { 01990 stunSendTest( myFd2, dest, username, password, 3 ,verbose ); 01991 } 01992 01993 if ( respTestI && (!respTestHairpin) ) 01994 { 01995 if ( ( testImappedAddr.addr != 0 ) && 01996 ( testImappedAddr.port != 0 ) ) 01997 { 01998 stunSendTest( myFd1, testImappedAddr, username, password, 11 ,verbose ); 01999 } 02000 } 02001 } 02002 else 02003 { 02004 //if (verbose) clog << "-----------------------------------------" << endl; 02005 assert( err>0 ); 02006 // data is avialbe on some fd 02007 02008 for ( int i=0; i<2; i++) 02009 { 02010 Socket myFd; 02011 if ( i==0 ) 02012 { 02013 myFd=myFd1; 02014 } 02015 else 02016 { 02017 myFd=myFd2; 02018 } 02019 02020 if ( myFd!=STUN_INVALID_SOCKET ) 02021 { 02022 if ( FD_ISSET(myFd,&fdSet) ) 02023 { 02024 char msg[STUN_MAX_MESSAGE_SIZE]; 02025 int msgLen = sizeof(msg); 02026 02027 StunAddress4 from; 02028 02029 getMessage( myFd, 02030 msg, 02031 &msgLen, 02032 &from.addr, 02033 &from.port,verbose ); 02034 02035 StunMessage resp; 02036 memset(&resp, 0, sizeof(StunMessage)); 02037 02038 stunParseMessage( msg,msgLen, resp,verbose ); 02039 02040 if ( verbose ) 02041 { 02042 clog << "Received message of type " << resp.msgHdr.msgType 02043 << " id=" << (int)(resp.msgHdr.id.octet[0]) << endl; 02044 } 02045 02046 switch( resp.msgHdr.id.octet[0] ) 02047 { 02048 case 1: 02049 { 02050 if ( !respTestI ) 02051 { 02052 02053 testIchangedAddr.addr = resp.changedAddress.ipv4.addr; 02054 testIchangedAddr.port = resp.changedAddress.ipv4.port; 02055 testImappedAddr.addr = resp.mappedAddress.ipv4.addr; 02056 testImappedAddr.port = resp.mappedAddress.ipv4.port; 02057 02058 respTestPreservePort = ( testImappedAddr.port == port ); 02059 if ( preservePort ) 02060 { 02061 *preservePort = respTestPreservePort; 02062 } 02063 02064 testI2dest.addr = resp.changedAddress.ipv4.addr; 02065 02066 if (sAddr) 02067 { 02068 sAddr->port = testImappedAddr.port; 02069 sAddr->addr = testImappedAddr.addr; 02070 } 02071 02072 count = 0; 02073 } 02074 respTestI=true; 02075 } 02076 break; 02077 case 2: 02078 { 02079 respTestII=true; 02080 } 02081 break; 02082 case 3: 02083 { 02084 respTestIII=true; 02085 } 02086 break; 02087 case 10: 02088 { 02089 if ( !respTestI2 ) 02090 { 02091 testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr; 02092 testI2mappedAddr.port = resp.mappedAddress.ipv4.port; 02093 02094 mappedIpSame = false; 02095 if ( (testI2mappedAddr.addr == testImappedAddr.addr ) && 02096 (testI2mappedAddr.port == testImappedAddr.port )) 02097 { 02098 mappedIpSame = true; 02099 } 02100 02101 02102 } 02103 respTestI2=true; 02104 } 02105 break; 02106 case 11: 02107 { 02108 02109 if ( hairpin ) 02110 { 02111 *hairpin = true; 02112 } 02113 respTestHairpin = true; 02114 } 02115 break; 02116 } 02117 } 02118 } 02119 } 02120 } 02121 } 02122 02123 // see if we can bind to this address 02124 //cerr << "try binding to " << testImappedAddr << endl; 02125 Socket s = openPort( 0/*use ephemeral*/, testImappedAddr.addr, false ); 02126 if ( s != STUN_INVALID_SOCKET ) 02127 { 02128 stunclosesocket(s); 02129 isNat = false; 02130 //cerr << "binding worked" << endl; 02131 } 02132 else 02133 { 02134 isNat = true; 02135 //cerr << "binding failed" << endl; 02136 } 02137 02138 if (verbose) 02139 { 02140 clog << "test I = " << respTestI << endl; 02141 clog << "test II = " << respTestII << endl; 02142 clog << "test III = " << respTestIII << endl; 02143 clog << "test I(2) = " << respTestI2 << endl; 02144 clog << "is nat = " << isNat <<endl; 02145 clog << "mapped IP same = " << mappedIpSame << endl; 02146 clog << "hairpin = " << respTestHairpin << endl; 02147 clog << "preserver port = " << respTestPreservePort << endl; 02148 } 02149 02150 #if 0 02151 // implement logic flow chart from draft RFC 02152 if ( respTestI ) 02153 { 02154 if ( isNat ) 02155 { 02156 if (respTestII) 02157 { 02158 return StunTypeConeNat; 02159 } 02160 else 02161 { 02162 if ( mappedIpSame ) 02163 { 02164 if ( respTestIII ) 02165 { 02166 return StunTypeRestrictedNat; 02167 } 02168 else 02169 { 02170 return StunTypePortRestrictedNat; 02171 } 02172 } 02173 else 02174 { 02175 return StunTypeSymNat; 02176 } 02177 } 02178 } 02179 else 02180 { 02181 if (respTestII) 02182 { 02183 return StunTypeOpen; 02184 } 02185 else 02186 { 02187 return StunTypeSymFirewall; 02188 } 02189 } 02190 } 02191 else 02192 { 02193 return StunTypeBlocked; 02194 } 02195 #else 02196 if ( respTestI ) // not blocked 02197 { 02198 if ( isNat ) 02199 { 02200 if ( mappedIpSame ) 02201 { 02202 if (respTestII) 02203 { 02204 return StunTypeIndependentFilter; 02205 } 02206 else 02207 { 02208 if ( respTestIII ) 02209 { 02210 return StunTypeDependentFilter; 02211 } 02212 else 02213 { 02214 return StunTypePortDependedFilter; 02215 } 02216 } 02217 } 02218 else // mappedIp is not same 02219 { 02220 return StunTypeDependentMapping; 02221 } 02222 } 02223 else // isNat is false 02224 { 02225 if (respTestII) 02226 { 02227 return StunTypeOpen; 02228 } 02229 else 02230 { 02231 return StunTypeFirewall; 02232 } 02233 } 02234 } 02235 else 02236 { 02237 return StunTypeBlocked; 02238 } 02239 #endif 02240 02241 return StunTypeUnknown; 02242 }
int stunOpenSocket | ( | StunAddress4 & | dest, | |
StunAddress4 * | mapAddr, | |||
int | port, | |||
StunAddress4 * | srcAddr, | |||
bool | verbose | |||
) |
Definition at line 2246 of file stun.cc.
02249 { 02250 assert( dest.addr != 0 ); 02251 assert( dest.port != 0 ); 02252 assert( mapAddr ); 02253 02254 if ( port == 0 ) 02255 { 02256 port = stunRandomPort(); 02257 } 02258 unsigned int interfaceIp = 0; 02259 if ( srcAddr ) 02260 { 02261 interfaceIp = srcAddr->addr; 02262 } 02263 02264 Socket myFd = openPort(port,interfaceIp,verbose); 02265 if (myFd == STUN_INVALID_SOCKET) 02266 { 02267 return myFd; 02268 } 02269 02270 char msg[STUN_MAX_MESSAGE_SIZE]; 02271 int msgLen = sizeof(msg); 02272 02273 StunAtrString username; 02274 StunAtrString password; 02275 02276 username.sizeValue = 0; 02277 password.sizeValue = 0; 02278 02279 #ifdef USE_TLS 02280 stunGetUserNameAndPassword( dest, username, password ); 02281 #endif 02282 02283 stunSendTest(myFd, dest, username, password, 1, 0/*false*/ ); 02284 02285 StunAddress4 from; 02286 02287 getMessage( myFd, msg, &msgLen, &from.addr, &from.port,verbose ); 02288 02289 StunMessage resp; 02290 memset(&resp, 0, sizeof(StunMessage)); 02291 02292 bool ok = stunParseMessage( msg, msgLen, resp,verbose ); 02293 if (!ok) 02294 { 02295 return -1; 02296 } 02297 02298 StunAddress4 mappedAddr = resp.mappedAddress.ipv4; 02299 StunAddress4 changedAddr = resp.changedAddress.ipv4; 02300 02301 //clog << "--- stunOpenSocket --- " << endl; 02302 //clog << "\treq id=" << req.id << endl; 02303 //clog << "\tresp id=" << id << endl; 02304 //clog << "\tmappedAddr=" << mappedAddr << endl; 02305 02306 *mapAddr = mappedAddr; 02307 02308 return myFd; 02309 }
bool stunOpenSocketPair | ( | StunAddress4 & | dest, | |
StunAddress4 * | mapAddr, | |||
int * | fd1, | |||
int * | fd2, | |||
int | port, | |||
StunAddress4 * | srcAddr, | |||
bool | verbose | |||
) |
Definition at line 2313 of file stun.cc.
02317 { 02318 assert( dest.addr!= 0 ); 02319 assert( dest.port != 0 ); 02320 assert( mapAddr ); 02321 02322 const int NUM=3; 02323 02324 if ( port == 0 ) 02325 { 02326 port = stunRandomPort(); 02327 } 02328 02329 *fd1=-1; 02330 *fd2=-1; 02331 02332 char msg[STUN_MAX_MESSAGE_SIZE]; 02333 int msgLen =sizeof(msg); 02334 02335 StunAddress4 from; 02336 int fd[NUM]; 02337 int i; 02338 02339 unsigned int interfaceIp = 0; 02340 if ( srcAddr ) 02341 { 02342 interfaceIp = srcAddr->addr; 02343 } 02344 02345 for( i=0; i<NUM; i++) 02346 { 02347 fd[i] = openPort( (port == 0) ? 0 : (port + i), 02348 interfaceIp, verbose); 02349 if (fd[i] < 0) 02350 { 02351 while (i > 0) 02352 { 02353 stunclosesocket(fd[--i]); 02354 } 02355 return false; 02356 } 02357 } 02358 02359 StunAtrString username; 02360 StunAtrString password; 02361 02362 username.sizeValue = 0; 02363 password.sizeValue = 0; 02364 02365 #ifdef USE_TLS 02366 stunGetUserNameAndPassword( dest, username, password ); 02367 #endif 02368 02369 for( i=0; i<NUM; i++) 02370 { 02371 stunSendTest(fd[i], dest, username, password, 1/*testNum*/, verbose ); 02372 } 02373 02374 StunAddress4 mappedAddr[NUM]; 02375 for( i=0; i<NUM; i++) 02376 { 02377 msgLen = sizeof(msg)/sizeof(*msg); 02378 getMessage( fd[i], 02379 msg, 02380 &msgLen, 02381 &from.addr, 02382 &from.port ,verbose); 02383 02384 StunMessage resp; 02385 memset(&resp, 0, sizeof(StunMessage)); 02386 02387 bool ok = stunParseMessage( msg, msgLen, resp, verbose ); 02388 if (!ok) 02389 { 02390 return false; 02391 } 02392 02393 mappedAddr[i] = resp.mappedAddress.ipv4; 02394 StunAddress4 changedAddr = resp.changedAddress.ipv4; 02395 } 02396 02397 if (verbose) 02398 { 02399 clog << "--- stunOpenSocketPair --- " << endl; 02400 for( i=0; i<NUM; i++) 02401 { 02402 clog << "\t mappedAddr=" << mappedAddr[i] << endl; 02403 } 02404 } 02405 02406 if ( mappedAddr[0].port %2 == 0 ) 02407 { 02408 if ( mappedAddr[0].port+1 == mappedAddr[1].port ) 02409 { 02410 *mapAddr = mappedAddr[0]; 02411 *fd1 = fd[0]; 02412 *fd2 = fd[1]; 02413 stunclosesocket( fd[2] ); 02414 return true; 02415 } 02416 } 02417 else 02418 { 02419 if (( mappedAddr[1].port %2 == 0 ) 02420 && ( mappedAddr[1].port+1 == mappedAddr[2].port )) 02421 { 02422 *mapAddr = mappedAddr[1]; 02423 *fd1 = fd[1]; 02424 *fd2 = fd[2]; 02425 stunclosesocket( fd[0] ); 02426 return true; 02427 } 02428 } 02429 02430 // something failed, close all and return error 02431 for( i=0; i<NUM; i++) 02432 { 02433 stunclosesocket( fd[i] ); 02434 } 02435 02436 return false; 02437 }
static bool stunParseAtrAddress | ( | char * | body, | |
unsigned int | hdrLen, | |||
StunAtrAddress4 & | result | |||
) | [static] |
Definition at line 48 of file stun.cc.
Referenced by stunParseMessage().
00049 { 00050 if ( hdrLen != 8 ) 00051 { 00052 clog << "hdrLen wrong for Address" <<endl; 00053 return false; 00054 } 00055 result.pad = *body++; 00056 result.family = *body++; 00057 if (result.family == IPv4Family) 00058 { 00059 UInt16 nport; 00060 memcpy(&nport, body, 2); body+=2; 00061 result.ipv4.port = ntohs(nport); 00062 00063 UInt32 naddr; 00064 memcpy(&naddr, body, 4); body+=4; 00065 result.ipv4.addr = ntohl(naddr); 00066 return true; 00067 } 00068 else if (result.family == IPv6Family) 00069 { 00070 clog << "ipv6 not supported" << endl; 00071 } 00072 else 00073 { 00074 clog << "bad address family: " << result.family << endl; 00075 } 00076 00077 return false; 00078 }
static bool stunParseAtrChangeRequest | ( | char * | body, | |
unsigned int | hdrLen, | |||
StunAtrChangeRequest & | result | |||
) | [static] |
Definition at line 81 of file stun.cc.
Referenced by stunParseMessage().
00082 { 00083 if ( hdrLen != 4 ) 00084 { 00085 clog << "hdr length = " << hdrLen << " expecting " << sizeof(result) << endl; 00086 00087 clog << "Incorrect size for ChangeRequest" << endl; 00088 return false; 00089 } 00090 else 00091 { 00092 memcpy(&result.value, body, 4); 00093 result.value = ntohl(result.value); 00094 return true; 00095 } 00096 }
static bool stunParseAtrError | ( | char * | body, | |
unsigned int | hdrLen, | |||
StunAtrError & | result | |||
) | [static] |
Definition at line 99 of file stun.cc.
Referenced by stunParseMessage().
00100 { 00101 if ( hdrLen >= sizeof(result) ) 00102 { 00103 clog << "head on Error too large" << endl; 00104 return false; 00105 } 00106 else 00107 { 00108 memcpy(&result.pad, body, 2); body+=2; 00109 result.pad = ntohs(result.pad); 00110 result.errorClass = *body++; 00111 result.number = *body++; 00112 00113 result.sizeReason = hdrLen - 4; 00114 memcpy(&result.reason, body, result.sizeReason); 00115 result.reason[result.sizeReason] = 0; 00116 return true; 00117 } 00118 }
static bool stunParseAtrIntegrity | ( | char * | body, | |
unsigned int | hdrLen, | |||
StunAtrIntegrity & | result | |||
) | [static] |
Definition at line 166 of file stun.cc.
Referenced by stunParseMessage().
00167 { 00168 if ( hdrLen != 20) 00169 { 00170 clog << "MessageIntegrity must be 20 bytes" << endl; 00171 return false; 00172 } 00173 else 00174 { 00175 memcpy(&result.hash, body, hdrLen); 00176 return true; 00177 } 00178 }
static bool stunParseAtrString | ( | char * | body, | |
unsigned int | hdrLen, | |||
StunAtrString & | result | |||
) | [static] |
Definition at line 142 of file stun.cc.
Referenced by stunParseMessage().
00143 { 00144 if ( hdrLen >= STUN_MAX_STRING ) 00145 { 00146 clog << "String is too large" << endl; 00147 return false; 00148 } 00149 else 00150 { 00151 if (hdrLen % 4 != 0) 00152 { 00153 clog << "Bad length string " << hdrLen << endl; 00154 return false; 00155 } 00156 00157 result.sizeValue = hdrLen; 00158 memcpy(&result.value, body, hdrLen); 00159 result.value[hdrLen] = 0; 00160 return true; 00161 } 00162 }
static bool stunParseAtrUnknown | ( | char * | body, | |
unsigned int | hdrLen, | |||
StunAtrUnknown & | result | |||
) | [static] |
Definition at line 121 of file stun.cc.
Referenced by stunParseMessage().
00122 { 00123 if ( hdrLen >= sizeof(result) ) 00124 { 00125 return false; 00126 } 00127 else 00128 { 00129 if (hdrLen % 4 != 0) return false; 00130 result.numAttributes = hdrLen / 4; 00131 for (int i=0; i<result.numAttributes; i++) 00132 { 00133 memcpy(&result.attrType[i], body, 2); body+=2; 00134 result.attrType[i] = ntohs(result.attrType[i]); 00135 } 00136 return true; 00137 } 00138 }
Definition at line 862 of file stun.cc.
Referenced by stunParseServerName().
00866 { 00867 in_addr sin_addr; 00868 00869 char host[512]; 00870 strncpy(host,peerName,512); 00871 host[512-1]='\0'; 00872 char* port = NULL; 00873 00874 int portNum = defaultPort; 00875 00876 // pull out the port part if present. 00877 char* sep = strchr(host,':'); 00878 00879 if ( sep == NULL ) 00880 { 00881 portNum = defaultPort; 00882 } 00883 else 00884 { 00885 *sep = '\0'; 00886 port = sep + 1; 00887 // set port part 00888 00889 char* endPtr=NULL; 00890 00891 portNum = strtol(port,&endPtr,10); 00892 00893 if ( endPtr != NULL ) 00894 { 00895 if ( *endPtr != '\0' ) 00896 { 00897 portNum = defaultPort; 00898 } 00899 } 00900 } 00901 00902 if ( portNum < 1024 ) return false; 00903 if ( portNum >= 0xFFFF ) return false; 00904 00905 // figure out the host part 00906 struct hostent* h; 00907 00908 #ifdef WIN32 00909 assert( strlen(host) >= 1 ); 00910 if ( isdigit( host[0] ) ) 00911 { 00912 // assume it is a ip address 00913 unsigned long a = inet_addr(host); 00914 //cerr << "a=0x" << hex << a << dec << endl; 00915 00916 ip = ntohl( a ); 00917 } 00918 else 00919 { 00920 // assume it is a host name 00921 h = gethostbyname( host ); 00922 00923 if ( h == NULL ) 00924 { 00925 int err = getErrno(); 00926 std::cerr << "error was " << err << std::endl; 00927 assert( err != WSANOTINITIALISED ); 00928 00929 ip = ntohl( 0x7F000001L ); 00930 00931 return false; 00932 } 00933 else 00934 { 00935 sin_addr = *(struct in_addr*)h->h_addr; 00936 ip = ntohl( sin_addr.s_addr ); 00937 } 00938 } 00939 00940 #else 00941 h = gethostbyname( host ); 00942 if ( h == NULL ) 00943 { 00944 int err = getErrno(); 00945 std::cerr << "error was " << err << std::endl; 00946 ip = ntohl( 0x7F000001L ); 00947 return false; 00948 } 00949 else 00950 { 00951 sin_addr = *(struct in_addr*)h->h_addr; 00952 ip = ntohl( sin_addr.s_addr ); 00953 } 00954 #endif 00955 00956 portVal = portNum; 00957 00958 return true; 00959 }
bool stunParseMessage | ( | char * | buf, | |
unsigned int | bufLen, | |||
StunMessage & | msg, | |||
bool | verbose | |||
) |
Definition at line 182 of file stun.cc.
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), stunServerProcessMsg(), and stunTest().
00183 { 00184 if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl; 00185 memset(&msg, 0, sizeof(msg)); 00186 00187 if (sizeof(StunMsgHdr) > bufLen) 00188 { 00189 clog << "Bad message" << endl; 00190 return false; 00191 } 00192 00193 memcpy(&msg.msgHdr, buf, sizeof(StunMsgHdr)); 00194 msg.msgHdr.msgType = ntohs(msg.msgHdr.msgType); 00195 msg.msgHdr.msgLength = ntohs(msg.msgHdr.msgLength); 00196 00197 if (msg.msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen) 00198 { 00199 clog << "Message header length doesn't match message size: " 00200 << msg.msgHdr.msgLength << " - " << bufLen << endl; 00201 return false; 00202 } 00203 00204 char* body = buf + sizeof(StunMsgHdr); 00205 unsigned int size = msg.msgHdr.msgLength; 00206 00207 //clog << "bytes after header = " << size << endl; 00208 00209 while ( size > 0 ) 00210 { 00211 // !jf! should check that there are enough bytes left in the buffer 00212 00213 StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body); 00214 00215 unsigned int attrLen = ntohs(attr->length); 00216 int atrType = ntohs(attr->type); 00217 00218 //if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl; 00219 if ( attrLen+4 > size ) 00220 { 00221 clog << "claims attribute is larger than size of message " 00222 <<"(attribute type="<<atrType<<")"<< endl; 00223 return false; 00224 } 00225 00226 body += 4; // skip the length and type in attribute header 00227 size -= 4; 00228 00229 switch ( atrType ) 00230 { 00231 case MappedAddress: 00232 msg.hasMappedAddress = true; 00233 if ( stunParseAtrAddress( body, attrLen, msg.mappedAddress )== false ) 00234 { 00235 clog << "problem parsing MappedAddress" << endl; 00236 return false; 00237 } 00238 else 00239 { 00240 if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl; 00241 } 00242 00243 break; 00244 00245 case ResponseAddress: 00246 msg.hasResponseAddress = true; 00247 if ( stunParseAtrAddress( body, attrLen, msg.responseAddress )== false ) 00248 { 00249 clog << "problem parsing ResponseAddress" << endl; 00250 return false; 00251 } 00252 else 00253 { 00254 if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl; 00255 } 00256 break; 00257 00258 case ChangeRequest: 00259 msg.hasChangeRequest = true; 00260 if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false) 00261 { 00262 clog << "problem parsing ChangeRequest" << endl; 00263 return false; 00264 } 00265 else 00266 { 00267 if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl; 00268 } 00269 break; 00270 00271 case SourceAddress: 00272 msg.hasSourceAddress = true; 00273 if ( stunParseAtrAddress( body, attrLen, msg.sourceAddress )== false ) 00274 { 00275 clog << "problem parsing SourceAddress" << endl; 00276 return false; 00277 } 00278 else 00279 { 00280 if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl; 00281 } 00282 break; 00283 00284 case ChangedAddress: 00285 msg.hasChangedAddress = true; 00286 if ( stunParseAtrAddress( body, attrLen, msg.changedAddress )== false ) 00287 { 00288 clog << "problem parsing ChangedAddress" << endl; 00289 return false; 00290 } 00291 else 00292 { 00293 if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl; 00294 } 00295 break; 00296 00297 case Username: 00298 msg.hasUsername = true; 00299 if (stunParseAtrString( body, attrLen, msg.username) == false) 00300 { 00301 clog << "problem parsing Username" << endl; 00302 return false; 00303 } 00304 else 00305 { 00306 if (verbose) clog << "Username = " << msg.username.value << endl; 00307 } 00308 00309 break; 00310 00311 case Password: 00312 msg.hasPassword = true; 00313 if (stunParseAtrString( body, attrLen, msg.password) == false) 00314 { 00315 clog << "problem parsing Password" << endl; 00316 return false; 00317 } 00318 else 00319 { 00320 if (verbose) clog << "Password = " << msg.password.value << endl; 00321 } 00322 break; 00323 00324 case MessageIntegrity: 00325 msg.hasMessageIntegrity = true; 00326 if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false) 00327 { 00328 clog << "problem parsing MessageIntegrity" << endl; 00329 return false; 00330 } 00331 else 00332 { 00333 //if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl; 00334 } 00335 00336 // read the current HMAC 00337 // look up the password given the user of given the transaction id 00338 // compute the HMAC on the buffer 00339 // decide if they match or not 00340 break; 00341 00342 case ErrorCode: 00343 msg.hasErrorCode = true; 00344 if (stunParseAtrError(body, attrLen, msg.errorCode) == false) 00345 { 00346 clog << "problem parsing ErrorCode" << endl; 00347 return false; 00348 } 00349 else 00350 { 00351 if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass) 00352 << " " << int(msg.errorCode.number) 00353 << " " << msg.errorCode.reason << endl; 00354 } 00355 00356 break; 00357 00358 case UnknownAttribute: 00359 msg.hasUnknownAttributes = true; 00360 if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false) 00361 { 00362 clog << "problem parsing UnknownAttribute" << endl; 00363 return false; 00364 } 00365 break; 00366 00367 case ReflectedFrom: 00368 msg.hasReflectedFrom = true; 00369 if ( stunParseAtrAddress( body, attrLen, msg.reflectedFrom ) == false ) 00370 { 00371 clog << "problem parsing ReflectedFrom" << endl; 00372 return false; 00373 } 00374 break; 00375 00376 case XorMappedAddress: 00377 msg.hasXorMappedAddress = true; 00378 if ( stunParseAtrAddress( body, attrLen, msg.xorMappedAddress ) == false ) 00379 { 00380 clog << "problem parsing XorMappedAddress" << endl; 00381 return false; 00382 } 00383 else 00384 { 00385 if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl; 00386 } 00387 break; 00388 00389 case XorOnly: 00390 msg.xorOnly = true; 00391 if (verbose) 00392 { 00393 clog << "xorOnly = true" << endl; 00394 } 00395 break; 00396 00397 case ServerName: 00398 msg.hasServerName = true; 00399 if (stunParseAtrString( body, attrLen, msg.serverName) == false) 00400 { 00401 clog << "problem parsing ServerName" << endl; 00402 return false; 00403 } 00404 else 00405 { 00406 if (verbose) clog << "ServerName = " << msg.serverName.value << endl; 00407 } 00408 break; 00409 00410 case SecondaryAddress: 00411 msg.hasSecondaryAddress = true; 00412 if ( stunParseAtrAddress( body, attrLen, msg.secondaryAddress ) == false ) 00413 { 00414 clog << "problem parsing secondaryAddress" << endl; 00415 return false; 00416 } 00417 else 00418 { 00419 if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl; 00420 } 00421 break; 00422 00423 default: 00424 if (verbose) clog << "Unknown attribute: " << atrType << endl; 00425 if ( atrType <= 0x7FFF ) 00426 { 00427 return false; 00428 } 00429 } 00430 00431 body += attrLen; 00432 size -= attrLen; 00433 } 00434 00435 return true; 00436 }
bool stunParseServerName | ( | char * | name, | |
StunAddress4 & | addr | |||
) |
find the IP address of a the specified stun server - return false is fails parse
Definition at line 963 of file stun.cc.
Referenced by SingleHostUnderlayConfigurator::initializeUnderlay().
00964 { 00965 assert(name); 00966 00967 // TODO - put in DNS SRV stuff. 00968 00969 bool ret = stunParseHostName( name, addr.addr, addr.port, 3478); 00970 if ( ret != true ) 00971 { 00972 addr.port=0xFFFF; 00973 } 00974 return ret; 00975 }
int stunRand | ( | ) |
Definition at line 650 of file stun.cc.
Referenced by stunBuildReqSimple(), stunCreateUserName(), and stunRandomPort().
00651 { 00652 // return 32 bits of random stuff 00653 assert( sizeof(int) == 4 ); 00654 static bool init=false; 00655 if ( !init ) 00656 { 00657 init = true; 00658 00659 UInt64 tick; 00660 00661 #if defined(MSVC_WIN32) 00662 volatile unsigned int lowtick=0,hightick=0; 00663 __asm 00664 { 00665 rdtsc 00666 mov lowtick, eax 00667 mov hightick, edx 00668 } 00669 tick = hightick; 00670 tick <<= 32; 00671 tick |= lowtick; 00672 #elif (defined(WIN32) || defined(__GNUC__)) && ( defined(__i686__) || defined(__i386__) || defined(__x86_64__) ) 00673 asm("rdtsc" : "=A" (tick)); 00674 #elif defined (__SUNPRO_CC) || defined( __sparc__ ) 00675 tick = gethrtime(); 00676 #elif defined(__MACH__) 00677 int fd=open("/dev/random",O_RDONLY); 00678 read(fd,&tick,sizeof(tick)); 00679 stunclosesocket(fd); 00680 #else 00681 # error Need some way to seed the random number generator 00682 #endif 00683 int seed = int(tick); 00684 #ifdef WIN32 00685 srand(seed); 00686 #else 00687 srandom(seed); 00688 #endif 00689 } 00690 00691 #ifdef WIN32 00692 assert( RAND_MAX == 0x7fff ); 00693 int r1 = rand(); 00694 int r2 = rand(); 00695 00696 int ret = (r1<<16) + r2; 00697 00698 return ret; 00699 #else 00700 return random(); 00701 #endif 00702 }
int stunRandomPort | ( | ) |
return a random number to use as a port
Definition at line 707 of file stun.cc.
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), and stunTest().
00708 { 00709 int min=0x4000; 00710 int max=0x7FFF; 00711 00712 int ret = stunRand(); 00713 ret = ret|min; 00714 ret = ret&max; 00715 00716 return ret; 00717 }
static void stunSendTest | ( | Socket | myFd, | |
StunAddress4 & | dest, | |||
const StunAtrString & | username, | |||
const StunAtrString & | password, | |||
int | testNum, | |||
bool | verbose | |||
) | [static] |
Definition at line 1733 of file stun.cc.
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), and stunTest().
01736 { 01737 assert( dest.addr != 0 ); 01738 assert( dest.port != 0 ); 01739 01740 bool changePort=false; 01741 bool changeIP=false; 01742 bool discard=false; 01743 01744 switch (testNum) 01745 { 01746 case 1: 01747 case 10: 01748 case 11: 01749 break; 01750 case 2: 01751 //changePort=true; 01752 changeIP=true; 01753 break; 01754 case 3: 01755 changePort=true; 01756 break; 01757 case 4: 01758 changeIP=true; 01759 break; 01760 case 5: 01761 discard=true; 01762 break; 01763 default: 01764 cerr << "Test " << testNum <<" is unkown\n"; 01765 assert(0); 01766 } 01767 01768 StunMessage req; 01769 memset(&req, 0, sizeof(StunMessage)); 01770 01771 stunBuildReqSimple( &req, username, 01772 changePort , changeIP , 01773 testNum ); 01774 01775 char buf[STUN_MAX_MESSAGE_SIZE]; 01776 int len = STUN_MAX_MESSAGE_SIZE; 01777 01778 len = stunEncodeMessage( req, buf, len, password,verbose ); 01779 01780 if ( verbose ) 01781 { 01782 clog << "About to send msg of len " << len << " to " << dest << endl; 01783 } 01784 01785 sendMessage( myFd, buf, len, dest.addr, dest.port, verbose ); 01786 01787 // add some delay so the packets don't get sent too quickly 01788 #ifdef WIN32 // !cj! TODO - should fix this up in windows 01789 clock_t now = clock(); 01790 assert( CLOCKS_PER_SEC == 1000 ); 01791 while ( clock() <= now+10 ) { }; 01792 #else 01793 usleep(10*1000); 01794 #endif 01795 01796 }
bool stunServerProcess | ( | StunServerInfo & | info, | |
bool | verbose | |||
) |
return true if all is OK
Definition at line 1350 of file stun.cc.
01351 { 01352 char msg[STUN_MAX_MESSAGE_SIZE]; 01353 int msgLen = sizeof(msg); 01354 01355 bool ok = false; 01356 bool recvAltIp =false; 01357 bool recvAltPort = false; 01358 01359 fd_set fdSet; 01360 Socket maxFd=0; 01361 01362 FD_ZERO(&fdSet); 01363 FD_SET(info.myFd,&fdSet); 01364 if ( info.myFd >= maxFd ) maxFd=info.myFd+1; 01365 FD_SET(info.altPortFd,&fdSet); 01366 if ( info.altPortFd >= maxFd ) maxFd=info.altPortFd+1; 01367 01368 if ( info.altIpFd != STUN_INVALID_SOCKET ) 01369 { 01370 FD_SET(info.altIpFd,&fdSet); 01371 if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1; 01372 } 01373 if ( info.altIpPortFd != STUN_INVALID_SOCKET ) 01374 { 01375 FD_SET(info.altIpPortFd,&fdSet); 01376 if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1; 01377 } 01378 01379 if (info.relay) 01380 { 01381 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01382 { 01383 StunMediaRelay* relay = &info.relays[i]; 01384 if (relay->fd) 01385 { 01386 FD_SET(relay->fd, &fdSet); 01387 if (relay->fd >= maxFd) 01388 { 01389 maxFd=relay->fd+1; 01390 } 01391 } 01392 } 01393 } 01394 01395 if ( info.altIpFd != STUN_INVALID_SOCKET ) 01396 { 01397 FD_SET(info.altIpFd,&fdSet); 01398 if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1; 01399 } 01400 if ( info.altIpPortFd != STUN_INVALID_SOCKET ) 01401 { 01402 FD_SET(info.altIpPortFd,&fdSet); 01403 if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1; 01404 } 01405 01406 struct timeval tv; 01407 tv.tv_sec = 0; 01408 tv.tv_usec = 1000; 01409 01410 int e = select( maxFd, &fdSet, NULL,NULL, &tv ); 01411 if (e < 0) 01412 { 01413 int err = getErrno(); 01414 clog << "Error on select: " << strerror(err) << endl; 01415 } 01416 else if (e >= 0) 01417 { 01418 StunAddress4 from; 01419 01420 // do the media relaying 01421 if (info.relay) 01422 { 01423 time_t now = time(0); 01424 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01425 { 01426 StunMediaRelay* relay = &info.relays[i]; 01427 if (relay->fd) 01428 { 01429 if (FD_ISSET(relay->fd, &fdSet)) 01430 { 01431 char msg[MAX_RTP_MSG_SIZE]; 01432 int msgLen = sizeof(msg); 01433 01434 StunAddress4 rtpFrom; 01435 ok = getMessage( relay->fd, msg, &msgLen, &rtpFrom.addr, &rtpFrom.port ,verbose); 01436 if (ok) 01437 { 01438 sendMessage(info.myFd, msg, msgLen, relay->destination.addr, relay->destination.port, verbose); 01439 relay->expireTime = now + MEDIA_RELAY_TIMEOUT; 01440 if ( verbose ) clog << "Relay packet on " 01441 << relay->fd 01442 << " from " << rtpFrom 01443 << " -> " << relay->destination 01444 << endl; 01445 } 01446 } 01447 else if (now > relay->expireTime) 01448 { 01449 stunclosesocket(relay->fd); 01450 relay->fd = 0; 01451 } 01452 } 01453 } 01454 } 01455 01456 01457 if (FD_ISSET(info.myFd,&fdSet)) 01458 { 01459 if (verbose) clog << "received on A1:P1" << endl; 01460 recvAltIp = false; 01461 recvAltPort = false; 01462 ok = getMessage( info.myFd, msg, &msgLen, &from.addr, &from.port,verbose ); 01463 } 01464 else if (FD_ISSET(info.altPortFd, &fdSet)) 01465 { 01466 if (verbose) clog << "received on A1:P2" << endl; 01467 recvAltIp = false; 01468 recvAltPort = true; 01469 ok = getMessage( info.altPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); 01470 } 01471 else if ( (info.altIpFd!=STUN_INVALID_SOCKET) && FD_ISSET(info.altIpFd,&fdSet)) 01472 { 01473 if (verbose) clog << "received on A2:P1" << endl; 01474 recvAltIp = true; 01475 recvAltPort = false; 01476 ok = getMessage( info.altIpFd, msg, &msgLen, &from.addr, &from.port ,verbose); 01477 } 01478 else if ( (info.altIpPortFd!=STUN_INVALID_SOCKET) && FD_ISSET(info.altIpPortFd, &fdSet)) 01479 { 01480 if (verbose) clog << "received on A2:P2" << endl; 01481 recvAltIp = true; 01482 recvAltPort = true; 01483 ok = getMessage( info.altIpPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); 01484 } 01485 else 01486 { 01487 return true; 01488 } 01489 01490 int relayPort = 0; 01491 if (info.relay) 01492 { 01493 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01494 { 01495 StunMediaRelay* relay = &info.relays[i]; 01496 if (relay->destination.addr == from.addr && 01497 relay->destination.port == from.port) 01498 { 01499 relayPort = relay->relayPort; 01500 relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; 01501 break; 01502 } 01503 } 01504 01505 if (relayPort == 0) 01506 { 01507 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01508 { 01509 StunMediaRelay* relay = &info.relays[i]; 01510 if (relay->fd == 0) 01511 { 01512 if ( verbose ) clog << "Open relay port " << relay->relayPort << endl; 01513 01514 relay->fd = openPort(relay->relayPort, info.myAddr.addr, verbose); 01515 relay->destination.addr = from.addr; 01516 relay->destination.port = from.port; 01517 relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; 01518 relayPort = relay->relayPort; 01519 break; 01520 } 01521 } 01522 } 01523 } 01524 01525 if ( !ok ) 01526 { 01527 if ( verbose ) clog << "Get message did not return a valid message" <<endl; 01528 return true; 01529 } 01530 01531 if ( verbose ) clog << "Got a request (len=" << msgLen << ") from " << from << endl; 01532 01533 if ( msgLen <= 0 ) 01534 { 01535 return true; 01536 } 01537 01538 bool changePort = false; 01539 bool changeIp = false; 01540 01541 StunMessage resp; 01542 StunAddress4 dest; 01543 StunAtrString hmacPassword; 01544 hmacPassword.sizeValue = 0; 01545 01546 StunAddress4 secondary; 01547 secondary.port = 0; 01548 secondary.addr = 0; 01549 01550 if (info.relay && relayPort) 01551 { 01552 secondary = from; 01553 01554 from.addr = info.myAddr.addr; 01555 from.port = relayPort; 01556 } 01557 01558 ok = stunServerProcessMsg( msg, msgLen, from, secondary, 01559 recvAltIp ? info.altAddr : info.myAddr, 01560 recvAltIp ? info.myAddr : info.altAddr, 01561 &resp, 01562 &dest, 01563 &hmacPassword, 01564 &changePort, 01565 &changeIp, 01566 verbose ); 01567 01568 if ( !ok ) 01569 { 01570 if ( verbose ) clog << "Failed to parse message" << endl; 01571 return true; 01572 } 01573 01574 char buf[STUN_MAX_MESSAGE_SIZE]; 01575 int len = sizeof(buf); 01576 01577 len = stunEncodeMessage( resp, buf, len, hmacPassword,verbose ); 01578 01579 if ( dest.addr == 0 ) ok=false; 01580 if ( dest.port == 0 ) ok=false; 01581 01582 if ( ok ) 01583 { 01584 assert( dest.addr != 0 ); 01585 assert( dest.port != 0 ); 01586 01587 Socket sendFd; 01588 01589 bool sendAltIp = recvAltIp; // send on the received IP address 01590 bool sendAltPort = recvAltPort; // send on the received port 01591 01592 if ( changeIp ) sendAltIp = !sendAltIp; // if need to change IP, then flip logic 01593 if ( changePort ) sendAltPort = !sendAltPort; // if need to change port, then flip logic 01594 01595 if ( !sendAltPort ) 01596 { 01597 if ( !sendAltIp ) 01598 { 01599 sendFd = info.myFd; 01600 } 01601 else 01602 { 01603 sendFd = info.altIpFd; 01604 } 01605 } 01606 else 01607 { 01608 if ( !sendAltIp ) 01609 { 01610 sendFd = info.altPortFd; 01611 } 01612 else 01613 { 01614 sendFd = info.altIpPortFd; 01615 } 01616 } 01617 01618 if ( sendFd != STUN_INVALID_SOCKET ) 01619 { 01620 sendMessage( sendFd, buf, len, dest.addr, dest.port, verbose ); 01621 } 01622 } 01623 } 01624 01625 return true; 01626 }
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 | |||
) |
Definition at line 1018 of file stun.cc.
Referenced by stunServerProcess().
01030 { 01031 01032 // set up information for default response 01033 01034 memset( resp, 0 , sizeof(*resp) ); 01035 01036 *changeIp = false; 01037 *changePort = false; 01038 01039 StunMessage req; 01040 bool ok = stunParseMessage( buf,bufLen, req, verbose); 01041 01042 if (!ok) // Complete garbage, drop it on the floor 01043 { 01044 if (verbose) clog << "Request did not parse" << endl; 01045 return false; 01046 } 01047 if (verbose) clog << "Request parsed ok" << endl; 01048 01049 StunAddress4 mapped = req.mappedAddress.ipv4; 01050 StunAddress4 respondTo = req.responseAddress.ipv4; 01051 UInt32 flags = req.changeRequest.value; 01052 01053 switch (req.msgHdr.msgType) 01054 { 01055 case SharedSecretRequestMsg: 01056 if(verbose) clog << "Received SharedSecretRequestMsg on udp. send error 433." << endl; 01057 // !cj! - should fix so you know if this came over TLS or UDP 01058 stunCreateSharedSecretResponse(req, from, *resp); 01059 //stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS"); 01060 return true; 01061 01062 case BindRequestMsg: 01063 if (!req.hasMessageIntegrity) 01064 { 01065 if (verbose) clog << "BindRequest does not contain MessageIntegrity" << endl; 01066 01067 if (0) // !jf! mustAuthenticate 01068 { 01069 if(verbose) clog << "Received BindRequest with no MessageIntegrity. Sending 401." << endl; 01070 stunCreateErrorResponse(*resp, 4, 1, "Missing MessageIntegrity"); 01071 return true; 01072 } 01073 } 01074 else 01075 { 01076 if (!req.hasUsername) 01077 { 01078 if (verbose) clog << "No UserName. Send 432." << endl; 01079 stunCreateErrorResponse(*resp, 4, 32, "No UserName and contains MessageIntegrity"); 01080 return true; 01081 } 01082 else 01083 { 01084 if (verbose) clog << "Validating username: " << req.username.value << endl; 01085 // !jf! could retrieve associated password from provisioning here 01086 if (strcmp(req.username.value, "test") == 0) 01087 { 01088 if (0) 01089 { 01090 // !jf! if the credentials are stale 01091 stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest"); 01092 return true; 01093 } 01094 else 01095 { 01096 if (verbose) clog << "Validating MessageIntegrity" << endl; 01097 // need access to shared secret 01098 01099 unsigned char hmac[20]; 01100 #ifndef NOSSL 01101 unsigned int hmacSize=20; 01102 01103 HMAC(EVP_sha1(), 01104 "1234", 4, 01105 reinterpret_cast<const unsigned char*>(buf), bufLen-20-4, 01106 hmac, &hmacSize); 01107 assert(hmacSize == 20); 01108 #endif 01109 01110 if (memcmp(buf, hmac, 20) != 0) 01111 { 01112 if (verbose) clog << "MessageIntegrity is bad. Sending " << endl; 01113 stunCreateErrorResponse(*resp, 4, 3, "Unknown username. Try test with password 1234"); 01114 return true; 01115 } 01116 01117 // need to compute this later after message is filled in 01118 resp->hasMessageIntegrity = true; 01119 assert(req.hasUsername); 01120 resp->hasUsername = true; 01121 resp->username = req.username; // copy username in 01122 } 01123 } 01124 else 01125 { 01126 if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl; 01127 } 01128 } 01129 } 01130 01131 // TODO !jf! should check for unknown attributes here and send 420 listing the 01132 // unknown attributes. 01133 01134 if ( respondTo.port == 0 ) respondTo = from; 01135 if ( mapped.port == 0 ) mapped = from; 01136 01137 *changeIp = ( flags & ChangeIpFlag )?true:false; 01138 *changePort = ( flags & ChangePortFlag )?true:false; 01139 01140 if (verbose) 01141 { 01142 clog << "Request is valid:" << endl; 01143 clog << "\t flags=" << flags << endl; 01144 clog << "\t changeIp=" << *changeIp << endl; 01145 clog << "\t changePort=" << *changePort << endl; 01146 clog << "\t from = " << from << endl; 01147 clog << "\t respond to = " << respondTo << endl; 01148 clog << "\t mapped = " << mapped << endl; 01149 } 01150 01151 // form the outgoing message 01152 resp->msgHdr.msgType = BindResponseMsg; 01153 for ( int i=0; i<16; i++ ) 01154 { 01155 resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i]; 01156 } 01157 01158 if ( req.xorOnly == false ) 01159 { 01160 resp->hasMappedAddress = true; 01161 resp->mappedAddress.ipv4.port = mapped.port; 01162 resp->mappedAddress.ipv4.addr = mapped.addr; 01163 } 01164 01165 if (1) // do xorMapped address or not 01166 { 01167 resp->hasXorMappedAddress = true; 01168 UInt16 id16 = req.msgHdr.id.octet[0]<<8 01169 | req.msgHdr.id.octet[1]; 01170 UInt32 id32 = req.msgHdr.id.octet[0]<<24 01171 | req.msgHdr.id.octet[1]<<16 01172 | req.msgHdr.id.octet[2]<<8 01173 | req.msgHdr.id.octet[3]; 01174 resp->xorMappedAddress.ipv4.port = mapped.port^id16; 01175 resp->xorMappedAddress.ipv4.addr = mapped.addr^id32; 01176 } 01177 01178 resp->hasSourceAddress = true; 01179 resp->sourceAddress.ipv4.port = (*changePort) ? altAddr.port : myAddr.port; 01180 resp->sourceAddress.ipv4.addr = (*changeIp) ? altAddr.addr : myAddr.addr; 01181 01182 resp->hasChangedAddress = true; 01183 resp->changedAddress.ipv4.port = altAddr.port; 01184 resp->changedAddress.ipv4.addr = altAddr.addr; 01185 01186 if ( secondary.port != 0 ) 01187 { 01188 resp->hasSecondaryAddress = true; 01189 resp->secondaryAddress.ipv4.port = secondary.port; 01190 resp->secondaryAddress.ipv4.addr = secondary.addr; 01191 } 01192 01193 if ( req.hasUsername && req.username.sizeValue > 0 ) 01194 { 01195 // copy username in 01196 resp->hasUsername = true; 01197 assert( req.username.sizeValue % 4 == 0 ); 01198 assert( req.username.sizeValue < STUN_MAX_STRING ); 01199 memcpy( resp->username.value, req.username.value, req.username.sizeValue ); 01200 resp->username.sizeValue = req.username.sizeValue; 01201 } 01202 01203 if (1) // add ServerName 01204 { 01205 resp->hasServerName = true; 01206 const char serverName[] = "Vovida.org " STUN_VERSION; // must pad to mult of 4 01207 01208 assert( sizeof(serverName) < STUN_MAX_STRING ); 01209 //cerr << "sizeof serverName is " << sizeof(serverName) << endl; 01210 assert( sizeof(serverName)%4 == 0 ); 01211 memcpy( resp->serverName.value, serverName, sizeof(serverName)); 01212 resp->serverName.sizeValue = sizeof(serverName); 01213 } 01214 01215 if ( req.hasMessageIntegrity & req.hasUsername ) 01216 { 01217 // this creates the password that will be used in the HMAC when then 01218 // messages is sent 01219 stunCreatePassword( req.username, hmacPassword ); 01220 } 01221 01222 if (req.hasUsername && (req.username.sizeValue > 64 ) ) 01223 { 01224 UInt32 source; 01225 assert( sizeof(int) == sizeof(UInt32) ); 01226 01227 sscanf(req.username.value, "%x", &source); 01228 resp->hasReflectedFrom = true; 01229 resp->reflectedFrom.ipv4.port = 0; 01230 resp->reflectedFrom.ipv4.addr = source; 01231 } 01232 01233 destination->port = respondTo.port; 01234 destination->addr = respondTo.addr; 01235 01236 return true; 01237 01238 default: 01239 if (verbose) clog << "Unknown or unsupported request " << endl; 01240 return false; 01241 } 01242 01243 assert(0); 01244 return false; 01245 }
void stunStopServer | ( | StunServerInfo & | info | ) |
Definition at line 1327 of file stun.cc.
Referenced by stunInitServer().
01328 { 01329 if (info.myFd > 0) stunclosesocket(info.myFd); 01330 if (info.altPortFd > 0) stunclosesocket(info.altPortFd); 01331 if (info.altIpFd > 0) stunclosesocket(info.altIpFd); 01332 if (info.altIpPortFd > 0) stunclosesocket(info.altIpPortFd); 01333 01334 if (info.relay) 01335 { 01336 for (int i=0; i<MAX_MEDIA_RELAYS; ++i) 01337 { 01338 StunMediaRelay* relay = &info.relays[i]; 01339 if (relay->fd) 01340 { 01341 stunclosesocket(relay->fd); 01342 relay->fd = 0; 01343 } 01344 } 01345 } 01346 }
void stunTest | ( | StunAddress4 & | dest, | |
int | testNum, | |||
bool | verbose, | |||
StunAddress4 * | sAddr | |||
) |
Definition at line 1812 of file stun.cc.
01813 { 01814 assert( dest.addr != 0 ); 01815 assert( dest.port != 0 ); 01816 01817 int port = stunRandomPort(); 01818 UInt32 interfaceIp=0; 01819 if (sAddr) 01820 { 01821 interfaceIp = sAddr->addr; 01822 if ( sAddr->port != 0 ) 01823 { 01824 port = sAddr->port; 01825 } 01826 } 01827 Socket myFd = openPort(port,interfaceIp,verbose); 01828 01829 StunAtrString username; 01830 StunAtrString password; 01831 01832 username.sizeValue = 0; 01833 password.sizeValue = 0; 01834 01835 #ifdef USE_TLS 01836 stunGetUserNameAndPassword( dest, username, password ); 01837 #endif 01838 01839 stunSendTest( myFd, dest, username, password, testNum, verbose ); 01840 01841 char msg[STUN_MAX_MESSAGE_SIZE]; 01842 int msgLen = STUN_MAX_MESSAGE_SIZE; 01843 01844 StunAddress4 from; 01845 getMessage( myFd, 01846 msg, 01847 &msgLen, 01848 &from.addr, 01849 &from.port,verbose ); 01850 01851 StunMessage resp; 01852 memset(&resp, 0, sizeof(StunMessage)); 01853 01854 if ( verbose ) clog << "Got a response" << endl; 01855 bool ok = stunParseMessage( msg,msgLen, resp,verbose ); 01856 01857 if ( verbose ) 01858 { 01859 clog << "\t ok=" << ok << endl; 01860 clog << "\t id=" << resp.msgHdr.id << endl; 01861 clog << "\t mappedAddr=" << resp.mappedAddress.ipv4 << endl; 01862 clog << "\t changedAddr=" << resp.changedAddress.ipv4 << endl; 01863 clog << endl; 01864 } 01865 01866 if (sAddr) 01867 { 01868 sAddr->port = resp.mappedAddress.ipv4.port; 01869 sAddr->addr = resp.mappedAddress.ipv4.addr; 01870 } 01871 }
static void toHex | ( | const char * | buffer, | |
int | bufferSize, | |||
char * | output | |||
) | [static] |
Definition at line 743 of file stun.cc.
Referenced by stunCreatePassword(), and stunCreateUserName().
00744 { 00745 static char hexmap[] = "0123456789abcdef"; 00746 00747 const char* p = buffer; 00748 char* r = output; 00749 for (int i=0; i < bufferSize; i++) 00750 { 00751 unsigned char temp = *p++; 00752 00753 int hi = (temp & 0xf0)>>4; 00754 int low = (temp & 0xf); 00755 00756 *r++ = hexmap[hi]; 00757 *r++ = hexmap[low]; 00758 } 00759 *r = 0; 00760 }