--- chan_iax2.c.orig 2006-01-09 23:48:48.000000000 +0100 +++ chan_iax2.c 2006-01-21 15:06:50.000000000 +0100 @@ -392,6 +392,7 @@ struct iax2_registry { struct sockaddr_in addr; /*!< Who we connect to for registration purposes */ + char hostname[80]; char username[80]; char secret[80]; /*!< Password or key name in []'s */ char random[80]; @@ -1036,6 +1037,26 @@ return res; } +static void iax2_refresh_register_dns(struct iax2_registry *reg) +{ + struct ast_hostent ahp; + struct hostent *hp; + char oldaddr[INET_ADDRSTRLEN]; + char newaddr[INET_ADDRSTRLEN]; + ast_log(LOG_DEBUG, "Refreshing DNS entry for '%s'\n", reg->hostname); + hp = ast_gethostbyname(reg->hostname, &ahp); + if (!hp) { + ast_log(LOG_WARNING, "Host '%s' not found \n", reg->hostname); + } else { + ast_inet_ntoa(oldaddr,sizeof(oldaddr),reg->addr.sin_addr); + ast_inet_ntoa(newaddr,sizeof(newaddr),*((struct in_addr *)hp->h_addr)); + if (strcmp(oldaddr,newaddr)!=0) { + memcpy(®->addr.sin_addr, hp->h_addr, sizeof(®->addr.sin_addr)); + ast_log(LOG_NOTICE, "Host '%s' changed IP addr from %s to %s\n", reg->hostname, oldaddr,newaddr); + } + } +} + static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int lockpeer, int sockfd) { int res = 0; @@ -1730,6 +1751,8 @@ memset(&iaxs[f->callno]->reg->us, 0, sizeof(iaxs[f->callno]->reg->us)); iaxs[f->callno]->reg->regstate = REG_STATE_TIMEOUT; iaxs[f->callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; + /* the timeout could be because the remote server has changed his IP address. Make sure we got the right one */ + iax2_refresh_register_dns(iaxs[f->callno]->reg); } iax2_destroy_nolock(f->callno); } @@ -4342,23 +4365,23 @@ static int iax2_show_registry(int fd, int argc, char *argv[]) { -#define FORMAT2 "%-20.20s %-10.10s %-20.20s %8.8s %s\n" -#define FORMAT "%-20.20s %-10.10s %-20.20s %8d %s\n" +#define FORMAT2 "%-30.30s %-20.20s %-10.10s %-20.20s %8.8s %s\n" +#define FORMAT "%-30.30s %-20.20s %-10.10s %-20.20s %8d %s\n" struct iax2_registry *reg; - char host[80]; + char ip[80]; char perceived[80]; char iabuf[INET_ADDRSTRLEN]; if (argc != 3) return RESULT_SHOWUSAGE; ast_mutex_lock(&peerl.lock); - ast_cli(fd, FORMAT2, "Host", "Username", "Perceived", "Refresh", "State"); + ast_cli(fd, FORMAT2, "Host", "IP", "Username", "Perceived", "Refresh", "State"); for (reg = registrations;reg;reg = reg->next) { - snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), reg->addr.sin_addr), ntohs(reg->addr.sin_port)); + snprintf(ip, sizeof(ip), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), reg->addr.sin_addr), ntohs(reg->addr.sin_port)); if (reg->us.sin_addr.s_addr) snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), reg->us.sin_addr), ntohs(reg->us.sin_port)); else ast_copy_string(perceived, "", sizeof(perceived)); - ast_cli(fd, FORMAT, host, + ast_cli(fd, FORMAT, reg->hostname, ip, reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); } ast_mutex_unlock(&peerl.lock); @@ -5516,6 +5539,7 @@ ast_copy_string(reg->secret, secret, sizeof(reg->secret)); reg->expire = -1; reg->refresh = IAX_DEFAULT_REG_EXPIRE; + ast_copy_string(reg->hostname,hostname,sizeof(reg->hostname)); reg->addr.sin_family = AF_INET; memcpy(®->addr.sin_addr, hp->h_addr, sizeof(®->addr.sin_addr)); reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); @@ -7397,6 +7421,8 @@ manager_event(EVENT_FLAG_SYSTEM, "Registry", "Channel: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr.callno]->reg->username, ies.cause ? ies.cause : ""); } iaxs[fr.callno]->reg->regstate = REG_STATE_REJECTED; + /* MAYBE _our_ server just changed his IP and the old IP has been taken by another iax server, so make sure we have the right IP */ + iax2_refresh_register_dns(iaxs[fr.callno]->reg); } /* Send ack immediately, before we destroy */ send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);