jak działa ping zero?

16

Czy ktoś może wyjaśnić, jak ping 0działa i co to tłumaczy 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
Rahul Patil
źródło
Pingujesz siebie: P
Alko

Odpowiedzi:

21

Specjalne (i AFAICT) nieco niedokumentowane zachowanie w iputils ping : pingujesz siebie.

Jeśli ping 0tak się dzieje (mocno edytowane i komentowane dla jasności):

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()nie jest POSIX, ale zakładam, że kopiuje zachowanie, inet_addr()gdy konwertowane są mniej niż 4 kropki dziesiętne. W przypadku pojedynczego numeru bez kropek jest on po prostu zapisywany w binarnym adresie sieciowym i 0x00000000jest równoważny postaci kropkowanej 0.0.0.0.

Możesz to zobaczyć, jeśli strace(jako 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.

Możesz również zobaczyć zmianę, jeśli zamiast tego powiążesz z określonym interfejsem:

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

Podczas gdy 0 może być traktowane jako 0.0.0.0 i adres rozgłoszeniowy w wielu przypadkach , wyraźnie nie robi tego ping . W przypadkach specjalnych oznacza to „podstawowy adres IP danego interfejsu” (z pewną dodatkową obsługą przypadków multiemisji / emisji).

RFC 1122 §3.2.1.3 wyjaśnia zachowanie: zarówno 0.0.0.0, jak i adres IP z maskowaną siecią („numer hosta”, np. 0.0.0.1 w przypadku pętli zwrotnej) oznaczają „ten host w tej sieci”.

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

Przynajmniej w przypadku 0 lub 0.0.0.0 tak pingzachowuje się iputils , inne pingi i inne systemy operacyjne mogą zachowywać się inaczej. Na przykład FreeBSD pinguje 0.0.0.0 domyślną trasą (co nie uważam za zachowanie „poprawne”).

ping 1lub 0.0.0.1nie działają tak, jak się spodziewano (i tak nie dla mnie, iputils-sss20101006 ).

pan. spuratic
źródło
@ mr.spuratic .. że tego się spodziewałem .. dzięki
Rahul Patil
Nie jest to technicznie traktując go jako 0.0.0.0, a następnie kolejno specjalnej obudowy 0.0.0.0 oznaczać „Głównym IP interfejsu”? Co się stanie, jeśli wyślesz ping 0.0.0.0?
Random832,
@ Random832 tak, to prawda.
mr.spuratic