From 4820c2bb973de13a52ce584045f4a20be381e5b0 Mon Sep 17 00:00:00 2001 From: Mark Spencer <markster@digium.com> Date: Fri, 3 Dec 2004 23:34:45 +0000 Subject: [PATCH] Add *preliminary* per-peer outbound proxy (bug #2859, new patch though) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4383 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- acl.c | 18 ++++++++++++++- channels/chan_sip.c | 51 +++++++++++++++++++++++++++++------------- include/asterisk/acl.h | 3 ++- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/acl.c b/acl.c index 935ec808da..c7eb342708 100755 --- a/acl.c +++ b/acl.c @@ -23,6 +23,7 @@ #include <asterisk/channel.h> #include <asterisk/utils.h> #include <asterisk/lock.h> +#include <asterisk/srv.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netdb.h> @@ -186,10 +187,20 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin) return res; } -int ast_get_ip(struct sockaddr_in *sin, char *value) +int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service) { struct hostent *hp; struct ast_hostent ahp; + char srv[256]; + char host[256]; + int tportno = ntohs(sin->sin_port); + if (service) { + snprintf(srv, sizeof(srv), "%s.%s", service, value); + if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) { + sin->sin_port = htons(tportno); + value = host; + } + } hp = ast_gethostbyname(value, &ahp); if (hp) { memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); @@ -200,6 +211,11 @@ int ast_get_ip(struct sockaddr_in *sin, char *value) return 0; } +int ast_get_ip(struct sockaddr_in *sin, const char *value) +{ + return ast_get_ip_or_srv(sin, value, NULL); +} + /* iface is the interface (e.g. eth0); address is the return value */ int ast_lookup_iface(char *iface, struct in_addr *address) { int mysock, res = 0; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 4220e82cae..dde707e283 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -186,6 +186,7 @@ static int noncodeccapability = AST_RTP_DTMF; static char ourhost[256]; static struct in_addr __ourip; +static struct sockaddr_in outboundproxyip; static int ourport; static int sipdebug = 0; @@ -8375,6 +8376,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int struct sip_peer *prev; struct ast_ha *oldha = NULL; int maskfound=0; + int obproxyfound=0; int found=0; prev = NULL; @@ -8480,18 +8482,22 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value); peer->dtmfmode = SIP_DTMF_RFC2833; } - } else if (!strcasecmp(v->name, "host")) { + } else if (!strcasecmp(v->name, "host") || !strcasecmp(v->name, "outboundproxy")) { if (!strcasecmp(v->value, "dynamic")) { - /* They'll register with us */ - peer->dynamic = 1; - if (!found) { - /* Initialize stuff iff we're not found, otherwise - we keep going with what we had */ - memset(&peer->addr.sin_addr, 0, 4); - if (peer->addr.sin_port) { - /* If we've already got a port, make it the default rather than absolute */ - peer->defaddr.sin_port = peer->addr.sin_port; - peer->addr.sin_port = 0; + if (!strcasecmp(v->name, "outboundproxy") || obproxyfound) { + ast_log(LOG_WARNING, "You can't have a dynamic outbound proxy, you big silly head at line %d.\n", v->lineno); + } else { + /* They'll register with us */ + peer->dynamic = 1; + if (!found) { + /* Initialize stuff iff we're not found, otherwise + we keep going with what we had */ + memset(&peer->addr.sin_addr, 0, 4); + if (peer->addr.sin_port) { + /* If we've already got a port, make it the default rather than absolute */ + peer->defaddr.sin_port = peer->addr.sin_port; + peer->addr.sin_port = 0; + } } } } else { @@ -8500,11 +8506,16 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int ast_sched_del(sched, peer->expire); peer->expire = -1; peer->dynamic = 0; - if (ast_get_ip(&peer->addr, v->value)) { - destroy_peer(peer); - return NULL; + if (!obproxyfound || !strcasecmp(v->name, "outboundproxy")) { + if (ast_get_ip_or_srv(&peer->addr, v->value, "_sip._udp")) { + destroy_peer(peer); + return NULL; + } } - strncpy(peer->tohost, v->value, sizeof(peer->tohost) - 1); + if (!strcasecmp(v->name, "outboundproxy")) + obproxyfound=1; + else + strncpy(peer->tohost, v->value, sizeof(peer->tohost) - 1); } if (!maskfound) inet_aton("255.255.255.255", &peer->mask); @@ -8652,6 +8663,9 @@ static int reload_config(void) global_realm[sizeof(global_realm)-1] = '\0'; strncpy(global_musicclass, "default", sizeof(global_musicclass) - 1); strncpy(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid) - 1); + memset(&outboundproxyip, 0, sizeof(outboundproxyip)); + outboundproxyip.sin_port = htons(DEFAULT_SIP_PORT); + outboundproxyip.sin_family = AF_INET; /* Type of address: IPv4 */ global_canreinvite = REINVITE_INVITE; videosupport = 0; compactheaders = 0; @@ -8748,6 +8762,13 @@ static int reload_config(void) global_nat = SIP_NAT_ALWAYS; else global_nat = SIP_NAT_NEVER; + } else if (!strcasecmp(v->name, "outboundproxy")) { + if (ast_get_ip_or_srv(&outboundproxyip, v->value, "_sip._udp") < 0) + ast_log(LOG_WARNING, "Unable to locate host '%s'\n", v->value); + } else if (!strcasecmp(v->name, "outboundproxyport")) { + /* Port needs to be after IP */ + sscanf(v->value, "%i", &format); + outboundproxyip.sin_port = htons(format); } else if (!strcasecmp(v->name, "autocreatepeer")) { autocreatepeer = ast_true(v->value); } else if (!strcasecmp(v->name, "srvlookup")) { diff --git a/include/asterisk/acl.h b/include/asterisk/acl.h index bcc7543d59..87c89bd592 100755 --- a/include/asterisk/acl.h +++ b/include/asterisk/acl.h @@ -31,7 +31,8 @@ struct ast_ha; extern void ast_free_ha(struct ast_ha *ha); extern struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path); extern int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin); -extern int ast_get_ip(struct sockaddr_in *sin, char *value); +extern int ast_get_ip(struct sockaddr_in *sin, const char *value); +extern int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service); extern int ast_ouraddrfor(struct in_addr *them, struct in_addr *us); extern int ast_lookup_iface(char *iface, struct in_addr *address); extern struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original); -- GitLab