【问题标题】:How to differentiate between extension and upper-layer header如何区分扩展头和上层头
【发布时间】:2017-07-06 07:08:10
【问题描述】:

我正在尝试解析通过原始套接字接收的 IPv6 数据包并确定它是否是 ICMPv6。我可以处理 EthernetIPv6 标头,但是还有可选的扩展标头。如果 IPv6 标头的 Next Header 字段不是 ICMPv6,我必须遍历可能之前的任何扩展。

迭代本身不是问题,因为每个扩展头都有自己的长度。但是,我找不到一个很好的方法来区分可能遵循的扩展标头和其他上层协议,例如 TCPUDP。我可以检查Next Header 是否是已知的扩展标头之一(在这种情况下我可以迭代)或者Next Header 是否是上层协议(在这种情况下我必须停止,不会有任何 ICMP..)。

在这两种方法中,我都依赖于一些我正在检查Next Header 的自建常量列表,并且该列表将来可能会改变。难道没有更好的方法来判断我何时处于扩展标头的末尾并且上层标头(或什么都没有)跟随?

【问题讨论】:

  • 不幸的是,无法确定未知的下一个标头值的含义。您必须依赖代码中的表。

标签: c sockets filter ipv6 icmp


【解决方案1】:

每个扩展头都有自己的Next Header 字段作为其第一个八位字节,与固定 IPv6 头的相应字段具有相同的含义(但相对位置不同)。您可以将这些与扩展标头的长度字段一起使用,以逐步检查扩展标头,直到找到传输层标头。维基百科covers this的一些细节。


更新:

关于您修改后的问题,不,没有标准函数或算法来区分指定扩展标头的标头代码和指定协议标头的标头代码,除了简单地知道哪个是哪个。它们是从相同的代码空间分配的,没有特殊的内部结构。

但是,只有 256 个可能的值,所以要知道哪些是可行的。但是请注意:近一半的可用代码当前未分配,但将来可能会分配给扩展头类型或协议类型。除非代码用尽,否则您的软件将需要识别 三个 类别:

  • 扩展头,
  • 协议头和
  • 未知

另外,对于实现这样的测试,我建议创建和使用查找表,而不是构建复杂的条件表达式。大致如下:

enum header_type { HDR_PROTOCOL, HDR_EXTENSION, HDR_UNKNOWN };

const enum header_type header_types[256] = {
    [0x00] = HDR_EXTENSION,  // IPv6 hop-by-hop option
    [0x01] = HDR_PROTOCOL,   // ICMP
    // ... both extension and protocol headers in this range ...
    [0x8e] = HDR_PROTOCOL,   // robust header compression
    [0x8f] = HDR_UNKNOWN,    // unassigned
    // ... more unassigned ...
    [0xfd] = HDR_UNKNOWN,    // for experimentation
    [0xfe] = HDR_UNKNOWN,    // for experimentation
    [0xff] = HDR_UNKNOWN,    // reserved
};

您可以使用它来回答多种问题,而且效率也很高。初始化程序中的显式指示符不是绝对必要的,但我认为它们是个好主意:它们将帮助您验证和维护表。

【讨论】:

  • 此外,IANA 在Assigned Internet Protocol Numbers 维护可能的 IPv4 协议/IPv6 下一个标头值列表(只有 256 个可能的值)。
  • 我现在明白了,我并没有说我已经在查看扩展标题的 Next Header 字段。问题仍然是我一直在寻找一些标准方法来确定下一个标题是否也将是扩展名。正如@RonMaupin 指出的那样,没有那么多值,所以我最终编写了这样的函数pastebin.com/SXeshCmA,但我希望有更好的方法。
  • @Raven,我已经用与您修改后的问题有关的信息和建议更新了这个答案。
【解决方案2】:

除了走链子之外真的没有什么可做的,听起来这就是你正在做的事情。正如您在评论中所问的那样,“找出下一个标头是否也将是扩展的标准方法”是它是否是意味着它是 IPv6 扩展标头的值之一。最初,除了逐跳扩展标头(大多数网络管理员忽略它,因为让终端设备决定路由是一种不好的做法)之外,所有中间节点(路由器等)都应该是@987654321 @:

除了一个例外,扩展标头不会被检查或处理 数据包传递路径上的任何节点,直到数据包到达 节点(或每组节点,在多播的情况下) 在 IPv6 标头的目标地址字段中标识。那里, IPv6 标头的 Next Header 字段的正常解复用 调用模块来处理第一个扩展头,或者 如果不存在扩展头,则为上层头。内容 每个扩展头的语义决定是否 继续下一个标题。因此,扩展头必须是 严格按照它们在数据包中出现的顺序进行处理;接收器 例如,不得扫描一个数据包以寻找特定的 一种扩展标头并在处理之前处理该标头 所有前面的。

上一段中提到的例外是Hop-by- Hop Options 标头,其中包含必须检查的信息 并由数据包传递路径上的每个节点处理,包括 源节点和目的节点。逐跳选项标头,当 存在,必须紧跟 IPv6 标头。它的存在是 由 IPv6 的 Next Header 字段中的值零表示 标题。

如果作为处理标头的结果,需要一个节点继续 到下一个标头,但当前标头中的下一个标头值是 节点无法识别,它应该丢弃数据包并发送一个 ICMP 参数问题消息到数据包的来源,带有 ICMP 代码值为 1(“遇到无法识别的下一个标头类型”)和 包含无法识别值的偏移量的 ICMP 指针字段 在原始数据包内。如果一个节点应该采取同样的行动 在除 IPv6 标头。

不幸的是,现实开始了,但情况已不再如此。现在甚至有可能中间节点会添加扩展头,头链最终可能会碎片化。

RFC 6564, A Uniform Format for IPv6 Extension Headers 尝试对 IPv6 扩展标头进行排序,但不幸的是,它对先前定义的 IPv6 扩展标头无能为力。

RFC 7045, Transmission and Processing of IPv6 Extension Headers 讨论有关 IPv6 扩展标头的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    相关资源
    最近更新 更多