Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.836 diff -u -r1.836 chan_sip.c --- channels/chan_sip.c 2 Sep 2005 19:24:32 -0000 1.836 +++ channels/chan_sip.c 6 Sep 2005 16:24:16 -0000 @@ -2996,8 +2996,11 @@ { struct sip_pvt *p; char *callid; - char tmp[256] = ""; + char toheader[128] = ""; + char fromheader[128] = ""; char *tag = "", *c; + char *fromtag = "", *totag = ""; + int badsyntax = 0; callid = get_header(req, "Call-ID"); @@ -3005,32 +3008,103 @@ /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy we need more to identify a branch - so we have to check branch, from and to tags to identify a call leg. - For Asterisk to behave correctly, you need to turn on pedanticsipchecking + For Asterisk to behave correctly, you need to turn on pedanticsipchecking in sip.conf */ + totag = get_header(req, "To"); + c = strcasestr(totag, ";tag="); + if (c) { + ast_copy_string(toheader, c+5 , sizeof(toheader)); + totag = toheader; + } else + totag = NULL; + if (totag) { + if ((c = strchr(totag, ';'))) + *c = '\0'; + } + fromtag = get_header(req, "From"); + c = strcasestr(fromtag, ";tag="); + if (c) { + ast_copy_string(fromheader, c+5, sizeof(fromheader)); + fromtag = fromheader; + } else + fromtag = NULL; + + if (fromtag) { + if ((c = strchr(fromtag, ';'))) + *c = '\0'; + } if (req->method == SIP_RESPONSE) - ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp)); + tag = totag; else - ast_copy_string(tmp, get_header(req, "From"), sizeof(tmp)); - tag = strcasestr(tmp, "tag="); - if (tag) { - tag += 4; - c = strchr(tag, ';'); - if (c) - *c = '\0'; + tag = fromtag; + if (option_debug > 2) { + if (req->method != SIP_RESPONSE) { /* Request */ + if (totag && fromtag) + ast_log(LOG_DEBUG, "...Request within an existing dialog\n"); + else if (totag && !fromtag) + ast_log(LOG_DEBUG, "...Request with no fromtag? Bad request.\n"); + else if (!totag && !fromtag) + ast_log(LOG_DEBUG, "...Request with no tags? Bad request.\n"); + else if (option_debug > 3) /* From tag, no to tag */ + ast_log(LOG_DEBUG, "New SIP request coming in: Call ID: %s (Checking %s) --From tag %s --To-tag %s \n", callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag); + } else { /* Response */ + if (totag && fromtag) + ast_log(LOG_DEBUG, "SIP response coming in: Call ID: %s (Checking %s) --From tag %s --To-tag %s \n", callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag); + else if (totag && !fromtag) + ast_log(LOG_DEBUG, "...Response with no fromtag? Bad response on bad request.\n"); + else if (!totag && !fromtag) + ast_log(LOG_DEBUG, "...Response with no tags at all? Bad response.\n"); + else /* From tag, no to tag */ + ast_log(LOG_DEBUG, "...Response with no to tag? Bad response.\n"); + + } + } + if (!fromtag) { /* Always need from tags */ + badsyntax = 1; + } + if (req->method == SIP_RESPONSE && !totag) { /* Responses need to-tags also */ + badsyntax = 1; + } + if ( badsyntax ) { + ast_log(LOG_WARNING, "Bad SIP %s in dialog %s. \n", req->method==SIP_RESPONSE ? "Response" : "Request", callid); } } + + if (!badsyntax && option_debug > 3) + ast_log(LOG_DEBUG, "===== Looking for Call ID: %s (Checking %s) --From tag %s --To-tag %s \n", callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag); ast_mutex_lock(&iflock); p = iflist; - while(p) { + while(p && !badsyntax) { int found = 0; if (req->method == SIP_REGISTER) found = (!strcmp(p->callid, callid)); else found = (!strcmp(p->callid, callid) && (!pedanticsipchecking || !tag || ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag))) ; + + if (option_debug > 3) + ast_log(LOG_DEBUG, "===== %s Their Call ID: %s Their Tag %s Our tag: as%08x\n", found ? "Found" : "No match", p->callid, p->theirtag, p->tag); + + /* If we get a new request within an existing to-tag - check the to tag as well */ + if (pedanticsipchecking && found && req->method != SIP_RESPONSE) { /* SIP Request */ + if (p->tag == 0 && totag) { + /* We have no to tag, and they have. Wrong dialog */ + found = 0; + } else if (totag) { /* Both have tags, compare them */ + char ourtag[12]; + sprintf(ourtag, "as%08x", p->tag); + if (strcmp(totag, ourtag)) { + found = 0; /* This is not our packet */ + } + } + if (!found && option_debug > 3) + ast_log(LOG_DEBUG, "===== This is not our match on request: Call ID: %s Ourtag Totag %s Method %s\n", p->callid, totag, sip_methods[req->method].text); + } + + if (found) { /* Found the call */ ast_mutex_lock(&p->lock);