79 lines
2.3 KiB
Go
79 lines
2.3 KiB
Go
package ping
|
|
|
|
import (
|
|
"net/netip"
|
|
|
|
"github.com/sagernet/sing-tun"
|
|
"github.com/sagernet/sing-tun/internal/gtcpip/header"
|
|
"github.com/sagernet/sing/common/buf"
|
|
)
|
|
|
|
type DestinationWriter struct {
|
|
tun.DirectRouteDestination
|
|
destination netip.Addr
|
|
}
|
|
|
|
func NewDestinationWriter(routeDestination tun.DirectRouteDestination, destination netip.Addr) *DestinationWriter {
|
|
return &DestinationWriter{routeDestination, destination}
|
|
}
|
|
|
|
func (w *DestinationWriter) WritePacket(packet *buf.Buffer) error {
|
|
var ipHdr header.Network
|
|
switch header.IPVersion(packet.Bytes()) {
|
|
case header.IPv4Version:
|
|
ipHdr = header.IPv4(packet.Bytes())
|
|
case header.IPv6Version:
|
|
ipHdr = header.IPv6(packet.Bytes())
|
|
default:
|
|
return w.DirectRouteDestination.WritePacket(packet)
|
|
}
|
|
ipHdr.SetDestinationAddr(w.destination)
|
|
if ipHdr4, isIPv4 := ipHdr.(header.IPv4); isIPv4 {
|
|
ipHdr4.SetChecksum(^ipHdr4.CalculateChecksum())
|
|
}
|
|
if ipHdr.TransportProtocol() == header.ICMPv6ProtocolNumber {
|
|
icmpHdr := header.ICMPv6(ipHdr.Payload())
|
|
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
|
|
Header: icmpHdr,
|
|
Src: ipHdr.SourceAddressSlice(),
|
|
Dst: ipHdr.DestinationAddressSlice(),
|
|
}))
|
|
}
|
|
return w.DirectRouteDestination.WritePacket(packet)
|
|
}
|
|
|
|
type ContextDestinationWriter struct {
|
|
tun.DirectRouteContext
|
|
destination netip.Addr
|
|
}
|
|
|
|
func NewContextDestinationWriter(context tun.DirectRouteContext, destination netip.Addr) *ContextDestinationWriter {
|
|
return &ContextDestinationWriter{
|
|
context, destination,
|
|
}
|
|
}
|
|
|
|
func (w *ContextDestinationWriter) WritePacket(packet []byte) error {
|
|
var ipHdr header.Network
|
|
switch header.IPVersion(packet) {
|
|
case header.IPv4Version:
|
|
ipHdr = header.IPv4(packet)
|
|
case header.IPv6Version:
|
|
ipHdr = header.IPv6(packet)
|
|
default:
|
|
return w.DirectRouteContext.WritePacket(packet)
|
|
}
|
|
ipHdr.SetSourceAddr(w.destination)
|
|
if ipHdr4, isIPv4 := ipHdr.(header.IPv4); isIPv4 {
|
|
ipHdr4.SetChecksum(^ipHdr4.CalculateChecksum())
|
|
}
|
|
if ipHdr.TransportProtocol() == header.ICMPv6ProtocolNumber {
|
|
icmpHdr := header.ICMPv6(ipHdr.Payload())
|
|
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
|
|
Header: icmpHdr,
|
|
Src: ipHdr.SourceAddressSlice(),
|
|
Dst: ipHdr.DestinationAddressSlice(),
|
|
}))
|
|
}
|
|
return w.DirectRouteContext.WritePacket(packet)
|
|
}
|