diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 45603ca4f20542ccba1fe052ded0e24a00f18c85..6e8dcb42de83dfff7a1e9fb257c3fae19defe2ff 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -457,8 +457,8 @@ static int globalcanreinvite = REINVITE_INVITE; static struct sockaddr_in bindaddr; static struct sockaddr_in localnet; -static struct sockaddr_in localmask; static struct sockaddr_in externip; +static struct ast_ha *localaddr; static struct ast_frame *sip_read(struct ast_channel *ast); static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req); @@ -500,13 +500,19 @@ static void sip_destroy(struct sip_pvt *p); static int ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us) { /* - check to see if them is contained in our localnet/mask, - if not, use our externip for us, otherwise use the - real internal address in bindaddr - */ - if (localnet.sin_addr.s_addr && externip.sin_addr.s_addr && - ((htonl(them->s_addr) & htonl(localnet.sin_addr.s_addr)) != htonl(localnet.sin_addr.s_addr))) + * Using the localaddr structure built up with localnet statements + * apply it to their address to see if we need to substitute our + * externip or can get away with our internal bindaddr + */ + struct sockaddr_in theirs; + theirs.sin_addr = *them; + if (localaddr && externip.sin_addr.s_addr && + ast_apply_ha(localaddr, &theirs)) { + char t[256]; memcpy(us, &externip.sin_addr, sizeof(struct in_addr)); + strcpy(t, inet_ntoa(*(struct in_addr *)&them->s_addr)); + ast_log(LOG_DEBUG, "Target address %s is not local, substituting externip\n", t); + } else if (bindaddr.sin_addr.s_addr) memcpy(us, &bindaddr.sin_addr, sizeof(struct in_addr)); else @@ -1976,7 +1982,7 @@ static int sip_register(char *value, int lineno) *hostname = '\0'; hostname++; } - if (!username || ast_strlen_zero(username) || !hostname || !strlen(hostname)) { + if (!username || ast_strlen_zero(username) || !hostname || ast_strlen_zero(hostname)) { ast_log(LOG_WARNING, "Format for registration is user[:secret[:authuser]]@host[:port][/contact] at line %d", lineno); return -1; } @@ -3122,9 +3128,9 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, c l = p->fromuser; if ((ourport != 5060) && ast_strlen_zero(p->fromdomain)) - snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=as%08x", n, l, strlen(p->fromdomain) ? p->fromdomain : inet_ntoa(p->ourip), ourport, p->tag); + snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=as%08x", n, l, ast_strlen_zero(p->fromdomain) ? inet_ntoa(p->ourip) : p->fromdomain, ourport, p->tag); else - snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=as%08x", n, l, strlen(p->fromdomain) ? p->fromdomain : inet_ntoa(p->ourip), p->tag); + snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=as%08x", n, l, ast_strlen_zero(p->fromdomain) ? inet_ntoa(p->ourip) : p->fromdomain, p->tag); if (!ast_strlen_zero(p->username)) { if (ntohs(p->sa.sin_port) != DEFAULT_SIP_PORT) { @@ -4654,8 +4660,8 @@ static int sip_show_users(int fd, int argc, char *argv[]) static int sip_show_peers(int fd, int argc, char *argv[]) { -#define FORMAT2 "%-15.15s %-15.15s %s %s %s %-15.15s %-8s %-10s\n" -#define FORMAT "%-15.15s %-15.15s %s %s %s %-15.15s %-8d %-10s\n" +#define FORMAT2 "%-15.15s %-15.15s %s %s %s %-15.15s %-8s %-10s\n" +#define FORMAT "%-15.15s %-15.15s %s %s %s %-15.15s %-8d %-10s\n" struct sip_peer *peer; char name[256] = ""; if (argc != 3 && argc != 5) @@ -4741,6 +4747,25 @@ static char *regstate2str(int regstate) } } +/*--- print_group: Print call group and pickup group ---*/ +static void print_group(int fd, unsigned int group) +{ + unsigned int i; + int first=1; + + for (i=0; i<=31; i++) { /* Max group is 31 */ + if (group & (1 << i)) { + if (!first) { + ast_cli(fd, ", "); + } else { + first=0; + } + ast_cli(fd, "%u", i); + } + } + ast_cli(fd, " (%u)\n", group); +} + /*--- sip_show_peer: Show one peer in detail ---*/ static int sip_show_peer(int fd, int argc, char *argv[]) { @@ -4754,15 +4779,17 @@ static int sip_show_peer(int fd, int argc, char *argv[]) if (peer) { ast_cli(fd,"\n\n"); ast_cli(fd, " * Name : %s\n", peer->name); - ast_cli(fd, " Secret : %s\n", strlen(peer->secret)?"<Set>":"<Not set>"); - ast_cli(fd, " MD5Secret : %s\n", strlen(peer->md5secret)?"<Set>":"<Not set>"); + ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); + ast_cli(fd, " MD5Secret : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>"); ast_cli(fd, " Context : %s\n", peer->context); ast_cli(fd, " Methods : %s\n", peer->methods); ast_cli(fd, " Language : %s\n", peer->language); ast_cli(fd, " FromUser : %s\n", peer->fromuser); ast_cli(fd, " FromDomain : %s\n", peer->fromdomain); - ast_cli(fd, " Callgroup : %d (bitfield, decimal)\n", peer->callgroup); - ast_cli(fd, " Pickupgroup : %d (bitfield, decimal)\n", peer->pickupgroup); + ast_cli(fd, " Callgroup : "); + print_group(fd, peer->callgroup); + ast_cli(fd, " Pickupgroup : "); + print_group(fd, peer->pickupgroup); ast_cli(fd, " Mailbox : %s\n", peer->mailbox); ast_cli(fd, " LastMsgsSent : %d\n", peer->lastmsgssent); ast_cli(fd, " Dynamic : %s\n", (peer->dynamic?"Yes":"No")); @@ -4841,8 +4868,8 @@ static int sip_show_peer(int fd, int argc, char *argv[]) static int sip_show_registry(int fd, int argc, char *argv[]) { -#define FORMAT2 "%-20.20s %-10.10s %8.8s %-20.20s\n" -#define FORMAT "%-20.20s %-10.10s %8d %-20.20s\n" +#define FORMAT2 "%-20.20s %-12.12s %8.8s %-20.20s\n" +#define FORMAT "%-20.20s %-12.12s %8d %-20.20s\n" struct sip_registry *reg; char host[80]; if (argc != 3) @@ -4994,7 +5021,7 @@ static void receive_info(struct sip_pvt *p, struct sip_request *req) if (!strcasecmp(get_header(req, "Content-Type"), "application/dtmf-relay")) { /* Try getting the "signal=" part */ - if (strlen(c = get_sdp(req, "Signal")) || strlen(c = get_sdp(req, "d"))) { + if (ast_strlen_zero(c = get_sdp(req, "Signal")) && ast_strlen_zero(c = get_sdp(req, "d"))) { strncpy(buf, c, sizeof(buf) - 1); } else { ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid); @@ -6981,7 +7008,7 @@ static int reload_config(void) memset(&bindaddr, 0, sizeof(bindaddr)); memset(&localnet, 0, sizeof(localnet)); - memset(&localmask, 0, sizeof(localmask)); + memset(&localaddr, 0, sizeof(localaddr)); memset(&externip, 0, sizeof(externip)); /* Initialize some reasonable defaults */ @@ -7053,15 +7080,13 @@ static int reload_config(void) memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); } } else if (!strcasecmp(v->name, "localnet")) { - if (!(hp = ast_gethostbyname(v->value, &ahp))) - ast_log(LOG_WARNING, "Invalid localnet keyword: %s\n", v->value); - else - memcpy(&localnet.sin_addr, hp->h_addr, sizeof(localnet.sin_addr)); - } else if (!strcasecmp(v->name, "localmask")) { - if (!(hp = ast_gethostbyname(v->value, &ahp))) - ast_log(LOG_WARNING, "Invalid localmask keyword: %s\n", v->value); + struct ast_ha *na; + if (!(na = ast_append_ha("d", v->value, localaddr))) + ast_log(LOG_WARNING, "Invalid localnet value: %s\n", v->value); else - memcpy(&localmask.sin_addr, hp->h_addr, sizeof(localmask.sin_addr)); + localaddr = na; + } else if (!strcasecmp(v->name, "localmask")) { + ast_log(LOG_WARNING, "Use of localmask is deprecated; use localnet with mask syntax\n"); } else if (!strcasecmp(v->name, "externip")) { if (!(hp = ast_gethostbyname(v->value, &ahp))) ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value); @@ -7560,6 +7585,10 @@ int unload_module() ast_log(LOG_WARNING, "Unable to lock the interface list\n"); return -1; } + /* Free memory for local network address mask */ + if (localaddr) { + ast_free_ha(localaddr); + } return 0; } diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index d87f090bf0543cd96533436a899c482e1ea1596b..c5e7146cfda3ba6fb144a8999be0830b8fd2eecd 100755 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -68,11 +68,15 @@ context = default ; Default context for incoming calls ;externip = 200.201.202.203 ; Address that we're going to put in outbound SIP messages ; if we're behind a NAT -;localnet = 192.168.1.0 ; Internal NETWORK address -;localmask = 255.255.255.0 ; Internal netmask - ; The externip, localnet and localmask is used - ; when registering and communication with other proxies + + ; The externip and localnet is used + ; when registering and communicating with other proxies ; that we're registered with + ; You may add multiple local networks. A reasonable set of defaults + ; are: +;localnet=192.168.0.0/255.255.0.0; All RFC 1918 addresses are local networks +;localnet=10.0.0.0/255.0.0.0 ; Also RFC1918 +;localnet=169.254.0.0/255.255.0.0 ;Zero conf local network ;[snomsip] ;type=friend