谁能解释或给我一个定义,IPPROTO_IP并帮助我理解IPPROTO_IP和之间有什么区别IPPROTO_RAW?
Fox*_*Fox 23
这是我/usr/include/netinet.in.h在Linux上的文件摘录.
/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
[.......]
IPPROTO_TCP = 6, /* Transmission Control Protocol. */
#define IPPROTO_TCP IPPROTO_TCP
IPPROTO_UDP = 17, /* User Datagram Protocol. */
#define IPPROTO_UDP IPPROTO_UDP
[.......]
IPPROTO_RAW = 255, /* Raw IP packets. */
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_MAX
};
Run Code Online (Sandbox Code Playgroud)
这是以下内容的摘录man socket:
该协议指定了与套接字一起使用的特定协议.通常,仅存在单个协议来支持给定协议族中的特定套接字类型,在这种情况下,协议可以指定为0.但是,可能存在许多协议,在这种情况下,必须以这种方式指定特定协议.要使用的协议号特定于进行通信的"通信域"; 见协议(5).有关如何将协议名称字符串映射到协议号,请参阅getprotoent(3).
在in.h文件中,注释说:Dummy protocol for TCP.
此常量的值为0.它实际上是一个自动选择,具体取决于套接字类型和系列.
如果您使用它,并且套接字类型是SOCK_STREAM且系列是AF_INET,则协议将自动为TCP(与您使用IPPROTO_TCP时完全相同).如果你将IPPROTO_IP与AF_INET和SOCK_RAW一起使用,则会出现错误,因为在这种情况下内核无法自动选择协议.
通常,您与OSI模型(TCP或UDP)的第4层交互.如果您使用IPPROTO_RAW,您将能够直接与第3层(IP)交互.这意味着你更低级别.例如,您可以编辑IP数据包的标头和有效负载(通常,内核将在其他模式下处理标头).编辑有效负载意味着您可以直接将所需内容放入IP有效负载中.内部或其他任何TCP段都不会.你可以自由地做你想做的事!
这显示了IP数据包的内存布局:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Run Code Online (Sandbox Code Playgroud)
考虑阅读man 7 raw包含有关RAW套接字使用的大量信息.
Raw sockets allow new IPv4 protocols to be implemented in user space.
A raw socket receives or sends the raw datagram not including link
level headers.
The IPv4 layer generates an IP header when sending a packet unless the
IP_HDRINCL socket option is enabled on the socket. When it is enabled,
the packet must contain an IP header. For receiving the IP header is
always included in the packet.
Only processes with an effective user ID of 0 or the CAP_NET_RAW capa?
bility are allowed to open raw sockets.
All packets or errors matching the protocol number specified for the
raw socket are passed to this socket. For a list of the allowed proto?
cols see RFC 1700 assigned numbers and getprotobyname(3).
A protocol of IPPROTO_RAW implies enabled IP_HDRINCL and is able to
send any IP protocol that is specified in the passed header. Receiving
of all IP protocols via IPPROTO_RAW is not possible using raw sockets.
?????????????????????????????????????????????????????
?IP Header fields modified on sending by IP_HDRINCL ?
?????????????????????????????????????????????????????
?IP Checksum ?Always filled in. ?
?????????????????????????????????????????????????????
?Source Address ?Filled in when zero. ?
?????????????????????????????????????????????????????
?Packet Id ?Filled in when zero. ?
?????????????????????????????????????????????????????
?Total Length ?Always filled in. ?
?????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
因此,为简单起见,您可以手动编辑IP标头的所有字段,但以下情况除外,它将始终由内核填充:
您可以使用struct ip编辑这些字段.
摘录自 /usr/include/netinet.ip.h
/*
* Structure of an internet header, naked of options.
*/
struct ip
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
};
Run Code Online (Sandbox Code Playgroud)
嗯,这取决于你想要的应用程序.某些应用程序有非常特殊的需求,只需要具有很大的灵活性.例如,如果要实现traceroute,则需要每次都增加TTL.
您可以使用更改TTL setsockopt,但如果您手动更改了许多标题字段,则最好接管IP标头的完全控制!
另一个用途是如果您想在IP之上实现自己的协议.
IPPROTO_IP 创建一个套接字,用于发送/接收基于 IPv4 的协议(TCP、UDP 等)的原始数据。它将为您处理 IP 标头,但您负责在 IP 有效负载内处理/创建其他协议数据。
IPPROTO_RAW 创建一个可以发送/接收任何类型协议的原始数据的套接字。它不会为您处理任何标头,您负责处理/创建所有有效负载数据,包括 IP 和其他标头。
| 归档时间: |
|
| 查看次数: |
26770 次 |
| 最近记录: |