TCP not matching valid peer.
authorDavid Vossel <dvossel@digium.com>
Fri, 8 May 2009 20:32:51 +0000 (20:32 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 8 May 2009 20:32:51 +0000 (20:32 +0000)
find_peer() does not find a valid peer when using pvt->recv as the sockaddr_in argument.  Because of the way TCP works, the port number in pvt->recv is not what we're looking for at all.  There is currently only one place that find_peer searches for a peer using the sockaddr_in argument.  If the peer is not found after using pvt->recv (works for UDP since the port number will be correct), a temp sockaddr_in struct is made using the Contact header in the sip_request.  This has the correct port number in it.

Review: http://reviewboard.digium.com/r/236/

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@193387 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index 1fc93cc..089abef 100644 (file)
@@ -13420,6 +13420,22 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
                if (!peer) {
                        peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE);
                }
+
+               /* If the peer is still not found, try the address and port from the
+                * contact header.  If the transport type is TCP or TLS it is not possible
+                * to find the peer using p->recv. Because of the way TCP works, the received
+                * packet's destination port will not match the one the peer table is
+                * built with. */
+               if (!peer && (p->socket.type != SIP_TRANSPORT_UDP)) {
+                       struct sockaddr_in tmpsin;
+                       char contact[SIPBUFSIZE];
+                       char *tmp;
+                       memcpy(&tmpsin, &p->recv, sizeof(tmpsin));
+                       ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
+                       tmp = get_in_brackets(contact);
+                       __set_address_from_contact(tmp, &tmpsin, 1);
+                       peer = find_peer(NULL, &tmpsin, TRUE, FINDPEERS, FALSE);
+               }
        }
 
        if (!peer) {