Linux:在KVM下本地未收到原始套接字已发送数据包

时间:2014-05-18 17:00:02

标签: linux sockets networking

我一直在尝试使用原始套接字发送UDP数据包,但是,发送的数据包不会在本地接收。如果发送到远程目的地,则接收相同的分组。测试在KVM下进行。相同的测试似乎在Parallels下工作。

套接字设置为:

raw_socket = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));

附加了一个接收过滤器,并将其设置为混杂。正确接收数据包。发送的数据包在Wireshark中接收并正确分析。但是,本地程序(例如nc -l -u -p ...)不接收数据包。如果我将相同的数据包发送到远程目标,则会正确接收数据包。 Wireshark收到数据包这一事实表明它没有被任何iptables规则删除(我还检查了所有DROP规则计数器并且没有丢弃的数据包)。

似乎数据包已被路由但未被网络堆栈重新处理,如果这甚至是有意义的。

它应该是网络课程中的示例代码,目前,我在学生面前丢脸。希望他们都不在这个名单上; - )。

感谢任何帮助,       尤瓦。

关于代码的一些评论。为简洁起见,UDP校验和设置为0,IP校验和从头部计算。两者都由Wireshark验证(并且也由KVM上的远程机器接受)。代码解析消息并在收到的缓冲区上发送回复。 udp_hdr和ip_hdr指向数据包缓冲区(缓冲区)中的相应标头,而有效负载指向L7数据的开头。

这里是代码:          {             / *处理请求。 * /             ssize_t msg_len;             int max_len = sizeof(buffer) - (payload - buffer);             int tmp_port;             in_addr_t tmp_ip;             struct ether_addr tmp_ether;

        msg_len = parse_and_send (ctx, payload, size, max_len);
        if (msg_len < 0)
        {
           /* Error */
           error_print (ctx, "Failed to parse and construct answer.");
       continue;
        }
        if (msg_len == 0)
        {
           /* No message to send. */
           continue;
        }

        /* Switch sources & destinations and update payload lengths. */
        tmp_port = udp_hdr->dest;
        udp_hdr->dest = udp_hdr->source;
        udp_hdr->source = tmp_port;
        udp_hdr->len = htons (msg_len +
                              (payload - (const uint8_t*) udp_hdr));
        tmp_ip = ip_hdr->daddr;
        compute_udp_cksum (udp_hdr);

        ip_hdr->daddr = ip_hdr->saddr;
    ip_hdr->saddr = tmp_ip;
        ip_hdr->tot_len = htons (msg_len +
                                 (payload - (const uint8_t*) ip_hdr));
        compute_ip_cksum (ip_hdr);

        memcpy (tmp_ether.ether_addr_octet, ether_hdr->ether_dhost,
                sizeof (tmp_ether));
        memcpy (ether_hdr->ether_dhost, ether_hdr->ether_shost, ETH_ALEN);
        memcpy (ether_hdr->ether_shost, tmp_ether.ether_addr_octet,
                sizeof (tmp_ether));

        if (sendto (ctx->raw_socket,
                    &buffer, msg_len + (payload - buffer), 0,
                    (struct sockaddr*) &ll_addr, sizeof (ll_addr)) < 0)
        {
           ERROR_SYSTEM (ctx, "Sending packet");
           error_print (ctx, "Failed to send packet");
       continue;
        }
     }

1 个答案:

答案 0 :(得分:0)

让我们写下我们所知道的事实:

1-你告诉你可以在数据包捕获程序中看到数据包(例如Wireshark)

2-你告诉你在发送数据包时无法使用netcat接收数据包 loopback接口。

3-您告诉您在将数据包发送到远程计算机时可以收到数据包。

所以问题出在你的代码或本地机器上。我有一堆建议:

1-在另一台机器上测试代码,并将数据包发送到环回接口并尝试使用netcat捕获它们。

2-尝试使用netcat将一堆UDP数据包发送到本地接口,并使用另一个netcat实例接收它们并检查它是否有效;如果它有效,你知道问题在你的代码中,否则问题可能是因为你的本地机器。