diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 9500d2251ed7a978048f6a8e1f81e1d4c89ec345..d28dfcd0f6dc0ea2b2e59fc7a7ae35079d7e24b0 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -9701,6 +9701,46 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq) return -1; } + +/*! \brief check received= and rport= in a SIP response. + * If we get a response with received= and/or rport= in the Via: + * line, use them as 'p->ourip' (see RFC 3581 for rport, + * and RFC 3261 for received). + * Using these two fields SIP can produce the correct + * address and port in the SIP headers without the need for STUN. + * The address part is also reused for the media sessions. + * Note that ast_sip_ouraddrfor() still rewrites p->ourip + * if you specify externip/seternaddr/stunaddr. + */ +static void check_via_response(struct sip_pvt *p, struct sip_request *req) +{ + char via[256]; + char *cur, *opts; + + ast_copy_string(via, get_header(req, "Via"), sizeof(via)); + + /* Work on the leftmost value of the topmost Via header */ + opts = strchr(via, ','); + if (opts) + *opts = '\0'; + + /* parse all relevant options */ + opts = strchr(via, ';'); + if (!opts) + return; /* no options to parse */ + *opts++ = '\0'; + while ( (cur = strsep(&opts, ";")) ) { + if (!strncmp(cur, "rport=", 6)) { + int port = strtol(cur+6, NULL, 10); + /* XXX add error checking */ + p->ourip.sin_port = ntohs(port); + } else if (!strncmp(cur, "received=", 9)) { + if (ast_parse_arg(cur+9, PARSE_INADDR, &p->ourip)) + ; /* XXX add error checking */ + } + } +} + /*! \brief check Via: header for hostname, port and rport request/answer */ static void check_via(struct sip_pvt *p, struct sip_request *req) { @@ -13332,6 +13372,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ gettag(req, "To", tag, sizeof(tag)); ast_string_field_set(p, theirtag, tag); } + check_via_response(p, req); if (p->relatedpeer && p->method == SIP_OPTIONS) { /* We don't really care what the response is, just that it replied back. Well, as long as it's not a 100 response... since we might