gpt4 book ai didi

c - AF_PACKET 和以太网

转载 作者:太空狗 更新时间:2023-10-29 12:22:46 25 4
gpt4 key购买 nike

我对 AF_PACKET 套接字系列(用于 SOCK_RAW 套接字)与以太网 (IEEE 802.3) 的具体关系感到非常困惑。

目前我的理解:

  • 我了解 OSI 模型,以及第 2 层技术如何像以太网适合该模型。

  • 我知道 AF_PACKET 可以与 SOCK_RAW 套接字一起使用接收包含 14 字节以太网报头的数据报,后跟一些其他高层协议(protocol)报头,例如 IPv4、IPv6 等,其次是可选的传输层协议(protocol),如 TCP,以及终于是一个有效载荷。

  • 我知道您可以将 ETH_P_ALLETH_P_IP 等标志作为socket 的协议(protocol)参数让内核过滤数据包对你来说,只向你发送包含特定标题的数据包类型。

  • 我了解使用 AF_PACKET 系列创建的套接字可以接收或发送到类型为 sockaddr_ll 的端点,该类型与特定 MAC 地址(EUI-48 地址)相关联,以及特定的网络接口(interface)(例如 eth0 或其他)。

我不明白的地方:

  • 我不明白 AF_PACKET 是否应该专门用于以太网设备,而不是其他第 2 层技术,例如 Wifi、蓝牙、 token 环、Infiniband 等。

  • 我不明白以太网设备与使用 14 字节以太网 header 的第 2 层协议(protocol)之间的关系。以太网 header 为 14 字节,可以定义如下: struct eth_hdr { char dest_address[6];字符源地址[6]; uint16_t 以太类型; }; 换句话说,这个 header 是否仅用于物理以太网设备?似乎答案是,因为如果我在环回接口(interface)上使用AF_PACKET,我仍然会收到包含14 字节以太网 header 的数据包。但是环回不是以太网设备。那么为什么它会收到包含以太网 header 的数据包呢?

  • 如果 AF_PACKET 可以与非以太网设备一起使用,ETH_P_ALL 协议(protocol)标志是否指示仅接受专门具有 14 字节以太网 header 的数据包?


我的问题:

使用 AF_PACKET 是否意味着您保证总是接收带有 14 字节以太网 header 的数据包?

如果是这样,是否也意味着 AF_PACKET 只能用于以太网设备(与其他第 2 层技术相反,如 Wifi、 token 环、蓝牙、Infiniband 等) ?

如果这些问题中的任何一个的答案是NO,那么应用程序如何以编程方式确定在 AF_PACKET 上接收数据报时预期的第 2 层报头类型 socket ?

最佳答案

警告:这是因为我对使用 PF_PACKET 的生产软件编写的一些代码进行了蚕食,它仅适用于以太网,所以它可能不完整/不准确。

您正在使用 ETH_P_ALL给您任何东西。但是,有许多 ETH_P_* 符号可供选择(例如 ETH_P_802_3_MIN)。

绑定(bind)/选择不仅基于 socket 调用,还基于给定的接口(interface)

首先您需要您想要的接口(interface)名称(例如eth0),您可以从ifconfig 获得列表。

然后,使用 ioctl(SIOCGIFINDEX,...) 从接口(interface)名称获取接口(interface) index [或者,您可以将其硬编码为 ifconfig 将按索引顺序打印出来]。

然后,根据接口(interface)索引绑定(bind)到该接口(interface)。

既然你知道接口(interface)的类型(例如你选择了eth0或wifi等),之后你应该能够消化物理层头,因为你知道它是否是是否构造 eth_hdr

请注意,还有许多其他 SIOCGIF* ioctl,您可以使用它们来获取接口(interface)列表和其他信息,这些信息可以让您辨别接口(interface)类型 [以及因此,什么物理期望的 header ]。

无论如何,这是我所做的一些示例代码:

int
init(const char *intf)
// intf -- interface name (e.g. eth0, etc. -- whatever comes from ifconfig)
{
int err;

#if 1
int styp = SOCK_RAW;
#else
int styp = SOCK_DGRAM;
#endif

int netsock = socket(PF_PACKET,styp,htons(ETH_P_ALL));

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

// get the index number of the interface
err = ioctl(netsock,SIOCGIFINDEX,&ifr);
if (err < 0)
do_whatever;

printf("init: IFRIDX ifr_ifindex=%d\n",ifr.ifr_ifindex);
int ifidx = ifr.ifr_ifindex;

struct sockaddr_ll addr;
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_ifindex = ifidx;

err = bind(netsock,(struct sockaddr *) &addr,
sizeof(struct sockaddr_ll));
if (err < 0)
do_whatever;

return netsock;
}

关于c - AF_PACKET 和以太网,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54056426/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com