📄 stun.c
字号:
/* set up information for default response */ memset( &req, 0 , sizeof(req) ); memset( resp, 0 , sizeof(*resp) ); *changeIp = FALSE; *changePort = FALSE; ok = stunParseMessage( buf,bufLen, &req); if (!ok) /* Complete garbage, drop it on the floor */ { ortp_error("stun: Request did not parse"); return FALSE; } //ortp_debug("stun: Request parsed ok"); mapped = req.mappedAddress.ipv4; respondTo = req.responseAddress.ipv4; flags = req.changeRequest.value; if (req.msgHdr.msgType==(STUN_METHOD_BINDING|STUN_REQUEST)) { if (!req.hasMessageIntegrity) { //ortp_debug("stun: BindRequest does not contain SA_MESSAGEINTEGRITY"); if (0) /* !jf! mustAuthenticate */ { ortp_error("stun: Received BindRequest with no SA_MESSAGEINTEGRITY. Sending 401."); stunCreateErrorResponse(resp, 4, 1, "Missing SA_MESSAGEINTEGRITY"); return TRUE; } } else { if (!req.hasUsername) { ortp_error("stun: No UserName. Send 432."); stunCreateErrorResponse(resp, 4, 32, "No UserName and contains SA_MESSAGEINTEGRITY"); return TRUE; } else { //ortp_debug("stun: Validating username: %s", req.username.value ); /* !jf! could retrieve associated password from provisioning here */ if (strcmp(req.username.value, "test") == 0) { if (0) { /* !jf! if the credentials are stale */ stunCreateErrorResponse(resp, 4, 30, "Stale credentials on BindRequest"); return TRUE; } else { unsigned char hmac[20]; //ortp_debug("stun: Validating SA_MESSAGEINTEGRITY"); /* need access to shared secret */#ifndef NOSSL { unsigned int hmacSize=20; HMAC(EVP_sha1(), "1234", 4, (const unsigned char*) buf, bufLen-20-4, hmac, &hmacSize); /*HMAC(EVP_sha1(), "1234", 4, reinterpret_cast<const unsigned char*>(buf), bufLen-20-4, hmac, &hmacSize); //assert(hmacSize == 20); */ }#endif if (memcmp(buf, hmac, 20) != 0) { ortp_error("stun: SA_MESSAGEINTEGRITY is bad. Sending "); stunCreateErrorResponse(resp, 4, 3, "Unknown username. Try test with password 1234"); return TRUE; } /* need to compute this later after message is filled in */ resp->hasMessageIntegrity = TRUE; /* assert(req.hasUsername); */ resp->hasUsername = TRUE; resp->username = req.username; /* copy username in */ } } else { ortp_error("stun: Invalid username: %s Send 430", req.username.value); } } } /* TODO !jf! should check for unknown attributes here and send 420 listing the unknown attributes. */ if ( respondTo.port == 0 ) { /* respondTo = from; */ memcpy(&respondTo, from, sizeof(StunAddress4)); } if ( mapped.port == 0 ) { /* mapped = from; */ memcpy(&mapped, from, sizeof(StunAddress4)); } *changeIp = ( flags & ChangeIpFlag )?TRUE:FALSE; *changePort = ( flags & ChangePortFlag )?TRUE:FALSE; //ortp_debug("stun: Request is valid:\n"); //ortp_debug("stun: \t flags= %i\n", flags ); //ortp_debug("stun: \t changeIp= %i\n", *changeIp ); //ortp_debug("stun: \t changePort=%i\n", *changePort ); //ortp_debug("stun: \t from= %i\n", from->addr ); //ortp_debug("stun: \t respond to= %i\n", respondTo.addr ); //ortp_debug("stun: \t mapped= %i\n", mapped.addr ); /* form the outgoing message */ resp->msgHdr.msgType = (STUN_METHOD_BINDING | STUN_SUCCESS_RESP); resp->msgHdr.magic_cookie = ntohl(req.msgHdr.magic_cookie); for (i=0; i<12; i++ ) { resp->msgHdr.tr_id.octet[i] = req.msgHdr.tr_id.octet[i]; } if (1) /* do xorMapped address or not */ { UInt32 cookie = 0x2112A442; UInt16 cookie16; resp->hasXorMappedAddress = TRUE; cookie16 = ((UInt8*)&cookie)[0]<<8 | ((UInt8*)&cookie)[1]; resp->xorMappedAddress.ipv4.port = mapped.port^cookie16; resp->xorMappedAddress.ipv4.addr = mapped.addr^cookie; } resp->hasSourceAddress = TRUE; resp->sourceAddress.ipv4.port = (*changePort) ? altAddr->port : myAddr->port; resp->sourceAddress.ipv4.addr = (*changeIp) ? altAddr->addr : myAddr->addr; resp->hasChangedAddress = TRUE; resp->changedAddress.ipv4.port = altAddr->port; resp->changedAddress.ipv4.addr = altAddr->addr; if ( req.hasUsername && req.username.sizeValue > 0 ) { /* copy username in */ resp->hasUsername = TRUE; /* assert( req.username.sizeValue % 4 == 0 ); */ /* assert( req.username.sizeValue < STUN_MAX_STRING ); */ memcpy( resp->username.value, req.username.value, req.username.sizeValue ); resp->username.sizeValue = req.username.sizeValue; } if (1) /* add ServerName */ { const char serverName[] = "oRTP " STUN_VERSION; /* must pad to mult of 4 */ resp->hasSoftware = TRUE; /* assert( sizeof(serverName) < STUN_MAX_STRING ); */ /* cerr << "sizeof serverName is " << sizeof(serverName) ); */ /* assert( sizeof(serverName)%4 == 0 ); */ memcpy( resp->softwareName.value, serverName, sizeof(serverName)); resp->softwareName.sizeValue = sizeof(serverName); } #if 0 if ( req.hasMessageIntegrity & req.hasUsername ) { /* this creates the password that will be used in the HMAC when then */ /* messages is sent */ stunCreatePassword( &req.username, hmacPassword ); }#endif if (req.hasUsername && (req.username.sizeValue > 64 ) ) { UInt32 source; /* assert( sizeof(int) == sizeof(UInt32) ); */ sscanf(req.username.value, "%x", &source); resp->hasReflectedFrom = TRUE; resp->reflectedFrom.ipv4.port = 0; resp->reflectedFrom.ipv4.addr = source; } destination->port = respondTo.port; destination->addr = respondTo.addr; return TRUE; } else { ortp_error("stun: Unknown or unsupported request "); return FALSE; } /* assert(0); */ return FALSE;}bool_tstunInitServer(StunServerInfo *info, const StunAddress4 *myAddr, const StunAddress4 *altAddr, int startMediaPort){ /* assert( myAddr.port != 0 ); */ /* assert( altAddr.port!= 0 ); */ /* assert( myAddr.addr != 0 ); */ /* assert( altAddr.addr != 0 ); */ /* info->myAddr = myAddr; */ info->myAddr.port = myAddr->port; info->myAddr.addr = myAddr->addr; /* info->altAddr = altAddr; */ info->altAddr.port = altAddr->port; info->altAddr.addr = altAddr->addr; info->myFd = INVALID_SOCKET; info->altPortFd = INVALID_SOCKET; info->altIpFd = INVALID_SOCKET; info->altIpPortFd = INVALID_SOCKET; memset(info->relays, 0, sizeof(info->relays)); if (startMediaPort > 0) { int i; info->relay = TRUE; for (i=0; i<MAX_MEDIA_RELAYS; ++i) { StunMediaRelay* relay = &info->relays[i]; relay->relayPort = startMediaPort+i; relay->fd = 0; relay->expireTime = 0; } } else { info->relay = FALSE; } if ((info->myFd = openPort(myAddr->port, myAddr->addr)) == INVALID_SOCKET) { ortp_error("stun: Can't open %i\n", myAddr->addr ); stunStopServer(info); return FALSE; } if ((info->altPortFd = openPort(altAddr->port,myAddr->addr)) == INVALID_SOCKET) { ortp_error("stun: Can't open %i\n", myAddr->addr ); stunStopServer(info); return FALSE; } info->altIpFd = INVALID_SOCKET; if ( altAddr->addr != 0 ) { if ((info->altIpFd = openPort( myAddr->port, altAddr->addr)) == INVALID_SOCKET) { ortp_error("stun: Can't open %i\n", altAddr->addr ); stunStopServer(info); return FALSE; } } info->altIpPortFd = INVALID_SOCKET; if ( altAddr->addr != 0 ) { if ((info->altIpPortFd = openPort(altAddr->port, altAddr->addr)) == INVALID_SOCKET) { ortp_error("stun: Can't open %i\n", altAddr->addr ); stunStopServer(info); return FALSE; } } return TRUE;}voidstunStopServer(StunServerInfo *info){ if (info->myFd > 0) closesocket(info->myFd); if (info->altPortFd > 0) closesocket(info->altPortFd); if (info->altIpFd > 0) closesocket(info->altIpFd); if (info->altIpPortFd > 0) closesocket(info->altIpPortFd); if (info->relay) { int i; for (i=0; i<MAX_MEDIA_RELAYS; ++i) { StunMediaRelay* relay = &info->relays[i]; if (relay->fd) { closesocket(relay->fd); relay->fd = 0; } } }}int stunFindLocalInterfaces(UInt32* addresses,int maxRet){#if defined(WIN32) || defined(_WIN32_WCE) || defined(__sparc__) return 0;#else struct ifconf ifc; int e; int s = socket( AF_INET, SOCK_DGRAM, 0 ); int len = 100 * sizeof(struct ifreq); char buf[ 100 * sizeof(struct ifreq) ]; char *ptr; int tl; int count=0; ifc.ifc_len = len; ifc.ifc_buf = buf; e = ioctl(s,SIOCGIFCONF,&ifc); ptr = buf; tl = ifc.ifc_len; while ( (tl > 0) && ( count < maxRet) ) { struct ifreq* ifr = (struct ifreq *)ptr; struct ifreq ifr2; struct sockaddr a; struct sockaddr_in* addr; UInt32 ai; int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr); tl -= si; ptr += si; /* char* name = ifr->ifr_ifrn.ifrn_name; */ /* cerr << "name = " << name ); */ ifr2 = *ifr; e = ioctl(s,SIOCGIFADDR,&ifr2); if ( e == -1 ) { break; } /* cerr << "ioctl addr e = " << e ; */ a = ifr2.ifr_addr; addr = (struct sockaddr_in*) &a; ai = ntohl( addr->sin_addr.s_addr ); if ((int)((ai>>24)&0xFF) != 127) { addresses[count++] = ai; } } closesocket(s); return count;#endif}voidstunBuildReqSimple( StunMessage* msg, const StunAtrString *username, bool_t changePort, bool_t changeIp, unsigned int id ){ int i; /* assert( msg ); */ memset( msg , 0 , sizeof(*msg) ); msg->msgHdr.msgType = (STUN_METHOD_BINDING|STUN_REQUEST); msg->msgHdr.magic_cookie = 0x2112A442; for ( i=0; i<12; i=i+4 ) { /* assert(i+3<16); */ int r = stunRand(); msg->msgHdr.tr_id.octet[i+0]= r>>0; msg->msgHdr.tr_id.octet[i+1]= r>>8; msg->msgHdr.tr_id.octet[i+2]= r>>16; msg->msgHdr.tr_id.octet[i+3]= r>>24; } if ( id != 0 ) { msg->msgHdr.tr_id.octet[0] = id; } if (changePort==TRUE || changeIp==TRUE) { msg->hasChangeRequest = TRUE; msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | (changePort?ChangePortFlag:0); } if ( username!=NULL && username->sizeValue > 0 ) { msg->hasUsername = TRUE; /* msg->username = username; */ memcpy(&msg->username, username, sizeof(StunAtrString)); }}static void stunSendTest( Socket myFd, StunAddress4 *dest, const StunAtrString *username, const StunAtrString *password, int testNum ){ /* assert( dest.addr != 0 ); */ /* assert( dest.port != 0 ); */ bool_t changePort=FALSE; bool_t changeIP=FALSE; bool_t discard=FALSE; StunMessage req; char buf[STUN_MAX_MESSAGE_SIZE]; int len = STUN_MAX_MESSAGE_SIZE; switch (testNum) { case 1: case 10: case 11: break; case 2: /* changePort=TRUE; */ changeIP=TRUE; break; case 3: changePort=TRUE; break; case 4: changeIP=TRUE; break; case 5: discard=TRUE; break; default: ortp_error("stun: Test %i is unkown\n", testNum); return ; /* error */ } memset(&req, 0, sizeof(StunMessage)); stunBuildReqSimple( &req, username, changePort , changeIP , testNum ); len = stunEncodeMessage( &req, buf, len, password ); //ortp_debug("stun: About to send msg of len %i to %s\n", len, ipaddr(dest) ); sendMessage( myFd, buf, len, dest->addr, dest->port ); /* add some delay so the packets don't get sent too quickly */#if defined(_WIN32_WCE) Sleep (10);#elif defined(WIN32)/* !cj! TODO - should fix this up in windows */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -