¿Por qué / proc / net / tcp6 representa :: 1 como :: 100: 0?

13

Estaba escribiendo una utilidad para verificar / proc / net / tcp y tcp6 para conexiones activas, ya que es más rápido que analizar la salida de netstat.

Como en realidad no tengo habilitado ipv6, estaba utilizando principalmente localhost como mi punto de referencia. Aquí hay una copia de mi / 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

Aquí está el correspondiente 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      -      

Las entradas 0-3 de tcp6 corresponden con los :: 's (todos ipv6), pero la entrada 4 es supuestamente la entrada correspondiente para :: 1.

Aquí es donde estoy confundido ...

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

Cuando ejecuto :: 1 a través de algún código para generar la representación hexadecimal completa obtengo:

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

No puedo alinear programáticamente estos dos valores, porque no coinciden (obviamente). ¿Por qué no coinciden? ¿Por qué piensa el núcleo :: 100: 0 es :: 1?

gregswift
fuente

Respuestas:

11

Esto se debe al orden de bytes contraintuitivo /proc/net/tcp6. La dirección se maneja como cuatro palabras que constan de cuatro bytes cada una. En cada una de esas cuatro palabras, los cuatro bytes están escritos en orden inverso.

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

Esto probablemente se deba a las diferencias de endianness. En la actualidad, la mayoría de las PC usan IA32 o AMD64, que utilizan la resistencia opuesta a la que se diseñó con IP. No tengo otros sistemas con los que probar para averiguar si puede confiar en / proc / net / tcp6 siempre con ese aspecto. Pero verifiqué que es el caso en las arquitecturas IA32 y AMD64.

kasperd
fuente
Buena respuesta, pero podría ser mejor proporcionar más aclaraciones. Su segunda oración no es tan clara como podría ser, creo que la única razón por la que tenía sentido era que alguien más me lo había explicado de manera diferente.
gregswift 01 de
@gregswift ya que el OP nunca tomó medidas, ¿tal vez podría editar esto usted mismo? Esta es una buena respuesta a una buena pregunta y esta información sería valiosa en mi opinión.
André Chalella
@kasperd lo editó ayer. Acabo de reordenar el ejemplo y agregué algo de formato para poder proporcionar algún contexto adicional
gregswift
3

Encontré este módulo de Perl destinado al análisis / proc / net / tcp http://search.cpan.org/~salva/Linux-Proc-Net-TCP-0.05/lib/Linux/Proc/Net/TCP.pm Cita el documentación del núcleo como se muestra a continuación.

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
fuente
0

Estoy analizando / proc / net / tcp, también / tcp6, / udp6 en Android y estos son mis métodos simples para la conversión, en Java. Gracias Kasperd por guiarme a esta solución.

/**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
fuente
¿Responde esto la pregunta?
Andrew Schulman
¿Debo eliminarlo? Tal vez ayude a alguien que realizará el análisis de ipv6 en el futuro o alguien pueda comprender mejor el código real.
Jan Tancibok
Es probable que nadie en el público objetivo esté haciendo ninguna programación en Java o en cualquier otro lenguaje.
Michael Hampton
@MichaelHampton Eso es una exageración. Hay personas que realizan tanto la administración como el desarrollo del sistema. Yo soy uno de ellos. (Aunque han pasado 9 años desde la última vez que hice Java)
Kasperd
@kasperd El punto es que la gente no va a pensar en acudir a Server Fault para obtener ejemplos de código. Ese es el otro sitio. :)
Michael Hampton