Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

can anybody explain how does ping 0 works and it translate to 127.0.0.1.

[champu@testsrv ]$ ping 0
PING 0 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.013 ms

--- 0 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.013/0.026/0.039/0.013 ms
share|improve this question
    
You are pinging yourself :P –  Alko Nov 8 '13 at 10:34
    
@Alko there are many reason.. but main use for application testing.. –  Rahul Patil Nov 8 '13 at 10:42
add comment

1 Answer

up vote 9 down vote accepted

Special (and AFAICT) slightly under-documented behaviour in iputils ping: you ping yourself.

If you ping 0 this is what happens (heavily edited and commented for clarity):

if (inet_aton(target, &whereto.sin_addr)) == 1) {
    // convert string to binary in_addr
}
// inet_aton returns 1 (success) and leaves the `in_addr` contents all zero.

if (source.sin_addr.s_addr == 0) {    
    // determine IP address of src interface, via UDP connect(), getsockname()
}

// special case for 0 dst address
if (whereto.sin_addr.s_addr == 0)
        whereto.sin_addr.s_addr = source.sin_addr.s_addr;

inet_aton() isn't POSIX, but I'm assuming it copies the behaviour of inet_addr() when less than 4 dotted-decimals are being converted. In the case of a dot-less single number, it's simply stored into the binary network address, and 0x00000000 is equivalent to the dotted form 0.0.0.0.

You can see this if you strace (as root):

# strace -e trace=network ping  0
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(1025), 
    sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getsockname(4, {sa_family=AF_INET, sin_port=htons(58056),   
    sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
...
PING 0 (127.0.0.1) 56(84) bytes of data.

You can also see the change if you bind to a specific interface instead:

# strace -e trace=network ping -I eth0  0
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_BINDTODEVICE, "eth0\0", 5) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(1025), 
    sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getsockname(4, {sa_family=AF_INET, sin_port=htons(58408),    
    sin_addr=inet_addr("192.168.0.123")}, [16]) = 0
setsockopt(3, SOL_RAW, ICMP_FILTER,  ...)
[...]
PING 0 (192.168.0.123) from 192.168.0.123 eth0: 56(84) bytes of data.

While 0 may be treated as 0.0.0.0 and a broadcast address in many cases that's clearly not what ping is doing. It special-cases this to mean "the primary IP of the interface in question" (with some extra handling for multicast/broadcast cases).

RFC 1122 §3.2.1.3 explains the behaviour: both 0.0.0.0 and the IP address with the network masked off (the "host number", e.g. 0.0.0.1 in the case of loopback) mean "this host on this network".

       (a)  { 0, 0 }

            This host on this network.  MUST NOT be sent, except as
            a source address as part of an initialization procedure
            by which the host learns its own IP address.

            See also Section 3.3.6 for a non-standard use of {0,0}.

       (b)  { 0, <Host-number> }

            Specified host on this network.  It MUST NOT be sent,
            except as a source address as part of an initialization
            procedure by which the host learns its full IP address.

At least in the case of 0 or 0.0.0.0 that is how iputils ping behaves, other pings and other OSs may behave differently. For example FreeBSD pings 0.0.0.0 via the default route (which I don't think is "correct" behaviour).

ping 1 or 0.0.0.1 don't quite work as hoped though (not for me anyway, iputils-sss20101006).

share|improve this answer
    
@mr.spuratic.. that what I expected.. thanks –  Rahul Patil Nov 8 '13 at 11:47
    
+1 for going to the source! –  Michael Kjörling Nov 8 '13 at 12:33
    
Isn't it technically treating it as 0.0.0.0 and then subsequently special-casing 0.0.0.0 to mean "the primary IP of the interface"? What happens if you ping 0.0.0.0? –  Random832 Nov 8 '13 at 15:04
    
@Random832 yes, that's correct. –  mr.spuratic Nov 8 '13 at 15:59
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.