Add *preliminary* per-peer outbound proxy (bug #2859, new patch though)
authorMark Spencer <markster@digium.com>
Fri, 3 Dec 2004 23:34:45 +0000 (23:34 +0000)
committerMark Spencer <markster@digium.com>
Fri, 3 Dec 2004 23:34:45 +0000 (23:34 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4383 65c4cc65-6c06-0410-ace0-fbb531ad65f3

acl.c
channels/chan_sip.c
include/asterisk/acl.h

diff --git a/acl.c b/acl.c
index 935ec80..c7eb342 100755 (executable)
--- 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;
index 4220e82..dde707e 100755 (executable)
@@ -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")) {
index bcc7543..87c89bd 100755 (executable)
@@ -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);