UNIX网络编程读书笔记:原始套接口

红心概述

应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket)。http://www.cnblogs.com/nufangrensheng/p/3583435.html

原始套接口是一种对原始网络报文进行处理的套接口。原始套接口主要应用在底层网络编程上,同时也是网络黑客的必备手段。例如sniffer、拒绝服务(DoS)、IP地址欺骗等都需要在原始套接字的基础上实现。

与原始套接字对应,之前的TCP/UDP的套接字称为标准套接字,如下图所示,为标准套接字与原始套接字之间的关系。标准套接字与网络协议栈的TCP、UDP层打交道,而原始套接字则与IP层级网络协议栈核心打交道。

image

原始网络套接口提供普通的TCP和UDP套接口不提供的以下3个功能:

1、有了原始套接口,进程可以读与写ICMPv4、IGMPv4和ICMPv6等分组。

2、有了原始套接口,进程可以读与写内核不处理其协议字段的IPv4数据报。

3、有了原始套接口,进程还可以使用IP_HDRINCL套接口选项自行构造IPv4头部。

红心原始套接口的创建

创建一个原始套接口涉及如下步骤:

1、把第2个参数指定为SOCK_RAW调用socket函数,以创建一个原始套接口。第3个参数(协议类型)通常不为0。

image

灯泡只有超级用户才能创建原始套接口。

2、可以在这个原始套接口上如下开启IP_HDRINCL套接口选项:

const int on = 1;
if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
    出错处理

3、可以在这个原始套接口上调用bind函数,不过比较少见。bind函数仅仅设置本地地址,因为原始套接口不存在端口的概念。

4、可以在这个原始套接口上调用connect函数,不过也比较少见。connect函数仅仅设置远地地址,同样因为原始套接字不存在端口的概念。

红心原始套接口输出

原始套接口的输出遵循以下规则:

1、普通输出通过调用sendto或sendmsg并指定宿IP地址完成。如果套接口已经连接,那么也可以调用write、writev或send。

2、如果IP_HDRINCL套接口选项未开启,那么由进程让内核发送的数据的起始地址指的是IP头部之后的第一个字节,因为内核将构造IP头部并把它置于来自进程的数据之前。内核把所构造的IPv4头部的协议字段设置成来自socket调用的第3个参数。

3、如果IP_HDRINCL套接口选项已开启,那么由进程让内核发送的数据的起始地址指的是IP头部的第一个字节。进程调用输出函数写出的数据量必须包括IP头部的大小。整个IP头部由进程构造,不过:(a)IPv4标识字段可置为0,从而告知内核设置该值;(b)IPv4头部校验和字段总是由内核计算并存储;(c)IPv4选项字段是可选的。

4、内核对于超出外出接口MTU的原始分组执行分片。

红心原始套接口输入

原始套接口输入遵循以下规则:

1、接收到的UDP分组和TCP分组绝不传递到任何原始套接口。如果一个进程想要读取含有UDP分组或TCP分组的IP数据报,它就必须在数据链路层读取这些分组。

2、大多数ICMP分组在内核完成处理其中的ICMP消息后传递到原始套接口。

3、所有IGMP分组在内核完成处理其中的IGMP消息后传递到原始套接口。

4、内核不认识其协议字段的所有IP数据报传递到原始套接口。内核对这些分组执行的唯一处理是针对某些IP头部字段的最小验证:IP版本、IPv4头部校验和、头部长度以及宿IP地址。

5、如果某个数据报以片段形式到达,那么在它的所有片段均到达且重组出该数据报之前,不传递任何片段分组到原始套接口。

原文地址:https://www.cnblogs.com/nufangrensheng/p/3596552.html