在 socket() 中使用 GGP(0x0003) 作为协议参数的目的是什么

What is the goal of using GGP(0x0003) as a protocol parameter in socket()

我开始编写数据包嗅探器程序,并且我搜索了要传递给 socket() 函数的正确参数,以便通过以太网 header[= 捕获数据包 39=].

我注意到在这个 tutorial 中,为了接收以太网 header,他们更改了这一行:

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

到这一行:

s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0x0003))

我的问题是:

  1. 我从这个 了解到 AF_INET 使用原始套接字不会给我以太网 header。我的问题是为什么?

  2. 为什么他还把IPPROTO_TCP改成了ntohs(0x0003)我知道这是GGP协议。据我了解,第三个参数说明套接字将接收的协议。如果协议参数是 GGP,那么套接字将查找以 GGP 作为其 Internet 层协议的数据包,不是吗?那么为什么他们通过 GGP 而不是 TCP 或 IP?毕竟,几乎每个 PDU 都有 IP and\or TCP\UDP 作为它们的数据协议。我的数据包嗅探器的第三个参数是什么重要?

  3. 除了第二个问题,我想我没有得到第三个参数的objective。如果是 IPPROTO_TCP,socket 会在网络层捕获带有 TCP 的数据包(例如不是 UDP)?如果我通过 IPPROTO_IP,socket 将捕获以 IP 作为其 internet 层协议的数据包,而不检查其他层的协议(对于 socket 来说网络层使用什么协议并不重要?它只关心 IP 作为互联网层协议存在)?

对语法错误表示感谢和抱歉(英语不是我的母语)。

  1. 可以在网络堆栈的不同层设置原始套接字功能,以允许内核在较低级别为您执行一些工作(例如:以太网制作)。

  2. 在您找到示例的网站上,对 GGP 协议的更改可能有意义,但这样做很丑陋,应该使用 getprotoent() 而不是使用幻数。

  3. 是的,您可以调整(过滤)数据包捕获的方式。如果要捕获所有数据包,请使用 ETH_P_ALL:

When protocol is set to htons(ETH_P_ALL) then all protocols are received.

如果你勾选 linux/if_ether.h 你会看到

#define ETH_P_ALL   0x0003  /* Every packet (be careful!!!) */

所以ETH_P_ALL的值为0x0003。本教程的作者使用 0x0003 而不是 ETH_P_ALL,因为在某些系统中使用 python 时会出现 "not defined" 错误。