Change the way that the transport option works for sip users. transport will now...
authorBrett Bryant <bbryant@digium.com>
Fri, 27 Jun 2008 16:28:06 +0000 (16:28 +0000)
committerBrett Bryant <bbryant@digium.com>
Fri, 27 Jun 2008 16:28:06 +0000 (16:28 +0000)
for new dialogs, and the rest listed will be acceptable ways for that peer to contact us. This fixes a minor bug where, because SIP TCP/UDP run on
the same port, could cause a TCP peer to be saved in the ast_db. There will also be warnings when a transport is changed for an unexpected reason.

(issue #12799)

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

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

index 1ac7c6e..f87697f 100644 (file)
@@ -378,6 +378,7 @@ enum check_auth_result {
        AUTH_UNKNOWN_DOMAIN = -5,
        AUTH_PEER_NOT_DYNAMIC = -6,
        AUTH_ACL_FAILED = -7,
+       AUTH_BAD_TRANSPORT = -8,
 };
 
 /*! \brief States for outbound registrations (with register= lines in sip.conf */
@@ -1461,6 +1462,7 @@ struct sip_mailbox {
 struct sip_peer {
        char name[80];                  /*!< peer->name is the unique name of this object */
        struct sip_socket socket;       /*!< Socket used for this peer */
+       unsigned int transports:3; /*!< Transports (enum sip_transport) that are acceptable for this peer */
        char secret[80];                /*!< Password */
        char md5secret[80];             /*!< Password in MD5 */
        struct sip_auth *auth;          /*!< Realm authentication list */
@@ -2714,6 +2716,27 @@ static inline int sip_debug_test_pvt(struct sip_pvt *p)
        return sip_debug_test_addr(sip_real_dst(p));
 }
 
+static inline const char *get_transport_list(struct sip_peer *peer) {
+       switch (peer->transports) {
+               case SIP_TRANSPORT_UDP:
+                       return "UDP";
+               case SIP_TRANSPORT_TCP:
+                       return "TCP";
+               case SIP_TRANSPORT_TLS:
+                       return "TLS";
+       }
+
+       if (peer->transports & (SIP_TRANSPORT_TLS | SIP_TRANSPORT_TCP))
+               return "TLS,TCP";
+       if (peer->transports & (SIP_TRANSPORT_TLS | SIP_TRANSPORT_UDP))
+               return "TLS,UDP";
+       if (peer->transports & (SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP))
+               return "TCP,UDP";
+
+       return peer->transports ? 
+               "TLS,TCP,UDP" : "UNKNOWN";
+}
+
 static inline const char *get_transport(enum sip_transport t)
 {
        switch (t) {
@@ -10321,8 +10344,9 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
                }
        }
 
-       copy_socket_data(&peer->socket, &req->socket);
-       copy_socket_data(&pvt->socket, &peer->socket);
+       if (peer->socket.type == req->socket.type)
+               copy_socket_data(&peer->socket, &req->socket);
+       copy_socket_data(&pvt->socket, &req->socket);
 
        /* Look for brackets */
        curi = contact;
@@ -10941,6 +10965,29 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
                                        res = 0;
                                        break;
                                }
+
+                               if (peer->socket.type != req->socket.type ) {
+                                       if (!(peer->transports & req->socket.type)) {
+                                               ast_log(LOG_ERROR,
+                                                       "peer '%s' has contacted us over %s, but we only accept '%s' for this peer! ending call.\n",
+                                                       peer->name, get_transport(req->socket.type), get_transport_list(peer)
+                                               );
+
+                                               ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+                                               transmit_response_with_date(p, "403 Forbidden", req);
+                                               res = AUTH_BAD_TRANSPORT;
+                                       } else if (peer->socket.type & SIP_TRANSPORT_TLS) {
+                                               ast_log(LOG_WARNING,
+                                                       "peer '%s' HAS STOPPED USING TLS in favor of '%s' (but this was allowed in sip.conf)!\n",
+                                                       peer->name, get_transport(req->socket.type)
+                                               );
+                                       } else {
+                                               ast_log(LOG_DEBUG,
+                                                       "peer '%s' has contacted us over %s even though we prefer %s.\n", 
+                                                       peer->name, get_transport(req->socket.type), get_transport(peer->socket.type)
+                                               );
+                                       }
+                               }
                        } 
                }
        }
@@ -11019,6 +11066,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
                                                        name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
                        }
                        break;
+               case AUTH_BAD_TRANSPORT:
                default:
                        break;
                }
@@ -19165,6 +19213,9 @@ static int handle_request_register(struct sip_pvt *p, struct sip_request *req, s
                case AUTH_ACL_FAILED:
                        reason = "Device does not match ACL";
                        break;
+               case AUTH_BAD_TRANSPORT:
+                       reason = "Device not configured to use this transport type";
+                       break;
                default:
                        reason = "Unknown failure";
                        break;
@@ -21198,17 +21249,21 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
        /* If we have realm authentication information, remove them (reload) */
        clear_realm_authentication(peer->auth);
        peer->auth = NULL;
+       peer->transports = 0;
+       peer->socket.type = 0;
 
        for (; v || ((v = alt) && !(alt=NULL)); v = v->next) {
                if (handle_common_options(&peerflags[0], &mask[0], v))
                        continue;
                if (!strcasecmp(v->name, "transport")) {
                        if (!strcasecmp(v->value, "udp")) 
-                               peer->socket.type = SIP_TRANSPORT_UDP;
+                               peer->transports &= SIP_TRANSPORT_UDP;
                        else if (!strcasecmp(v->value, "tcp"))
-                               peer->socket.type = SIP_TRANSPORT_TCP;
+                               peer->transports &= SIP_TRANSPORT_TCP;
                        else if (!strcasecmp(v->value, "tls"))
-                               peer->socket.type = SIP_TRANSPORT_TLS;
+                               peer->transports &= SIP_TRANSPORT_TLS;
+                       if (!peer->socket.type) /*!< The first transport listed should be used for outgoing */
+                               peer->socket.type = peer->transports;
                } else if (realtime && !strcasecmp(v->name, "regseconds")) {
                        ast_get_time_t(v->value, &regseconds, 0, NULL);
                } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
@@ -21450,6 +21505,11 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                }
        }
 
+       if (!peer->socket.type) {
+               peer->transports  = SIP_TRANSPORT_UDP;
+               peer->socket.type = SIP_TRANSPORT_UDP;
+       }
+
        if (fullcontact->used > 0) {
                ast_copy_string(peer->fullcontact, fullcontact->str, sizeof(peer->fullcontact));
                peer->rt_fromcontact = TRUE;
index 3879c06..3f10a4c 100644 (file)
@@ -685,6 +685,7 @@ srvlookup=yes                       ; Enable DNS SRV lookups on outbound calls
 ; deny                        deny
 ; secret                      secret
 ; md5secret                   md5secret
+; transport                   transport
 ; dtmfmode                    dtmfmode
 ; canreinvite                 canreinvite
 ; nat                         nat
@@ -753,6 +754,9 @@ srvlookup=yes                       ; Enable DNS SRV lookups on outbound calls
 ;fromuser=yourusername                 ; Many SIP providers require this!
 ;fromdomain=provider.sip.domain        
 ;host=box.provider.com
+;transport=udp,tcp                 ; This sets the transport type to udp for outgoing, and will
+;                           ;   accept both tcp and udp. Default is udp. The first transport
+;                           ;   listed will always be used for outgoing connections.
 ;usereqphone=yes                       ; This provider requires ";user=phone" on URI
 ;callcounter=yes                       ; Enable call counter
 ;busylevel=2                           ; Signal busy at 2 or more calls
@@ -767,6 +771,9 @@ srvlookup=yes                       ; Enable DNS SRV lookups on outbound calls
 ;fromuser=4015552299           ; how your provider knows you
 ;secret=youwillneverguessit
 ;callbackextension=123         ; Register with this server and require calls coming back to this extension
+;transport=udp,tcp                 ; This sets the transport type to udp for outgoing, and will
+;                           ;   accept both tcp and udp. Default is udp. The first transport
+;                           ;   listed will always be used for outgoing connections.
 
 ;------------------------------------------------------------------------------
 ; Definitions of locally connected SIP devices