mirror of
https://github.com/nxtrace/NTrace-core.git
synced 2025-08-12 06:26:39 +00:00
handleICMPMessage 采用更健壮的方案处理ICMPv6头部,之前使用了一个固定的偏移量来从 ICMPv6 错误消息中提取 UDP 源端口,现在改为动态计算偏移量
This commit is contained in:
@@ -117,27 +117,88 @@ func (t *UDPTracerIPv6) listenICMP() {
|
||||
}
|
||||
}
|
||||
|
||||
// handleICMPMessage 处理 ICMPv6 消息并提取 UDP 源端口
|
||||
//
|
||||
// ICMPv6 错误消息格式:
|
||||
// - ICMPv6 头部 (8 字节)
|
||||
// - 原始 IPv6 包 (包含 IPv6 头部和 UDP 头部)
|
||||
//
|
||||
// 处理步骤:
|
||||
// 1. 验证消息长度
|
||||
// 2. 解析 ICMPv6 头部
|
||||
// 3. 提取原始 IPv6 包
|
||||
// 4. 处理可能的扩展头部
|
||||
// 5. 提取 UDP 源端口
|
||||
// 6. 发送结果到对应通道
|
||||
func (t *UDPTracerIPv6) handleICMPMessage(msg ReceivedMessage) {
|
||||
// 对于IPv6,我们需要从ICMP消息中提取UDP源端口
|
||||
// 这里假设UDP头部在ICMP消息的固定位置
|
||||
if len(msg.Msg) < 48+8 {
|
||||
return
|
||||
}
|
||||
// ICMPv6 错误消息至少需要包含 IPv6 头部(40字节)和部分 UDP 头部
|
||||
if len(msg.Msg) < 48 {
|
||||
return
|
||||
}
|
||||
|
||||
// IPv6 ICMP错误消息包含原始数据包的IPv6头(40字节)和UDP头(8字节)
|
||||
// 从UDP头部提取源端口(前2字节)
|
||||
srcPort := int(uint16(msg.Msg[48])<<8 | uint16(msg.Msg[49]))
|
||||
|
||||
t.inflightRequestLock.Lock()
|
||||
defer t.inflightRequestLock.Unlock()
|
||||
ch, ok := t.inflightRequest[srcPort]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ch <- Hop{
|
||||
Success: true,
|
||||
Address: msg.Peer,
|
||||
}
|
||||
// 尝试解析 ICMPv6 消息中包含的原始数据包
|
||||
var offset int = 8 // ICMPv6 头部长度
|
||||
|
||||
// 检查剩余长度是否足够包含 IPv6 头部
|
||||
if len(msg.Msg) < offset+40 {
|
||||
return
|
||||
}
|
||||
|
||||
// 验证 IPv6 版本 (前4位应该是6)
|
||||
if (msg.Msg[offset] >> 4) != 6 {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取下一个头部类型
|
||||
nextHeader := msg.Msg[offset+6]
|
||||
|
||||
// 跳过 IPv6 基本头部
|
||||
offset += 40
|
||||
|
||||
// 处理可能的扩展头部
|
||||
for nextHeader != 17 && offset+2 < len(msg.Msg) { // 17 是 UDP 协议号
|
||||
switch nextHeader {
|
||||
case 0: // Hop-by-Hop Options
|
||||
case 43: // Routing
|
||||
case 44: // Fragment
|
||||
case 50: // ESP
|
||||
case 51: // AH
|
||||
case 60: // Destination Options
|
||||
if offset+2 >= len(msg.Msg) {
|
||||
return // 不够长,无法读取扩展头部长度
|
||||
}
|
||||
nextHeader = msg.Msg[offset]
|
||||
headerLen := int(msg.Msg[offset+1])*8 + 8
|
||||
offset += headerLen
|
||||
default:
|
||||
// 未知或不支持的扩展头部类型
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 确认下一个头部是 UDP (17)
|
||||
if nextHeader != 17 {
|
||||
return
|
||||
}
|
||||
|
||||
// 确保有足够的数据来读取 UDP 源端口
|
||||
if offset+2 > len(msg.Msg) {
|
||||
return
|
||||
}
|
||||
|
||||
// 从 UDP 头部提取源端口(前2字节)
|
||||
srcPort := int(uint16(msg.Msg[offset])<<8 | uint16(msg.Msg[offset+1]))
|
||||
|
||||
t.inflightRequestLock.Lock()
|
||||
defer t.inflightRequestLock.Unlock()
|
||||
ch, ok := t.inflightRequest[srcPort]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ch <- Hop{
|
||||
Success: true,
|
||||
Address: msg.Peer,
|
||||
}
|
||||
}
|
||||
|
||||
var cachedLocalPortv6 int
|
||||
|
||||
Reference in New Issue
Block a user