como funciona o ping zero?

15

alguém pode explicar como funciona ping 0 e traduz para 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
    
por Rahul Patil 08.11.2013 / 11:20

1 resposta

18

Comportamento especial (e AFAICT) pouco documentado em iputils ping : you pingar você mesmo.

Se você ping 0 é o que acontece (muito editado e comentado para maior clareza):

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() não é POSIX, mas suponho que copie o comportamento de inet_addr() quando menos de 4 decimais pontilhados estão sendo convertidos. No caso de um número sem ponto único, ele é simplesmente armazenado no endereço de rede binário e 0x00000000 é equivalente ao formulário pontilhado 0.0.0.0 .

Você pode ver isso se você for strace (como 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.

Você também pode ver a mudança se ligar a uma interface específica :

# 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
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;
", 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.

Embora 0 possa ser tratado como 0.0.0.0 e um endereço de broadcast em muitos casos isso claramente não é o que o ping está fazendo . Em casos especiais, isso significa "o IP principal da interface em questão" (com algum tratamento extra para casos multicast / broadcast).

RFC 1122 §3.2.1.3 explica o comportamento: tanto o 0.0.0.0 quanto o endereço IP com a rede mascarada (o "número do host", por exemplo, 0.0.0.1 no caso de loopback) significa "este host nesta rede".

       (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.

Pelo menos no caso de 0 ou 0.0.0.0, é assim que o iputils ping se comporta, outros pings e outros SOs podem se comportar de maneira diferente. Por exemplo, o FreeBSD pinga 0.0.0.0 através da rota padrão (que eu não acho que seja um comportamento "correto").

ping 1 ou 0.0.0.1 não funcionam como esperado (não para mim, iputils-sss20101006 ).

    
por 08.11.2013 / 12:12