Pergunta

Estou escrevendo um módulo do kernel que registra um gancho netfilter. Eu estou tentando obter o endereço IP do autor da chamada, utilizando o membro sk_buff->saddr. Existe uma maneira eu posso obter o IP em legível ou seja, formato humano x.x.x.x?

Eu encontrei a função inet_ntop() mas não parece estar disponível em cabeçalhos do kernel. Como faço para converter \ xC0 \ xA8 \ x00 \ x01 para 192.168.0.1?

Foi útil?

Solução

Existem dois macros definido em include / linux / kernel.h

NIPQUAD para IPv4 endereços e NIP6 para IPv6 endereços.

#define NIPQUAD(addr) \
    ((unsigned char *)&addr)[0], \
    ((unsigned char *)&addr)[1], \
    ((unsigned char *)&addr)[2], \
    ((unsigned char *)&addr)[3]

#define NIP6(addr) \
    ntohs((addr).s6_addr16[0]), \
    ntohs((addr).s6_addr16[1]), \
    ntohs((addr).s6_addr16[2]), \
    ntohs((addr).s6_addr16[3]), \
    ntohs((addr).s6_addr16[4]), \
    ntohs((addr).s6_addr16[5]), \
    ntohs((addr).s6_addr16[6]), \
    ntohs((addr).s6_addr16[7])

Há amplos exemplos nas fontes do kernel que fazem uso delas para imprimir endereços IP em formato legível. Por exemplo:

printk(KERN_DEBUG "Received packet from source address: %d.%d.%d.%d!\n",NIPQUAD(iph->saddr));

Espero que isso ajude.

Outras dicas

Você deve usar a PI4% estendeu especificadores de formato fornecidos pelo printk ():

printk(KERN_DEBUG "IP addres = %pI4\n", &local_ip);

printk pode lidar com isso diretamente:

endereços IPv4:

%pI4    1.2.3.4
%pi4    001.002.003.004
%p[Ii]4[hnbl]

For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4'
specifiers result in a printed address with ('i4') or without ('I4')
leading zeros.

The additional 'h', 'n', 'b', and 'l' specifiers are used to specify
host, network, big or little endian order addresses respectively. Where
no specifier is provided the default network/big endian order is used.

Passed by reference.

Os endereços IPv6:

%pI6    0001:0002:0003:0004:0005:0006:0007:0008
%pi6    00010002000300040005000600070008
%pI6c   1:2:3:4:5:6:7:8

For printing IPv6 network-order 16-bit hex addresses. The 'I6' and 'i6'
specifiers result in a printed address with ('I6') or without ('i6')
colon-separators. Leading zeros are always used.

The additional 'c' specifier can be used with the 'I' specifier to
print a compressed IPv6 address as described by
http://tools.ietf.org/html/rfc5952

Passed by reference.

Referência: https://www.kernel.org/doc/Documentation/ printk-formats.txt

Simples. O endereço IP no formato "x.x.x.x" é chamado pontilhada-quad por uma razão. Cada número representa um byte, para um total de 4 bytes em seu endereço.

Assim, com o endereço de 4 bytes, você poderia simplesmente imprimir o valor decimal de cada byte.

Rápido e exemplo suja (substitua printf com sua função de escolha de saída):

unsigned char *addr = (unsigned char*)sk_buff->addr;
printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);

Você pode usar strtol para converter cada peça a ele de número inteiro formulário.

/* Convinience union to __be32 to ip address  */
union ip_address {
    u8 a[4];
    __be32 saddr;
};

Endereço IP pode ser obtido a [0] .a [1] .a [2] .a [3]

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top