[Asterisk-Dev] NAT patch for chan_sip.c

Jeremy McNamara jj at nufone.net
Thu Oct 30 11:05:00 MST 2003


What does this patch do that nat=yes doesn't accomplish?

Also, this should be submitted to http://bugs.digium.com/ not the 
mailing list.



Jeremy McNamara



William Waites wrote:

>This is not thoroughly tested, but seems to work for me. It consists in
>three changes:
>
> 1. introduction of inside_net, inside_mask and outside_addr global
>    parameters for sip.conf
> 2. change transmit_register to call ast_sip_ouraddrfor() before
>    building the contact header
> 3. change ast_sip_ouraddrfor() to check if the destination is
>    internal or external. if internal, continue as usual, if external
>    return outside_addr in *us
>
>Consider this patch suitably disclaimed, and without any warranty
>whatsoever. This code was produced on behalf of NTG Clarity Networks,
>Montréal.
>
>Index: chan_sip.c
>===================================================================
>RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
>retrieving revision 1.203
>diff -u -r1.203 chan_sip.c
>--- chan_sip.c  25 Oct 2003 17:41:02 -0000      1.203
>+++ chan_sip.c  30 Oct 2003 17:23:54 -0000
>@@ -390,6 +390,9 @@
> 
> 
> static struct sockaddr_in bindaddr;
>+static struct sockaddr_in inside_net;
>+static struct sockaddr_in inside_mask;
>+static struct sockaddr_in outside_addr;
> 
> static struct ast_frame  *sip_read(struct ast_channel *ast);
> static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request
>*req);
>@@ -425,7 +428,15 @@
> 
> static int ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us)
> {
>-       if (bindaddr.sin_addr.s_addr)
>+       /*
>+         check to see if them is contained in our inside_net/mask,
>+         if not, use our outside_addr for us, otherwise use the 
>+         real internal address in bindaddr
>+         */
>+       if (inside_net.sin_addr.s_addr && outside_addr.sin_addr.s_addr &&
>+           ((htonl(them->s_addr) & htonl(inside_net.sin_addr.s_addr)) !=
>htonl(inside_net.sin_addr.s_addr)))
>+               memcpy(us, &outside_addr.sin_addr, sizeof(struct in_addr));
>+       else if (bindaddr.sin_addr.s_addr)
>                memcpy(us, &bindaddr.sin_addr, sizeof(struct in_addr));
>        else
>                return ast_ouraddrfor(them, us);
>@@ -2951,6 +2962,8 @@
>        char via[80];
>        char addr[80];
>        struct sip_pvt *p;
>+       struct hostent *hp;
>+
>        /* 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))) {
>                ast_log(LOG_NOTICE, "Strange, trying to register when
>registration already pending\n");
>@@ -2984,9 +2997,16 @@
>                        strncpy(p->peername, r->username, sizeof(p->peername)-1);
>                strncpy(p->username, r->username, sizeof(p->username)-1);
>                strncpy(p->exten, r->contact, sizeof(p->exten) - 1);
>-               /* Always bind to our IP if specified */
>-               if (bindaddr.sin_addr.s_addr)
>-                       memcpy(&p->ourip, &bindaddr.sin_addr, sizeof(p->ourip));
>+
>+               /*
>+                 check which address we should use in our contact header 
>+                 based on whether the remote host is on the external or
>+                 internal network so we can register through nat
>+                */
>+               if ((hp = gethostbyname(r->hostname))) {
>+                       if (ast_sip_ouraddrfor((struct in_addr *)hp->h_addr,
>&p->ourip))
>+                               memcpy(&p->ourip, &bindaddr.sin_addr,
>sizeof(p->ourip));
>+               }
>                build_contact(p);
>        }
> 
>@@ -5921,6 +5941,10 @@
>        sip_prefs_free();
> 
>        memset(&bindaddr, 0, sizeof(bindaddr));
>+       memset(&inside_net, 0, sizeof(inside_net));
>+       memset(&inside_mask, 0, sizeof(inside_mask));
>+       memset(&outside_addr, 0, sizeof(outside_addr));
>+
>        /* Initialize some reasonable defaults */
>        strncpy(context, "default", sizeof(context) - 1);
>        strcpy(language, "");
>@@ -5979,6 +6003,21 @@
>                        } else {
>                                memcpy(&bindaddr.sin_addr, hp->h_addr,
>sizeof(bindaddr.sin_addr));
>                        }
>+               } else if (!strcasecmp(v->name, "inside_net")) {
>+                       if (!(hp = gethostbyname(v->value)))
>+                               ast_log(LOG_WARNING, "Invalid INSIDE_NET:
>%s\n", v->value);
>+                       else 
>+                               memcpy(&inside_net.sin_addr, hp->h_addr,
>sizeof(inside_net.sin_addr));
>+               } else if (!strcasecmp(v->name, "inside_mask")) {
>+                       if (!(hp = gethostbyname(v->value)))
>+                               ast_log(LOG_WARNING, "Invalid INSIDE_MASK:
>%s\n", v->value);
>+                       else
>+                               memcpy(&inside_mask.sin_addr, hp->h_addr,
>sizeof(inside_mask.sin_addr));
>+               } else if (!strcasecmp(v->name, "outside_addr")) {
>+                       if (!(hp = gethostbyname(v->value))) 
>+                               ast_log(LOG_WARNING, "Invalid OUTSIDE_MASK:
>%s\n", v->value);
>+                       else
>+                               memcpy(&outside_addr.sin_addr, hp->h_addr,
>sizeof(outside_addr.sin_addr));
>                } else if (!strcasecmp(v->name, "allow")) {
>                        format = ast_getformatbyname(v->value);
>                        if (format < 1)
>
>_______________________________________________
>Asterisk-Dev mailing list
>Asterisk-Dev at lists.digium.com
>http://lists.digium.com/mailman/listinfo/asterisk-dev
>  
>





More information about the asterisk-dev mailing list