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

liw*_*ing 5 c sockets network-programming

这是一项任务,必须使用原始套接字.我需要编写一个简单的icmp ping程序.我用它作为基础http://www.pdbuchan.com/rawsock/icmp4.c.第127行是wlan0,Im使用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);
Run Code Online (Sandbox Code Playgroud)

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

编辑:我检查了这个原始套接字监听器,但它没有解决我的问题.

Ant*_*hys 7

我不认为你在使用IPPROTO_RAW时能得到答复.

你必须使用

socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
Run Code Online (Sandbox Code Playgroud)

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

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

看看真正的ping灵感.