如何区分扩展和上层头

时间:2017-02-16 23:02:00

标签: c sockets filter ipv6 icmp

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

迭代本身不是问题,因为每个扩展标头都有其长度。但是,我找不到区分可能遵循的扩展标头和其他高级协议(例如 TCP UDP )的好方法。我可以检查Next Header是否是已知的扩展标头之一(在这种情况下我可以迭代)或者如果Next Header是上层协议(在这种情况下我必须停止,那么赢了&# 39; t是任何 ICMP ..)。

在这两种方法中,我都依赖于一些自建的常量列表,我会检查Next Header,并且该列表将来可能会发生变化。当我在扩展标题的末尾和上层标题(或者没有标题)后面有什么更好的方法可以告诉我吗?

2 个答案:

答案 0 :(得分:3)

每个扩展标头都有自己的Next Header字段作为其第一个八位字节,其含义与固定IPv6标头的相应字段具有相同的含义(但不同的相对位置)。您可以将这些与扩展标题一起使用' length字段逐步执行扩展标头,直到找到传输层标头。维基百科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
};

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

答案 1 :(得分:2)

除了走链子之外别无其他事情,听起来就像你正在做的那样。正如您在评论中提到的那样,“标准方法,以确定下一个标题是否也将是扩展名”,如果它是其中一个值,则表示它是IPv6扩展标头。最初,除了逐跳扩展头(大多数网络管理员忽略,因为让终端设备指示路由是一种不好的做法),所有中间节点(路由器等)都应该{{ 3}}:

  

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

     

前一段中提到的例外是Hop-by-   Hop Options标头,包含必须检查的信息   并且每个节点沿着数据包的传递路径进行处理,包括   源节点和目标节点。 Hop-by-Hop选项标题,何时   目前,必须立即遵循IPv6标头。它的存在是   由IPv6的Next Header字段中的值零指示   报头中。

     

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

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

ignore extension headers尝试为IPv6扩展标头添加一些订单,但遗憾的是,它无法对先前定义的IPv6扩展标头执行任何操作。

RFC 6564, A Uniform Format for IPv6 Extension Headers讨论了有关IPv6扩展标头的问题。