[Home]

Summary:ASTERISK-02801: SIP messages contain 0.0.0.0 as IP for Asterisk
Reporter:benjk (benjk)Labels:
Date Opened:2004-11-12 21:00:21.000-0600Date Closed:2005-01-09 08:56:36.000-0600
Priority:MinorRegression?No
Status:Closed/CompleteComponents:Core/General
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:
Description:Newly installed Asterisk 1.02 system is unable to register with any SIP registrar because Asterisk puts 0.0.0.0 as its host address in the various headers. Yet the Call-ID header contains the proper IP address after the @ mark, so it would seem that Asterisk did indeed pick up its IP address.

This happens on two different systems running Asterisk 1.02 on OSX 10.3.5 with patch 2833 applied.

****** ADDITIONAL INFORMATION ******

the register directive in sip.conf looks like this:
register => 05012345678:passwd:AUTHUSR@ispvoip-9999.ocn.ne.jp/05012345678

the SIP message log looks like this:
REGISTER sip:ispvoip-9999.ocn.ne.jp SIP/2.0
Via: SIP/2.0/UDP 0.0.0.0:5060;branch=z9hG4bK3d1d0887

and further down ...

Call-ID: 3b2h34e70a4a3f545fc6526f51936f58@1.2.3.4

still further down ...

Contact: <sip:05012345678@0.0.0.0>
Event: registration

Note that the Call-ID does contain the proper IP while via and contact headers don't. This is what confuses me.

For a log of the console when Asterisk is launched on this system, please see bug report 2833 (now resolved and closed) which has the complete startup session log attached.

running Asterisk with the -d switch shows the usual loader messages loading modules/apps and registering channels, nothing unusual.

The SIP related messages which may be of interest are:

Nov 13 11:51:00 DEBUG[-1610571284]: channel.c:198 ast_channel_register_ex: Registered handler for 'SIP' (Session Initiation Protocol (SIP))
Nov 13 11:51:00 DEBUG[-1610571284]: chan_sip.c:2402 sip_alloc: Allocating new SIP call for (null)
Nov 13 11:51:00 DEBUG[-1610571284]: chan_sip.c:2402 sip_alloc: Allocating new SIP call for 202f10d071f8d8310839b36c04327bac@1.2.3.4

and later:

Nov 13 11:51:00 DEBUG[25224704]: chan_sip.c:828 __sip_ack: Stopping retransmission on '4d051324082bc7fd7256b73b1b17bd22@1.2.3.4' of Request 102: Found
Nov 13 11:51:00 DEBUG[25224704]: chan_sip.c:828 __sip_ack: Stopping retransmission on '202f10d071f8d8310839b36c04327bac@1.2.3.4' of Request 102: Found

If there are any other tests I could run to get a better indication of what the cause of this is, please let me know.
Comments:By: benjk (benjk) 2004-11-12 21:25:18.000-0600

OK, I have now set the 'bindaddr' directive in sip.conf explicitly to the external NIC's IP address.

This now gets rid of the 0.0.0.0 in the SIP headers, but now I am unable to communicate on the internal NIC (192.168.x.x address) using SIP because Asterisk now only listens on the external NIC for SIP.

I seem to remember that this had once been an issue a long long time ago, like a year ago or more, but I couldn't find it. I guess there is a workaround or a patch somewhere.

By: Mark Spencer (markster) 2004-11-12 21:46:23.000-0600

This is a configuration issue.

By: benjk (benjk) 2004-11-12 21:54:14.000-0600

This problem occurs using the sample configuration sip.conf that comes with Asterisk with one single line added:

register => user:pass:authusr@domain.com/user

nothing else has been modified, no sip peers have been defined yet.

the very same sip.conf on  three earlier versions of Asterisk (from within the last six months) do not show the problem.

So, if this is a configuration issue and not a bug, could you please provide a pointer to a change log that explains how Asterisk's behavious was changed in respect of not allowing multiple NICs anymore with a vanilla sip.conf in which the binaddr has not been set.

thanks a lot
regards
benjk

By: Mark Spencer (markster) 2004-11-13 10:45:38.000-0600

The bug tracker ins not a source for technical support.  I suggest you find bkw_, oej, or someone else on #asterisk to help you (given your history with Asterisk, I'm even willing to help you myself) or alternatively get support from a commercial provider like Digium.  Whatever you do though, keep it off the bug tracker unless it does, in the end, actually end up being a bug, but this almost certainly is a configuration issue.

By: benjk (benjk) 2004-11-13 21:47:36.000-0600

Synopsis: bug in function transmit_register() in chan_sip.c

Dear Mark,

I appreciate you probably had a hard long day with plenty of annoying things popping up, but that's not a reason to lecture me and make accusations that I was abusing the bug tracker, because you know very well that I am not the kind of person who would do that.

I may not know the Asterisk code so well, but I am pretty good at behavioural analysis because in a former life I used to earn a living as a sysadmin for thousands of closed source systems running hundreds of closed source applications. Behavioural analysis was all we got back then and just like you, closed source vendors, too would claim that their bugs were features, so we had to be good to proof otherwise.

Anyway, I can show you that you have a bug in function transmit_register() where it calls function ast_sip_ouraddrfor() in chan_sip.c if you allow me to present my case ...

As far as I can see, function ast_sip_ouraddrfor() in chan_sip.c is supposed to determine which address we are to present to the remote peer.

If externip has been set, then this function is supposed to use that, otherwise it is supposed to use the address through which we are talking to the peer. That means, if bindaddr is not explicitly set, but at default (0.0.0.0), then ast_sip_ouraddrfor() is supposed to find out what the actual address is. Function transmit_register() has to take that into account and must not simply copy bindaddr (which is 0.0.0.0 in this case) into p->ourip.

Unfortunately though this is what transmit_register() is doing. It does not care that bindaddr is at default and that this default (0.0.0.0) does not represent a routable ip address. It copies that value (0.0.0.0) lock, stock and barrel into p->ourip regardless.

Consequently, I consider this is a bug, not a configuration issue.

#################### Console log follows ####################
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:2345 sip_alloc: p->ourip is: 61.122.x.x
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:2375 sip_alloc: p->ourip is: 61.122.x.x
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4114 transmit_register: We have just initialised p by calling sip_alloc()
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4115 transmit_register: p->ourip is: 61.122.x.x
Nov 14 12:19:20 NOTICE[25262592]: chan_sip.c:4152 transmit_register: Values used for registration:
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4164 transmit_register: We are about to call ast_sip_ouraddrfor()
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4165 transmit_register: p->ourip is: 61.122.x.x
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4171 transmit_register: We have just called ast_sip_ouraddrfor()
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4172 transmit_register: p->ourip is: 0.0.0.0
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4183 transmit_register: Scheduled a timeout # 103
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4211 transmit_register: We are about to transmit
Nov 14 12:19:20 DEBUG[25262592]: chan_sip.c:4213 transmit_register: p->ourip is: 0.0.0.0
11 headers, 0 lines
Reliably Transmitting:
REGISTER sip:fwd.pulver.com SIP/2.0
Via: SIP/2.0/UDP 0.0.0.0:5060;branch=z9hG4bK5c894353
From: <sip:register => 12345@fwd.pulver.com>;tag=as032dde87
To: <sip:register => 12345@fwd.pulver.com>
Call-ID: 675326dd041cac2a766afb8169a60ee3@61.122.x.x
CSeq: 153 REGISTER
User-Agent: Asterisk PBX
Expires: 120
Contact: <sip:s@0.0.0.0>
Event: registration
#################### End of console log ####################

Contents of /etc/asterisk/sip.conf ...
========================================
[general]
port=5060
context=default                 ; Default context for incoming calls
srvlookup=yes
nat=no
;
register => 12345:blah@fwd.pulver.com
;
; Nothing else in here!
;
========================================

interface/address information for the host running Asterisk follows ...

# ifconfig -u
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
       inet6 ::1 prefixlen 128
       inet6 fe80::1 prefixlen 64 scopeid 0x1
       inet 127.0.0.1 netmask 0xff000000
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1454
       inet6 fe80::230:65ff:fe50:1888 prefixlen 64 scopeid 0x4
       inet 61.122.x.x netmask 0xfffffff8 broadcast 61.122.x.x
       ether 00:30:65:xx:xx:xx
       media: autoselect (100baseTX <full-duplex>) status: active
       supported media: none autoselect 10baseT/UTP <half-duplex> 10baseT/UTP <full-duplex> 10baseT/UTP <full-duplex,hw-loopback> 100baseTX <half-duplex> 100baseTX <full-duplex> 100baseTX <full-duplex,hw-loopback>
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1454
       inet6 fe80::250:fcff:fecf:6e9c prefixlen 64 scopeid 0x6
       inet 192.168.x.x netmask 0xffffff00 broadcast 192.168.x.x
       ether 00:50:fc:xx:xx:xx
       media: autoselect (100baseTX <full-duplex>) status: active
       supported media: autoselect 10baseT/UTP <half-duplex> 10baseT/UTP <full-duplex> 100baseTX <half-duplex> 100baseTX <full-duplex>

thanks for your patience
regards
benjk

edited on: 11-14-04 03:19

edited on: 11-14-04 03:20

By: benjk (benjk) 2004-11-14 02:22:47.000-0600

I have now looked into ast_sip_ouraddrfor() a bit further and I have come to the conclusion that there is an error in logic, probably as a result of false assumptions what the function returns under what circumstances.

When transmit_register() calls ast_sip_ouraddrfor() it assumes that it must substitute p->ourip if the return value is not zero and this assumption is wrong in the event that ast_sip_ouraddrfor() has called ast_ouraddrfor().

here is a commented version of ast_sip_ouraddrfor() to show what the three possible scenarios are:

#############################################################################
static int ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us)
{
        ast_log(LOG_DEBUG, "Entered ast_sip_ouraddrfor()\n");
       /*
        * 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 externip is defined and target address is not local
        * then use externip as our address
        * ------------------------------------------------------
        */
       if (localaddr && externip.sin_addr.s_addr &&
          ast_apply_ha(localaddr, &theirs)) {
               char iabuf[INET_ADDRSTRLEN];
               memcpy(us, &externip.sin_addr, sizeof(struct in_addr));
               ast_inet_ntoa(iabuf, sizeof(iabuf), *(struct in_addr *)&them->s_addr);
               ast_log(LOG_DEBUG, "Target address %s is not local, substituting externip\n", iabuf);
       }
       /* ------------------------------------------------------
        * Otherwise, if bindaddr is not 0.0.0.0
        * then use bindaddr as our address
        * ------------------------------------------------------
        */
       else if (bindaddr.sin_addr.s_addr) {
               char iabuf2[INET_ADDRSTRLEN];
               memcpy(us, &bindaddr.sin_addr, sizeof(struct in_addr));
               ast_inet_ntoa(iabuf2, sizeof(iabuf2), *(struct in_addr *)&bindaddr.sin_addr);
               ast_log(LOG_DEBUG, "Bindaddr %s is not 0.0.0.0, substituting bindaddr\n", iabuf2);
       }
       /* ------------------------------------------------------
        * Otherwise, if bindaddr is 0.0.0.0
        * then call ast_ouraddfor() to determine our address
        * and use the return value as our own return value
        * ------------------------------------------------------
        */
       else {
               ast_log(LOG_DEBUG, "Calling ast_ouraddrfor() to determine our address, no address substitution\n");
               return ast_ouraddrfor(them, us);
       }
       /* ------------------------------------------------------
        * If we are here, that means we just substituted either
        * externip or bindaddr and we return zero in this case
        * ------------------------------------------------------
        */
       ast_log(LOG_DEBUG, "Leaving ast_sip_ouraddrfor(), returning 0\n");
       return 0;
}
#############################################################################

Now, if ast_sip_ouraddrfor() calls ast_ouraddrfor(), then in my (previously documented) case, it does not return 0, because ast_ouraddrfor() doesn't return 0.

However, ast_sip_ouraddrfor() takes anything other than zero as a trigger to override p->ourip with bindaddr (0.0.0.0) ...

#############################################################################
               if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
                       memcpy(&p->ourip, &bindaddr.sin_addr, sizeof(p->ourip));
#############################################################################

If that had been the intention, why would we have bothered to indirectly call ast_ouraddr() before?!

This is where the bug is. There needs to be an additional check for the scenario when ast_sip_ouraddrfor() has called ast_ouraddrfor() and if it did, then p->ourip must not be overwritten with bindaddr.

I am not going to attempt to make a change to this respect myself now, because I prefer to leave that up to somebody more experienced. As this example shows, bugs can be introduced by somebody adding stuff without fully understanding what all the bits and pieces do.

Now, one thing I would like to suggest though is to document return values of functions in the code, and preferably also the input parameters.

In a former life when I was involved in software development, we used a methodology developed by IBM, called VDM (for Vienna Development Method). Now, this was rather complex and not always easy to understand on the detail level. However, the principle behind VDM was very simple and powerful:

1) all parameters entering a function or procedure must be documented as pre-conditions

2) all parameters altered or returned when leaving a function or procedure must be documented as post-conditions

3) anything that doesn't match either #1 or #2 must be documented as an error-condition

I can see that Asterisk code has a total lack of even any attempt to document this sort of thing and I can assure from experience that even without knowing anything more about VDM than the above three rules, adhering to those rules will prevent bugs like the one I have documented above and it will also go a long way for newcomers to understand the code and be able to contribute new code.

just my 2 cents
regards
benjk

edited on: 11-14-04 02:26

By: benjk (benjk) 2004-11-14 03:52:24.000-0600

One more thing ...

transmit_register() may not be the only place affected. the same assumptions may have led to similar bugs elsewhere, so it may be worthwhile checking that out.

By: Olle Johansson (oej) 2004-11-14 10:23:40.000-0600

Benjk: THis could be an os/x problem. The acl.c doesn't have any ifdefs for OS/X, check that it works correctly.

By: Olle Johansson (oej) 2004-11-16 12:07:20.000-0600

Moving this bug to "portability/MAC OS/X" since it now seems to be a problem with the routing routines in acl.c on a Darwin system.

By: Mark Spencer (markster) 2004-11-16 17:02:24.000-0600

And as far as I'm concerned this is "minor" since it only affects OSX

By: Olle Johansson (oej) 2004-12-12 15:57:57.000-0600

OK, who has a patch for this? Anyone? Is it still a problem? Benjk: Mail me or find me on IRC to discuss a solution...

By: sailer (sailer) 2004-12-18 13:38:56.000-0600

oej: if the current ast_ouraddrfor routine in acl.c indeed doesn't work on MacOSX, then the patch attached to Bug ID 0003084, which replaces ast_ouraddrfor by a simpler and hopefully more portable version, might help.

By: twisted (twisted) 2005-01-04 01:16:31.000-0600

Is this still an issue?  benjk?  oej?  Any outcome of the request for email/irc discussion?

By: Mark Spencer (markster) 2005-01-09 03:57:11.000-0600

This should already be fixed in CVS head.  Feel free to reopen if it isn't.