精华内容
下载资源
问答
  • 2022-03-02 16:52:00

    sniff(count=0,store=1,offline=None,prn=None,filter=None,L2socket=None,timeout=None,opened_socket=None,stop_filter=None,iface=None)

    count:抓取报的数量,设置为0时则一直捕获

    store:保存抓取的数据包或者丢弃,1保存,0丢弃

    offline:从pcap文件中读取数据包,而不进行嗅探,默认为None

    prn:为每个数据包定义一个回调函数

    filter:过滤规则,可以在里面定义winreshark里面的过滤语法

    L2socket:使用给定的L2socket

    timeout:在给定的事件后停止嗅探,默认为None

    opened_socket:对指定的对象使用.recv进行读取

    stop_filter:定义一个函数,决定在抓到指定的数据之后停止

    iface:指定抓包的网卡,不指定则代表所有网卡

    更多相关内容
  • SNIFF真是一个古老的话题,关于在网络上采用SNIFF来获取敏感信息已经不是什么新鲜事,也不乏很多成功的案例,那么,SNIFF究竟是什么呢?SNIFF就是嗅探器,就是窃听器,SNIFF静悄悄的工作在网络的底层,把你的秘密...
  • AIM Sniff-开源

    2021-05-01 01:34:07
    AIM Sniff是一种网络嗅探器,专门用于拾取使用AIM或MSN客户端及其派生类发送的消息。 所有信息都可以发送到STDOUT或MySQL DB。
  • Sniff-and-Sniff-Sub-rating-Modes_WP_V10 - 副本.zip
  • 蓝牙白皮书之sniff mode

    2018-08-10 22:07:32
    中文版的关于蓝牙sniff mode白皮书,是本人自己在看完英文版后原创翻译的,读完相信你就能彻底了解了蓝牙sniff模式极其相应的设置,对于从事带电池的蓝牙设备开发有相当好的指导作用。
  • VB-Sniff.zip

    2019-09-14 13:15:14
    多年前收藏的代码,作者不详,VB6写的网络数据嗅探工具
  • Packet Sniff

    2016-10-10 09:30:58
    Packet Sniff, 一款专业的抓空气包软件。
  • 主要介绍了SQL Server中参数化SQL写法遇到parameter sniff ,导致不合理执行计划重用的快速解决方法的相关资料,需要的朋友可以参考下
  • sniff_docs3_sniff_

    2021-10-03 04:02:52
    sniff 4.0.2 documents 3
  • sniff_docs1_sniff_源码

    2021-10-04 00:26:43
    sniff 4.0.2 documents 1
  • 蓝牙Sniff_mode_白皮书

    2013-07-29 11:06:15
    蓝牙Sniff mode 白皮书;蓝牙学习的好资料
  • 2.7.3 SniffSniff Sub-rating 模式的切换...........................................................................................................13 2.7.4 在 Sniff Sub-rating 模式下同步设备.......

    译注:译文略去了部分与技术无关的内容如版本历史及贡献者等,对于某些专有名词,译词反而词不

    达意,故不做翻译。译文难免有错误之处,请不吝指出,任何疑问和探讨,请联络:

    jinhuagu.sh@126.com 或者 qiaofeifan@gmail.com

    1目录

    1 介绍......................................................................................................................................................................................... 3

    1.1 术语和缩写 ................................................................................................................................................................... 3

    1.2 参考................................................................................................................................................................................. 3

    2 一个 Idle 的 ACL 连接........................................................................................................................................................ 4

    2.1 目的和假定 ................................................................................................................................................................... 4

    2.2 时钟和数据通信.......................................................................................................................................................... 4

    2.3 时隙................................................................................................................................................................................. 5

    2.4 Sniff 模式 ........................................................................................................................................................................ 8

    2.4.1 Sniff 参数图........................................................................................................................................................... 8

    2.5 请求 SNIFF 模式 ........................................................................................................................................................11

    2.6 选择 Sniff 参数...........................................................................................................................................................11

    2.7 Sniff Sub-rating..........................................................................................................................................................13

    2.7.1 Sniff Sub-rating 概览........................................................................................................................................13

    2.7.2 建立 Sniff Sub-rating 模式.............................................................................................................................13

    2.7.3 Sniff 和 Sniff Sub-rating 模式的切换...........................................................................................................13

    2.7.4 在 Sniff Sub-rating 模式下同步设备..........................................................................................................14

    3 总结.......................................................................................................................................................................................15

    23

    1 介绍

    Snifff 和 Sniff-Subrating 模式提供了一种蓝牙设备连接时减少电源功耗的有效途径。此白皮书尝试通过对

    Bluetooth core Specification 的相关信息的详细解读来澄清这些模式的使用。

    1.1 术语和缩写

    名称 说明

    ACL Asynchronous Connection-oriented (logical transport)

    面向连接的异步传输链路(译注:这是相对同步连接链路(SCO)而言

    的,在整个蓝牙世界里,除了音频(耳机)SCO外,其他几乎都是异

    步的)

    eSCO Extended Synchronous Connection-Oriented面向连接的扩展同步传

    输链路(译注:与SCO的区别未知),总体是是为stream流服务的连接

    FHS Frequency Hop Synchronization (packet) 跳频同步包,是一个特殊的

    控制包,用于实现主从设备的时钟同步

    HCI Host Controller Interface 主机控制接口,是基带层对上的接口,有了

    该接口可以实现底层硬件和上次会话的分离

    HF Hands Free device role of the HFP 免提协议中的免提设备

    HFP Hands-Free Profile 免提Profile

    L2CAP Logical Link Control And Adaptation Protocol 逻辑链路控制和适配协

    议,是在管理链路层并未应用层提供服务的协议层

    LMP Link Manager Protocol 链路管理协议,主要负责创建、修改、释放蓝

    牙逻辑连接

    LT_ADDR Logical Transport Address 逻辑传输地址

    PBAP Phonebook Access Profile 电话簿访问Profile

    PMP Participant in Multiple Piconets 多个微微网参与者(译注:基本上等同

    于与多个设备同时连接)

    PPM Parts Per Million 百万分之一

    SCO Synchronous connection-Oriented 面向连接的同步传输链接

    1.2 参考

    [1] Bluetooth Core Specification 2.0 + EDR, 4 November 2004

    [2] Bluetooth Core Specification 2.1 + EDR, 26 July 2007 2 一个 Idle 的 ACL 连接

    2.1 目的和假定

    在讨论 sniff 模式前,很有必要在基带层对蓝牙通信有一个较好的认识。本节检视了一个已建立的 ACL

    连接相应的链路管理,并假定该链路之上并没有更高层协议(L2CAP 及以上)来主动管理链路通路。建立链路

    的过程在本文讨论范围之外。

    2.2 时钟和数据通信

    数据通信本质上是建立在一个主时钟上的,但在更深层次探讨它之前,请考虑两个现实生活中的情景。

    情景 1:参加某一个运动会的所有运动员都使用同一个时钟,比赛用的时钟放在所有人都看得见的比分

    板上。每个人都可以获取这个信息并且准确地知道比赛什么时候会暂停或者结束。

    让我们重新回到数字世界中考虑一个不寻常的带有流量控制(流控)的串行连接。发送端知道何时发送数

    据是因为接收端可以利用流控来请求数据。在蓝牙无线技术中,连接的每一端都使用自己的时钟来决定何

    时发送何时监听。时钟并不会为各个 bit 位来提供时间基准,而是像流控方式定义数据包何时应该被发送,

    接收端何时应该监听数据。

    情况 2:每一个参与者都有自己独立的时钟。请参考以下场景。

    Charles 在一封电邮中告诉 Teddy,“我明天早上九点给你打电话。” 第二天早上 Teddy 比约定时间提早

    了 15 分钟坐在了桌子前想起了 Charles 的电邮并思考着他现在应该是去咖啡馆喝杯咖啡还是坐在桌子前等

    着 Charles 给他打电话。

    他在做出决定的过程中肯定思考了以下几个条件:

    1. Teddy 的时区和 Charles 的时区之间的时差是多少?

    2. Charles 有多大可能是正好在 9 点整给他打电话,而不是 9 点之前或之后几秒?

    3. Charles 的表有多大可能走的比较慢,从而导致他迟了 10 分钟打电话?

    4. Charles 的表有多大可能走的比较快,从而导致他早了 10 分钟打电话?

    5. 有多大可能 Charles 今日的安排被打乱了从而导致他今天根本不会打电话?

    我们假定 Teddy 是想和 Charles 打电话的,所以在他离开他的桌子之前他必须得决定去一趟咖啡馆是不

    是会导致他错过这个电话。我们同时假设 Teddy 的确想要喝一杯咖啡的,所以如果 Charles 没有在 9 点整给

    他打电话,他也得做出决定什么时候要停止等电话然后去喝咖啡。

    我们回到蓝牙无线技术中,所有 Teddy 要考虑的条件都代表了蓝牙中很重要的概念。

    在我们的例子中,Teddy 一直注意着他的手机有没有 Charles 来电的提醒。在蓝牙无线技术中,从设备

    必须监听来自主设备的传输。

    由于两个设备运行时都使用自己的时钟并且主设备的数据传输是建立在他自己的时钟

    2

    上的,对于从设

    备来说,获取充分的信息来知道什么时候监听和监听多久是十分重要的,下面列出了这些信息项。

    项 1:Teddy 知道他在 Charles 西边的一个时区,所以当 Charles 说“我的早上 9 点“时,Teddy 必须减去

    一个小时,从而预计电话会在他(Terry)这边早上 8 点打过来。蓝牙时钟并不如同某一个地区的当地时间

    一样被同步到一个绝对的值。重要的是主设备与从设备时钟的时间差。如果主设备时钟的值是 100 而从设

    备是 91,那么时钟偏差

    3

    (clock offset)就是 9。由于从设备知道这个偏差,同时还知道主设备只会在偶序数

    1

    该白皮书只适用于 Basic Rate/Extended Rate(BR/EDR)连接

    2

    蓝牙时钟是一个有预定义容错频率范围的 28 比特自主运转计数器

    3

    此处做了简化处理,实际的主从设备时钟的频率会有微小的差别,因而相对偏差是在逐渐漂移的

    4个 slot 序数传输,从设备会把 9 加到它的时钟值里来决定什么时候来监听。

    项 2:在离整点还有 5 秒时 Charles 按下了给 Teddy 打电话的按钮。那么 Teddy 的电话在什么时候会响

    呢?这个取决于电话网络要花多久来建立这个连接。这个值很大程度上不能被确定。它也许会花两秒,也许

    会花5秒。每当Charles打一个电话,这个时间可能会是不同的。在蓝牙的环境里,这个偏差叫做抖动(jitter)。

    不可量化的影响能轻微地改变一个数据包的到达时间。抖动在理想状态下每一次都是不一样的,并且不会

    随着时间而累积。

    项 3 和 4:这与每个设备蓝牙时钟的频率的总体精度有关。任何一个时钟都有一个内在的精确度,意味

    着它会比表面上显示的时间运行的更快或者更慢。经过时间的积累,这些固定的误差会累积成一个对于表

    面上时间来说不可忽略的偏差。这个就叫做漂移(drift)。这些误差要花多久才累积成可以在表面上显现取

    决于时钟的精确度。关于时钟精度的信息会在链路建立的时候在主从设备之间共享。对于在蓝牙中的时间

    计算,主从设备各自的漂移率也得考虑进去。

    项 5:大多数大学生对于‘15 分钟规则’会比较了解。如果教授在原定上课时间 15 分钟之内没有出现,

    学生会开始离开并且自由利用多出来的时间。像这些大学生一样,Teddy 会等 Charles 一段时间直到他确信

    Charles 不会再打电话过来。回到蓝牙无线技术中;运行一个接收设备也许会比传输数据一样或者更加消耗

    电量。从设备会在条件 1-4 中描述过的时间之后开始监听。从设备还会计算出它还得监听多久。它监听得

    越久,越多的电量会被消耗掉,所以这个时间值得确保在大多数情况下任何往从设备发送的数据会被监听

    到,但与此同时这个时间值也不能是无限长的。这段监听时间被称为不确定窗口(uncertainty window)。

    在两个时钟是完美同步的并且抖动漂移都是零的情况下,不确定窗口的起点应该是传输的开始时刻。

    2.3 时隙

    蓝牙协议是由一个 3.2kHz,等同于 312.5 µs 的周期,自主运转的系统时钟所驱动的。这个 312.5 µs 的

    时隙被用来进行 inquiry 和 paging,在此不会作讨论。两个已经连接上的设备的通讯是建立在 625 µs 的周

    期上的,或者两倍于基准时钟的周期。在蓝牙的语言里,这样一个周期叫做一个时隙(slot)并且是蓝牙里

    时间测量的一个基本单位。

    可靠的蓝牙通讯建立在知道下一个时隙何时会开始。在理想环境中,下一个时隙会在当前时隙后的 625

    µs 之后到来;在现实环境中,事物不会这么精确地运行,正如前一节所示,漂移抖动共同使得任意给定

    的 slot 有些模糊(偏移)。在讨论如何估计这个偏移值之前,先考虑对于一个给定连接,我们知道什么哪些,

    又如何获取。

    项 1 时钟偏移(clock offset):在连接建立时,主设备发送跳频同步(FHS)给从设备,除了其他信息外,这个数据

    包还包括主设备的当前时钟值。从设备利用该值计算主从设备时钟间的偏移

    项 2 抖动(jitter):核心规范 Volume 2, Part B, section 2.2.5 定义了活跃连接的最差抖动“瞬时时间应该不超

    过平均时间 1us”,因此,最大抖动定义为±1 μs。

    项 3 项 4 漂移(drift):抖动一样,最大时钟偏移在核心规范有定义。在 STANDBY 和 Park,Hold 以及 Sniff 等各

    种(省电)模式中,本地时钟可能是由一个± 250PPM 的低功耗晶振(LPO)驱动的,而其他模式时,本地时钟应由

    ±20PPM 的高精度晶振驱动。设备可通过 LMP 命令 LMP_timing_accuracy_req 请求获取对方的漂移抖动,该命

    令具体介绍参见核心规范 Volume 2, Part C, Section 4.3.1

    项 5 不确定性(uncertainty):这个是由从设备从前述信息中综合计算而得的。

    通过这些信息,第 k 个 slot 的边界时间可以用这个公式计算:

    公式 1 来源于核心规范 2.1+EDR – Vol.2, PartB, Sect. 2.2.5

    其中:

    5tk是 slot 边界时间

    Di是第 i 个 Slot 的漂移

    TN是名义上的 625us 的 slot 长度

    jk抖动(jitter)的绝对值

    Offset 是为了与主设备时钟同步而添加到从设备时钟的偏移值

    计算 tk时可以做一些简化。由于每个 slot 的实际漂移值是未知的,我们可以采用其最坏值 20ppm(对于

    低功耗时钟是 250ppm)。由于 slot 长度是固定的,该公式变成:

    公式 2 简化的 slot 边界时间

    对于低功耗时钟(250ppm),进一步简化为:

    公式 3 250ppm 时钟的 Slot 边界时间

    对于高精度时钟(20ppm):

    公式 4 20ppm 时钟的 Slot 边界时间

    核心规范(Volume2, 2.2.5.1)建议从设备通常采用 20us 的不确定窗口。(如图 1)也就是说,从设备应该

    提前 10us 开始监听主设备向从设备的传输,并且在边界后继续监听 10us。如果在此期间没有数据包,从设

    备即可停止监听并等待下一个窗口,也就是 2 个 slot 之后。显然,尽量减小不确定窗口是省电的关键点,

    特别是对于那些电池设备如耳机。

    图 1 slot 时间和不确定窗口

    每次从设备收到主设备的包,它会根据实际包的到达时间调整自身的本地时间。这种做法使得从设备在当

    前接收包到达时间加上1240us后开始寻找下一次传输(1240us2slots减去10us不确定窗口时间)。这也暗

    示了从设备必须通过阶段性的接收来达到与master的同步。如果传输的间隔变大,那么从设备必须延长其不确

    定窗口时间,否则它可能再也无法与master同步,从而导致因链路supervision超时引发的连接丢失。当两个连

    接设备无法在先前协商的时间周期内交换数据包,则链路supervision超时,连接自动中止。

    考虑两个真实设备的例子,图2的抓包截屏显示了利用Poll和空包交换进行链路维护。由于双方包都没有负

    载数据,所以他们都很小,从而减少了电源功耗。主设备发送一个Poll(Slave不允许发送POLL),要求从设备

    即使没有数据需要发送也得响应。如果链路当前并不载有LMP或者更高层协议数据,从设备将响应一个空包。

    6图 2 抓包跟踪窗口的轮询和空包

    图中的时间戳显示,主设备每隔约 20ms 间隔发送一个查询包。20ms 间隔对应于每隔 32 个 slots 发送查询

    包。假定从设备正使用低功耗时钟,利用前面的公式,最差时钟漂移是 5us。对于活跃中的主设备,通常

    采用高精度时钟,那么漂移缩为 0.4us。由于每个设备最大允许的抖动为 1us,与理想情况的最大偏差可以

    将这些项目相加计算。

    Slave drift + Slave jitter + Master drift + Master jitter -> 5 μs + 1 μs + 0.4 μs + 1 μs = 7.4 μs

    这个结果,7.4 μs, 与蓝牙核心规范所要求的不确定窗口大小± 10 μs相当吻合。

    请记住,保持与主设备的同步,并根据主设备的发送间隔调整不确定窗口,是从设备的责任。这体现

    在核心规范的Volume 2, 2.2.5.2中,上面说明了如果双方在都使用高精度时钟且超过250ms接收不到数据

    时,从设备就会无法与主设备同步。结合上述已知的链路管理,懂了吗?250ms对应于400slots,乘以

    20ppm最差情况的漂移大约会是5us(单个设备)。加上抖动后,250ms的最差情况是12us,超出了一般活

    跃链路所推荐使用的± 10 μs不确定窗口。所以该警告实际是链路参数的逻辑推算出来的。

    当两个设备较长时间不交换数据包而失去同步时,sniff模式等(工作方式)需要其重新同步。由于主

    时钟始终用于控制链路,所以同步工作必然是由从设备来完成。从设备计算下一个主设备到从设备的发送

    slot,发送频点(频点是由主设备的蓝牙设备地址和主时钟决定的)以及不确定窗口大小。在此期间,主从设

    备都使用高精度时钟(20ppm),从设备监听主设备的传输。由于主设备向从设备的发送间隔延长了,有必

    要增加从设备的不确定窗口以保证从设备能收到传输。窗口可能会超过一个slot长度(625us),但不能与下

    一个窗口重叠如图3,举个例子,如果有超过1秒无数据包交换,则最大偏离大约是± 42 μs,或者不确定

    窗口84us。从设备应该在预测的slot边界前超过42us的时刻开始监听主设备的传输。

    图 3 不确定窗口

    78

    2.4 Sniff 模式

    很多蓝牙设备是电池供电的,很有必要提供一种机制来保证在不需要工作时只消耗最小的电量。正如图

    2 所示,已连接的蓝牙设备之间必然会持续交换数据包来维持正确的时钟同步。在示例中,主设备基本每隔

    20ms 发送一个查询包给从设备。有兴趣的读者可以推导出相当于每秒 50 次查询。这些包很短但依然会在

    没有 Profile 层的数据发送时消耗设备电量。

    Sniff 模式是蓝牙核心规范(core specification)定义的 3 个低功耗模式中的一个,其他 2 个是 hold 和 pack

    状态,本文不对此做进一步讨论。Sniff 模式提供了一种机制来管理主从设备间无 ACL 包交换期间的时间。

    同步包传输如 SCO 和 eSCO 并不会受 sniff 模式影响。Sniff 模式的这种定期空闲使得设备通过关闭其 Radio

    并进入低功耗模式来节省电量。

    以下概念对于讨论 sniff 模式很重要,一些概念难以用文字表达,因此会在定义后紧跟例子:

    Anchor point(锚点) – Slot 边界起始点,从该点开始从设备侦听主设备的发送信号,而实际的从设

    备使能其接收器的时间点则是锚点时刻减去不确定窗口时间的一半(译注:也就是说会提前一点),

    而不确定窗口的长度依赖于链路空闲时长以及每个设备的 slot 时钟精度。

    Tsniff – 两个锚点之间的 slot 数。因为主设备只能在偶序数 slots 发送数据给从设备,这个值必须是

    大于 0 的偶数

    Dsniff – 是一个偏移值,该偏移值必须是 0 到(Tsniff-2)间的偶数,一个锚点必须满足如下关系:

    Dsniff = 时钟值(bits26-1) mod Tsniff

    该公式将会在后续章节讨论

    Nsniff attempt – 是包含锚点在内的,从设备应该监听主设备传输的 slots 数量。因为该值代表的只是偶

    序数 slots,所以其值的范围必须在: 1≤ N <( Tsniff /2)

    Nsniff timeout – 是从设备在收到包含它自己的 LT_ADDR 包后连续侦听主设备传输包的 slots 数量。这个

    窗口允许数据开始传输后连续在后面的 slots 中进行数据交换,而不需要等下一个锚点。Sniff 超时

    计数器会在一个包被接收后清 0 重启,还有一种清 0 重启的情况是数据包交换始终持续,一直到

    下一个 sniff 的锚点

    Sniff instant – 这个概念在《Bluetooth Core 2.1+EDR Specification》中引用了 2 次但没有被定义,

    事实上应该是要写为 Sniff 锚点

    很重要的一点,如果一个设备必须参与另一个 piconet 的活动(译注:可以理解为它需要与其他设备进行

    蓝牙通信了),它可以不遵循规则而在 Sniff attempt 或者 sniff timeout 到期前停止监听,建议大家合理

    地考虑这些参数。

    2.4.1 Sniff 参数图

    以下一些时序图仅仅是展示这些概念,并不代表实际的 sniff 参数。例如,实际上很少有将 sniff interval

    设为 6 的,但这样的图很便于演示。真实的 sniff 参数会在后续的参数定义图中讨论。

    图 4 Tsniff 间隔

    图 4 显示了 Tsniff 间隔为 6 的情况。这里,初始 sniff 锚点被定义为如下关系:9

    Clock26-1mod TSniff = 0

    公式 5 Tsniff 与时钟关系

    换句话说,当 slot 时钟值正好可以被 6 整除时,该 slot 就是 sniff 锚点。细心的读者可能注意到公式中

    只用了 28 位蓝牙时钟的 26 位,最高位 bit27 被略去了。在 Core Spec 中实际上有 2 个公式,它们都略去了

    bit27。最低位bit0没有被采用,这是因为时钟正好是slot 长度的2倍。Slots是625us,而时钟周期是312.5us。

    因为 sniff 只关注整个周期,所以最低位不予考虑。

    在初始锚点定下来后,后续的锚点都可以通过当前锚点加固定的时间间隔 Tsniff 来进行计算。因为时钟

    可能回滚,时钟模组 Tsniff=0 的关系可能无法满足。换句话说,Dsniff的值可能会在时钟回滚时改变。

    这还不是完整的故事,想象一下,当主设备设备有 2 个从设备且这 2 个从设备都需要用 Tsniff = 6 的 sniff

    模式。公式 5 提示了 2 个设备的锚点是相同的,时间一致的,而主设备在一个给定的 slot 时间只能处理一

    个从设备,因此无法工作。幸好,sniff 特性还提供了一个偏移量 Dsniff,使其在 Tsniff 间隔内解决了此问题(译注:

    通过偏移使得 2 个设备在不同时刻得以处理)。因此,实际上公式 5 是一个特别的情况,而更通用的情况则

    是下述公式 6。

    Clock26-1mod TSniff = Dsniff

    公式 6 Tsniff 与时钟关系

    图 5 展示了与图 4 相同的 sniff 连接情景,但此图的第二个设备采用 Tsniff = 6 和 Dsniff = 2.

    图 5 加入了第二个连接来演示 Dsniff=0 (红) 和 Dsniff=2 (蓝)

    设计 Sniff 的目的是通过减少维护连接两个设备所需要的数据交换数量以节约电量,且还允许 PMP 设

    备因为参与其他 piconet 网络而缺席某个 piconet 网络。在这些情况下,sniff 锚点可能会有一两秒的离开。

    如果一个 sniff 锚点事务消失,往往是因为主设备忙于另一个 piconet 网络中,或者主设备与从设备无法联

    网,此时,从设备需要等待下一个 Sniff 间隔到来才能和主设备通信。为了增强链路的健壮性,sniff 设置包

    含了一个参数,用于改进锚点只出现在一个间隔的单一 slot 的概念,取而代之的,锚点可以是“多个 slot”。

    图 6 Sniff attempt 演示

    图 6 展示了一个 Tsniff值大于 6 的链路,由于另一个锚点在本图中不可见,而 Nsniff attempt =3,这里重要的

    点包括:

    Nsniff attempt是单指主设备到从设备的 slot 数量

    Nsniff attempt包含了锚点 slot,因此它必须被设为大于 1 的值

    Sniff attempt的最大值是Tsniff / 2

    从设备需要在 Nsniff attempt 个周期内的每个主设备到从设备 slot 上保持监听正如 Nsniff attempt会用于在每个锚点以增强重新建立连接的健壮性,Nsniff timeout会被用于确保任何请求数据

    在设备进入低功耗状态并等待下一个锚点能完成传送。

    以下图示展示了所有这些概念。

    图 7 没有主设备通信的锚点

    在图 7 中,从设备在所设计的 slot 中没有等到主设备数据。由于 Nsniff attempt的值是 1, 从设备不需要继续

    监听下一个主设备到从设备的 slot。取而代之的,它恢复到低功耗模式,并等待下一个锚点的到来,届时它

    会醒过来并重新监听来自于主设备的包。

    图 8 没有数据的锚点

    在图 8 中,主设备在锚点发送一个查询包,从设备则应答了一个空包。由于没有 ACL 数据传输,从设

    备被允许回到低功耗模式并等下一个 sniff 锚点。但注意,规则还说了从设备可以继续监听主设备到从设备

    的 Slot。

    图 9 带 ACL 数据的锚点

    在图 9 中,主设备发送了 ACL 数据给从设备,且从设备向主设备应答了 ACL 数据。在这里,Nsniff timeout

    为 2,从设备会继续监听来自于主设备的信号,从设备收到来自于主设备的另一个 ACL 数据包并且合理应

    答。由于是有数据交换的,定时计数器被重置而从设备将继续监听,直到在定时期间始终没有主设备到从设

    备的 ACL 包。

    图 10 单个数据交换锚点

    图 10 展示了数据超时的情况。主设备和从设备在锚点位置交换数据,然后,从设备继续监听 2 个主设

    1011

    备->从设备的 slot,当看到没有主设备包信号时,从设备回到低功耗模式,直到下一个锚点。

    图 11 数据交换时的锚点(译注:原图不清晰)

    在图 11 中,两个设备持续交换数据并超过了整个 Tsniff 间隔。当锚点到来时,所有的 sniff 值被复位了,

    且链路会等待锚点包。注意 sniff 超时还有一个 slot 才到,但在锚点被终止了。一旦下一个锚点到达,图示

    7~10 所描述的行为在这里同样会出现。(译注:也就是说当始终由数据通信时超时计数器会在下一个锚点被

    复位)

    2.5 请求 SNIFF 模式

    前文sniff参数的讨论是从sniff链路管理角度阐述的。记住,最终还是由链路管理软件来协商链路管理

    的细节的,包括同步数据的slot预分配和sniff参数。应用向链路管理器发送请求,而链路管理器与远端的链

    路管理器协商所有细节。

    在使用HCI层的系统中,sniff模式是由Host通过HCI命令HCI_Sniff_Mode请求的,请求参数为:

    Connection_Handle – 两字节整数,用于标识相应ACL连接

    Sniff_Max_Interval – 链路在sniff模式可保留的最大slots数,或者用链路管理协议(LMP)规范讲就是

    Tsniff最大值。由于它只与主设备到从设备的slot相关,该值必须为偶数。同时该值必须大于最小

    sniff间隔,并且强制范围为0x6到0x540,相当于3.75ms到840ms。但实现角度是可以接受该范围

    之外的值的(译注:程序可以接受该范围之外的值,但最终采用的必然是范围内值)

    Sniff_Min_Interval – 最小可接受的Tsniff值。该值范围与上面最大间隔相同,但必须小于指定的最

    大间隔值。

    Sniff_Attempt – 从设备设备需要监听主设备传输的slot数量,包含锚点slot,该值不超过Tsniff/

    2。

    Sniff_Timeout – 当大于0时表示从设备会连续监听主设备的slots数,需要从接收到最后一个包含

    ACL数据的主设备发送Slot开始算起。

    注意,由于应用层无法知道链路管理做了什么样的分配,所以是由链路来协商TsniffDsniff的值,因

    此它们并不能算作HCI sniff参数集的一部分。(译注:也就是说TsniffDsniff并不是HCI Sniff参数集的一部分)

    2.6 选择 Sniff 参数

    当使用sniff来降低功耗时,有一些事务必须考虑:

    1. 响应时间有什么要求

    一些设备需要他们配对设备有快速的响应。100毫秒的延迟对于耳机上用按钮接听来电是可接受

    的,而1秒的延迟则未必。每个应用应该评估自己的特定需求并通过实验来决定合适的sniff间隔

    2. 不同sniff间隔下的会有什么样的功耗要求

    图 12 示例了电流和 sniff 间隔的关系曲线。该图示并不是来自于真实的应用,不能直接用于产品设计。

    但它还是揭示了一个通用准则,sniff 间隔越小,所能节省的功耗越小,而随着间隔增大,节省的功耗越多,

    但边际效应也越明显。随着 sniff 间隔变长,从设备必须延长它的不确定窗口大小以抵消时钟偏移,因此它在每个锚点会消耗更多能量。可以咨询你的蓝牙芯片提供商来获取针对你的实现的特定场景信息。同时,记

    住当蓝牙芯片处于 sniff 模式时,可以让外部的处理器也处于低功耗状态以降低整体功耗。如果这个方式在

    你的设计中可行,请确保考虑处理器的唤醒时间以及它对所要求的响应时间的影响。对于一个特定的设计,

    设置 sniff 间隔在 80~100 毫秒范围可能是最佳选择。短的间隔会快速增加功耗,而更长的间隔在降低响应

    时间的同时所能节省的功耗会越来越少。

    图 12: 电流与 sniff 间隔关系示例图

    3. Sniff Attempts和timeout值

    除了sniff间隔造成的绝对延迟,产品设计者也必须考虑链路鲁棒性以及数据传输特性,通常通过选择

    Nsniff attempt Nsniff timeout的值来调整。在一个理想世界中,从设备设备始终会在锚点接收到主设备传的信

    号,实际情况下却总是可能发生RF干扰导致的包丢失情况。如果Sniff attempt值设为1,那么从设备将

    被强制等到下一个sniff interval周期才有机会发送给主设备,这个也许是可接受的。假如从设备是一个

    远程传感器并自带存储功能,并且只需要传输一些并不时间敏感的数据,那么错过一个锚点是OK的。

    其他应用可能有不同的需求。

    设置 Nsniff attempt 为一个大于1的较小值将会极大增加通信复原的成功性,代价是略微高一点的功耗。

    蓝牙移动电话和蓝牙耳机设备间通用的sniff attempt值是4个主设备到从设备的slot,这里sniff interval

    0.5秒。 (相当于2)

    定义一个合理的Nsniff timeout就有点复杂了,因为这个参数只是对主设备有利。从设备只能在奇数slot

    送,如果它在之前的slot收到了来自于主设备的包。Sniff timeout使得从设备继续监听,但是从设备却

    无法按照所定义的interval,在奇数slots向主设备发送包,除非主设备发送了一些东西(此时从设备即

    可在slot上传送包)。为便于说明,考虑以下例子:

    在出现手机电话簿访问Profile(PBAP)之前,许多免提设备通过用一堆GSM AT命令来请求和响应手机

    电话簿。该协议并没有在蓝牙profile中定义,但却广泛实现并且稳定运行。现在,考虑免提设备(HF)

    当主(设备),而电话当从(设备)。链路为sniff模式,sniff间隔1秒。HF等待下一个sniff锚点并发送一个

    请求给电话,要求发送电话簿条目,电话接收到了请求,但无法及时地完成访问数据、格式化数据并

    添加到发送队列,从而在从设备发送窗口进行发送(这一系列操作)HF(主设备)LM(链路管理)并不

    知晓协议层,因此不知道从设备有数据要发送,从而只是在锚点与从设备通信,它把链路看成是休眠

    12的,直到下一个锚点,也就是一秒钟后。此时,从设备发送电话簿条目。如果主设备已经准备好下一

    个请求,或者链路 足够长的sniff timeout,那么主设备可以发送其下一个请求。从设备将会遇到和第

    一次同样的问题,它将无法立即响应主设备,因此会再一次等待一个sniff锚点,每秒传送一个电话簿

    条目,如果电话簿很大,那么会耗费很长时间传输。

    现在交换角色,如果电话是主设备,且timeout值足够长,它可以容许在回复来自HF的电话簿请求时

    有些许延迟,因为HF作为从设备在接收到数据后继续监听Nsniff timeoutslot。如果HF始终能保持以固定

    时间准时发送下一个请求,那2个设备可以在无需持续等下一个锚点的情况下完成所有电话簿数据的

    传输。从几个厂家的设定看,并不存在什么典型的timeout值,有些是0,有些是1,而有些则高达8

    4. 找到适合你需求的

    底线如下:所有这些参数的设定值依赖于用户场景和设备在其中所起的角色。设置这些值的最好方法

    是做大量互操作的测试,尝试不同的值组合来看哪个是是最佳的。当然需要和同时考虑功耗和响应时间。

    2.7 Sniff Sub-rating

    2.7.1 Sniff Sub-rating 概览

    Sniff sub-rating(SSR)提供了进一步金地链路管理功耗的方法。SSR允许任何设备增加sniff锚点间的时

    间。而此种变化会降低链路的及时响应, 它也减少了为了维护链路所需的交换包的数据,因而减少了功

    耗。SSR特别有利于那种长时间不活动而阶段性活动的设备。计算机鼠标就是一个好的例子,用户在word

    处理时会用鼠标打开文档并定位鼠标,一旦完成这些操作,用户仅会长时间用键盘而不碰鼠标。在这段不

    活动的时间,鼠标可以进入SSR模式来减少电源消耗。

    SSR参数是由HCI命令HCI_Sniff_Subrating建立的,核心参数包括:

    Maximum_Latency: 最大延迟,单位是基带slots(625us)。该值被链路管理层用于计算

    max_sniff_subrate,而是max_sniff_subrate由作为LMP命令的一个参数,用于开启sniff subrating

    注意,蓝牙核心规范会称呼该值为max_sniff_subrate, maximum_sniff subrate, or max subrate,取决

    于你参考的哪个section。这些命名指的是同一件事,本文只用了max_sniff_subrate来避免混乱。

    Minimum_Remote_TimeoutMinimum_Local_Timeout: 最小远程超时和最小本地超时,单位是基带

    slots(625us),该值用于链路管理层决定何时将设备从sniff模式转为sniff subrate模式。

    在基带层,max_sniff_subrate是基于Tsniff值的整数倍。例如,Tsniff20slots,而

    max_sniff_subrate4,那么当设备进入到sniff subrating模式时,每个锚点将分为80slots

    2.7.2 建立 Sniff Sub-rating 模式

    Sniff sub-rating模式是由某个设备发送LMP命令LMP_sniff_subrating_req且另一个设备以

    LMP_sniff_subrating_res响应此命令,在该交换中,链路主设备设备应该提供一个蓝牙时钟值作为sniff

    sub-rating的实例,该时钟值是将来的sniff sub-rating模式开始的时间点。这些PDU同样交换设备间的

    max_sniff_subrate值。而该值的计算必须保证2个锚点间的时间不超过HCI提供的最大延迟或者链路

    supervision超时值。如果超过了后者,那么连接将会超时断开并等待下一个锚点。如果主设备需要改变链

    supervision超时值(LSTO)且更新值小于sniff sub-rating锚点间隔,那么主设备必须在设置LSTO之前退

    sniff sub-rating,然后重新建立sniff sub-rating

    2.7.3 Sniff 和 Sniff Sub-rating 模式的切换

    每个设备可以在在sniff模式和sniff sub-rating模式间自由切换。因为所有的sub-rating锚点也都是sniff

    锚点,设备始终是可以重连的。

    为了建立sniff sub-rating,每个设备需要通过HCI层提供一个超时值。当设备进入sniff模式时,定时器开始

    1314

    计时,当定时器超过sub-rating的超时值时,设备转到sniff sub-rating模式。由于两个设备可能有不同的超

    时值,每个模式的当前模式可以是独立于另一个设备的。

    设备应该何时从sniff sub-rating模式转为sniff模式呢?有两种情况,一种是它收到带有设备间的LMP

    信号的ACL-C数据,另一种是它收到来自对方设备L2CAP信息的ACL-U数据。转换后的sniff模式将一直持

    续到下一次sniff定时器超时从而将设备返回至sniff sub-rating模式。

    当从设备在等待传送包的基带Ack信号时,应暂时退出sniff sub-rating模式而处于sniff模式。

    2.7.4 在 Sniff Sub-rating 模式下同步设备

    一旦sniff sub-rating模式成功建立,每一个配对设备应独立进入或退出sub-rating模式,这意味着会有

    以下4种可能的状态

    1 – 没有设备在sub-rating模式 此时遵循sniff模式的规则

    2 – piconet网的主设备处于sub-rating模式,从设备处于sniff模式

    3 – piconet网的主设备处于sniff模式,从设备处于sub-rating模式

    4 – 两个设备都处于sub-rating模式

    对于23,那个非sub-rating设备每隔Tsniffslots或者传输或者监听(取决于其自身角色是主还是从)

    由于另一个设备基于其max_sniff_subrate值大幅减少了传输和监听的次数,此设备决定了重新建立通信的

    延迟。

    对于4,情况更加复杂,因为两个设备会有不同的max_sniff_subrate值。考虑以Tsniff=10为例,主设备

    max_sniff_subrate值为5而从设备的max_sniff_subrate值为3,那么,如果每个设备只是简单地使用自

    己的max_sniff_subrate值,那么两个设备间的重连将耗费相当长时间。

    主设备发送 从设备接收

    30

    50

    60

    90

    100

    120

    150 150

    表 1 较晚的重连情况

    规范并没有提供更佳的计算sub-rating锚点的方法。

    如果两个max_sniff_subrate值相同,那么每个设备可以如预期一样使用其值,如下例所示,表格中Tsniff

    20,而两个设备的max_sniff_subrate值均为3

    主设备发送 从设备接收

    60 60

    120 120

    180 180

    240 240

    300 300

    … …

    表 2 一致的 max_sniff_subrate 值

    如果两个max_sniff_subrate值不同,那么较小值的设备还是会持续发送或者监听的。

    采用了较大本地max_sniff_subrate值的会用较小值来计算下一个可能的锚点,因此,大概率上还是会继续如表2

    那样运行。

    “大概率上”表明了还有一种情况未表述。设定j为较大max_sniff_subrate与较小max_sniff_subrate的商取15

    整,以53举例:

    5/3=1.66, 则j=1

    又如114

    11/4=2.75,则j=2

    较大本地max_sniff_subrate值的设备应该每隔j个锚点发送或者监听一次。回到表1的情况,Tsniff10,主

    设备max_sniff_subrate值为5而从设备为3,进而算出j=1,这就要求主设备每隔30slot发送一次。

    主设备发送 从设备接收

    30 30

    60 60

    90 90

    120 120

    … …

    表 3 采用锚点规则

    如果主设备的max_sniff_subrate变为7,则j的值变为2,进而允许主设备跳过一些锚点。为了维护链路

    的最快反应速度,跳过主锚点大体上步时什么好主意。

    主设备发送 从设备接收

    30 30

    60

    90 90

    120

    … …

    表 4 跳过主设备锚点并不推荐但是允许的

    相反,从设备的max_sniff_subrate值变为7,而主设备为3,则j的值同样变为2,从而允许从设备跳过一

    些锚点。

    主设备发送 从设备接收

    30 30

    60

    90 90

    120

    … …

    表 5 跳过从设备锚点是允许的

    3 总结

    希望本文档能多少指明 sniff 和 sniff 模式的一些操作和用途。通过仔细遴选参数以及大量地实际测试以

    验证设备反应,这些模式肯定能明显节省蓝牙设备电源功耗。

    展开全文
  • sniff

    2017-10-13 19:39:28
    struct sniff_ethernet {  u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */  u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */  u_short ether_type; /* IP? ARP...
    #define APP_NAME        "sniffex"
    #define APP_DESC        "Sniffer example using libpcap"
    #define APP_COPYRIGHT    "Copyright (c) 2005 The Tcpdump Group"
    #define APP_DISCLAIMER    "THERE IS ABSOLUTELY NO WARRANTY FOR THIS PROGRAM."

    #include <pcap.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>

    /* default snap length (maximum bytes per packet to capture) */
    #define SNAP_LEN 1518

    /* ethernet headers are always exactly 14 bytes [1] */
    #define SIZE_ETHERNET 14

    /* Ethernet addresses are 6 bytes */
    #define ETHER_ADDR_LEN    6

    /* Ethernet header */
    struct sniff_ethernet {
            u_char  ether_dhost[ETHER_ADDR_LEN];    /* destination host address */
            u_char  ether_shost[ETHER_ADDR_LEN];    /* source host address */
            u_short ether_type;                     /* IP? ARP? RARP? etc */
    };

    /* IP header */
    struct sniff_ip {
            u_char  ip_vhl;                 /* version << 4 | header length >> 2 */
            u_char  ip_tos;                 /* type of service */
            u_short ip_len;                 /* total length */
            u_short ip_id;                  /* identification */
            u_short ip_off;                 /* fragment offset field */
            #define IP_RF 0x8000            /* reserved fragment flag */
            #define IP_DF 0x4000            /* dont fragment flag */
            #define IP_MF 0x2000            /* more fragments flag */
            #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
            u_char  ip_ttl;                 /* time to live */
            u_char  ip_p;                   /* protocol */
            u_short ip_sum;                 /* checksum */
            struct  in_addr ip_src,ip_dst;  /* source and dest address */
    };
    #define IP_HL(ip)               (((ip)->ip_vhl) & 0x0f)
    #define IP_V(ip)                (((ip)->ip_vhl) >> 4)

    /* TCP header */
    typedef u_int tcp_seq;

    struct sniff_tcp {
            u_short th_sport;               /* source port */
            u_short th_dport;               /* destination port */
            tcp_seq th_seq;                 /* sequence number */
            tcp_seq th_ack;                 /* acknowledgement number */
            u_char  th_offx2;               /* data offset, rsvd */
    #define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
            u_char  th_flags;
            #define TH_FIN  0x01
            #define TH_SYN  0x02
            #define TH_RST  0x04
            #define TH_PUSH 0x08
            #define TH_ACK  0x10
            #define TH_URG  0x20
            #define TH_ECE  0x40
            #define TH_CWR  0x80
            #define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
            u_short th_win;                 /* window */
            u_short th_sum;                 /* checksum */
            u_short th_urp;                 /* urgent pointer */
    };

    void
    got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);

    void
    print_payload(const u_char *payload, int len);

    void
    print_hex_ascii_line(const u_char *payload, int len, int offset);

    void
    print_app_banner(void);

    void
    print_app_usage(void);

    /*
     * app name/banner
     */
    void
    print_app_banner(void)
    {

        printf("%s - %s\n", APP_NAME, APP_DESC);
        printf("%s\n", APP_COPYRIGHT);
        printf("%s\n", APP_DISCLAIMER);
        printf("\n");

    return;
    }

    /*
     * print help text
     */
    void
    print_app_usage(void)
    {

        printf("Usage: %s [interface]\n", APP_NAME);
        printf("\n");
        printf("Options:\n");
        printf("    interface    Listen on <interface> for packets.\n");
        printf("\n");

    return;
    }

    /*
     * print data in rows of 16 bytes: offset   hex   ascii
     *
     * 00000   47 45 54 20 2f 20 48 54  54 50 2f 31 2e 31 0d 0a   GET / HTTP/1.1..
     */
    void
    print_hex_ascii_line(const u_char *payload, int len, int offset)
    {

        int i;
        int gap;
        const u_char *ch;

        /* offset */
        printf("%05d   ", offset);
        
        /* hex */
        ch = payload;
        for(i = 0; i < len; i++) {
            printf("%02x ", *ch);
            ch++;
            /* print extra space after 8th byte for visual aid */
            if (i == 7)
                printf(" ");
        }
        /* print space to handle line less than 8 bytes */
        if (len < 8)
            printf(" ");
        
        /* fill hex gap with spaces if not full line */
        if (len < 16) {
            gap = 16 - len;
            for (i = 0; i < gap; i++) {
                printf("   ");
            }
        }
        printf("   ");
        
        /* ascii (if printable) */
        ch = payload;
        for(i = 0; i < len; i++) {
            if (isprint(*ch))
                printf("%c", *ch);
            else
                printf(".");
            ch++;
        }

        printf("\n");

    return;
    }

    /*
     * print packet payload data (avoid printing binary data)
     */
    void
    print_payload(const u_char *payload, int len)
    {

        int len_rem = len;
        int line_width = 16;            /* number of bytes per line */
        int line_len;
        int offset = 0;                    /* zero-based offset counter */
        const u_char *ch = payload;

        if (len <= 0)
            return;

        /* data fits on one line */
        if (len <= line_width) {
            print_hex_ascii_line(ch, len, offset);
            return;
        }

        /* data spans multiple lines */
        for ( ;; ) {
            /* compute current line length */
            line_len = line_width % len_rem;
            /* print line */
            print_hex_ascii_line(ch, line_len, offset);
            /* compute total remaining */
            len_rem = len_rem - line_len;
            /* shift pointer to remaining bytes to print */
            ch = ch + line_len;
            /* add offset */
            offset = offset + line_width;
            /* check if we have line width chars or less */
            if (len_rem <= line_width) {
                /* print last line and get out */
                print_hex_ascii_line(ch, len_rem, offset);
                break;
            }
        }

    return;
    }

    /*
     * dissect/print packet
     */
    void
    got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
    {

        static int count = 1;                   /* packet counter */
        
        /* declare pointers to packet headers */
        const struct sniff_ethernet *ethernet;  /* The ethernet header [1] */
        const struct sniff_ip *ip;              /* The IP header */
        const struct sniff_tcp *tcp;            /* The TCP header */
        const char *payload;                    /* Packet payload */

        int size_ip;
        int size_tcp;
        int size_payload;
        
        printf("\nPacket number %d:\n", count);
        count++;
        
        /* define ethernet header */
        ethernet = (struct sniff_ethernet*)(packet);
        
        /* define/compute ip header offset */
        ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
        size_ip = IP_HL(ip)*4;
        if (size_ip < 20) {
            printf("   * Invalid IP header length: %u bytes\n", size_ip);
            return;
        }

        /* print source and destination IP addresses */
        printf("       From: %s\n", inet_ntoa(ip->ip_src));
        printf("         To: %s\n", inet_ntoa(ip->ip_dst));
        
        /* determine protocol */    
        switch(ip->ip_p) {
            case IPPROTO_TCP:
                printf("   Protocol: TCP\n");
                break;
            case IPPROTO_UDP:
                printf("   Protocol: UDP\n");
                return;
            case IPPROTO_ICMP:
                printf("   Protocol: ICMP\n");
                return;
            case IPPROTO_IP:
                printf("   Protocol: IP\n");
                return;
            default:
                printf("   Protocol: unknown\n");
                return;
        }
        
        /*
         *  OK, this packet is TCP.
         */
        
        /* define/compute tcp header offset */
        tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
        size_tcp = TH_OFF(tcp)*4;
        if (size_tcp < 20) {
            printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
            return;
        }
        
        printf("   Src port: %d\n", ntohs(tcp->th_sport));
        printf("   Dst port: %d\n", ntohs(tcp->th_dport));
        
        /* define/compute tcp payload (segment) offset */
        payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
        
        /* compute tcp payload (segment) size */
        size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
        
        /*
         * Print payload data; it might be binary, so don't just
         * treat it as a string.
         */
        if (size_payload > 0) {
            printf("   Payload (%d bytes):\n", size_payload);
            print_payload(payload, size_payload);
        }

    return;
    }

    int main(int argc, char **argv)
    {

        char *dev = NULL;            /* capture device name */
        char errbuf[PCAP_ERRBUF_SIZE];        /* error buffer */
        pcap_t *handle;                /* packet capture handle */

        char filter_exp[] = "ip";        /* filter expression [3] */
        struct bpf_program fp;            /* compiled filter program (expression) */
        bpf_u_int32 mask;            /* subnet mask */
        bpf_u_int32 net;            /* ip */
        int num_packets = 10;            /* number of packets to capture */

        print_app_banner();

        /* check for capture device name on command-line */
        if (argc == 2) {
            dev = argv[1];
        }
        else if (argc > 2) {
            fprintf(stderr, "error: unrecognized command-line options\n\n");
            print_app_usage();
            exit(EXIT_FAILURE);
        }
        else {
            /* find a capture device if not specified on command-line */
            dev = pcap_lookupdev(errbuf);
            if (dev == NULL) {
                fprintf(stderr, "Couldn't find default device: %s\n",
                    errbuf);
                exit(EXIT_FAILURE);
            }
        }
        
        /* get network number and mask associated with capture device */
        if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
            fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
                dev, errbuf);
            net = 0;
            mask = 0;
        }

        /* print capture info */
        printf("Device: %s\n", dev);
        printf("Number of packets: %d\n", num_packets);
        printf("Filter expression: %s\n", filter_exp);

        /* open capture device */
        handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
        if (handle == NULL) {
            fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
            exit(EXIT_FAILURE);
        }

        /* make sure we're capturing on an Ethernet device [2] */
        if (pcap_datalink(handle) != DLT_EN10MB) {
            fprintf(stderr, "%s is not an Ethernet\n", dev);
            exit(EXIT_FAILURE);
        }

        /* compile the filter expression */
        if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
            fprintf(stderr, "Couldn't parse filter %s: %s\n",
                filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }

        /* apply the compiled filter */
        if (pcap_setfilter(handle, &fp) == -1) {
            fprintf(stderr, "Couldn't install filter %s: %s\n",
                filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }

        /* now we can set our callback function */
        pcap_loop(handle, num_packets, got_packet, NULL);

        /* cleanup */
        pcap_freecode(&fp);
        pcap_close(handle);

        printf("\nCapture complete.\n");

    return 0;
    }
    展开全文
  • insys-sniff:测试任务

    2021-04-17 22:01:26
    $ cd insys-sniff/ $ git clone https://github.com/zserge/jsmn $ make 跑步 在命令行中提供参数,-d表示网络设备,-f表示单个过滤器。 您也可以添加多个过滤器。 例子 $ sudo ./insys-sniff -d eth0 -f u,8.8.8.8,...
  • Sniff 绿色版 网络传输包查看工具
  • SNIff嗅探工具

    2012-03-26 21:28:34
    SNIff嗅探工具 分享一下 嘿嘿 学习学习
  • 蓝牙的sniff mode

    千次阅读 2019-03-12 15:02:51
    在解析蓝牙的sniff mode之前,我们先来回顾一下蓝牙有哪些连接状态。 一、 蓝牙的连接状态转换图如下: http://blog.chinaunix.net/attachment/201605/6/21411227_1462520395149C.png Con...

    https://blog.csdn.net/z497544849/article/details/84143224
     

    在解析蓝牙的sniff mode之前,我们先来回顾一下蓝牙有哪些连接状态。

    一、 蓝牙的连接状态转换图如下:
         http://blog.chinaunix.net/attachment/201605/6/21411227_1462520395149C.png

    Connection State:如上图所示,蓝牙的连接态有几个子状态,分别如下:

    其中包含三种状态属于节能态,Sniff/Hold/Park Mode.

        Connectionless Slave Broadcast Mode:

    用来传输特性广播数据(profile broadcast data)。

        Active Mode:(主动模式)

    在此模式下,微微网内部所有的从设备都可以和主设备通信,当然按照Spec最多只能有七个从设备。所有的通信都有主设备来主导。微微网所有的从设备都会在主设备-> 从设备时隙上监听数据包。如果一个从设备没有被寻址,它将等待下一个数据传输。从设备能从主设备传输的包头获取传输占用的时隙,在此期间没有被寻址的设备将会等待传输时隙。具体可以参考下图,多从设备传输时序图:
    http://blog.chinaunix.net/attachment/201605/6/21411227_1462520423hUQF.png

        Sniff Mode:(呼吸模式)

    呼吸模式通过减少主设备发送数据的时隙数并相应减少从设备监听的时隙数,从而达到节省电源的目的。在sniff模式下主设备将每隔Tsniff向从设备发送数据包,所以从设备每隔Tsniff去监听主设备的数据包即可!slave就是只在sniff anchor point时监听。sniff mode只能应用于异步传输,不能应用于同步逻辑传输。后面会详细介绍这部分。

        Hold Mode:

    保持模式是蓝牙节能模式中最简单的一种。主从设备将对从设备处于保持模式的时间进行协商 ,一旦连接处于保持模式,此连接就不再支持数据包,从而可以节省电源或参与到其它微微网(piconet)中。有一点非常重要,即当每次进入保持模式时都需要对保持周期进行协商。关于保持模式还有一个更加重要的方面,即一旦设备进入保持模式就不能取消,并且保持周期必须在通信恢复前结束。

    从机和主机协商一个保持时间,在此期间从设备进入低功耗模式但仍然保持LT_ADDR。异步传输在此模式下,不响应当然微微网的任何数据包。但在同步传输模式下(SCO,eSCO)需要支持保留时隙的数据包。在此模式下的设备可以scanning, paging, inquiring, 或者加入其它的微微网。

        Park State:

    暂停模式可以最大限度的节省电源。当一个从设备不需要一直参与微微网的信道,但是却需要保持跟信道的同步时,从设备可以进入Park state。

    处于Park state状态下的从设备只有很少的活动,它会选择放弃它的逻辑传输地址 LT_ADDR,取而代之的是,它会使用两个新的地址:

    PM_ADDR: 8-bit Parked Member Address

    AR_ADDR: 8-bit Access Request Address

    另外,为了达到低功耗的目的,在Park state下,一个master可以连接多于七个slaves. 在一时刻, 只有七个slaves可以开始连接状态。但是,通过交换active slave 和park slave, 在微微网中的slaves的数目可以达到更多(255 如果PM_ADDR被使用的时候,并且如果用了BD_ADDR,这个数目还可以随机大);

    二、sniff mode及其参数的解释

        sniff mode干什么用的?

    简单来说,他就是为了省电用的。在active mode,slave必须在每个master-to-slave的slot中监听master的数据,看看有没有发给自己的;而一旦进入sniff mode,slave就不必每个master-to-slave slot都去监听。这样slave就可以更加省电了,没事儿的时候就可以睡下去。但是它必须定期醒过来,看看master是否有消息传过来。

        sniff mode的基本概念

    https://img-blog.csdn.net/20150215183400065?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    上面这张图说的就是前面讲得sniff mode。

    首先是sniff interval,也就是slave定期(醒来)监听master数据的时间周期。图中用Tsniff来表示这个参数。其实它是以slot为单位的,具体的周期还得乘以0.625ms。假如某个slave请求的sniff mode的interval为18个slot,则它的Tsniff为18,周期为18*0.625=11.25ms。

    其次是sniff anchor point,也就是所谓的sniff锚点。从这个锚点开始,slave会监听一段时间master的报文(从而锚点必然是某个master-to-slave slot的开始)。如果没有消息,那么slave可能就要休息去了。具体slave监听多久,有几个参数来决定。Wait,我们等会再讨论它们。上面这张图说的是一个slave的情况,那要是有多个slave怎么办呢?看下面这张图:

    https://img-blog.csdn.net/20150215190226692?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    此图说明了多个slave的情况。当遇到多个slave请求进入sniff mode时,slave必须在sniff interval的基础上通过设置一个偏移量来决定自己实际的anchor point。这一点是通过下面这个等式来实现的:

    Dsniff = Clock_Value (bits 26-1) mod Tsniff

    这里的Dsniff就是前面提到的offset。它必须为偶数,因为master只会在偶数slot给slave发包。slave在请求进入sniff mode时,通过Dsniff这个参数就可以与其他处在sniff mode的设备区分开,获得不同时间的anchor point。(有没有觉得以上的两张图风格不一样?前一个是core spec的,后一个则是whitepaper中的)。

    下面来看看剩下的两个参数——Nsniff_attempt和Nsniff_timeout。先说说Nsniff attempt,它表示slave在每个sniff interval中监听master-to-slave的slot数量。下图说明了Nsniff_attempts为3的情况,slave必须在anchor point到来后的3个slot内保持监听状态。

    https://img-blog.csdn.net/20150215191813317?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    几点说明:

    1)由于master-to-slave和slave-to-master的slot是交叉出现的,因此图中Nsniff_attempt的持续时间为3+2=5个slot,包含3个master-to-slave slot;

    2)由于包含anchor point开始的第一个slot,因此Nsniff_attempt的值必须至少为1;

    3)Nsniff_attempt的最大不得超过Tsniff/2;

    4)在Nsniff_attempt中的每个master-to-slave slot,slave都必须处在监听状态;

    5)如果在Nsniff_attempt期间slave没有收到master的数据,那么slave就可以睡下去了。

    最后一个参数是Nsniff_timeout,它的作用在下图得到了较好的说明:

    https://img-blog.csdn.net/20150215192927114?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    在上面这张图中,如果在Nsniff_attempt期间收到master的数据,那么slave还必须继续继续监听Nsniff_timeout数量的master-to-slave slot,以便两者继续交换data而不用等到下一个anchor point到来。注意,一旦收到数据,slave就必须重新等待Nsniff_timeout个slot,这个值不会改变。
    ---------------------  
    作者:no输给现实  
    来源:CSDN  
    原文:https://blog.csdn.net/z497544849/article/details/84143224  
    版权声明:本文为博主原创文章,转载请附上博文链接!

     

    展开全文
  • cocoa-sniff 有助于尝试使用 Cocoa 进行文本编码转换。 它可以让您快速: 通过 Cocoa 名称和最近的 IANA 字符集名称列出 Cocoa 已知的编码 尝试使用给定的编码读取文件,并查看是否出现此错误 查看 Cocoa 为文件...
  • 搜集的两个usb分析工具sniffUSB、 USBlyzer。
  • sniff教程.pdf

    2021-09-30 18:42:40
    sniff教程.pdf
  • 我在模拟这个过程中的服务器,在接收到客户端的request报文后,发送ack,同时也发送服务器端的request报文 然后用sniff函数在侦探的时候,会抓到客户端的request报文,然后也会抓到自己发送的request报文, 我百度后...
  • 嗅探探针 即插即用的bash脚本,用于嗅探802.11探测请求。 什么是探测请求? 探测请求是802.11 WIFI数据包类型,其功能是自动将网络设备连接到它们先前关联的无线...IFACE=wlan0 ./sniff-probes.sh 00:00:19 -88dBm 00
  • Python Scapy工具-sniff函数

    千次阅读 2021-07-23 15:38:12
    Scapy 是适用于 Python 的一个快速、高层次的屏幕抓取和 web 抓取框架,用于抓取 web站点并从页面中提取结构化的数据。 Scapy可以轻松地处理扫描(Scanning)、路由跟踪(Tracerouting)、探测(Probing)、...sniff(count=
  • python – 使用sniff()函数进行Scapy过滤

    千次阅读 2021-03-17 02:16:51
    我正在使用scapy函数sniff()进行数据包捕获.我想只捕获EAP数据包.我可以使用tcpdump使用以下过滤器过滤EAP数据包:# tcpdump -i mon0 -p ether proto 0x888etcpdump: WARNING: mon0: no IPv4 address ...
  • 我使用scapy函数sniff()来捕获数据包。我只想捕获EAP数据包。我可以使用以下筛选器使用tcpdump筛选EAP数据包:# tcpdump -i mon0 -p ether proto 0x888etcpdump: WARNING: mon0: no IPv4 address assignedtcpdump: ...
  • sniff源代码

    2013-06-14 15:03:55
    c++实现的sniff,使用winsock,获取包并分析。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,279
精华内容 3,711
关键字:

sniff