2009-02-25 5 views
10

Sto scrivendo un modulo del kernel che registra un hook netfilter. Sto cercando di ottenere l'indirizzo IP del chiamante usando il membro sk_buff-> saddr. C'è un modo per ottenere l'IP in formato leggibile dall'uomo, cioè il formato x.x.x.x?Indirizzo IP da sk_buff

Ho trovato la funzione inet_ntop() ma non sembra disponibile nelle intestazioni del kernel. Come faccio a convertire \ xC0 \ xA8 \ x00 \ x01 a 192.168.0.1?

+0

inet_ntop() e suo fratello inet_pton() sono in realtà in arpa/inet.h, sto cercando le implementazioni del kernel ora. –

+0

ummm, l'obiettivo del registro di netfilter deve farlo ... Io guarderei lì. – derobert

+0

& Rohit: ad essere onesti, se non sai come formattare i byte in una stringa del genere, probabilmente non dovresti scrivere un modulo del kernel. Prova prima alcune cose dello spazio utente. –

risposta

12

ci sono due macro definite in include/linux/kernel.h

NIPQUAD per gli indirizzi IPv4 e NIP6 per gli indirizzi IPv6.

#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]) 

Ci sono ampi esempi nelle sorgenti del kernel che fanno uso di questi per stampare gli indirizzi IP in formato leggibile. Ad esempio:

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

Spero che questo aiuti.

+9

Ora l'ho trovato. Per il beneficio di altri che potrebbero imbattersi in questo, 'NIPQUAD' è stato valutato dopo 2.6.38. Usa '% pI4' invece – pratikm

+0

Came attraverso questo più tardi. C'è ora 'in4_pton()' in /net/core/utils.c – BonBon

+0

@BonBon: 'in4_pton()' fa il contrario. –

0

È possibile utilizzare strtol per convertire ogni pezzo in forma intera.

+0

Sono quasi certo che esiste una macro che fa proprio questo, proprio non riesco a trovarlo ATM. –

2

Semplice. L'indirizzo IP nel formato "x.x.x.x" è chiamato punteggiato-quad per un motivo. Ogni numero rappresenta un byte, per un totale di 4 byte nel tuo indirizzo.

Quindi, con l'indirizzo a 4 byte, si stampa semplicemente il valore decimale di ogni byte.

esempio rapido e sporco (sostituire printf con la vostra funzione di uscita di scelta):

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

questo ha causato l'arresto anomalo del kernel – Rohit

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

indirizzo IP potrebbe essere ottenuto a [0] .a [1] .a [2] .a [3]

11

Si consiglia di utilizzare i% PI4 identificatori di formato esteso forniti da printk():

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

printk grado di gestire questo direttamente:

indirizzi IPv4: affronta

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

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. 

Riferimento: https://www.kernel.org/doc/Documentation/printk-formats.txt