从C++缓冲区中提取IP地址(Linux套接字)

3

在以下的情况下,是否可以提取目标IP地址和源IP地址?我能够从in_buffer中提取以太网源地址和目标地址。如果可能的话,请给予建议。

sockaddr_ll sockaddr = sockaddr_ll();

sockaddr.sll_family = PF_PACKET;
sockaddr.sll_protocol = htons(ETH_P_ALL);
// is the interface index of the interface
sockaddr.sll_ifindex = if_nametoindex(argv[1]);
sockaddr.sll_hatype = 1;

boost::asio::io_service io_service;

raw_protocol_t::socket socket(io_service, raw_protocol_t(PF_PACKET, SOCK_RAW));
socket.bind(raw_endpoint_t(&sockaddr, sizeof(sockaddr)));

boost::asio::generic::raw_protocol::socket::receive_buffer_size option;
socket.get_option(option);

std::string in_buffer(option.value(), '\0');

raw_endpoint_t rep = raw_endpoint_t();

while (true)
{
   size_t len = socket.receive_from(boost::asio::buffer(&in_buffer[0], in_buffer.size()), rep);
}

抱歉,如果从您的代码中无法确定,那么IP地址是以二进制还是可读形式呈现的? - cadaniluk
我不太清楚。我正在尝试提取它们。 - Mazzy
如果您不知道它们的格式,那么提取它们就是不可能的。您至少需要了解地址的格式。您能否在没有任何进一步转换的情况下将它们打印出来?如果可以,它们就是字符串,即可读的。 - cadaniluk
我应该使用asio来提取它们还是采用其他方法? - Mazzy
1个回答

1

是的,您可以从原始数据包缓冲区中读取IP地址。当然,前提是数据包中有IP地址。如果协议是IP,则存储在in_buffer中的数据包包括完整的IP头。

请注意,接收到的数据可能包含任何协议。它可以是IPv4,然后您可以在其中找到IP地址,但它也可以是IPv6甚至更不常见的没有IP地址的协议。

假设接收到的数据包是包含IPv4数据的Ethernet-II数据包。那么您可以轻松获取IP地址:

  // Source addr
  printf("%d.%d.%d.%d", (unsigned char)(in_buffer[26]),
                        (unsigned char)(in_buffer[27]),
                        (unsigned char)(in_buffer[28]),
                        (unsigned char)(in_buffer[29]));
  // Destination addr
  printf("%d.%d.%d.%d", (unsigned char)(in_buffer[30]),
                        (unsigned char)(in_buffer[31]),
                        (unsigned char)(in_buffer[32]),
                        (unsigned char)(in_buffer[33]));

当然,这并不好,并且你需要检查缓冲区是否包含所期望的内容,但这取决于你。

那么魔数 26 - 32 是什么意思?

Ethernet II 标头大小为 14 字节。前 6 个字节是目标 MAC,接下来的 6 个字节是源 MAC,最后 2 个字节是以太类型。以太类型 0x0800 表示数据包含 IPv4。源 IPv4 地址位于 IP 标头中的偏移量为 12,目标 IP 位于偏移量为 16 的位置。因此,魔数 26 意味着从数据包开头的偏移量为 14(以太网标头大小)+12(IP 标头中的偏移量)。


源端口和目标端口是什么? - Mazzy
端口更加复杂。它们位于UDP或TCP的头部。您需要确定IP头的长度(通常为20个字节,但可能更长),识别有效载荷类型(位于IP头中偏移量为9的1个字节),以及如果是TCP或UDP,则从UDP或TCP头读取端口作为“无符号短整数”。请参见RFC中的头定义,或访问https://en.wikipedia.org/wiki/IPv4、https://en.wikipedia.org/wiki/Transmission_Control_Protocol和https://en.wikipedia.org/wiki/User_Datagram_Protocol。或者,您可以使用现有的头处理库,如http://research.wand.net.nz/software/libtrace.php。 - Zaboj Campula
1
@ZabojCampula,我相信缓冲区的索引存在错误。当您重新索引目标地址时,您从缓冲区的同一位置获取最后两个八位字节。 - Croolman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接