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