2009-02-25 152 views
10

我在寫一個內核模塊,它註冊了一個netfilter鉤子。我試圖通過使用sk_buff-> saddr成員來獲取調用者的IP地址。有沒有一種方法可以讓我的IP以可讀的形式出現,即x.x.x.x格式?sk_buff的IP地址

我找到函數inet_ntop(),但它似乎在內核頭文件中不可用。如何將\ xC0 \ xA8 \ x00 \ x01轉換爲192.168.0.1?

+0

inet_ntop()和它的兄弟inet_pton()實際上是在arpa/inet.h中,我正在尋找內核實現。 – 2009-02-25 05:07:09

+0

ummm,netfilter的日誌目標必須這樣做......我會看那裏。 – derobert 2009-02-25 05:56:21

+0

&Rohit:說實話,如果你不知道如何格式化字符串中的字節,那麼你可能不應該編寫一個內核模塊。首先嚐試一些用戶空間的東西。 – 2009-04-02 15:30:54

回答

12

有在定義了兩個宏包括/ LINUX/kernel.h當

NIPQUAD用於IPv6地址的IPv4地址和NIP6。

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

有內核源的利用這些打印的IP地址在人類可讀的格式充足的例子。例如:

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

希望這會有所幫助。

0

您可以使用strtol將每一塊轉換爲整數形式。

2

簡單。出於某種原因,「x.x.x.x」格式的IP地址稱爲虛線四方形。每個數字表示一個字節,在您的地址中總共有4個字節。

因此,使用4字節地址,您只需打印每個字節的十進制值。

快速和骯髒的例子(與您選擇的輸出函數printf的替換):

unsigned char *addr = (unsigned char*)sk_buff->addr; 
printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); 
0
/* Convinience union to __be32 to ip address */ 
union ip_address { 
    u8 a[4]; 
    __be32 saddr; 
}; 

IP地址可以得到一個[0] .A [1] .A [2] .A [3]

11

您應該使用的printk()提供的%PI4擴展格式說明:

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

的printk可以直接處理這個問題:

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. 

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. 

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