there is a bug in turn-server

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 Hi,

    There is a bug in pj-turn-server. Two sides do the ICE negotiation, if one side is behind a NAT which is symmetrical type, it would happen that two sides do the ICE negotiation successfully, but the side mentioned before can't receive the data sent by turn-server.  When doing the ICE negotiation, the turn-server will receive the "CreatePermission" request, and create permission for one turn allocation, when ICE done, , because the Peer is behind symmetrical NAT, the prflx address is not equal to its srvflx,  turn-server will receive a "ChannelBind" request of the turn allocation to Update the Peer address. but pj-turn-server uses address only to hash the peer address. it will find a hash node whose address part is same as new prflx and ignore it simply.  But in fact, there port is different. 


      So a easy way to fix it is, when do the ChannelBind, if permission node is found by address, it should be updated every time.


English is not my first language. I hope you can understand what I said. The code:



} else if (msg->hdr.type == PJ_STUN_CHANNEL_BIND_REQUEST) {
	/*
	 * ChannelBind request.
	 */
	pj_stun_channel_number_attr *ch_attr;
	pj_stun_xor_peer_addr_attr *peer_attr;
	pj_turn_permission *p1, *p2;


	ch_attr = (pj_stun_channel_number_attr*)
		  pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_CHANNEL_NUMBER, 0);
	peer_attr = (pj_stun_xor_peer_addr_attr*)
		    pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);


	if (!ch_attr || !peer_attr) {
	    send_reply_err(alloc, rdata, PJ_TRUE, 
			   PJ_STUN_SC_BAD_REQUEST, NULL);
	    return PJ_SUCCESS;
	}


	/* Find permission with the channel number */
	p1 = lookup_permission_by_chnum(alloc, PJ_STUN_GET_CH_NB(ch_attr->value));


	/* If permission is found, this is supposed to be a channel bind 
	 * refresh. Make sure it's for the same peer.
	 */
	if (p1) {
	    if (pj_sockaddr_cmp(&p1->hkey.peer_addr, &peer_attr->sockaddr)) {
		/* Address mismatch. Send 400 */
		send_reply_err(alloc, rdata, PJ_TRUE, 
			       PJ_STUN_SC_BAD_REQUEST, 
			       "Peer address mismatch");
		return PJ_SUCCESS;
	    }


	    /* Refresh permission */
	    refresh_permission(p1);


	    /* Send response */
	    send_reply_ok(alloc, rdata);


	    /* Done */
	    return PJ_SUCCESS;
	}


	/* If permission is not found, create a new one. Make sure the peer
	 * has not alreadyy assigned with a channel number. 
	 */
	p2 = lookup_permission_by_addr(alloc, &peer_attr->sockaddr,
				       pj_sockaddr_get_len(&peer_attr->sockaddr));
	if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) {


	    send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 
			   "Peer address already assigned a channel number");
	    return PJ_SUCCESS;
	}


	/* Create permission if it doesn't exist */
	if (!p2) {
	    p2 = create_permission(alloc, &peer_attr->sockaddr,
				   pj_sockaddr_get_len(&peer_attr->sockaddr));
	    if (!p2)
		return PJ_SUCCESS;
	}


        /* my fix */
        pj_memcpy(&p2->hkey.peer_addr,&peer_attr->sockaddr,pj_sockaddr_get_len(&peer_attr->sockaddr));
        
	/* Assign channel number to permission */
	p2->channel = PJ_STUN_GET_CH_NB(ch_attr->value);


	/* Register to hash table */
	pj_assert(sizeof(p2->channel==2));
	pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel, 
		    sizeof(p2->channel), 0, p2);


	/* Update */
	refresh_permission(p2);


	/* Reply */
	send_reply_ok(alloc, rdata);


	return PJ_SUCCESS;


    } else if (msg->hdr.type == PJ_STUN_ALLOCATE_REQUEST) {

...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/attachments/20131029/f1ce6106/attachment-0001.html>


[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux