0

当我想在 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, 0, (struct sockaddr *)&recv, (socklen_t *)&addr_len)) < 0)
{
    perror("[ERROR] Receive data failed");
    return;
}
printf("ret: %d\n", ret);

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

4

1 回答 1

0

好吧,也许我们在 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", 1, 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 数据报可以做到这一点。

于 2021-01-22T03:38:13.463 回答