reverse minor sip registration regression
authorDavid Vossel <dvossel@digium.com>
Tue, 15 Dec 2009 18:43:06 +0000 (18:43 +0000)
committerDavid Vossel <dvossel@digium.com>
Tue, 15 Dec 2009 18:43:06 +0000 (18:43 +0000)
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

index c089c3d..851471d 100644 (file)
@@ -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(&regobjs, 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), "<sip:%s@%s>;tag=%s", r->username, r->regdomain, p->tag);
-       if (!ast_strlen_zero(p->theirtag)) {
-               snprintf(to, sizeof(to), "<sip:%s@%s>;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), "<sip:%s>;tag=%s", r->username, p->tag);
+               if (!ast_strlen_zero(p->theirtag))
+                       snprintf(to, sizeof(to), "<sip:%s>;tag=%s", r->username, p->theirtag);
+               else
+                       snprintf(to, sizeof(to), "<sip:%s>", 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), "<sip:%s@%s>", r->username, r->regdomain);
+               snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->tag);
+               if (!ast_strlen_zero(p->theirtag))
+                       snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->theirtag);
+               else
+                       snprintf(to, sizeof(to), "<sip:%s@%s>", 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(&regl, 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;