我写了一个程序,它使用原始套接字发送 TTL=1 的 UDP 数据包,当我在本地主机上运行这个程序时,我可以接收 ICMP 数据包。但是当我在 Planetlab 节点上运行它时,它无法接收 ICMP 数据包。
在planetlab 节点上,每个节点由多个用户共享,每个用户只分配一个虚拟切片。所以一般来说,只有当你有一个进程绑定到特定端口时,你才能从那个端口接收数据包,否则,随机数据包不能被系统传送到你的切片。
但是我下载了traceroute源代码并在planetlab节点上运行,它可以接收到ICMP TTL超过的数据包。
即:我使用 tcpdump 在 Planetlab 节点上捕获 ICMP 数据包。当我运行程序发送 TTL=1 的 UDP 数据包时,tcpdump 无法捕获 ICMP 数据包,但是当我使用 traceroute 发送 TTL=1 的 UDP 数据包时,tcpdump 可以捕获 ICMP 数据包。
这种差异的潜在原因是什么?
谢谢!
我的一些源代码:
if ((sendfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) {
perror("Failed in creating socket\n");
exit(1);
}
if ((recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("Failed in creating socket\n");
exit(1);
}
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_port = htons(src_port);
if ((bind(sendfd, (struct sockaddr *)& local_addr, sizeof(local_addr))) < 0) {
perror("Failed in binding socket\n");
exit(1);
}
if (setsockopt(sendfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
perror("Failed in setsockopt!\n");
exit(1);
}
if ((bind(recvfd, (struct sockaddr *)& local_addr, sizeof(local_addr))) < 0) {
perror("Failed in binding socket\n");
exit(1);
}
if (setsockopt(recvfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
perror("Failed in setsockopt!\n");
exit(1);
}
memset(&dst_addr, 0, sizeof(dst_addr));
dst_addr.sin_family = AF_INET;
dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
dst_addr.sin_port = htons(dst_port);
nr_bytes = sendto(sendfd, UDPpacket, pkt_len, 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr));
nr_bytes = recvfrom(recvfd, buf, 2000, 0, (struct sockaddr *)&dst_addr, &len);