Fix port setting of external address in SIP.
authorMark Michelson <mmichelson@digium.com>
Mon, 19 Jul 2010 17:16:23 +0000 (17:16 +0000)
committerMark Michelson <mmichelson@digium.com>
Mon, 19 Jul 2010 17:16:23 +0000 (17:16 +0000)
There are two changes here:

1. Since the externip setting can now have a port attached
to it, calling it "externip" is misleading. The option is now
documented and parsed as "externaddr." This also extends to the
"matchexterniplocally" setting. It is now documented and parsed
as "matchexternaddrlocally." The old names for the options may
still be used, but they are no longer used in the sip.conf.sample
file.

2. If no port is set for the externaddr, and UDP is the transport
to be used, then we will set the port of the externaddr to that of
the udpbindaddr. This was how things worked prior to the IPv6 merge,
so this is a regression fix.

(closes issue #17665)
Reported by: mmichelson
Patches:
      17665.diff#2 uploaded by pprindeville (license 347)
Tested by: pprindeville

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

channels/chan_sip.c
channels/sip/include/sip.h
configs/sip.conf.sample

index b6e167a..7970cbc 100644 (file)
@@ -1131,11 +1131,11 @@ struct ast_sockaddr bindaddr;   /*!< UDP: The address we bind to */
 static struct ast_sockaddr internip;
 
 /*! \brief our external IP address/port for SIP sessions.
- * externip.sin_addr is only set when we know we might be behind
+ * externaddr.sin_addr is only set when we know we might be behind
  * a NAT, and this is done using a variety of (mutually exclusive)
  * ways from the config file:
  *
- * + with "externip = host[:port]" we specify the address/port explicitly.
+ * + with "externaddr = host[:port]" we specify the address/port explicitly.
  *   The address is looked up only once when (re)loading the config file;
  *
  * + with "externhost = host[:port]" we do a similar thing, but the
@@ -1143,12 +1143,12 @@ static struct ast_sockaddr internip;
  *   is refreshed every 'externrefresh' seconds;
  *
  * + with "stunaddr = host[:port]" we run queries every externrefresh seconds
- *   to the specified server, and store the result in externip.
+ *   to the specified server, and store the result in externaddr.
  *
  * Other variables (externhost, externexpire, externrefresh) are used
  * to support the above functions.
  */
-static struct ast_sockaddr externip;      /*!< External IP address if we are behind NAT */
+static struct ast_sockaddr externaddr;      /*!< External IP address if we are behind NAT */
 static struct ast_sockaddr media_address; /*!< External RTP IP address if we are behind NAT */
 
 static char externhost[MAXHOSTNAMELEN];   /*!< External host name */
@@ -3078,20 +3078,20 @@ static void build_via(struct sip_pvt *p)
  *
  * Using the localaddr structure built up with localnet statements in sip.conf
  * apply it to their address to see if we need to substitute our
- * externip or can get away with our internal bindaddr
+ * externaddr or can get away with our internal bindaddr
  * 'us' is always overwritten.
  */
 static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us, struct sip_pvt *p)
 {
        struct ast_sockaddr theirs;
-       struct sockaddr_in externip_sin;
+       struct sockaddr_in externaddr_sin;
 
        /* Set want_remap to non-zero if we want to remap 'us' to an externally
         * reachable IP address and port. This is done if:
         * 1. we have a localaddr list (containing 'internal' addresses marked
         *    as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them,
         *    and AST_SENSE_ALLOW on 'external' ones);
-        * 2. either stunaddr or externip is set, so we know what to use as the
+        * 2. either stunaddr or externaddr is set, so we know what to use as the
         *    externally visible address;
         * 3. the remote address, 'them', is external;
         * 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY
@@ -3106,39 +3106,39 @@ static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_socka
        ast_sockaddr_copy(&theirs, them);
 
        if (ast_sockaddr_is_ipv6(&theirs)) {
-               if (localaddr && !ast_sockaddr_isnull(&externip)) {
+               if (localaddr && !ast_sockaddr_isnull(&externaddr)) {
                        ast_log(LOG_WARNING, "Address remapping activated in sip.conf "
                                "but we're using IPv6, which doesn't need it. Please "
-                               "remove \"localnet\" and/or \"externip\" settings.\n");
+                               "remove \"localnet\" and/or \"externaddr\" settings.\n");
                }
        } else {
                want_remap = localaddr &&
-                       !(ast_sockaddr_isnull(&externip) && stunaddr.sin_addr.s_addr) &&
+                       !(ast_sockaddr_isnull(&externaddr) && stunaddr.sin_addr.s_addr) &&
                        ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ;
        }
 
        if (want_remap &&
-           (!sip_cfg.matchexterniplocally || !ast_apply_ha(localaddr, us)) ) {
+           (!sip_cfg.matchexternaddrlocally || !ast_apply_ha(localaddr, us)) ) {
                /* if we used externhost or stun, see if it is time to refresh the info */
                if (externexpire && time(NULL) >= externexpire) {
                        if (stunaddr.sin_addr.s_addr) {
-                               ast_sockaddr_to_sin(&externip, &externip_sin);
-                               ast_stun_request(sipsock, &stunaddr, NULL, &externip_sin);
+                               ast_sockaddr_to_sin(&externaddr, &externaddr_sin);
+                               ast_stun_request(sipsock, &stunaddr, NULL, &externaddr_sin);
                        } else {
-                               if (ast_sockaddr_resolve_first(&externip, externhost, 0)) {
+                               if (ast_sockaddr_resolve_first(&externaddr, externhost, 0)) {
                                        ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
                                }
                                externexpire = time(NULL);
                        }
                        externexpire = time(NULL) + externrefresh;
                }
-               if (!ast_sockaddr_isnull(&externip)) {
-                       ast_sockaddr_copy(us, &externip);
+               if (!ast_sockaddr_isnull(&externaddr)) {
+                       ast_sockaddr_copy(us, &externaddr);
                        switch (p->socket.type) {
                        case SIP_TRANSPORT_TCP:
-                               if (!externtcpport && ast_sockaddr_port(&externip)) {
-                                       /* for consistency, default to the externip port */
-                                       externtcpport = ast_sockaddr_port(&externip);
+                               if (!externtcpport && ast_sockaddr_port(&externaddr)) {
+                                       /* for consistency, default to the externaddr port */
+                                       externtcpport = ast_sockaddr_port(&externaddr);
                                }
                                ast_sockaddr_set_port(us, externtcpport);
                                break;
@@ -3146,16 +3146,18 @@ static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_socka
                                ast_sockaddr_set_port(us, externtlsport);
                                break;
                        case SIP_TRANSPORT_UDP:
-                               break; /* fall through */
+                               if (!ast_sockaddr_port(&externaddr)) {
+                                       ast_sockaddr_set_port(us, ast_sockaddr_port(&bindaddr));
+                               }
+                               break;
                        default:
-                               /* we should never get here */
-                               ast_sockaddr_set_port(us, STANDARD_SIP_PORT);
+                               break;
                        }
                }
                else {
                        ast_log(LOG_WARNING, "stun failed\n");
                }
-               ast_debug(1, "Target address %s is not local, substituting externip\n",
+               ast_debug(1, "Target address %s is not local, substituting externaddr\n",
                          ast_sockaddr_stringify(them));
        } else if (p) {
                /* no remapping, but we bind to a specific address, so use it. */
@@ -14397,7 +14399,7 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
  * 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.
+ * if you specify externaddr/seternaddr/stunaddr.
  */
 static attribute_unused void check_via_response(struct sip_pvt *p, struct sip_request *req)
 {
@@ -16586,17 +16588,17 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
        /* determine if/how SIP address can be remapped */
        if (localaddr == NULL)
                msg = "Disabled, no localnet list";
-       else if (ast_sockaddr_isnull(&externip))
+       else if (ast_sockaddr_isnull(&externaddr))
                msg = "Disabled";
        else if (stunaddr.sin_addr.s_addr != 0)
                msg = "Enabled using STUN";
        else if (!ast_strlen_zero(externhost))
                msg = "Enabled using externhost";
        else
-               msg = "Enabled using externip";
+               msg = "Enabled using externaddr";
        ast_cli(a->fd, "  SIP address remapping:  %s\n", msg);
        ast_cli(a->fd, "  Externhost:             %s\n", S_OR(externhost, "<none>"));
-       ast_cli(a->fd, "  Externip:               %s\n", ast_sockaddr_stringify(&externip));
+       ast_cli(a->fd, "  externaddr:               %s\n", ast_sockaddr_stringify(&externaddr));
        ast_cli(a->fd, "  Externrefresh:          %d\n", externrefresh);
        ast_cli(a->fd, "  Internal IP:            %s\n", ast_sockaddr_stringify(&internip));
        {
@@ -26155,7 +26157,7 @@ static int reload_config(enum channelreloadreason reason)
        struct ast_sockaddr old_bindaddr = bindaddr;
        int registry_count = 0, peer_count = 0, timerb_set = 0, timert1_set = 0;
        time_t run_start, run_end;
-       struct sockaddr_in externip_sin;
+       struct sockaddr_in externaddr_sin;
        int bindport = 0;
 
        run_start = time(0);
@@ -26264,7 +26266,7 @@ static int reload_config(enum channelreloadreason reason)
        /* Free memory for local network address mask */
        ast_free_ha(localaddr);
        memset(&localaddr, 0, sizeof(localaddr));
-       memset(&externip, 0, sizeof(externip));
+       memset(&externaddr, 0, sizeof(externaddr));
        memset(&media_address, 0, sizeof(media_address));
        memset(&default_prefs, 0 , sizeof(default_prefs));
        memset(&sip_cfg.outboundproxy, 0, sizeof(struct sip_proxy));
@@ -26373,7 +26375,7 @@ static int reload_config(enum channelreloadreason reason)
        global_t38_maxdatagram = -1;
        global_shrinkcallerid = 1;
 
-       sip_cfg.matchexterniplocally = DEFAULT_MATCHEXTERNIPLOCALLY;
+       sip_cfg.matchexternaddrlocally = DEFAULT_MATCHEXTERNADDRLOCALLY;
 
        /* Copy the default jb config over global_jbconf */
        memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
@@ -26669,16 +26671,16 @@ static int reload_config(enum channelreloadreason reason)
                } else if (!strcasecmp(v->name, "media_address")) {
                        if (ast_parse_arg(v->value, PARSE_ADDR, &media_address))
                                ast_log(LOG_WARNING, "Invalid address for media_address keyword: %s\n", v->value);
-               } else if (!strcasecmp(v->name, "externip")) {
-                       if (ast_parse_arg(v->value, PARSE_ADDR, &externip)) {
+               } else if (!strcasecmp(v->name, "externaddr") || !strcasecmp(v->name, "externip")) {
+                       if (ast_parse_arg(v->value, PARSE_ADDR, &externaddr)) {
                                ast_log(LOG_WARNING,
-                                       "Invalid address for externip keyword: %s\n",
+                                       "Invalid address for externaddr keyword: %s\n",
                                        v->value);
                        }
                        externexpire = 0;
                } else if (!strcasecmp(v->name, "externhost")) {
                        ast_copy_string(externhost, v->value, sizeof(externhost));
-                       if (ast_sockaddr_resolve_first(&externip, externhost, 0)) {
+                       if (ast_sockaddr_resolve_first(&externaddr, externhost, 0)) {
                                ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost);
                        }
                        externexpire = time(NULL);
@@ -26797,8 +26799,8 @@ static int reload_config(enum channelreloadreason reason)
                        default_maxcallbitrate = atoi(v->value);
                        if (default_maxcallbitrate < 0)
                                default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE;
-               } else if (!strcasecmp(v->name, "matchexterniplocally")) {
-                       sip_cfg.matchexterniplocally = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "matchexternaddrlocally") || !strcasecmp(v->name, "matchexterniplocally")) {
+                       sip_cfg.matchexternaddrlocally = ast_true(v->value);
                } else if (!strcasecmp(v->name, "session-timers")) {
                        int i = (int) str2stmode(v->value);
                        if (i < 0) {
@@ -26953,11 +26955,11 @@ static int reload_config(enum channelreloadreason reason)
        if (stunaddr.sin_addr.s_addr != 0) {
                ast_debug(1, "stun to %s:%d\n",
                        ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port));
-               ast_sockaddr_to_sin(&externip, &externip_sin);
+               ast_sockaddr_to_sin(&externaddr, &externaddr_sin);
                ast_stun_request(sipsock, &stunaddr,
-                       NULL, &externip_sin);
+                       NULL, &externaddr_sin);
                ast_debug(1, "STUN sees us at %s\n",
-                       ast_sockaddr_stringify(&externip));
+                       ast_sockaddr_stringify(&externaddr));
        }
        ast_mutex_unlock(&netlock);
 
@@ -27140,8 +27142,8 @@ static int reload_config(enum channelreloadreason reason)
                }
 
                /* Our extern IP address, if configured */
-               if (!ast_sockaddr_isnull(&externip)) {
-                       add_sip_domain(ast_sockaddr_stringify(&externip), SIP_DOMAIN_AUTO,
+               if (!ast_sockaddr_isnull(&externaddr)) {
+                       add_sip_domain(ast_sockaddr_stringify(&externaddr), SIP_DOMAIN_AUTO,
                                       NULL);
                }
 
index 706a8e7..b4137bf 100644 (file)
 #define DEFAULT_NOTIFYCID      DISABLED        /*!< Include CID with ringing notifications */
 #define DEFAULT_PEDANTIC       FALSE    /*!< Avoid following SIP standards for dialog matching */
 #define DEFAULT_AUTOCREATEPEER FALSE    /*!< Don't create peers automagically */
-#define        DEFAULT_MATCHEXTERNIPLOCALLY FALSE /*!< Match extern IP locally default setting */
+#define        DEFAULT_MATCHEXTERNADDRLOCALLY FALSE /*!< Match extern IP locally default setting */
 #define DEFAULT_QUALIFY        FALSE    /*!< Don't monitor devices */
 #define DEFAULT_CALLEVENTS     FALSE    /*!< Extra manager SIP call events */
 #define DEFAULT_ALWAYSAUTHREJECT  FALSE /*!< Don't reject authentication requests always */
@@ -686,7 +686,7 @@ struct sip_settings {
        int allow_external_domains; /*!< Accept calls to external SIP domains? */
        int callevents;             /*!< Whether we send manager events or not */
        int regextenonqualify;      /*!< Whether to add/remove regexten when qualifying peers */
-       int matchexterniplocally;   /*!< Match externip/externhost setting against localnet setting */
+       int matchexternaddrlocally;   /*!< Match externaddr/externhost setting against localnet setting */
        char regcontext[AST_MAX_CONTEXT];  /*!< Context for auto-extensions */
        unsigned int disallowed_methods;   /*!< methods that we should never try to use */
        int notifyringing;          /*!< Send notifications on ringing */
index 1ec5ae3..6014163 100644 (file)
@@ -344,7 +344,7 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ;outboundproxy=tls://proxy.provider.domain      ; same as '=proxy.provider.domain' except we try to connect with tls
 ;                                               ; (could also be tcp,udp) - defining transports on the proxy line only
 ;                                               ; applies for the global proxy, otherwise use the transport= option
-;matchexterniplocally = yes     ; Only substitute the externip or externhost setting if it matches
+;matchexternaddrlocally = yes     ; Only substitute the externaddr or externhost setting if it matches
                                 ; your localnet setting. Unless you have some sort of strange network
                                 ; setup you will not need to enable this.
 
@@ -671,7 +671,7 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ;   to a host outside the NAT. This information is derived by one of the
 ;   following (mutually exclusive) config file parameters:
 ;
-;   a. "externip = hostname[:port]" specifies a static address[:port] to
+;   a. "externaddr = hostname[:port]" specifies a static address[:port] to
 ;      be used in SIP and SDP messages.
 ;      The hostname is looked up only once, when [re]loading sip.conf .
 ;      If a port number is not present, use the port specified in the "udpbindaddr"
@@ -680,15 +680,15 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ;      This approach can be useful if you have a NAT device where you can
 ;      configure the mapping statically. Examples:
 ;
-;        externip = 12.34.56.78          ; use this address.
-;        externip = 12.34.56.78:9900     ; use this address and port.
-;        externip = mynat.my.org:12600   ; Public address of my nat box.
+;        externaddr = 12.34.56.78          ; use this address.
+;        externaddr = 12.34.56.78:9900     ; use this address and port.
+;        externaddr = mynat.my.org:12600   ; Public address of my nat box.
 ;        externtcpport = 9900   ; The externally mapped tcp port, when Asterisk is behind a static NAT or PAT. 
-;                               ; externtcpport will default to the externip or externhost port if either one is set. 
+;                               ; externtcpport will default to the externaddr or externhost port if either one is set. 
 ;        externtlsport = 12600  ; The externally mapped tls port, when Asterisk is behind a static NAT or PAT.
 ;                               ; externtlsport port will default to the RFC designated port of 5061.  
 ;
-;   b. "externhost = hostname[:port]" is similar to "externip" except
+;   b. "externhost = hostname[:port]" is similar to "externaddr" except
 ;      that the hostname is looked up every "externrefresh" seconds
 ;      (default 10s). This can be useful when your NAT device lets you choose
 ;      the port mapping, but the IP address is dynamic.
@@ -708,16 +708,16 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ;        externrefresh = 15
 ;
 ;   Note that at the moment all these mechanism work only for the SIP socket.
-;   The IP address discovered with externip/externhost/STUN is reused for
+;   The IP address discovered with externaddr/externhost/STUN is reused for
 ;   media sessions as well, but the port numbers are not remapped so you
 ;   may still experience problems.
 ;
 ; NOTE 1: in some cases, NAT boxes will use different port numbers in
-; the internal<->external mapping. In these cases, the "externip" and
+; the internal<->external mapping. In these cases, the "externaddr" and
 ; "externhost" might not help you configure addresses properly, and you
 ; really need to use STUN.
 ;
-; NOTE 2: when using "externip" or "externhost", the address part is
+; NOTE 2: when using "externaddr" or "externhost", the address part is
 ; also used as the external address for media sessions. Even if you 
 ; use "stunaddr", STUN queries will be sent only from the SIP port,
 ; not from media sockets. Thus, the port information in the SDP may be wrong!