Chinaunix首页 | 论坛 | 博客
  • 博客访问: 539313
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: C/C++

2014-11-06 10:49:00

一、特点
有了raw socket,有了区别于TCP和UDP套接字的几个特点:
1.可以处理ICMPv4,IGMPv4,ICMPv6.
2.可以读写内核不处理其协议字段的IPv4数据报.
3.使用IP_HDRINCL套接字选项自行构造IPv4首部。这个能力可用于构造譬如说TCP或UDP分组.
4.TCP/UDP收发报文都只关心数据部分,而不关心IP头,tcp头,和udp头。而raw socket可以在收发报文的时候关心这些,甚至修改,如上面的IP_HDRINCL套接字选项。

二、raw socket的创建
1)把socket API的第二个参数设置成为SOCK_RAW,以创建一个原始套接字,第三个参数这是通常不为0,而是如IPPROTO_IGMP等等。
2)只有超级用户才能创建raw socket,防止普通用户往网络写出它们自行构造的IP数据报。
3)可以在这个raw socket上开启IP_HDRINCL套接字选项:
    const int on = 1;
    setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on))
4)可以在raw socket上调用bind函数
5) 可以在raw socket调用connect函数

三、原始套接字输出
1)普通输出通过调用sendto或sendmsg并指定目的IP地址完成。如果套接字已经连接,那么也可以调用write,writev或send。
2)如果IP_HDRINCL未开启,那么由进程让内核发送的数据的起始地址是IP首部之后的第一个字节,因为内核将构造IP首部并把它置于来自进程的数据之前。内核把所构造IPv4首部的协议字段设置成来自socket调用的第三个参数。
3)如果IP_HDRINCL开启,那么由进程让内核发送的数据的起始地址是IP首部的第一个字节。进程调用输出函数写出的数据量必须包括IP首部的大小。整个IP首部由进程构造,不过
    a)ipv4标识字段可置为0,由内核设置。
    b)IPv4首部校验和字段总是由内核计算并存储
    c)ipv4选项字段是可选的。
4)内核对超出外出接口MTU的原始分组进行分片

四、原始套接字输入
1)接收到的UDP、TCP分组绝不会传递到任何原始套接字
2)大多数ICMP分组在内核处理完其中的ICMP消息后传递到原始套接字(除了回射请求,时间戳请求或地址掩码请求---这几个由内核完全处理)
3)所以IGMP分组在内核处理完其中的IGMP消息后传递给原始套接字。
4)内核不认识其协议字段的所有IP数据报传递到原始套接字
5)分片重组后传递给原始套接字

内核传递条件:
1.raw socket的创建函数中protocol字段非0,并且与收到的数据报的协议字段匹配
2.raw socket bind了某个本地地址,那么收到的数据包的目的地址必须匹配这个绑定地址。
3.raw socket 由connect指定了某个外地地址,那么收到的数据报的源IP地址必须匹配这个已连接地址。
4.raw socket以0协议值创建,并且未调用bind ,connect,那么该套接字将接收由内核传递的每一个原始数据报的一个副本。

传递报文情况:
1)无论何时往一个原始IPv4套接字传递一个接收到的数据报,传递到该套接字所在进程的都是包括IP首部在内的完整数据报。
2)对于原始IPv6套接字,传递到套接字的只是扣除了IPv6首部和所有扩展首部的净荷(payload).
阅读(1370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~