]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix / Clean Up Some Items To Handle The New auto_* NAT Options
authorMichael L. Young <elgueromexicano@gmail.com>
Fri, 1 Mar 2013 04:32:01 +0000 (04:32 +0000)
committerMichael L. Young <elgueromexicano@gmail.com>
Fri, 1 Mar 2013 04:32:01 +0000 (04:32 +0000)
The original report had to do with a realtime peer behind NAT being pruned and
the peer's private address being used instead of its external address.  Upon
debugging, it was discovered that this was being caused by the addition of
the auto_force_rport and auto_comedia settings.

This patch does the following:

* Adds a missing note to the CHANGES file indicating that the default global nat
  setting is auto_force_rport

* Constify the 'req' parameter for check_via()

* Add calls to check_via() in a couple of places in order for the auto_*
  settings to do their job in attempting to determine if NAT is involved

* Set the flags SIP_NAT_FORCE_RPORT and SIP_PAGE2_SYMMETRICRTP if the auto_*
  settings are in use where it was needed

* Moves the copying of peer flags up in build_peer() to before they are used;
  this fixes the realtime prune issue

* Update the contrib/realtime schemas to allow the nat column to handle the
  different nat setting combinations we have

This patch received a review and "Ship It!" on the issue itself.

(closes issue ASTERISK-20904)
Reported by: JoshE
Tested by: JoshE, Michael L. Young
Patches:
  asterisk-20904-nat-auto-and-rt-peersv2.diff Michael L. Young (license 5026)
........

Merged revisions 382322 from http://svn.asterisk.org/svn/asterisk/branches/11

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

CHANGES
channels/chan_sip.c
contrib/realtime/mysql/sippeers.sql
contrib/realtime/postgresql/realtime.sql

diff --git a/CHANGES b/CHANGES
index 109f4f60d024bad99b48ab32c10f9b1141f0c2f3..2ef538eab140b267ea6d93172c2c4969bcf1c0cc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -398,6 +398,9 @@ chan_sip
    detects that an incoming SIP request crossed a NAT after being sent by
    the remote endpoint.
 
+ * The default global nat setting in sip.conf has been changed from force_rport
+   to auto_force_rport.
+
  * NAT settings are now a combinable list of options. The equivalent of the
    deprecated nat=yes is nat=force_rport,comedia. nat=no behaves as before.
 
index cdf020ad70a36395aea4210143c592070d35d74d..1adf7a00faeb921755a9d7964ea22bda216f7bb6 100644 (file)
@@ -1399,7 +1399,7 @@ static int get_refer_info(struct sip_pvt *transferer, struct sip_request *outgoi
 static int get_also_info(struct sip_pvt *p, struct sip_request *oreq);
 static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req);
 static int set_address_from_contact(struct sip_pvt *pvt);
-static void check_via(struct sip_pvt *p, struct sip_request *req);
+static void check_via(struct sip_pvt *p, const struct sip_request *req);
 static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
 static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason, char **reason_str);
 static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id);
@@ -8747,9 +8747,8 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
 
        if (useglobal_nat && addr) {
                /* Setup NAT structure according to global settings if we have an address */
-               ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT_FORCE_RPORT);
                ast_sockaddr_copy(&p->recv, addr);
-
+               check_via(p, req);
                do_setnat(p);
        }
 
@@ -12116,8 +12115,9 @@ static int transmit_response_using_temp(ast_string_field callid, struct ast_sock
 
        if (useglobal_nat && addr) {
                ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT_FORCE_RPORT);
+               ast_copy_flags(&p->flags[2], &global_flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
                ast_sockaddr_copy(&p->recv, addr);
-               do_setnat(p);
+               check_via(p, req);
        }
 
        ast_string_field_set(p, fromdomain, default_fromdomain);
@@ -17958,7 +17958,7 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
 }
 
 /*! \brief check Via: header for hostname, port and rport request/answer */
-static void check_via(struct sip_pvt *p, struct sip_request *req)
+static void check_via(struct sip_pvt *p, const struct sip_request *req)
 {
        char via[512];
        char *c, *maddr;
@@ -18092,6 +18092,21 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
                return AUTH_DONT_KNOW;
        }
 
+       /*  build_peer, called through sip_find_peer, is not able to check the
+        *  sip_pvt->natdetected flag in order to determine if the peer is behind
+        *  NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
+        *  are set on the peer.  So we check for that here and set the peer's
+        *  address accordingly.
+        */
+       if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+               ast_set_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT);
+               ast_sockaddr_copy(&peer->addr, &p->recv);
+       }
+
+       if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
+               ast_set_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP);
+       }
+
        if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) {
                ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
                sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED");
@@ -28426,7 +28441,10 @@ static int handle_request_do(struct sip_request *req, struct ast_sockaddr *addr)
        owner_chan_ref = sip_pvt_lock_full(p);
 
        copy_socket_data(&p->socket, &req->socket);
-       ast_sockaddr_copy(&p->recv, addr);
+
+       if (ast_sockaddr_isnull(&p->recv)) { /* This may already be set before getting here */
+               ast_sockaddr_copy(&p->recv, addr);
+       }
 
        /* if we have an owner, then this request has been authenticated */
        if (p->owner) {
@@ -30637,7 +30655,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                        } else if (!strcasecmp(v->name, "host")) {
                                if (!strcasecmp(v->value, "dynamic")) {
                                        /* They'll register with us */
-                                       if ((!found && !realtime) || !peer->host_dynamic) {
+                                       if ((!found && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) || !peer->host_dynamic) {
                                                /* Initialize stuff if this is a new peer, or if it used to
                                                 * not be dynamic before the reload. */
                                                ast_sockaddr_setnull(&peer->addr);
@@ -30990,6 +31008,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                set_socket_transport(&peer->socket, peer->default_outbound_transport);
        }
 
+       ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags);
+       ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags);
+       ast_copy_flags(&peer->flags[2], &peerflags[2], mask[2].flags);
+
        if (ast_str_strlen(fullcontact)) {
                ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
                peer->rt_fromcontact = TRUE;
@@ -31083,9 +31105,6 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                sip_poke_peer(peer, 0);
        }
 
-       ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags);
-       ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags);
-       ast_copy_flags(&peer->flags[2], &peerflags[2], mask[2].flags);
        if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) {
                sip_cfg.allowsubscribe = TRUE;  /* No global ban any more */
        }
index 5c58df7ea1e67487417b25cd57f85d4e8c55e145..e0dbe1a430492662e8d4fae8af77222a4859d7f3 100644 (file)
@@ -24,7 +24,7 @@ CREATE TABLE IF NOT EXISTS `sippeers` (
       `transport` enum('udp','tcp','udp,tcp','tcp,udp') DEFAULT NULL,
       `dtmfmode` enum('rfc2833','info','shortinfo','inband','auto') DEFAULT NULL,
       `directmedia` enum('yes','no','nonat','update') DEFAULT NULL,
-      `nat` enum('yes','no','never','route') DEFAULT NULL,
+      `nat` varchar(29) DEFAULT NULL,
       `callgroup` varchar(40) DEFAULT NULL,
       `pickupgroup` varchar(40) DEFAULT NULL,
       `language` varchar(40) DEFAULT NULL,
index abcadd2fd801676b0767dfdfb77e0e789b2ac4a9..cba8d3895db4a3af738ee7075a839c21be20d200 100644 (file)
@@ -48,7 +48,7 @@ insecure character varying(4),
 "language" character varying(2),
 mailbox character varying(50),
 md5secret character varying(80),
-nat character varying(5) DEFAULT 'no' NOT NULL,
+nat character varying(29) DEFAULT '' NOT NULL,
 permit character varying(95),
 deny character varying(95),
 mask character varying(95),