2009-02-25 151 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