From 181f617fd7ac47a01214dba1de2f4dce7e2e4f56 Mon Sep 17 00:00:00 2001 From: David Vossel Date: Tue, 15 Dec 2009 18:43:06 +0000 Subject: reverse minor sip registration regression A registration regression caused by a code tweak in (issue #14331) and a bug fix in (issue #15539) caused some sip registration config entries to be constructed incorrectly. Origially issue #14331 contained the code tweak as well as a bug fix, but since the issue was reported as a tweak the bug fix portion was moved into issue #15539. Both the tweak and the bug fix contained minor incorrect logic that resulted in some SIP registrations to fail. (issue #14331) (issue #15539) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@235132 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 99 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index c089c3d00..851471d3c 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2090,8 +2090,7 @@ struct sip_registry { AST_STRING_FIELD(nonce); /*!< Authorization nonce */ AST_STRING_FIELD(opaque); /*!< Opaque nonsense */ AST_STRING_FIELD(qop); /*!< Quality of Protection, since SIP wasn't complicated enough yet. */ - AST_STRING_FIELD(authdomain); /*!< Authorization domain */ - AST_STRING_FIELD(regdomain); /*!< Registration domain */ + AST_STRING_FIELD(domain); /*!< Authorization domain */ AST_STRING_FIELD(username); /*!< Who we are registering as */ AST_STRING_FIELD(authuser); /*!< Who we *authenticate* as */ AST_STRING_FIELD(hostname); /*!< Domain or host we register to */ @@ -7758,10 +7757,6 @@ static int sip_register(const char *value, int lineno) AST_APP_ARG(host); AST_APP_ARG(port); ); - AST_DECLARE_APP_ARGS(user2, - AST_APP_ARG(userpart); - AST_APP_ARG(domain); - ); if (!value) return -1; @@ -7858,20 +7853,6 @@ static int sip_register(const char *value, int lineno) */ AST_NONSTANDARD_RAW_ARGS(host3, host2.hostpart, ':'); - /*! - * pre1.peer => peer - * pre2.transport = transport - * user2.userpart => user - * user2.domain => domain (regdomain) - * user1.secret => secret - * user1.authuser => authuser - * host3.host => host - * host3.port => port - * host2.extension => extension (callback) - * host1.expiry => expiry - */ - AST_NONSTANDARD_RAW_ARGS(user2, user1.userpart, '@'); - if (host3.port) { if (!(portnum = port_str2int(host3.port, 0))) { ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", host3.port, lineno); @@ -7915,9 +7896,8 @@ static int sip_register(const char *value, int lineno) ast_atomic_fetchadd_int(®objs, 1); ASTOBJ_INIT(reg); ast_string_field_set(reg, callback, ast_strip_quoted(S_OR(host2.extension, "s"), "\"", "\"")); - ast_string_field_set(reg, username, ast_strip_quoted(S_OR(user2.userpart, ""), "\"", "\"")); + ast_string_field_set(reg, username, ast_strip_quoted(S_OR(user1.userpart, ""), "\"", "\"")); ast_string_field_set(reg, hostname, ast_strip_quoted(S_OR(host3.host, ""), "\"", "\"")); - ast_string_field_set(reg, regdomain, ast_strip_quoted(S_OR(user2.domain, S_OR(host3.host, "")), "\"", "\"")); ast_string_field_set(reg, authuser, ast_strip_quoted(S_OR(user1.authuser, ""), "\"", "\"")); ast_string_field_set(reg, secret, ast_strip_quoted(S_OR(user1.secret, ""), "\"", "\"")); ast_string_field_set(reg, peername, ast_strip_quoted(S_OR(pre1.peer, ""), "\"", "\"")); @@ -12153,6 +12133,8 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * struct sip_pvt *p; struct sip_peer *peer = NULL; int res; + char *fromdomain; + char *domainport = NULL; /* exit if we are already in process with this registrar ?*/ if (r == NULL || ((auth == NULL) && (r->regstate == REG_STATE_REGSENT || r->regstate == REG_STATE_AUTHSENT))) { @@ -12235,7 +12217,9 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * ast_string_field_set(r, callid, p->callid); if (!r->dnsmgr && r->portno) { p->sa.sin_port = htons(r->portno); - p->recv.sin_port = htons(r->portno); + p->recv.sin_port = htons(r->portno); + } else { /* Set registry port to the port set from the peer definition/srv or default */ + r->portno = ntohs(p->sa.sin_port); } ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */ r->call = dialog_ref(p, "copying dialog into registry r->call"); /* Save pointer to SIP dialog */ @@ -12287,19 +12271,55 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * ast_debug(1, "Scheduled a registration timeout for %s id #%d \n", r->hostname, r->timeout); } - snprintf(from, sizeof(from), ";tag=%s", r->username, r->regdomain, p->tag); - if (!ast_strlen_zero(p->theirtag)) { - snprintf(to, sizeof(to), ";tag=%s", r->username, r->regdomain, p->theirtag); + if ((fromdomain = strchr(r->username, '@'))) { + /* the domain name is just behind '@' */ + fromdomain++ ; + /* We have a domain in the username for registration */ + snprintf(from, sizeof(from), ";tag=%s", r->username, p->tag); + if (!ast_strlen_zero(p->theirtag)) + snprintf(to, sizeof(to), ";tag=%s", r->username, p->theirtag); + else + snprintf(to, sizeof(to), "", r->username); + + /* If the registration username contains '@', then the domain should be used as + the equivalent of "fromdomain" for the registration */ + if (ast_strlen_zero(p->fromdomain)) { + ast_string_field_set(p, fromdomain, fromdomain); + } } else { - snprintf(to, sizeof(to), "", r->username, r->regdomain); + snprintf(from, sizeof(from), ";tag=%s", r->username, p->tohost, p->tag); + if (!ast_strlen_zero(p->theirtag)) + snprintf(to, sizeof(to), ";tag=%s", r->username, p->tohost, p->theirtag); + else + snprintf(to, sizeof(to), "", r->username, p->tohost); } - /* Host is what we are registered to, reguardless of domain in username field */ - if (ntohs(p->sa.sin_port) != STANDARD_SIP_PORT) - snprintf(addr, sizeof(addr), "sip:%s:%d", r->hostname, ntohs(p->sa.sin_port)); - else - snprintf(addr, sizeof(addr), "sip:%s", r->hostname); - + /* Fromdomain is what we are registering to, regardless of actual + host name from SRV */ + if (!ast_strlen_zero(p->fromdomain)) { + domainport = strrchr(p->fromdomain, ':'); + if (domainport) { + *domainport++ = '\0'; /* trim off domainport from p->fromdomain */ + if (ast_strlen_zero(domainport)) + domainport = NULL; + } + if (domainport) { + if (atoi(domainport) != STANDARD_SIP_PORT) + snprintf(addr, sizeof(addr), "sip:%s:%s", p->fromdomain, domainport); + else + snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain); + } else { + if (r->portno && r->portno != STANDARD_SIP_PORT) + snprintf(addr, sizeof(addr), "sip:%s:%d", p->fromdomain, r->portno); + else + snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain); + } + } else { + if (r->portno && r->portno != STANDARD_SIP_PORT) + snprintf(addr, sizeof(addr), "sip:%s:%d", r->hostname, r->portno); + else + snprintf(addr, sizeof(addr), "sip:%s", r->hostname); + } ast_string_field_set(p, uri, addr); p->branch ^= ast_random(); @@ -12320,7 +12340,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * if (!ast_strlen_zero(global_useragent)) add_header(&req, "User-Agent", global_useragent); - if (auth) /* Add auth header */ + if (auth) /* Add auth header */ add_header(&req, authheader, auth); else if (!ast_strlen_zero(r->nonce)) { char digest[1024]; @@ -12334,7 +12354,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * ast_debug(1, " >>> Re-using Auth data for %s@%s\n", r->username, r->hostname); ast_string_field_set(p, realm, r->realm); ast_string_field_set(p, nonce, r->nonce); - ast_string_field_set(p, domain, r->authdomain); + ast_string_field_set(p, domain, r->domain); ast_string_field_set(p, opaque, r->opaque); ast_string_field_set(p, qop, r->qop); p->noncecount = ++r->noncecount; @@ -15261,12 +15281,11 @@ static int manager_show_registry(struct mansession *s, const struct message *m) "Host: %s\r\n" "Port: %d\r\n" "Username: %s\r\n" - "Domain: %s\r\n" "Refresh: %d\r\n" "State: %s\r\n" "RegistrationTime: %ld\r\n" "\r\n", idtext, iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT, - iterator->username, iterator->regdomain, iterator->refresh, regstate2str(iterator->regstate), (long) iterator->regtime.tv_sec); + iterator->username, iterator->refresh, regstate2str(iterator->regstate), (long) iterator->regtime.tv_sec); ASTOBJ_UNLOCK(iterator); total++; } while(0)); @@ -16438,7 +16457,6 @@ static char *sip_show_registry(struct ast_cli_entry *e, int cmd, struct ast_cli_ #define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" #define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" char host[80]; - char user[80]; char tmpdat[256]; struct ast_tm tm; int counter = 0; @@ -16461,13 +16479,12 @@ static char *sip_show_registry(struct ast_cli_entry *e, int cmd, struct ast_cli_ ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { ASTOBJ_RDLOCK(iterator); snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT); - snprintf(user, sizeof(user), "%s@%s", iterator->username, iterator->regdomain); if (iterator->regtime.tv_sec) { ast_localtime(&iterator->regtime, &tm, NULL); ast_strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm); } else tmpdat[0] = '\0'; - ast_cli(a->fd, FORMAT, host, (iterator->dnsmgr) ? "Y" : "N", user, iterator->refresh, regstate2str(iterator->regstate), tmpdat); + ast_cli(a->fd, FORMAT, host, (iterator->dnsmgr) ? "Y" : "N", iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat); ASTOBJ_UNLOCK(iterator); counter++; } while(0)); @@ -17798,7 +17815,7 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header if (strcmp(r->nonce, p->nonce)) { ast_string_field_set(r, realm, p->realm); ast_string_field_set(r, nonce, p->nonce); - ast_string_field_set(r, authdomain, p->domain); + ast_string_field_set(r, domain, p->domain); ast_string_field_set(r, opaque, p->opaque); ast_string_field_set(r, qop, p->qop); r->noncecount = 0; -- cgit v1.2.3