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 <io.h>
00011 #include <time.h>
00012 #else
00013
00014 #include <stdlib.h>
00015 #include <unistd.h>
00016 #include <string.h>
00017 #include <sys/ioctl.h>
00018 #include <sys/socket.h>
00019 #include <sys/time.h>
00020 #include <sys/types.h>
00021 #include <arpa/inet.h>
00022 #include <fcntl.h>
00023 #include <netdb.h>
00024 #include <netinet/in.h>
00025 #include <arpa/nameser.h>
00026 #include <resolv.h>
00027 #include <net/if.h>
00028
00029 #endif
00030
00031
00032 #if defined(__sparc__) || defined(WIN32)
00033 #define NOSSL
00034 #endif
00035 #define NOSSL
00036
00037 #include "stun_udp.h"
00038 #include "stun.h"
00039
00040
00041 using namespace std;
00042
00043
00044 static void
00045 computeHmac(char* hmac, const char* input, int length, const char* key, int keySize);
00046
00047 static bool
00048 stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4& result )
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 }
00079
00080 static bool
00081 stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest& result )
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 }
00097
00098 static bool
00099 stunParseAtrError( char* body, unsigned int hdrLen, StunAtrError& result )
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 }
00119
00120 static bool
00121 stunParseAtrUnknown( char* body, unsigned int hdrLen, StunAtrUnknown& result )
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 }
00139
00140
00141 static bool
00142 stunParseAtrString( char* body, unsigned int hdrLen, StunAtrString& result )
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 }
00163
00164
00165 static bool
00166 stunParseAtrIntegrity( char* body, unsigned int hdrLen, StunAtrIntegrity& result )
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 }
00179
00180
00181 bool
00182 stunParseMessage( char* buf, unsigned int bufLen, StunMessage& msg, bool verbose)
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
00208
00209 while ( size > 0 )
00210 {
00211
00212
00213 StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body);
00214
00215 unsigned int attrLen = ntohs(attr->length);
00216 int atrType = ntohs(attr->type);
00217
00218
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;
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
00334 }
00335
00336
00337
00338
00339
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 }
00437
00438
00439 static char*
00440 encode16(char* buf, UInt16 data)
00441 {
00442 UInt16 ndata = htons(data);
00443 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16));
00444 return buf + sizeof(UInt16);
00445 }
00446
00447 static char*
00448 encode32(char* buf, UInt32 data)
00449 {
00450 UInt32 ndata = htonl(data);
00451 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt32));
00452 return buf + sizeof(UInt32);
00453 }
00454
00455
00456 static char*
00457 encode(char* buf, const char* data, unsigned int length)
00458 {
00459 memcpy(buf, data, length);
00460 return buf + length;
00461 }
00462
00463
00464 static char*
00465 encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4& atr)
00466 {
00467 ptr = encode16(ptr, type);
00468 ptr = encode16(ptr, 8);
00469 *ptr++ = atr.pad;
00470 *ptr++ = IPv4Family;
00471 ptr = encode16(ptr, atr.ipv4.port);
00472 ptr = encode32(ptr, atr.ipv4.addr);
00473
00474 return ptr;
00475 }
00476
00477 static char*
00478 encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest& atr)
00479 {
00480 ptr = encode16(ptr, ChangeRequest);
00481 ptr = encode16(ptr, 4);
00482 ptr = encode32(ptr, atr.value);
00483 return ptr;
00484 }
00485
00486 static char*
00487 encodeAtrError(char* ptr, const StunAtrError& atr)
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 }
00497
00498
00499 static char*
00500 encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr)
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 }
00510
00511
00512 static char*
00513 encodeXorOnly(char* ptr)
00514 {
00515 ptr = encode16(ptr, XorOnly );
00516 return ptr;
00517 }
00518
00519
00520 static char*
00521 encodeAtrString(char* ptr, UInt16 type, const StunAtrString& atr)
00522 {
00523 assert(atr.sizeValue % 4 == 0);
00524
00525 ptr = encode16(ptr, type);
00526 ptr = encode16(ptr, atr.sizeValue);
00527 ptr = encode(ptr, atr.value, atr.sizeValue);
00528 return ptr;
00529 }
00530
00531
00532 static char*
00533 encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr)
00534 {
00535 ptr = encode16(ptr, MessageIntegrity);
00536 ptr = encode16(ptr, 20);
00537 ptr = encode(ptr, atr.hash, sizeof(atr.hash));
00538 return ptr;
00539 }
00540
00541
00542 unsigned int
00543 stunEncodeMessage( const StunMessage& msg,
00544 char* buf,
00545 unsigned int bufLen,
00546 const StunAtrString& password,
00547 bool verbose)
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 }
00648
00649 int
00650 stunRand()
00651 {
00652
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 }
00703
00704
00706 int
00707 stunRandomPort()
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 }
00718
00719
00720 #ifdef NOSSL
00721 static void
00722 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
00723 {
00724 strncpy(hmac,"hmac-not-implemented",20);
00725 }
00726 #else
00727 #include <openssl/hmac.h>
00728
00729 static void
00730 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
00731 {
00732 unsigned int resultSize=0;
00733 HMAC(EVP_sha1(),
00734 key, sizeKey,
00735 reinterpret_cast<const unsigned char*>(input), length,
00736 reinterpret_cast<unsigned char*>(hmac), &resultSize);
00737 assert(resultSize == 20);
00738 }
00739 #endif
00740
00741
00742 static void
00743 toHex(const char* buffer, int bufferSize, char* output)
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 }
00761
00762 void
00763 stunCreateUserName(const StunAddress4& source, StunAtrString* username)
00764 {
00765 UInt64 time = stunGetSystemTimeSecs();
00766 time -= (time % 20*60);
00767
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
00798 }
00799
00800 void
00801 stunCreatePassword(const StunAtrString& username, StunAtrString* password)
00802 {
00803 char hmac[20];
00804 char key[] = "Fluffy";
00805
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
00812 }
00813
00814
00815 UInt64
00816 stunGetSystemTimeSecs()
00817 {
00818 UInt64 time=0;
00819 #if defined(WIN32)
00820 SYSTEMTIME t;
00821
00822 GetSystemTime( &t );
00823 time = (t.wHour*60+t.wMinute)*60+t.wSecond;
00824 #else
00825 struct timeval now;
00826 gettimeofday( &now , NULL );
00827
00828 time = now.tv_sec;
00829 #endif
00830 return time;
00831 }
00832
00833
00834 ostream& operator<< ( ostream& strm, const UInt128& r )
00835 {
00836 strm << int(r.octet[0]);
00837 for ( int i=1; i<16; i++ )
00838 {
00839 strm << ':' << int(r.octet[i]);
00840 }
00841
00842 return strm;
00843 }
00844
00845 ostream&
00846 operator<<( ostream& strm, const StunAddress4& addr)
00847 {
00848 UInt32 ip = addr.addr;
00849 strm << ((int)(ip>>24)&0xFF) << ".";
00850 strm << ((int)(ip>>16)&0xFF) << ".";
00851 strm << ((int)(ip>> 8)&0xFF) << ".";
00852 strm << ((int)(ip>> 0)&0xFF) ;
00853
00854 strm << ":" << addr.port;
00855
00856 return strm;
00857 }
00858
00859
00860
00861 bool
00862 stunParseHostName( char* peerName,
00863 UInt32& ip,
00864 UInt16& portVal,
00865 UInt16 defaultPort )
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
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
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
00906 struct hostent* h;
00907
00908 #ifdef WIN32
00909 assert( strlen(host) >= 1 );
00910 if ( isdigit( host[0] ) )
00911 {
00912
00913 unsigned long a = inet_addr(host);
00914
00915
00916 ip = ntohl( a );
00917 }
00918 else
00919 {
00920
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 }
00960
00961
00962 bool
00963 stunParseServerName( char* name, StunAddress4& addr)
00964 {
00965 assert(name);
00966
00967
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 }
00976
00977
00978 static void
00979 stunCreateErrorResponse(StunMessage& response, int cl, int number, const char* msg)
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 }
00987
00988 #if 0
00989 static void
00990 stunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg)
00991 {
00992 response.msgHdr.msgType = SharedSecretErrorResponseMsg;
00993 response.hasErrorCode = true;
00994 response.errorCode.errorClass = cl;
00995 response.errorCode.number = number;
00996 strcpy(response.errorCode.reason, msg);
00997 }
00998 #endif
00999
01000 static void
01001 stunCreateSharedSecretResponse(const StunMessage& request, const StunAddress4& source, StunMessage& response)
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 }
01012
01013
01014
01015
01016
01017 bool
01018 stunServerProcessMsg( char* buf,
01019 unsigned int bufLen,
01020 StunAddress4& from,
01021 StunAddress4& secondary,
01022 StunAddress4& myAddr,
01023 StunAddress4& altAddr,
01024 StunMessage* resp,
01025 StunAddress4* destination,
01026 StunAtrString* hmacPassword,
01027 bool* changePort,
01028 bool* changeIp,
01029 bool verbose)
01030 {
01031
01032
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)
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
01058 stunCreateSharedSecretResponse(req, from, *resp);
01059
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)
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
01086 if (strcmp(req.username.value, "test") == 0)
01087 {
01088 if (0)
01089 {
01090
01091 stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest");
01092 return true;
01093 }
01094 else
01095 {
01096 if (verbose) clog << "Validating MessageIntegrity" << endl;
01097
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
01118 resp->hasMessageIntegrity = true;
01119 assert(req.hasUsername);
01120 resp->hasUsername = true;
01121 resp->username = req.username;
01122 }
01123 }
01124 else
01125 {
01126 if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl;
01127 }
01128 }
01129 }
01130
01131
01132
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
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)
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
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)
01204 {
01205 resp->hasServerName = true;
01206 const char serverName[] = "Vovida.org " STUN_VERSION;
01207
01208 assert( sizeof(serverName) < STUN_MAX_STRING );
01209
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
01218
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 }
01246
01247 bool
01248 stunInitServer(StunServerInfo& info, const StunAddress4& myAddr,
01249 const StunAddress4& altAddr, int startMediaPort, bool verbose )
01250 {
01251 assert( myAddr.port != 0 );
01252 assert( altAddr.port!= 0 );
01253 assert( myAddr.addr != 0 );
01254
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
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
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
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
01321 }
01322
01323 return true;
01324 }
01325
01326 void
01327 stunStopServer(StunServerInfo& info)
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 }
01347
01348
01349 bool
01350 stunServerProcess(StunServerInfo& info, bool verbose)
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
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;
01590 bool sendAltPort = recvAltPort;
01591
01592 if ( changeIp ) sendAltIp = !sendAltIp;
01593 if ( changePort ) sendAltPort = !sendAltPort;
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 }
01627
01628 int
01629 stunFindLocalInterfaces(UInt32* addresses,int maxRet)
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
01657
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
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 }
01693
01694
01695 void
01696 stunBuildReqSimple( StunMessage* msg,
01697 const StunAtrString& username,
01698 bool changePort, bool changeIp, unsigned int id )
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 }
01730
01731
01732 static void
01733 stunSendTest( Socket myFd, StunAddress4& dest,
01734 const StunAtrString& username, const StunAtrString& password,
01735 int testNum, bool verbose )
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
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
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 }
01797
01798
01799 void
01800 stunGetUserNameAndPassword( const StunAddress4& dest,
01801 StunAtrString* username,
01802 StunAtrString* password)
01803 {
01804
01805
01806 stunCreateUserName(dest, username);
01807 stunCreatePassword(*username, password);
01808 }
01809
01810
01811 void
01812 stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* sAddr )
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 }
01872
01873
01874 NatType
01875 stunNatType( StunAddress4& dest,
01876 bool verbose,
01877 bool* preservePort,
01878 bool* hairpin,
01879 int port,
01880 StunAddress4* sAddr
01881 )
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;
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
01960 cerr << "Error " << e << " " << strerror(e) << " in select" << endl;
01961 return StunTypeFailure;
01962 }
01963 else if ( err == 0 )
01964 {
01965
01966 count++;
01967
01968 if ( !respTestI )
01969 {
01970 stunSendTest( myFd1, dest, username, password, 1 ,verbose );
01971 }
01972
01973 if ( (!respTestI2) && respTestI )
01974 {
01975
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
02005 assert( err>0 );
02006
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
02124
02125 Socket s = openPort( 0, testImappedAddr.addr, false );
02126 if ( s != STUN_INVALID_SOCKET )
02127 {
02128 stunclosesocket(s);
02129 isNat = false;
02130
02131 }
02132 else
02133 {
02134 isNat = true;
02135
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
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 )
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
02219 {
02220 return StunTypeDependentMapping;
02221 }
02222 }
02223 else
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 }
02243
02244
02245 int
02246 stunOpenSocket( StunAddress4& dest, StunAddress4* mapAddr,
02247 int port, StunAddress4* srcAddr,
02248 bool verbose )
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 );
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
02302
02303
02304
02305
02306 *mapAddr = mappedAddr;
02307
02308 return myFd;
02309 }
02310
02311
02312 bool
02313 stunOpenSocketPair( StunAddress4& dest, StunAddress4* mapAddr,
02314 int* fd1, int* fd2,
02315 int port, StunAddress4* srcAddr,
02316 bool verbose )
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, 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
02431 for( i=0; i<NUM; i++)
02432 {
02433 stunclosesocket( fd[i] );
02434 }
02435
02436 return false;
02437 }
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