[Asterisk-Dev] NAT patch for chan_sip.c

Olle E. Johansson oej at edvina.net
Thu Oct 30 11:51:07 MST 2003


Jeremy McNamara wrote:

> What does this patch do that nat=yes doesn't accomplish?
It may help Asterisk as a SIP client, not a SIP server, to connect to
outside SIP servers like fwd.pulver.com. However, it needs to be
tested for this situation.

nat=yes works when * is a SIP server. There seems to be a problem when
you have clients both inside a NAT and outside, propably with the RTP
stream after re-invite. Maybe this patch with some additional magic
can make asterisk NOT re-invite when setting up a call in this
situation, but stay in the media stream.

/Olle
> 
> 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
>>  
>>
> 
> 
> _______________________________________________
> Asterisk-Dev mailing list
> Asterisk-Dev at lists.digium.com
> http://lists.digium.com/mailman/listinfo/asterisk-dev
> 


-- 
*** Olle E. Johansson, oej at edvina.net

Mobile +46 70 593 68 51, Edvina AB, http://www.edvina.net
Runbovägen 10, 192 48 Sollentuna, Sweden
Phone: +46 8 594 78 810, Fax: +46 8 594 78 820





More information about the asterisk-dev mailing list