UNIX网络编程--原始套接字(二十八)

时间:2024-03-19 08:30:36

UNIX网络编程---原始套接字(二十八)

一、概述

1) 有了原始套接字,进程可以读写ICMPv4、IGMPv4和ICMPv6等分组。举例来说,ping程序就使用原始套接字发送ICMP回射请求并接受ICMP回射应答。多播路由守护程序mrouted也使用原始套接字发送和接受IGMPv4分组。

2) 进程可以读写内核不处理其协议字段的IPV4数据报。

3) 进程可以使用IP_HDRINCL套接字自行构造IPV4首部。这个能力可用于构造譬如说TCP或UDP分组。

二、原始套接字创建

创建的步骤如下:

1) 把第二个参数指定为SOCK_RAW并调用socket函数,以创建一个原始套接字。第三个参数(协议)通常不为0.

Int sockfd;

Sockfd=socket(AF_INET,SOCK_RAW,protocol);

其中protocol参数是形如IPPROTO_XXX的某个常值,定义在<netinet/in.h>头文件中,如IPPROTO_TGMP.

2) 可以在这个原始套接字上按以下方式开启IP_HDRINCL套接字选项

Const int on=1;

If(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on))<0)

出错处理

3) 可以在这个原始套接字上调用bind函数,不过比较少见。Bind函数仅仅设置本地地址,因为原始套接字不存在端口号的概念。调用bind设置的是将用于从这个原始套接字发送的所有数据报的源IP地址。如果不调用bind,内核就把源IP地址设置为外出接口的IP地址。

4) 可以在这个原始套接字上调用connect函数

三、原始套接字输出

输出的规则有:

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

2) 如果IP_HDRINCL套接字选项为开启,那么由进程让内核发送的数据的其实地址指的是IP首部之后的第一个字节,因为内核将构造IP首部并把它置于来自进程的数据之前。

3) 如果IP_HDRINCL套接字选项已开启,那么由进程让内核发送的数据的其实地址指的是IP首部的第一个字节。进程调用输出函数写出的数据量必须包括IP首部的大小

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

对于IPV4,计算并设置IPV4首部之后所含的任何首部校验和是用户进程的责任。举例来说,在我们的ping 程序中,我们必须在调用sendto之前计算ICMPv4校验和并将它存在ICMPv4首部。

四、原始套接字输入

内核把哪些接收到的IP数据报传递到原始套接字?遵循的规则如下:

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

2) 大多数ICMP分组在内核处理完其中的ICMP消息后传递到元是套接字。

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

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

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

当内核有一个需传递到原始套接字的IP数据报时,它将检查所有进程上的所有原始套接字,以寻找所有匹配的套接字。每个匹配的套接字将被递送以该IP数据报的一个副本。内核对每个原始套接字均执行如下3个测试:

1) 如果创建这个原始套接字时指定了非0的协议参数(socket的第三个参数),那么接受到的数据报的协议字段必须匹配该值,苟泽该数据报不递送到这个套接字

2) 如果这个原始套接字已由bind调用绑定了某个本地IP地址,那么接收到的数据报的目的IP地址必须匹配这个绑定地址,否则数据报不递送到这个套接字。

3) 如果这个原始套接字已由connect调用指定了某个外地IP地址,那么接受到的数据包的源IP地址必须匹配这个已连接地址,否则该数据报不递送到这个套接字。

五、Ping程序

Ping程序的操作非常简单,往某个IP地址发送一个IDMP回射请求,该节点则以一个ICMP回射应答响应。

在这里有一个关于ping程序代码的解析

UNIX网络编程--原始套接字(二十八)

上面是ping程序的各个函数以及调用关系的概貌。

UNIX网络编程--原始套接字(二十八)

关于源代码部分等待更新……

六、Traceroute程序

Traceroute运行我们确定IP数据报从本地主机游历到某个远程主机所经过的路径。

同样是程序源代码的分析…

七、一个icmp消息守护进程

八、这里也是一个程序源代码的分析….