[英]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.