Dlaczego / proc / net / tcp6 reprezentuje :: 1 jako :: 100: 0

13

Pisałem narzędzie do sprawdzania / proc / net / tcp i tcp6 pod kątem aktywnych połączeń, ponieważ jest szybsze niż parsowanie danych wyjściowych netstat.

Ponieważ tak naprawdę nie mam włączonej obsługi IPv6, użyłem głównie hosta lokalnego jako punktu odniesienia. Oto kopia mojego / proc / net / tcp6

sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
 0: 00000000000000000000000000000000:006F 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 19587 1 ffff880262630000 100 0 0 10 -1
 1: 00000000000000000000000000000000:0050 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 22011 1 ffff880261c887c0 100 0 0 10 -1
 2: 00000000000000000000000000000000:0016 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 21958 1 ffff880261c88000 100 0 0 10 -1
 3: 00000000000000000000000001000000:0277 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 28592 1 ffff88024eea0000 100 0 0 10 -1

Oto pasujący netstat -6 -pant

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp6       0      0 :::111                  :::*                    LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 ::1:631                 :::*                    LISTEN      -      

Wpisy 0-3 z tcp6 odpowiadają :: :: (wszystkie ipv6), ale pozycja 4 jest podobno odpowiednim wpisem dla :: 1.

Tutaj jestem zdezorientowany ...

00000000000000000000000001000000 => 0000: 0000: 0000: 0000: 0000: 0000: 0100: 0000 => :: 100: 0

Kiedy uruchamiam :: 1 przez jakiś kod, aby wygenerować pełną reprezentację szesnastkową, otrzymuję:

import binascii
import socket
print binascii.hexlify(socket.inet_pton(socket.AF_INET6, '::1'))
00000000000000000000000000000001

Nie mogę programowo wyrównać tych dwóch wartości, ponieważ nie pasują one (oczywiście). Dlaczego się nie zgadzają? Dlaczego jądro myśli :: 100: 0 to :: 1?

gregswift
źródło

Odpowiedzi:

11

Wynika to z sprzecznej z intuicją kolejności bajtów w /proc/net/tcp6. Adres jest obsługiwany jako cztery słowa składające się z czterech bajtów każdy. W każdym z tych czterech słów cztery bajty są zapisane w odwrotnej kolejności.

2001:0db8       :: 0123:4567:89ab:cdef would thus come out as:
B80D 0120 00000000 6745 2301 EFCD AB89 (with spaces inserted for clarity).

Jest to prawdopodobnie spowodowane różnicami endianizmu. Większość komputerów w dzisiejszych czasach korzysta z IA32 lub AMD64, które używają odwrotnego endianizmu niż IP. Nie mam żadnych innych systemów do przetestowania, aby dowiedzieć się, czy możesz polegać na / proc / net / tcp6, zawsze tak wyglądającym. Ale sprawdziłem, że tak jest zarówno w przypadku architektur IA32, jak i AMD64.

kasperd
źródło
Dobra odpowiedź, ale może być lepiej podać więcej wyjaśnień. Twoje drugie zdanie nie jest tak jasne, jak mogłoby być, myślę, że jedynym powodem, dla którego miało sens, było to, że ktoś inny wyjaśnił mi to inaczej.
gregswift
@gregswift, ponieważ OP nigdy nie podjął działania, może mógłbyś to edytować samodzielnie? To dobra odpowiedź na dobre pytanie i ta część informacji byłaby cenna dla IMO.
André Chalella,
@kasperd dokonał edycji wczoraj. Właśnie zmieniłem przykład i dodałem trochę formatowania, aby, mam nadzieję, zapewnić jakikolwiek dodatkowy kontekst
gregswift
3

Znaleziono ten moduł perla przeznaczony do analizowania / proc / net / tcp http://search.cpan.org/~salva/Linux-Proc-Net-TCP-0.05/lib/Linux/Proc/Net/TCP.pm Cytuje dokumentacja jądra, jak pokazano poniżej.

This document describes the interfaces /proc/net/tcp and
/proc/net/tcp6.  Note that these interfaces are deprecated in favor
of tcp_diag.

These /proc interfaces provide information about currently active TCP
connections, and are implemented by tcp4_seq_show() in
net/ipv4/tcp_ipv4.c and tcp6_seq_show() in net/ipv6/tcp_ipv6.c,
respectively.

It will first list all listening TCP sockets, and next list all
established TCP connections. A typical entry of /proc/net/tcp would
look like this (split up into 3 parts because of the length of the
line):

46: 010310AC:9C4C 030310AC:1770 01 
|      |      |      |      |   |--> connection state
|      |      |      |      |------> remote TCP port number
|      |      |      |-------------> remote IPv4 address
|      |      |--------------------> local TCP port number
|      |---------------------------> local IPv4 address
|----------------------------------> number of entry

00000150:00000000 01:00000019 00000000  
  |        |     |     |       |--> number of unrecovered RTO timeouts
  |        |     |     |----------> number of jiffies until timer expires
  |        |     |----------------> timer_active (see below)
  |        |----------------------> receive-queue
  |-------------------------------> transmit-queue

1000        0 54165785 4 cd1e6040 25 4 27 3 -1
|          |    |     |    |     |  | |  | |--> slow start size threshold, 
|          |    |     |    |     |  | |  |      or -1 if the threshold
|          |    |     |    |     |  | |  |      is >= 0xFFFF
|          |    |     |    |     |  | |  |----> sending congestion window
|          |    |     |    |     |  | |-------> (ack.quick<<1)|ack.pingpong
|          |    |     |    |     |  |---------> Predicted tick of soft clock
|          |    |     |    |     |              (delayed ACK control data)
|          |    |     |    |     |------------> retransmit timeout
|          |    |     |    |------------------> location of socket in memory
|          |    |     |-----------------------> socket reference count
|          |    |-----------------------------> inode
|          |----------------------------------> unanswered 0-window probes
|---------------------------------------------> uid

timer_active:
0  no timer is pending
1  retransmit-timer is pending
2  another timer (e.g. delayed ack or keepalive) is pending
3  this is a socket in TIME_WAIT state. Not all fields will contain 
 data (or even exist)
4  zero window probe timer is pending
Sanxiago
źródło
0

Przetwarzam / proc / net / tcp, także / tcp6, / udp6 na Androida i to są moje proste metody konwersji w Javie. Dziękuję kasperd za poprowadzenie mnie do tego rozwiązania.

/**B80D01200000000067452301EFCDAB89 -> 2001:0db8:0000:0000:0123:4567:89ab:cdef
 * */
public static String toRegularHexa(String hexaIP){
    StringBuilder result = new StringBuilder();
    for(int i=0;i<hexaIP.length();i=i+8){
        String word = hexaIP.substring(i,i+8);
        for (int j = word.length() - 1; j >= 0; j = j - 2) {
            result.append(word.substring(j - 1, j + 1));
            result.append((j==5)?":":"");//in the middle
        }
        result.append(":");
    }
    return result.substring(0,result.length()-1).toString();
}
/**0100A8C0 -> 192.168.0.1*/
public static String hexa2decIPv4 (String hexa) {
    StringBuilder result = new StringBuilder();
    //reverse Little to Big
    for (int i = hexa.length() - 1; i >= 0; i = i - 2) {
        String wtf = hexa.substring(i - 1, i + 1);
        result.append(Integer.parseInt(wtf, 16));
        result.append(".");
    }
    //remove last ".";
    return result.substring(0,result.length()-1).toString();
}
/**0000000000000000FFFF00008370E736 -> 0.0.0.0.0.0.0.0.0.0.255.255.54.231.112.131
  0100A8C0 -> 192.168.0.1
*/
public static String hexa2decIP (String hexa) {
    StringBuilder result = new StringBuilder();
    if(hexa.length()==32){
        for(int i=0;i<hexa.length();i=i+8){
            result.append(hexa2decIPv4(hexa.substring(i, i + 8)));
            result.append(".");
        }
    }else {
        if(hexa.length()!=8){return "0.0.0.0";}
        return hexa2decIPv4(hexa);
    }
    //remove last ".";
    return result.substring(0,result.length()-1).toString();
}

/**Simple hexa to dec, for ports 
 * 01BB -> 403
 * */
public static String hexa2decPort(String hexa) {
    StringBuilder result = new StringBuilder();
    result.append(Integer.parseInt(hexa, 16));
    return result.toString();
}
Jan Tancibok
źródło
Czy to odpowiada na pytanie?
Andrew Schulman
Czy powinienem to usunąć? Być może pomaga to komuś, kto w przyszłości będzie analizował IPv6, lub ktoś może lepiej zrozumieć patrząc na prawdziwy kod.
Jan Tancibok
Nikt w grupie docelowej prawdopodobnie nie będzie programował w Javie ani w żadnym innym języku.
Michael Hampton
@MichaelHampton To przesada. Są ludzie, którzy zajmują się zarówno administracją, jak i rozwojem systemu. Jestem jednym z nich. (Chociaż minęło 9 lat, odkąd ostatnio grałem w Javie.)
kasperd
@kasperd Chodzi o to, że ludzie nie zamierzają przychodzić do Server Fault po próbki kodu. To druga strona. :)
Michael Hampton