Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 12459) +++ channels/chan_sip.c (working copy) @@ -5855,11 +5855,7 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req) { char contact[250]; - char *c, *n, *pt; - int port; - struct hostent *hp; - struct ast_hostent ahp; - struct sockaddr_in oldsin; + char *c; /* Look for brackets */ ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); @@ -5870,28 +5866,57 @@ /* Save URI for later ACKs, BYE or RE-invites */ ast_string_field_set(pvt, okcontacturi, c); + + /* We should return false for URI:s we can't handle, + like sips:, tel:, mailto:,ldap: etc */ + return TRUE; +} + +/*! \brief Change the other partys IP address based on given contact */ +static int set_adddress_from_contact(struct sip_pvt *pvt) +{ + struct hostent *hp; + struct ast_hostent ahp; + struct sockaddr_in oldsin; + int port; + char *c, *host, *pt; + char *contact; + + /* Copy address into old address field */ + memcpy(&oldsin, &pvt->sa, sizeof(oldsin)); + + if ((ast_test_flag(pvt, SIP_NAT) & SIP_NAT_ROUTE)) { + /* NAT: Don't trust the contact field. Just use what they came to us + with. */ + memcpy(&pvt->sa, &pvt->recv, sizeof(pvt->sa)); + return 0; + } + + /* Work on a copy */ + contact = ast_strdupa(pvt->fullcontact); + /* Make sure it's a SIP URL */ - if (strncasecmp(c, "sip:", 4)) { - ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", c); + if (strncasecmp(contact, "sip:", 4)) { + ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact); } else - c += 4; + contact += 4; /* Ditch arguments */ - n = strchr(c, ';'); - if (n) - *n = '\0'; + host = strchr(contact, ';'); + if (host) + *host = '\0'; /* Grab host */ - n = strchr(c, '@'); - if (!n) { - n = c; + host = strchr(contact, '@'); + if (!host) { /* No username part */ + host = contact; c = NULL; } else { - *n = '\0'; - n++; + *host = '\0'; + host++; } - pt = strchr(n, ':'); + pt = strchr(host, ':'); if (pt) { *pt = '\0'; pt++; @@ -5899,24 +5924,18 @@ } else port = DEFAULT_SIP_PORT; - memcpy(&oldsin, &pvt->sa, sizeof(oldsin)); - if (!(ast_test_flag(pvt, SIP_NAT) & SIP_NAT_ROUTE)) { - /* XXX This could block for a long time XXX */ - /* We should only do this if it's a name, not an IP */ - hp = ast_gethostbyname(n, &ahp); - if (!hp) { - ast_log(LOG_WARNING, "Invalid host '%s'\n", n); - return -1; - } - pvt->sa.sin_family = AF_INET; - memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr)); - pvt->sa.sin_port = htons(port); - } else { - /* Don't trust the contact field. Just use what they came to us - with. */ - memcpy(&pvt->sa, &pvt->recv, sizeof(pvt->sa)); + /* XXX This could block for a long time XXX */ + /* We should only do this if it's a name, not an IP */ + hp = ast_gethostbyname(host, &ahp); + if (!hp) { + ast_log(LOG_WARNING, "Can't resolve host name/IP '%s'\n", host); + return -1; } + pvt->sa.sin_family = AF_INET; + memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr)); + pvt->sa.sin_port = htons(port); + return 0; } @@ -9618,6 +9637,7 @@ /* This is important when we have a SIP proxy between us and the phone */ if (outgoing) { parse_ok_contact(p, req); + set_adddress_from_contact(p); /* Save Record-Route for any later requests we make on this dialogue */ build_route(p, req, 1); @@ -10404,6 +10424,7 @@ if (debug) ast_verbose("Using INVITE request as basis request - %s\n", p->callid); sip_cancel_destroy(p); + parse_ok_contact(p, req); /* This call is no longer outgoing if it ever was */ ast_clear_flag(p, SIP_OUTGOING); /* This also counts as a pending invite */