aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2008-06-27 16:28:06 +0000
committerbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2008-06-27 16:28:06 +0000
commit373bfa2d0a19286bff67de0191eb25a1e423e5af (patch)
tree3ee59ff52b8b6ad0d72e135abe7b94c806a39dbe
parent0b41dddce2699e8bc1b6bd8031fb69d3c3b796f0 (diff)
Change the way that the transport option works for sip users. transport will now take multiple arguments, the first one listed will be the one used
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: http://svn.digium.com/svn/asterisk/trunk@125891 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_sip.c70
-rw-r--r--configs/sip.conf.sample7
2 files changed, 72 insertions, 5 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 1ac7c6e70..f87697f46 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -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;
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index 3879c062d..3f10a4ce4 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -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