来自sk_buff的IP地址

时间:2009-02-25 04:27:01

标签: c linux-kernel netfilter

我正在编写一个注册netfilter挂钩的内核模块。我试图通过使用sk_buff->saddr成员获取调用者的IP地址。有没有办法以人类可读的x.x.x.x格式获取IP?

我找到了函数inet_ntop()但它似乎在内核头文件中不可用。如何将\ xC0 \ xA8 \ x00 \ x01转换为192.168.0.1?

6 个答案:

答案 0 :(得分:16)

您应该使用printk()提供的%pI4扩展格式说明符:

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

答案 1 :(得分:13)

include / linux / kernel.h中定义了两个宏

用于ipv4地址的NIPQUAD和用于ipv6地址的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));

希望这有帮助。

答案 2 :(得分:3)

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://api-build.vitalware.com/metadata?xsd=1

答案 3 :(得分:2)

简单。 “x.x.x.x”格式的IP地址由于某种原因称为dotted-quad。每个数字代表一个字节,地址总共4个字节。

因此,使用4字节地址,您只需打印每个字节的十进制值。

快速而肮脏的例子(用您选择的输出功能替换printf):

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

答案 4 :(得分:0)

您可以使用strtol将每个部分转换为整数形式。

答案 5 :(得分:0)

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

IP地址可以获得[0] .a [1] .a [2] .a [3]