簡體   English   中英

通過原始套接字接收數據包

[英]Receiving packets via raw socket

我正在嘗試通過原始套接字接收以太網數據包。 但行為並不像預期的那樣。

代碼在這里。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <net/ethernet.h>
#include <linux/if_packet.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>
 
int32_t main(int32_t argc, int8_t *argv[])
{
   int32_t sock;
   int8_t buf[1522];
   int32_t ret;
   int32_t bytes;
 
   sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
   if (sock == -1)
   {
      printf("socket open failed\n");
      return 1;
   }
 
   ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, "ens193", (strlen("ens193")+1));
   if (ret == -1)
   {
      printf("interface binding failed\n");
      close(sock);
      return 1;
   }
 
   while(1)
   {
      bytes = recvfrom(sock, buf, 1522, 0, NULL, NULL);
      if (bytes < 0)
      {
         printf("error in recvfrom\n");
         exit;
      }
      printf("bytes = %d\n", bytes);
   }
 
   close(sock);
   return 0;
}

執行 output 在這里。

# ./a.out
[Nothing happening for a while]
bytes = 60
bytes = 42
bytes = 134
bytes = 118
bytes = 118
bytes = 118
bytes = 118
bytes = 118
bytes = 118
bytes = 66
...
...
...

但我認為接口實際上並沒有收到任何數據包。 如果我看到 ifconfig output,則 RX 計數沒有增加。 是因為我的代碼中遺漏了一些東西嗎? 如果你有什么好主意,請告訴我!

我查看了 tcpdump/libpcap 代碼並修改了我的代碼,如下所示。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>

/* Return the index of the given device name */
static int32_t iface_to_id(int32_t sk, int8_t *device)
{
   struct ifreq   ifr;
   int32_t  ret;

   memset(&ifr, 0, sizeof(struct ifreq));
   strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));

   ret = ioctl(sk, SIOCGIFINDEX, &ifr);
   if (ret < 0)
   {
      printf("failed to get index\n");
      return -1;
   }

   return ifr.ifr_ifindex;
}

/* Bint the socket to the given device */
static int32_t iface_bind_to_device(int32_t sk, int32_t ifindex, int32_t protocol)
{
   struct sockaddr_ll   sll;
   int32_t ret;

   memset(&sll, 0x0, sizeof(struct sockaddr_ll));
   sll.sll_family    = AF_PACKET;
   sll.sll_ifindex   = ifindex;
   sll.sll_protocol  = protocol;

   ret = bind(sk, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll));
   if (ret == -1)
   {
      return -1;
   }

   return 0;
}

int32_t main(int32_t argc, int8_t *argv[])
{
   int32_t sock;
   int8_t buf[1522];
   int32_t ifindex;
   int32_t ret;
   int32_t bytes;
   struct packet_mreq mr;

   sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
   if (sock == -1)
   {
      printf("socket open failed\n");
      return 1;
   }

   ifindex = iface_to_id(sock, "ens193");
   if (ifindex < 0)
   {
      close(sock);
      return 1;
   }

   ret = iface_bind_to_device(sock, ifindex, htons(ETH_P_ALL));
   if (ret < 0)
   {
      close(sock);
      printf("interface binding error\n");
      return 1;
   }

   while(1)
   {
      bytes = recvfrom(sock, buf, 1522, 0, NULL, NULL);
      if (bytes < 0)
      {
         printf("error in recvfrom\n");
         exit;
      }
      printf("received bytes = %d\n", bytes);
   }

   close(sock);
   return 0;
}

進行這樣的更改后,行為符合預期。 如果我向接口 ens193 發送 ping。 然后,我看到 output 如下所示。

# ./a.out
received bytes = 98
received bytes = 98

所以, htons(ETH_P_ALL) 不是問題。 似乎使用“setsockopt 和 SO_BINDTODEVICE”不是正確的方法。 現在,我的問題是 SO_BINDTODEVICE 是什么意思以及何時使用它。

如果有人對此有意見,請在此處添加。 我也會研究更多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM