c - 如何使用原始套接字在 C 中接收 ICMP 请求

标签 c sockets network-programming

这是一项任务,它必须与原始套接字一起使用。我需要编写一个简单的 icmp ping。 我以此为基础 http://www.pdbuchan.com/rawsock/icmp4.c .第 127 行是 wlan0,我使用的是 eth0。在第 290 行中,我编写了以下代码:

struct sockaddr_in rec;
  
unsigned char * pkt = (unsigned char *) malloc (IP_MAXPACKET * sizeof (unsigned char));

if (recvfrom (sd, (void*)pkt, IP4_HDRLEN + ICMP_HDRLEN+datalen , 0, NULL, (socklen_t*)sizeof (struct sockaddr)) < 0)  {
  perror ("recvfrom() failed ");
  exit (EXIT_FAILURE);
}
struct ip *ip = (struct ip *)pkt;
struct icmphdr *icmp = (struct icmphdr *)(pkt + IP4_HDRLEN);

printf("%s %s %d\n",(char*)inet_ntoa(*(struct in_addr*)&ip->ip_dst),
        (char*)inet_ntoa(*(struct in_addr*)&ip->ip_src),
        icmp->type);
free (pkt);

问题是 ip_dst 和 ip_src 显示为我机器的 IP,icmp 类型为 0 而不是 8。Wireshark 显示 icmp 回复和请求。 可能我的 recvfrom 是错误的,但我听说 linux 自己的 TCP/IP 可能正在处理数据包。如果是这样,解决方法是什么?

编辑:我检查了这个raw socket listener但这并没有解决我的问题。

最佳答案

我认为您在使用 IPPROTO_RAW 时无法得到回复。

你必须使用

socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);

使用 IPPROTO_ICMP,您只能发送一个 ICMP 数据包,而不是整个 IP 数据包。

然而,当接收时,您将获得整个 IP 数据包并且必须提取 ICMP 回复。请注意,您将获得发送到主机的所有 ICMP 数据包的副本,因此您必须过滤它们。

关于c - 如何使用原始套接字在 C 中接收 ICMP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13543554/

相关文章:

c++ - 如何检测TCP连接中网线被拔掉?

控制每个请求的名称解析服务器 (DNS) 地址

c++ - 在C/C++中检测内存IO以进行硬件仿真

c - execve args 未复制超出空字节

c++ - 如何在 C++ 中进行惰性构造?

对 recv() 感到困惑

algorithm - 网络流中跨 block 的字符串匹配

c++ - 运行程序时出现运行时错误,但使用调试器时却没有

c - 你如何在 C (STDIN) 中扫描重定向的文件?

ios - Socket.io session 管理?