无法在 MacOS 中接收 GRE 数据包

问题描述

我想在MacOS上实现PPTP客户端时,我电脑的PPTP服务器收不到GRE包中封装的LCP包,操作系统是Catalina 10.15.2。

这是我用 C 编写的代码。

int ppp_fd;
      
if ((ppp_fd = socket(AF_INET,SOCK_RAW,IPPROTO_GRE)) <= 0)
{
     perror("[Error] Create a new socket failed");
     return;
}
struct sockaddr_in recv;
recv.sin_addr.s_addr = htonl(INADDR_ANY);
recv.sin_port = 0;
recv.sin_family = AF_INET;

char buffer[BUFSIZ];
int ret;
int addr_len =  sizeof(recv);
if((ret = recvfrom(ppp_fd,buffer,BUFSIZ,(struct sockaddr *)&recv,(socklen_t *)&addr_len)) < 0)
{
    perror("[ERROR] Receive data failed");
    return;
}
printf("ret: %d\n",ret);

Wireshark 可以正确捕获配置请求,但是代码似乎被阻塞并且什么也不打印。

解决方法

好吧,也许我们在MacOS中无法通过raw socket正常接收数据,但是Wireshark、tcpdump等软件可以捕获流量。因此,要解决上述问题,只需按照以下几个步骤操作即可。

  1. 使用 brew 等软件管理器安装 libpcap。
  2. 在源文件中包含头文件 #include<pcap/pcap.h>
  3. 举个简单的例子如下:

#include <stdio.h>
#include <pcap/pcap.h>      

void get_packet_cb(u_char *arg,const struct pcap_pkthdr *pkthdr,const u_char *packet)
{
      printf("Packet length: %d\n",pkthdr->len);
}

int main()      
{      
      
      char err_msg[PCAP_ERRBUF_SIZE] = {0};
      pcap_t *pcap_handler = pcap_open_live("vmnet8",65535,1,100,err_msg);

      if(pcap_handler == NULL){
            printf("[ERROR] %s\n",err_msg);
            return (-1);
      }
      struct bpf_program filter;
      if(pcap_compile(pcap_handler,&filter,"ip proto gre",0) == -1){
            pcap_perror(pcap_handler,"[ERROR] Compile the expression of filter failed");
            goto _close;
      }
      pcap_setfilter(pcap_handler,&filter);

      int id = 0;
      
      pcap_loop(pcap_handler,-1,get_packet_cb,NULL);

      
      _close:pcap_close(pcap_handler);
      return 0;
}



  1. 在终端中输入命令行 gcc source_name.c -lpcap -o output_name 进行编译和链接。

实际上,MacOS 中的许多协议无法正确接收,在我的实践中,至少 ICMP 数据报可以做到这一点。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...