在下列情况下是否可以提取目标和源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);
}
答案 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)。