C 中的原始套接字,连接不是多余的吗?

Raw sockets in C, isn't connect redundant?

我正在编写一个简单的程序来创建以太网 I 帧并通过接口将其发送到指定的 MAC。

正如我所读,在 UNIX 中连接到套接字的过程有点像:

int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
struct sockaddr_ll sll;
/* populate sll with the target and interface info */
connect(sockfd, (struct sockaddr*)&sll, sizeof(sll));
write(sockfd, stuff, sizeof(stuff));
close(sockfd)

对我来说,事情是一个有效的 eth 框架,已经包含将数据包发送到目的地所需的一切。那么连接步骤不是多余的吗?我错过了什么?

祝你有愉快的一天。

连接不仅“冗余”,而且是一个错误——根据 Linux man 页面:

The connect(2) operation is not supported on packet sockets.

所以连接可能失败但实际上没有做任何事情。由于您忽略了连接的 return 值,因此您不会注意到失败。

如上所述,连接步骤错误。

我会在这个post中详细说明我是如何解决它的,以防有需要的人看到这个:(这是我的理解,请随时纠正我)

要在用户空间进行真正的原始通信,您必须了解三个概念:

  1. 套接字类似于文件描述符。
  2. 绑定套接字就像打开一个文件。
  3. 您无法读取或写入套接字,请让内核为您完成。

我遵循的过程如下:

int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
struct sockaddr_ll sll;
sll.sll_family = AF_PACKET;   
sll.sll_ifindex = index; //This is the index of your network card
//Can be obtained through ioctl with SIOCGIFINDEX
sll.sll_protocol = htons(ETH_P_ALL); 
bind(sockfd, (struct sockaddr*)&sll, sizeof(sll));
size_t send_len = write(sockfd, data, size);

如您所见,我们并没有真正使用连接,因为它确实是一个错误。

p.s。完整示例:https://github.com/TretornESP/RAWRP