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

时间:2016-01-26 11:00:40

标签: c++ sockets 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);
}

1 个答案:

答案 0 :(得分:1)

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

请注意,收到的数据可能包含任何协议。它可以是IPv4,然后你可以在那里找到IP地址,但它可以是IPv6,甚至是没有IP地址的更加模糊的协议。

假设接收的数据包是包含Ethernet-II数据的IPv4数据包。然后您可以轻松获取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?

以太网II头的大小为14个字节。前6个字节是目标MAC,接下来的6个字节是源MAC,后2个字节是ethertype。 Ethertype 0x0800表示数据包含IPv4。源IPv4地址在IP头中偏移12,目标IP在偏移16处。因此,幻数26表示从数据包开始偏移,其14(ethernetHeaderSize)+ 12(offsetInIPHeader)。