Files
sing-tun/ping/cmsg_windows.go
2025-08-23 16:16:28 +08:00

47 lines
1.2 KiB
Go

package ping
import (
"encoding/binary"
"fmt"
"unsafe"
"golang.org/x/net/ipv6"
"golang.org/x/sys/windows"
)
const (
IPV6_HOPLIMIT = 21
IPV6_TCLASS = 39
IPV6_RECVTCLASS = 40
)
var (
alignedSizeofCmsghdr = (sizeofCmsghdr + cmsgAlignTo - 1) & ^(cmsgAlignTo - 1)
sizeofCmsghdr = int(unsafe.Sizeof(windows.WSACMSGHDR{}))
cmsgAlignTo = int(unsafe.Sizeof(uintptr(0)))
)
func cmsgAlign(n int) int {
return (n + cmsgAlignTo - 1) & ^(cmsgAlignTo - 1)
}
func parseIPv6ControlMessage(cmsg []byte) (*ipv6.ControlMessage, error) {
var controlMessage ipv6.ControlMessage
for len(cmsg) >= sizeofCmsghdr {
cmsghdr := (*windows.WSACMSGHDR)(unsafe.Pointer(unsafe.SliceData(cmsg)))
msgLen := int(cmsghdr.Len)
msgSize := cmsgAlign(msgLen)
if msgLen < sizeofCmsghdr || msgSize > len(cmsg) {
return nil, fmt.Errorf("invalid control message length %d", cmsghdr.Len)
}
switch cmsghdr.Type {
case IPV6_TCLASS:
controlMessage.TrafficClass = int(binary.NativeEndian.Uint32(cmsg[alignedSizeofCmsghdr : alignedSizeofCmsghdr+4]))
case IPV6_HOPLIMIT:
controlMessage.HopLimit = int(binary.NativeEndian.Uint32(cmsg[alignedSizeofCmsghdr : alignedSizeofCmsghdr+4]))
}
cmsg = cmsg[msgSize:]
}
return &controlMessage, nil
}