Linux UDP 服务器 - 目标 IP 错误

Linux UDP server - Destination IP wrong

我有一个嵌入式 linux 设备可以侦听 UDP 数据包。 该设备有两个以太网接口,因此可以在两个接口上检索数据包。 在某些 UDP messages/packets 上,我必须针对接收它的接口做一些特定的事情。所以我需要检测哪个接口收到了数据包。

我在 Whosebug 上找到了展示如何从 IP_PKTINFO 中提取目标 IP 的帖子和示例。如果我一个一个地测试接口,这很好用。两个接口都连接,接收目的IP相同。

我注意到 ifindex 不一样,但是我不明白为什么 ipi_spec_dst 是一样的,当我在两个不同的接口上用两个不同的 IP 清楚地收到一个数据包时.

C/C++ 负责提取目的IP的代码:

    ssize_t byteCount=recvmsg(f_socket, &message, 0);
    if (byteCount==-1) {
        printf("%s",strerror(errno));
    }

    for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&message); 
         cmsg != NULL; 
         cmsg = CMSG_NXTHDR(&message, cmsg)) 
    {
        if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO) continue;
        struct in_pktinfo *pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
        char* destAddr = (char*) calloc(4, sizeof(char));
        destAddr = inet_ntoa(pi->ipi_spec_dst);
        std::cout << destAddr << " " << std::to_string(pi->ipi_ifindex) << std::endl;
    }

输出eth0连接:

172.20.55.9 4
172.20.55.9 4
172.20.55.9 4
...

输出eth0连接:

200.0.0.101 6
200.0.0.101 6
200.0.0.101 6
...

输出eth0和eth1连接:

172.20.55.9 6
172.20.55.9 4
172.20.55.9 6
172.20.55.9 4
...

预期输出:

200.0.0.101 6
172.20.55.9 4
200.0.0.101 6
172.20.55.9 4
...

首先,我不确定这是否是预期的,我认为不是,但我可能没有正确理解文档。

如果需要,我可以提供更多代码。

代码取自:

  1. Getting the destination address of UDP packet
  2. Get destination address of a received UDP packet


非常感谢任何帮助。谢谢。

-aln

我认为这几行有问题:

char* destAddr = (char*) calloc(4, sizeof(char));
destAddr = inet_ntoa(pi->ipi_spec_dst);
std::cout << destAddr << " " << std::to_string(pi->ipi_ifindex) << std::endl;

两个问题:

  • 您应该使用 ipi_addr 而不是 ipi_spec_dst(参见 man 7 ip
  • 你不需要 calloc 的东西(那是

    • 不够大,
    • 未正确初始化,
    • 未释放。)

您可以通过以下方式简化它:

printf("%s %d\n", inet_ntoa(pi->ipi_addr), pi->ipi_ifindex);

因此,要恢复,您的循环可能如下所示:

for (   struct cmsghdr *cmsg = CMSG_FIRSTHDR(&message); 
        cmsg != NULL; 
        cmsg = CMSG_NXTHDR(&message, cmsg)) 
{
    if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO) 
        continue;

    struct in_pktinfo *pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
    printf("%s %d\n", inet_ntoa(pi->ipi_addr), pi->ipi_ifindex);
}

我通过使用 ifindex 获取接口名称然后用于执行接口特定代码解决了这个问题。