1. 原始套接字能力:

(1) 进程可以读写ICMP,IGMP等分组,如ping程序;

(2) 进程可以读写内核不处理协议字段的ipv4数据报;如OSPF等;

(3) 进程可以使用IP_HDRINCL套接字选项自行构造ipv4首部;

2. 原始套接字的创建:

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

开启ip头构造选项:

const int on = ;
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < ){
error...
}

当选项开启时,我们需要构造完整的IP首部,下列情况除外:

(1) IP总是计算并存储IP首部校验和;

(2) 如果我们将IP标识字段设置为0,内核将设置该字段;

(3) 如果源ip地址是INADDR_ANY,IP将把它设置为外出接口的IP地址;

(4) 如何设置IP选项取决于实现。有些实现取出我们预先使用IP_OPTIONS套接字选项设置的任何IP选项,把它们添加到我们的构造首部中,而其他实现则要求我们亲自在首部指定任何期望的IP选项;

(5) IP首部中的有些字段必须以主机字节序填写,有些字段必须以网络字节序填写,具体取决于实现。linux上所有字节都采用网络字节序;

3. 原始套接字的输出:

(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的原始分组执行分片;

另:ip首部之后所含有的其他任何首部的校验和需要用户进程计算;

4. 原始套接字的输入:

(1) 接收到的udp/tcp分组决不传递到任何原始套接字;进程只能通过数据链路层读取这些分组;但是可以发哦;

(2) 大多数icmp分组在内核处理完其中的icmp消息后传递到原始套接字;源自Berkeley的实现把不是回射请求,时间戳请求或者地址掩码请求(这三类均有内核处理)的所有接收到的icmp分组传递给原始套接字;

(3) 所有igmp分组在内核完成处理其中的igmp消息后传递给原始套接字;

(4) 内核不认识协议字段的所有ip数据报传递到原始套接字;内核对这些分组进行ip头最小验证:ip版本,ip校验和,首部长度,目的ip地址;

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

(6) 如果创建原始套接字制定了非0协议参数,那么接收到的数据报协议字段必须匹配该值,否则该数据报不会传递到该套接字;

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

(8) 如果这个原始套接字由connect调用制定了某个外地ip地址,那么接收到的数据报的源ip地址必须匹配该连接,否则数据报不会传递到该套接字;

注意:如果一个原始套接字是以0值协议参数创建,并且既未调用bind,也未调用connect,那么该套接字将接收可由内核传递到原始套接字的每个原始数据报的一个副本;

无论何时往一个原始IPv4套接字传递一个接收的数据报,传到该套接字所在进程都包括ip首部在内的完整数据报;ipv6不包含首部;

5. 数据链路层访问:

接收所有帧:

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

接收ipv4帧:

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));

注意:如果设置接口为混杂模式,则可接收所有经过数据流,而不论其目的地址是否是它;

原始套接字&&数据链路层访问的更多相关文章

  1. Linux Socket 原始套接字编程

    对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...

  2. Linux系统编程(37)—— socket编程之原始套接字

    原始套接字的特点 原始套接字(SOCK_RAW)可以用来自行组装IP数据包,然后将数据包发送到其他终端.也就是说原始套接字是基于IP数据包的编程(SOCK_PACKET是基于数据链路层的编程).另外, ...

  3. UNIX网络编程——原始套接字SOCK_RAW

    实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM).而这些数据包都是由系统提供的协议栈实现, ...

  4. Go中原始套接字的深度实践

    1. 介绍 2. 传输层socket 2.1 ICMP 2.2 TCP 2.3 传输层协议 3. 网络层socket 3.1 使用Go库 3.2 系统调用 3.3 网络层协议 4. 总结 4.1 参考 ...

  5. raw_socket(原始套接字)以及普通socket使用终极总结

      一.传输层socket(四层socket,普通socket) 可参考本人以下博客: Windows Socket编程之UDP实现大文件的传输:http://blog.csdn.net/luchen ...

  6. Linux网络编程——原始套接字能干什么?

    通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...

  7. Linux基础(11)原始套接字

    一边接收函数返回一边判断返回值时一定要把接收的优先级加()提高再去判断 例 if((sockfd = socket()) < 0) 问题: 如何实现SYN扫描器扫描端口 , 比如AB两个设备要进 ...

  8. Linux原始套接字抓取底层报文

    1.原始套接字使用场景 我们平常所用到的网络编程都是在应用层收发数据,每个程序只能收到发给自己的数据,即每个程序只能收到来自该程序绑定的端口的数据.收到的数据往往只包括应用层数据,原有的头部信息在传递 ...

  9. Linux网络编程:原始套接字简介

    Linux网络编程:原始套接字编程 一.原始套接字用途 通常情况下程序员接所接触到的套接字(Socket)为两类: 流式套接字(SOCK_STREAM):一种面向连接的Socket,针对于面向连接的T ...

随机推荐

  1. SocketServer-实现并发处理2

    转发自MnCu的博客: http://www.cnblogs.com/MnCu8261/p/5546823.html python基础之socket与socketserver ---引入 Socket ...

  2. [SCOI2013]摩托车交易 kruskal重构树(最大生成树) 倍增

    ---题面--- 题解: 这题想法简单,,,写起来真的是失智,找了几个小时的错误结果是inf没开到LL范围.... 首先我们需要找到任意两点之间能够携带黄金的上限值,因为是在经过的道路权值中取min, ...

  3. SPOJ8222/NSUBSTR:Substrings——题解

    https://www.luogu.org/problemnew/show/SP8222#sub http://www.spoj.com/problems/NSUBSTR/ 翻译来自洛谷. 你得到一个 ...

  4. IOI2000 Post Office (POJ1160)

    前言 昨天XY讲课!讲到这题!还是IOI的题!不过据说00年的时候DP还不流行. 题面 http://poj.org/problem?id=1160 分析  § 1 中位数 首先我们考虑,若有x1 & ...

  5. oracle-java7-installer安装java失败之后的处理

    最开始尝试使用installer安装jdk7,但是未能进行完整,之后每次安装软件都会报错,说oracle-java7-installer处有错误,查得如下解决办法: sudo rm /var/lib/ ...

  6. 解决requests获取源代码时中文乱码问题

    用requests获取源代码时,如果是中文网页,就可能会出现乱码,下面我以中关村的网站为例: import requests url = 'http://desk.zol.com.cn/meinv/' ...

  7. The database cluster was initialized with RELSEG_SIZE 1048576, but the server was compiled with RELSEG_SIZE 8388608

    由于一次误操作,将线上机器的数据库程序目录删除,虽然不影响程序的正常使用,数据也未丢失,但后面如果出现服务器宕机或数据库宕机,数据库将无法启动,而且数据库对应的编译参数也已无法查看,所以征得开发同意后 ...

  8. sleep方法和wait方法的区别?

    sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复.调用sleep 不会释放对象锁.wait 是Object 类的方法 ...

  9. Matrix.(POJ-2155)(树状数组)

    题目是让每次对一个子矩阵进行翻转(0变1,1变0), 然后有多次询问,询问某个点是0还是1 这题可以用二维的树状数组来解决,考虑传统的树状数组是改变某个点,然后查询某一段, 而这个题是改变某一段,查询 ...

  10. DOM动态操纵控件案例

    点击登陆显示登陆框 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head ...