简体   繁体   English

来自 sk_buff 的 IP 地址

[英]IP-address from sk_buff

I am writing a kernel module which registers a netfilter hook.我正在编写一个注册 netfilter 钩子的 kernel 模块。 I am trying to get the ip address of the caller by using the sk_buff->saddr member.我正在尝试使用sk_buff->saddr成员获取调用者的 ip 地址。 Is there a way I can get the IP in human readable iexxxx format?有没有办法以人类可读的 iexxxx 格式获取 IP?

I found the function inet_ntop() but it doesn't seem to be available in kernel headers.我找到了 function inet_ntop()但它似乎在 kernel 标头中不可用。 How do I convert \xC0\xA8\x00\x01 to 192.168.0.1?如何将 \xC0\xA8\x00\x01 转换为 192.168.0.1?

You should use the %pI4 extended format specifiers provided by printk():您应该使用 printk() 提供的 %pI4 扩展格式说明符:

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

There are two macros defined in include/linux/kernel.h include/linux/kernel.h 中定义了两个宏

NIPQUAD for ipv4 addresses and NIP6 for ipv6 addresses. NIPQUAD 用于 ipv4 地址, NIP6 用于 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])

There are ample examples in the kernel sources that make use of these to print ip addresses in human-readable format. kernel 源中有大量示例,它们利用这些示例以人类可读的格式打印 ip 地址。 For instance:例如:

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

Hope this helps.希望这可以帮助。

printk can handle this directly: printk 可以直接处理这个:

IPv4 addresses: 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 addresses: 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.

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

Simple.简单的。 The IP address in "xxxx" format is called dotted-quad for a reason. “xxxx”格式的 IP 地址被称为点分四边形是有原因的。 Each number represents a byte, for a total of 4 bytes in your address.每个数字代表一个字节,地址中总共有 4 个字节。

So, with the 4 byte address, you would simply print the decimal value of each byte.因此,使用 4 字节地址,您只需打印每个字节的十进制值。

Quick and dirty example (replace printf with your output function of choice):快速而肮脏的示例(用您选择的 output function 替换 printf):

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

You can use strtol to convert each piece to it's integer form.您可以使用strtol将每个部分转换为 integer 形式。

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

IP Address could be obtained a[0].a[1].a[2].a[3] IP 地址可以得到a[0].a[1].a[2].a[3]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM