IP-адрес от sk_buff
Я пишу модуль ядра, который регистрирует перехватчик netfilter. Я пытаюсь получить IP-адрес вызывающего абонента, используя sk_buff->saddr
член. Есть ли способ получить IP-адрес в удобочитаемом формате iexxxx?
Я нашел функцию, inet_ntop()
но, похоже, она недоступна в заголовках ядра. Как преобразовать \ xC0 \ xA8 \ x00 \ x01 в 192.168.0.1?
Ответов (6)6
В include / linux / kernel.h определены два макроса.
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])
В исходных кодах ядра есть множество примеров, в которых они используются для печати IP-адресов в удобочитаемом формате. Например:
printk(KERN_DEBUG "Received packet from source address: %d.%d.%d.%d!\n",NIPQUAD(iph->saddr));
Надеюсь это поможет.
Вы можете использовать strtol для преобразования каждой части в целочисленную форму.
Простой. IP-адрес в формате «xxxx» не зря называется пунктирной четверкой. Каждое число представляет собой байт, всего в вашем адресе 4 байта.
Итак, с 4-байтовым адресом вы просто напечатаете десятичное значение каждого байта.
Быстрый и грязный пример (замените printf на выбранную вами функцию вывода):
unsigned char *addr = (unsigned char*)sk_buff->addr;
printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[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://www.kernel.org/doc/Documentation/printk-formats.txt