如何在C / C ++中接收原始的第2层数据包?

时间:2010-08-19 22:32:17

标签: c++ c sockets posix vxworks

如何在POSIXy C ++中接收第2层数据包?数据包只有src和dst MAC地址,类型/长度和自定义格式的数据。它们不是TCP或UDP或IP或IGMP或ARP或其他 - 它们是由硬件人员给我的家庭酿造格式。

我的socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)永远不会从recvfrom()返回。

我可以发送正常,无论我在网络堆栈中使用什么选项,我都无法接收。

(平台是VxWorks,但我可以翻译POSIX或Linux或其他......)

接收代码(当前的化身):

 int s;

 if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) {
  printf("socket create error.");
      return -1;
 }

   struct ifreq          _ifr;   
   strncpy(_ifr.ifr_name, "lltemac0", strlen("lltemac0"));
   ioctl(s, IP_SIOCGIFINDEX, &_ifr);

   struct sockaddr_ll _sockAttrib;
   memset(&_sockAttrib, 0, sizeof(_sockAttrib));
   _sockAttrib.sll_len      = sizeof(_sockAttrib);
   _sockAttrib.sll_family   = AF_PACKET;
   _sockAttrib.sll_protocol = IFT_ETHER;
   _sockAttrib.sll_ifindex  = _ifr.ifr_ifindex;
   _sockAttrib.sll_hatype   = 0xFFFF;
   _sockAttrib.sll_pkttype  = PACKET_HOST;
   _sockAttrib.sll_halen    = 6;
   _sockAttrib.sll_addr[0]  = 0x00;
   _sockAttrib.sll_addr[1]  = 0x02;
   _sockAttrib.sll_addr[2]  = 0x03;
   _sockAttrib.sll_addr[3]  = 0x12;
   _sockAttrib.sll_addr[4]  = 0x34;
   _sockAttrib.sll_addr[5]  = 0x56;
   int _sockAttribLen = sizeof(_sockAttrib);


 char packet[64];
 memset(packet, 0, sizeof(packet));

   if (recvfrom(s, (char *)packet, sizeof(packet), 0,
                (struct sockaddr *)&_sockAttrib, &_sockAttribLen) < 0)
   {
      printf("packet receive error.");
   }

   // code never reaches here

5 个答案:

答案 0 :(得分:4)

我认为这样做的方法是编写自己的网络服务,该服务绑定到VxWorks网络堆栈中的MUX层。这在VxWorks网络程序员指南中得到了相当详细的记录,而且我已经做了很多次。

可以配置自定义网络服务,以使用MUX_PROTO_SNARF服务类型查看网络接口上收到的所有第2层数据包,这是Wind River自己的WDB协议的工作方式,或具有特定协议类型的数据包。

还可以通过编写位于网络服务和套接字API之间的自定义套接字后端,为自定义网络服务添加套接字接口。如果您乐意在网络服务中进行应用程序处理,则不需要这样做。

您还没有说过您正在使用哪个版本的VxWorks,但我认为以上适用于VxWorks 5.5.x和6.x

答案 1 :(得分:3)

您是否尝试按htons(ETH_P_ALL)中的规定将套接字协议设置为packet(7)?你正在做什么与IP没什么关系(尽管IPPROTO_RAW可能是一些通配符值,不知道)

答案 2 :(得分:1)

我认为这将是一个比你预期更难解决的问题。鉴于它根本不是IP(或者显然任何其他协议都可以识别),我认为你不能完全用用户级代码解决你的问题。在Linux上,我认为您需要编写自己的device agnostic interface驱动程序(可能使用NAPI)。在VxWorks下使用它几乎肯定是非平凡的(更像是从头开始完全重写而不是大多数人认为的端口)。

答案 3 :(得分:0)

您是否尝试通过Wireshark确认数据包实际上是从另一端发送的?

此外,为了进行调试,请询问您的硬件用户是否有调试引脚(您可以连接到逻辑分析仪),以便在收到数据包时可以断言。只是为了确保硬件正常运行。

答案 4 :(得分:0)

首先,您需要将协议指定为ETH_P_ALL,以便您的接口获取所有数据包。将套接字设置为混杂模式。然后在执行接收之前将RAW套接字绑定到接口。