原始套接口(RAW SOCKET)

原始套接口(RAW SOCKET)

 

原始套接口提供三种TCP和UDP套接口不提供的功能:

1). 可以读写ICMPv4, IGMPv4和ICMPv6分组. 例如Ping和Traceroute程序就是利用ICMP分组

2). 可以读写特殊的IPv4数据报, 内核不处理这些数据报IPv4协议字段

3). 使用IP_HDRINCL选项可以构造自己IPv4头部. 可以用这个特性来构造自己的TCP和UTP分组

 

原始套接口创建

1). 设置第二个参数为SOCK_RAW

int sockfd; sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_XXX);

这个IPPROTO_XXX可以在找到定义, 例如可以为IPPROTO_ICMP,IPPROTO_IP, IPPRPTO_TCP和IPPRPTO_UDP等

2). 可以设置IP_HDRINCL选项

const int on = 1; if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) error

3). 可以调用bind绑定本地IP

4). 可以调用connect绑定目的IP

 

原始套接口输出

1). 通过sendto或sendmsg到目的IP, 或write, writev或send到connect的原始套接口

2). 如果IP_HDRINCL没有设置, 用户数据从IP头之后开始

3). 如果IP_HDRINCL设置, 用户数据必须包括IP头, 并且要自己设置IPv4标示字段和校验和之外的所有字段

4). 对以超出外出MTU分组, 内核将其分片

 

原始套接口输入

1). 接收到的TCP和UTP分组绝不会传递给任何原始套接口

2). 绝大多数ICMP分组会传递给相应的原始套接口

3). 所有IGMP分组会传递给给相应的原始套接口

4). 多有带有内核不能识别的协议字段的IP数据报会给相应的原始套接口

5). 如果数据包是分片, 内核要等到接收到所有片才转发

在内核准备传递一个数据报时, 将对所有原始套接口进行检查, 如果满足下面三个条件将传送一个拷贝:

1). 协议字段不为0是必须匹配

2). 如果绑定了本地IP, 必须匹配

3). 如果设置了目的IP, 必须匹配

所以如果没有bind和connect, 而且协议为0, 则接收多有数据报

 

Ping

原理: 发送ICMP到目的IP, 等待接收回射ICMP包, 先看一下ping程序输出

========================================================================

li@li-linux:~$ ping www.google.cn
PING google.cn (203.208.39.99) 56(84) bytes of data.
64 bytes from bi-in-f99.google.com (203.208.39.99): icmp_seq=1 ttl=244 time=77.7 ms
64 bytes from bi-in-f99.google.com (203.208.39.99): icmp_seq=2 ttl=244 time=34.1 ms
64 bytes from bi-in-f99.google.com (203.208.39.99): icmp_seq=3 ttl=244 time=80.0 ms

--- google.cn ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 10424ms
rtt min/avg/max/mdev = 34.134/63.984/80.031/21.128 ms
========================================================================

 

下面是Ping程序消息格式

 

原始套接口(RAW SOCKET)_第1张图片

标识符将设置为Ping程序进程ID, 序列好每次发送增1. 在可选数据设置时间可以在收到时计算一次应答的时间.  发送是设置type为ICMP_ECHO, 接收时为ICMP_IREQREPLY

 

 

你可能感兴趣的:(原始套接口(RAW SOCKET))