SIP should use the transport type set in the Moved Temporarily for the next

invite.
(closes issue #11843)
 Reported by: pestermann
 Patches: 
       20080723__issue11843_302_ignores_transport_16branch.diff uploaded by bbryant (license 36)
       20080723__issue11843_302_ignores_transport_trunk.diff uploaded by bbryant (license 36)
 Tested by: pabelanger


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@135126 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.1
Tilghman Lesher 17 years ago
parent 577d6a5c78
commit 6cb6583475

@ -1950,6 +1950,37 @@ static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer
static int sip_refer_allocate(struct sip_pvt *p); static int sip_refer_allocate(struct sip_pvt *p);
static void ast_quiet_chan(struct ast_channel *chan); static void ast_quiet_chan(struct ast_channel *chan);
static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target); static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
/*!
* \brief generic function for determining if a correct transport is being
* used to contact a peer
*
* this is done as a macro so that the "tmpl" var can be passed either a
* sip_request or a sip_peer
*/
#define check_request_transport(peer, tmpl) ({ \
int ret = 0; \
if (peer->socket.type == tmpl->socket.type) \
; \
else if (!(peer->transports & tmpl->socket.type)) {\
ast_log(LOG_ERROR, \
"'%s' is not a valid transport for '%s'. we only use '%s'! ending call.\n", \
get_transport(tmpl->socket.type), peer->name, get_transport_list(peer) \
); \
ret = 1; \
} else if (peer->socket.type & SIP_TRANSPORT_TLS) { \
ast_log(LOG_WARNING, \
"peer '%s' HAS NOT USED (OR SWITCHED TO) TLS in favor of '%s' (but this was allowed in sip.conf)!\n", \
peer->name, get_transport(tmpl->socket.type) \
); \
} else { \
ast_debug(1, \
"peer '%s' has contacted us over %s even though we prefer %s.\n", \
peer->name, get_transport(tmpl->socket.type), get_transport(peer->socket.type) \
); \
}\
(ret); \
})
/*--- Device monitoring and Device/extension state/event handling */ /*--- Device monitoring and Device/extension state/event handling */
static int cb_extensionstate(char *context, char* exten, int state, void *data); static int cb_extensionstate(char *context, char* exten, int state, void *data);
@ -2103,7 +2134,7 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, const char *msg
static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p); static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p);
static void build_via(struct sip_pvt *p); static void build_via(struct sip_pvt *p);
static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer); static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer);
static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin); static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin, int newdialog);
static char *generate_random_string(char *buf, size_t size); static char *generate_random_string(char *buf, size_t size);
static void build_callid_pvt(struct sip_pvt *pvt); static void build_callid_pvt(struct sip_pvt *pvt);
static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain); static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain);
@ -4135,6 +4166,11 @@ static void copy_socket_data(struct sip_socket *to_sock, const struct sip_socket
*/ */
static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
{ {
/* this checks that the dialog is contacting the peer on a valid
* transport type based on the peers transport configuration,
* otherwise, this function bails out */
if (dialog->socket.type && check_request_transport(peer, dialog))
return -1;
copy_socket_data(&dialog->socket, &peer->socket); copy_socket_data(&dialog->socket, &peer->socket);
if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) && if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
@ -4260,10 +4296,11 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
return 0; return 0;
} }
/*! \brief create address structure from device name /*! \brief create address structure from device name
* Or, if peer not found, find it in the global DNS * Or, if peer not found, find it in the global DNS
* returns TRUE (-1) on failure, FALSE on success */ * returns TRUE (-1) on failure, FALSE on success */
static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin) static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin, int newdialog)
{ {
struct hostent *hp; struct hostent *hp;
struct ast_hostent ahp; struct ast_hostent ahp;
@ -4284,13 +4321,12 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
peer = find_peer(peername, NULL, TRUE, TRUE); peer = find_peer(peername, NULL, TRUE, TRUE);
if (peer) { if (peer) {
int res = create_addr_from_peer(dialog, peer); int res;
if (newdialog)
dialog->socket.type = 0;
res = create_addr_from_peer(dialog, peer);
unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup"); unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup");
return res; return res;
} else {
/* Setup default parameters for this dialog's socket. Currently we only support regular UDP SIP as the default */
dialog->socket.type = SIP_TRANSPORT_UDP;
dialog->socket.port = bindaddr.sin_port;
} }
ast_string_field_set(dialog, tohost, peername); ast_string_field_set(dialog, tohost, peername);
@ -4306,7 +4342,10 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
if (sin) { if (sin) {
memcpy(&dialog->sa.sin_addr, &sin->sin_addr, sizeof(dialog->sa.sin_addr)); memcpy(&dialog->sa.sin_addr, &sin->sin_addr, sizeof(dialog->sa.sin_addr));
if (!sin->sin_port) { if (!sin->sin_port) {
portno = port ? atoi(port) : (dialog->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT; if (ast_strlen_zero(port) || sscanf(port, "%u", &portno) != 1) {
portno = dialog->socket.type & SIP_TRANSPORT_TLS ?
STANDARD_TLS_PORT : STANDARD_SIP_PORT;
}
} else { } else {
portno = ntohs(sin->sin_port); portno = ntohs(sin->sin_port);
} }
@ -4339,6 +4378,8 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr)); memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr));
} }
if (!dialog->socket.type)
dialog->socket.type = SIP_TRANSPORT_UDP;
dialog->sa.sin_port = htons(portno); dialog->sa.sin_port = htons(portno);
dialog->recv = dialog->sa; dialog->recv = dialog->sa;
return 0; return 0;
@ -4406,7 +4447,6 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
p->t38.state = T38_LOCAL_DIRECT; p->t38.state = T38_LOCAL_DIRECT;
ast_debug(1, "T38State change to %d on channel %s\n", p->t38.state, ast->name); ast_debug(1, "T38State change to %d on channel %s\n", p->t38.state, ast->name);
} }
} }
res = 0; res = 0;
@ -9442,7 +9482,7 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
return -1; return -1;
} }
if (create_addr(p, channame, NULL)) { if (create_addr(p, channame, NULL, 0)) {
/* Maybe they're not registered, etc. */ /* Maybe they're not registered, etc. */
dialog_unlink_all(p, TRUE, TRUE); dialog_unlink_all(p, TRUE, TRUE);
dialog_unref(p, "unref dialog inside for loop" ); dialog_unref(p, "unref dialog inside for loop" );
@ -9654,7 +9694,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
r->us.sin_port = htons(r->portno); r->us.sin_port = htons(r->portno);
/* Find address to hostname */ /* Find address to hostname */
if (create_addr(p, r->hostname, &r->us)) { if (create_addr(p, r->hostname, &r->us, 0)) {
/* we have what we hope is a temporary network error, /* we have what we hope is a temporary network error,
* probably DNS. We need to reschedule a registration try */ * probably DNS. We need to reschedule a registration try */
dialog_unlink_all(p, TRUE, TRUE); dialog_unlink_all(p, TRUE, TRUE);
@ -10852,27 +10892,10 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
break; break;
} }
if (peer->socket.type != req->socket.type ) { if (check_request_transport(peer, req)) {
if (!(peer->transports & req->socket.type)) { ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
ast_log(LOG_ERROR, transmit_response_with_date(p, "403 Forbidden", req);
"peer '%s' has contacted us over %s, but we only accept '%s' for this peer! ending call.\n", res = AUTH_BAD_TRANSPORT;
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)
);
}
} }
} }
} }
@ -14423,7 +14446,7 @@ static char *sip_cli_notify(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
return CLI_FAILURE; return CLI_FAILURE;
} }
if (create_addr(p, a->argv[i], NULL)) { if (create_addr(p, a->argv[i], NULL, 0)) {
/* Maybe they're not registered, etc. */ /* Maybe they're not registered, etc. */
dialog_unlink_all(p, TRUE, TRUE); dialog_unlink_all(p, TRUE, TRUE);
dialog_unref(p, "unref dialog inside for loop" ); dialog_unref(p, "unref dialog inside for loop" );
@ -14996,13 +15019,41 @@ static struct ast_custom_function sipchaninfo_function = {
static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req) static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
{ {
char tmp[SIPBUFSIZE]; char tmp[SIPBUFSIZE];
char *s, *e, *t; char *s, *e, *t, *trans;
char *domain; char *domain;
enum sip_transport transport = SIP_TRANSPORT_UDP;
ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp)); ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
if ((t = strchr(tmp, ','))) if ((t = strchr(tmp, ',')))
*t = '\0'; *t = '\0';
s = remove_uri_parameters(get_in_brackets(tmp));
s = get_in_brackets(tmp);
if ((trans = strcasestr(s, ";transport="))) do {
trans += 11;
if ((e = strchr(trans, ';')))
*e = '\0';
if (!strncasecmp(trans, "tcp", 3))
transport = SIP_TRANSPORT_TCP;
else if (!strncasecmp(trans, "tls", 3))
transport = SIP_TRANSPORT_TLS;
else {
if (strncasecmp(trans, "udp", 3))
ast_debug(1, "received contact with an invalid transport, '%s'\n", s);
transport = SIP_TRANSPORT_UDP;
}
} while(0);
s = remove_uri_parameters(s);
if (p->socket.ser) {
ao2_ref(p->socket.ser, -1);
p->socket.ser = NULL;
}
p->socket.fd = -1;
p->socket.type = transport;
if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
if (!strncasecmp(s, "sip:", 4)) if (!strncasecmp(s, "sip:", 4))
s += 4; s += 4;
@ -15011,9 +15062,9 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
e = strchr(s, '/'); e = strchr(s, '/');
if (e) if (e)
*e = '\0'; *e = '\0';
ast_debug(2, "Found promiscuous redirection to 'SIP/%s'\n", s); ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s);
if (p->owner) if (p->owner)
ast_string_field_build(p->owner, call_forward, "SIP/%s", s); ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s);
} else { } else {
e = strchr(tmp, '@'); e = strchr(tmp, '@');
if (e) { if (e) {
@ -17095,7 +17146,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
if ((peerorhost = strchr(uri, ':'))) { if ((peerorhost = strchr(uri, ':'))) {
*peerorhost++ = '\0'; *peerorhost++ = '\0';
} }
create_addr(p, peerorhost, NULL); create_addr(p, peerorhost, NULL, 0);
ast_string_field_set(p, theirtag, NULL); ast_string_field_set(p, theirtag, NULL);
for (pkt = p->packets; pkt; pkt = pkt->next) { for (pkt = p->packets; pkt; pkt = pkt->next) {
if (pkt->seqno == p->icseq && pkt->method == SIP_INVITE) { if (pkt->seqno == p->icseq && pkt->method == SIP_INVITE) {
@ -20068,6 +20119,8 @@ static struct ast_channel *sip_request_call(const char *type, int format, void *
char *secret = NULL; char *secret = NULL;
char *md5secret = NULL; char *md5secret = NULL;
char *authname = NULL; char *authname = NULL;
char *trans = NULL;
enum sip_transport transport = 0;
int oldformat = format; int oldformat = format;
/* mask request with some set of allowed formats. /* mask request with some set of allowed formats.
@ -20119,29 +20172,48 @@ static struct ast_channel *sip_request_call(const char *type, int format, void *
*host++ = '\0'; *host++ = '\0';
ext = tmp; ext = tmp;
secret = strchr(ext, ':'); secret = strchr(ext, ':');
if (secret) { }
*secret++ = '\0'; if (secret) {
md5secret = strchr(secret, ':'); *secret++ = '\0';
if (md5secret) { md5secret = strchr(secret, ':');
*md5secret++ = '\0'; }
authname = strchr(md5secret, ':'); if (md5secret) {
if (authname) *md5secret++ = '\0';
*authname++ = '\0'; authname = strchr(md5secret, ':');
} }
if (authname) {
*authname++ = '\0';
trans = strchr(authname, ':');
}
if (trans) {
*trans++ = '\0';
if (!strcasecmp(trans, "tcp"))
transport = SIP_TRANSPORT_TCP;
else if (!strcasecmp(trans, "tls"))
transport = SIP_TRANSPORT_TLS;
else {
if (strcasecmp(trans, "udp"))
ast_log(LOG_WARNING, "'%s' is not a valid transport option to Dial() for SIP calls, using udp by default.\n", trans);
transport = SIP_TRANSPORT_UDP;
} }
} else { }
if (!host) {
ext = strchr(tmp, '/'); ext = strchr(tmp, '/');
if (ext) if (ext)
*ext++ = '\0'; *ext++ = '\0';
host = tmp; host = tmp;
} }
p->socket.fd = -1;
p->socket.type = transport;
/* We now have /* We now have
host = peer name, DNS host name or DNS domain (for SRV) host = peer name, DNS host name or DNS domain (for SRV)
ext = extension (user part of URI) ext = extension (user part of URI)
dnid = destination of the call (applies to the To: header) dnid = destination of the call (applies to the To: header)
*/ */
if (create_addr(p, host, NULL)) { if (create_addr(p, host, NULL, 1)) {
*cause = AST_CAUSE_UNREGISTERED; *cause = AST_CAUSE_UNREGISTERED;
ast_debug(3, "Cant create SIP call - target device not registred\n"); ast_debug(3, "Cant create SIP call - target device not registred\n");
dialog_unlink_all(p, TRUE, TRUE); dialog_unlink_all(p, TRUE, TRUE);

@ -7,7 +7,7 @@
; syntaxes for dialing SIP devices. ; syntaxes for dialing SIP devices.
; SIP/devicename ; SIP/devicename
; SIP/username@domain (SIP uri) ; SIP/username@domain (SIP uri)
; SIP/username[:password[:md5secret[:authname]]]@host[:port] ; SIP/username[:password[:md5secret[:authname[:transport]]]]@host[:port]
; SIP/devicename/extension ; SIP/devicename/extension
; ;
; ;

Loading…
Cancel
Save