diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 7ff2abb233c40d245161e2698ce404acf4cdd7a4..b056a34418c4bb2293efc994d3d3d309b233de42 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2087,7 +2087,8 @@ 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(domain); /*!< Authorization domain */ + AST_STRING_FIELD(authdomain); /*!< Authorization domain */ + AST_STRING_FIELD(regdomain); /*!< Registration 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 */ @@ -7464,7 +7465,7 @@ static int sip_register(const char *value, int lineno) char buf[256] = ""; char *username = NULL; char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *tmp=NULL; - char *callback=NULL, *peername=NULL; + char *callback=NULL, *peername=NULL, *regdomain=NULL; if (!value) return -1; @@ -7513,11 +7514,18 @@ static int sip_register(const char *value, int lineno) authuser = NULL; } } - if ((authuser) && (ast_strlen_zero(authuser))) + if ((authuser) && (ast_strlen_zero(authuser))) authuser = NULL; - if ((secret) && (ast_strlen_zero(secret))) + if ((secret) && (ast_strlen_zero(secret))) secret = NULL; + /* The user portion may be of the form username@regdomain so split off any regdomain */ + regdomain = strchr(username, '@'); + if (regdomain) { + *regdomain++ = '\0'; + } + + if (!(reg = ast_calloc(1, sizeof(*reg)))) { ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n"); return -1; @@ -7536,6 +7544,9 @@ static int sip_register(const char *value, int lineno) ast_string_field_set(reg, username, username); if (hostname) ast_string_field_set(reg, hostname, hostname); + ast_string_field_set(reg, regdomain, hostname); + if (regdomain) + ast_string_field_set(reg, regdomain, regdomain); if (authuser) ast_string_field_set(reg, authuser, authuser); if (secret) @@ -11586,8 +11597,6 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * struct sip_pvt *p; struct sip_peer *peer; 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))) { @@ -11670,9 +11679,7 @@ 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); - } else { /* Set registry port to the port set from the peer definition/srv or default */ - r->portno = ntohs(p->sa.sin_port); + p->recv.sin_port = htons(r->portno); } 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 */ @@ -11684,7 +11691,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * ast_string_field_set(p, peermd5secret, r->md5secret); /* User name in this realm - if authuser is set, use that, otherwise use username */ - if (!ast_strlen_zero(r->authuser)) { + if (!ast_strlen_zero(r->authuser)) { ast_string_field_set(p, peername, r->authuser); ast_string_field_set(p, authname, r->authuser); } else if (!ast_strlen_zero(r->username)) { @@ -11724,55 +11731,20 @@ 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); } - 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); - } + 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); } else { - 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); + snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, r->regdomain); } - - /* Fromdomain is what we are registering to, regardless of actual + + /* Domain 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); - } + if (ntohs(p->sa.sin_port) != STANDARD_SIP_PORT) + snprintf(addr, sizeof(addr), "sip:%s:%d", r->regdomain, ntohs(p->sa.sin_port)); + else + snprintf(addr, sizeof(addr), "sip:%s", r->regdomain); + ast_string_field_set(p, uri, addr); p->branch ^= ast_random(); @@ -11793,8 +11765,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]; @@ -11808,7 +11779,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->domain); + ast_string_field_set(p, domain, r->authdomain); ast_string_field_set(p, opaque, r->opaque); ast_string_field_set(p, qop, r->qop); p->noncecount = ++r->noncecount; @@ -11818,7 +11789,6 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * add_header(&req, "Authorization", digest); else ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", r->username, r->hostname); - } snprintf(tmp, sizeof(tmp), "%d", r->expiry); @@ -14742,11 +14712,12 @@ 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", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT, - iterator->username, iterator->refresh, regstate2str(iterator->regstate), (long) iterator->regtime.tv_sec); + iterator->username, iterator->regdomain, iterator->refresh, regstate2str(iterator->regstate), (long) iterator->regtime.tv_sec); ASTOBJ_UNLOCK(iterator); total++; } while(0)); @@ -15889,6 +15860,7 @@ 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; @@ -15911,12 +15883,13 @@ 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", iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat); + ast_cli(a->fd, FORMAT, host, (iterator->dnsmgr) ? "Y" : "N", user, iterator->refresh, regstate2str(iterator->regstate), tmpdat); ASTOBJ_UNLOCK(iterator); counter++; } while(0)); @@ -17226,7 +17199,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, domain, p->domain); + ast_string_field_set(r, authdomain, p->domain); ast_string_field_set(r, opaque, p->opaque); ast_string_field_set(r, qop, p->qop); r->noncecount = 0;