【发布时间】:2014-07-06 15:12:16
【问题描述】:
我一直在尝试使用原始套接字发送 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 指向包缓冲区(buffer)中对应的headers,而payload指向L7数据的开始。
代码如下: { /* 处理请求。 */ ssize_t msg_len; int max_len = sizeof (buffer) - (payload - buffer); 诠释 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;
}
}
【问题讨论】:
-
如果数据包被 Wireshark 接收到,并不意味着它们没有被丢弃;但如果你检查了它就可以了。请准确提及您用于在 shell 中接收数据包的命令。
-
为了简单起见,我使用了 nc -l -u -p 2222。在远程机器上它工作正常。在本地机器上(使用原始套接字),什么都没有收到。
-
你能给出你用来发送数据包的代码吗?
-
代码如下:
-
显然这是上面的代码。无法将代码放入评论中...谢谢。
标签: linux sockets networking