AF_PACKET和以太网 [英] AF_PACKET and Ethernet

查看:243
本文介绍了AF_PACKET和以太网的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm very confused about exactly how the AF_PACKET socket family (for SOCK_RAW sockets) specifically relates to Ethernet (IEEE 802.3).

到目前为止,我了解的信息:

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

  • I understand the OSI Model, and how Layer 2 technologies like Ethernet fit into the model.

我了解 AF_PACKET 可以与 SOCK_RAW 套接字一起使用接收包含14字节以太网报头的数据报,后面跟一些其他较高层协议标头,例如IPv4,IPv6等,其次是可选的传输层协议(例如TCP),以及最后是有效载荷.

I understand that AF_PACKET can be used with a SOCK_RAW socket to receive datagrams that contain a 14-byte Ethernet header, followed by some other higher layer protocol header(s), such as IPv4, IPv6, etc., followed by optionally a transport layer protocol like TCP, and finally a payload.

我知道您可以将 ETH_P_ALL ETH_P_IP 等标志传递为 socket 的协议参数以具有内核过滤器数据包为您服务,只需向您发送包含特定报头的数据包类型.

I understand you can pass flags such as ETH_P_ALL or ETH_P_IP as the protocol argument to socket to have the kernel filter packets for you, by only sending you packets containing headers of a certain type.

我不了解的内容

  • 我不知道 AF_PACKET 是否应该专门用于以太网设备,而不是其他第二层技术,例如Wifi,蓝牙,令牌环,Infiniband等.

  • I don't understand if AF_PACKET is supposed to exclusively work with Ethernet devices, as opposed to other Layer 2 technologies, such as Wifi, Bluetooth, Token Ring, Infiniband, etc.

我不了解以太网设备与使用14字节 Ethernet标头 的第2层协议之间的关系.以太网头是14个字节,可以定义为: struct eth_hdr {char dest_address [6];char source_address [6];uint16_t ethertype;}; 换句话说,此标头仅用于物理以太网设备吗?似乎答案为,因为如果在环回接口上使用 AF_PACKET ,我仍然会收到包含14字节以太网头的数据包.但是环回不是以太网设备.那么为什么它会接收包含以太网标头的数据包呢?

I don't understand the relationship between Ethernet devices versus Layer 2 protocols that use the 14-byte Ethernet header. The Ethernet header is 14-bytes, and can be defined as something like: struct eth_hdr { char dest_address[6]; char source_address[6]; uint16_t ethertype; }; In other words, is this header only used with physical Ethernet devices? It seems the answer is no, because if I use AF_PACKET on the loopback interface, I still receive packets containing 14-byte Ethernet headers. But loopback is not an Ethernet device. So why does it receive packets containing Ethernet headers?

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

If AF_PACKET can be used with non-Ethernet devices, does the ETH_P_ALL protocol flag indicate to only accept packets that specifically have a 14-byte Ethernet header?


我的问题

使用 AF_PACKET 是否意味着可以保证始终 接收带有14字节以太网报头的数据包?

Does using AF_PACKET imply you are guaranteed to always receive packets with 14-byte Ethernet headers?

如果是的话,这是否也意味着 AF_PACKET 仅应与以太网设备一起使用(与其他第2层技术(例如Wifi,令牌环,蓝牙,Infiniband等)相反)?

If so, does that also imply that AF_PACKET is meant to be used ONLY with Ethernet devices (as opposed to other Layer 2 technologies, like Wifi, Token Ring, Bluetooth, Infiniband, etc.)?

如果这两个问题的答案均​​为,那么应用程序如何以编程方式确定在 AF_PACKET 上接收到数据报时期望的第2层标头的类型插座?

If the answer to either of these questions is NO, then how can an application programatically determine what type of Layer 2 header to expect when receiving a datagram on an AF_PACKET socket?

推荐答案

注意事项:这是因为吞噬了我为使用 PF_PACKET 的生​​产软件编写的一些代码仅适用于以太网,因此 可能不完整/不准确.

Caveat: This comes from cannibalizing some code I wrote for production software that used PF_PACKET, which was only for ethernet, so it may be incomplete/inaccurate.

您正在使用将给您任何东西的 ETH_P_ALL .但是,有很多 ETH_P _ * 符号可供选择(例如 ETH_P_802_3_MIN ).

You're using ETH_P_ALL which will give you anything. But, there are many ETH_P_* symbols to choose from (e.g. ETH_P_802_3_MIN).

绑定/选择不仅基于调用,而且还基于给定的 interface 接口.

The binding/selection is not based on not merely the socket call, but is based on a given interface as well.

首先,您需要从 ifconfig 获得的列表中想要的接口 name (例如 eth0 ).

First you need the interface name you want (e.g. eth0) from the list you can get from ifconfig.

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

Then, get the interface index using ioctl(SIOCGIFINDEX,...) from the interface name [or, you could just hard code it as ifconfig will print them out in index order].

然后根据接口索引绑定到该接口.

Then, bind to that interface, based on the interface index.

由于您知道接口的类型(例如,选择了 eth0 或wifi等),在那之后,您应该能够消化物理层头,因为您知道它是否是是否使用struct eth_hdr .

Since you know the type of interface (e.g. you chose eth0 or wifi, etc.), after that, you should be able to digest the physical layer header because you know whether it's struct eth_hdr or not.

请注意,您还可以使用许多其他 SIOCGIF * ioctl来获取接口列表和其他信息,这些信息可能使您可以辨别接口类型[因此确定物理类型.标头].

Note that there are a number of other SIOCGIF* ioctls that you can use to get a list of interfaces and other information that may allow you to discern the interface type [and, therefore, what physical header to expect].

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

Anyway, here's some sample code from what I did:

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;
}

这篇关于AF_PACKET和以太网的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆