ping: Add bitwiseID

This commit is contained in:
wwqgtxx 2025-08-25 10:32:59 +08:00
parent 06ddb3e0a7
commit ce050baa58

View file

@ -26,6 +26,7 @@ type Conn struct {
ctx context.Context ctx context.Context
logger logger.ContextLogger logger logger.ContextLogger
privileged bool privileged bool
bitwiseID bool
conn net.Conn conn net.Conn
destination netip.Addr destination netip.Addr
source atomic.TypedValue[netip.Addr] source atomic.TypedValue[netip.Addr]
@ -37,10 +38,15 @@ func Connect(ctx context.Context, logger logger.ContextLogger, privileged bool,
if err != nil { if err != nil {
return nil, err return nil, err
} }
replaceID := true
if _, ok := conn.(*UnprivilegedConn); ok {
replaceID = false
}
return &Conn{ return &Conn{
ctx: ctx, ctx: ctx,
logger: logger, logger: logger,
privileged: privileged, privileged: privileged,
bitwiseID: replaceID,
conn: conn, conn: conn,
destination: destination, destination: destination,
}, nil }, nil
@ -102,6 +108,12 @@ func (c *Conn) ReadIP(buffer *buf.Buffer) error {
} }
ttl = controlMessage.TTL ttl = controlMessage.TTL
} }
if c.bitwiseID {
icmpHdr := header.ICMPv4(buffer.Bytes())
icmpHdr.SetIdent(^icmpHdr.Ident())
icmpHdr.SetChecksum(0)
icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr[:header.ICMPv4MinimumSize], checksum.Checksum(icmpHdr.Payload(), 0)))
}
ipHdr := header.IPv4(buffer.ExtendHeader(header.IPv4MinimumSize)) ipHdr := header.IPv4(buffer.ExtendHeader(header.IPv4MinimumSize))
ipHdr.Encode(&header.IPv4Fields{ ipHdr.Encode(&header.IPv4Fields{
// TOS: uint8(tos), // TOS: uint8(tos),
@ -135,6 +147,9 @@ func (c *Conn) ReadIP(buffer *buf.Buffer) error {
trafficClass = controlMessage.TrafficClass trafficClass = controlMessage.TrafficClass
} }
icmpHdr := header.ICMPv6(buffer.Bytes()) icmpHdr := header.ICMPv6(buffer.Bytes())
if c.bitwiseID {
icmpHdr.SetIdent(^icmpHdr.Ident())
}
icmpHdr.SetChecksum(0) icmpHdr.SetChecksum(0)
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
Header: icmpHdr[:header.ICMPv6DstUnreachableMinimumSize], Header: icmpHdr[:header.ICMPv6DstUnreachableMinimumSize],
@ -173,6 +188,9 @@ func (c *Conn) ReadIP(buffer *buf.Buffer) error {
ipHdr.SetChecksum(0) ipHdr.SetChecksum(0)
ipHdr.SetChecksum(^ipHdr.CalculateChecksum()) ipHdr.SetChecksum(^ipHdr.CalculateChecksum())
icmpHdr := header.ICMPv4(ipHdr.Payload()) icmpHdr := header.ICMPv4(ipHdr.Payload())
if c.bitwiseID {
icmpHdr.SetIdent(^icmpHdr.Ident())
}
icmpHdr.SetChecksum(0) icmpHdr.SetChecksum(0)
icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr[:header.ICMPv4MinimumSize], checksum.Checksum(icmpHdr.Payload(), 0))) icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr[:header.ICMPv4MinimumSize], checksum.Checksum(icmpHdr.Payload(), 0)))
c.logger.TraceContext(c.ctx, "read icmpv4 echo reply from ", ipHdr.SourceAddr(), " to ", ipHdr.DestinationAddr()) c.logger.TraceContext(c.ctx, "read icmpv4 echo reply from ", ipHdr.SourceAddr(), " to ", ipHdr.DestinationAddr())
@ -183,6 +201,9 @@ func (c *Conn) ReadIP(buffer *buf.Buffer) error {
} }
ipHdr.SetDestinationAddr(c.source.Load()) ipHdr.SetDestinationAddr(c.source.Load())
icmpHdr := header.ICMPv6(ipHdr.Payload()) icmpHdr := header.ICMPv6(ipHdr.Payload())
if c.bitwiseID {
icmpHdr.SetIdent(^icmpHdr.Ident())
}
icmpHdr.SetChecksum(0) icmpHdr.SetChecksum(0)
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
Header: icmpHdr, Header: icmpHdr,
@ -219,11 +240,27 @@ func (c *Conn) WriteIP(buffer *buf.Buffer) error {
defer buffer.Release() defer buffer.Release()
if !c.destination.Is6() { if !c.destination.Is6() {
ipHdr := header.IPv4(buffer.Bytes()) ipHdr := header.IPv4(buffer.Bytes())
if c.bitwiseID {
icmpHdr := header.ICMPv4(ipHdr.Payload())
icmpHdr.SetIdent(^icmpHdr.Ident())
icmpHdr.SetChecksum(0)
icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr[:header.ICMPv4MinimumSize], checksum.Checksum(icmpHdr.Payload(), 0)))
}
c.source.Store(M.AddrFromIP(ipHdr.SourceAddressSlice())) c.source.Store(M.AddrFromIP(ipHdr.SourceAddressSlice()))
c.logger.TraceContext(c.ctx, "write icmpv4 echo request from ", ipHdr.SourceAddr(), " to ", ipHdr.DestinationAddr()) c.logger.TraceContext(c.ctx, "write icmpv4 echo request from ", ipHdr.SourceAddr(), " to ", ipHdr.DestinationAddr())
return common.Error(c.conn.Write(ipHdr.Payload())) return common.Error(c.conn.Write(ipHdr.Payload()))
} else { } else {
ipHdr := header.IPv6(buffer.Bytes()) ipHdr := header.IPv6(buffer.Bytes())
if c.bitwiseID {
icmpHdr := header.ICMPv6(ipHdr.Payload())
icmpHdr.SetIdent(^icmpHdr.Ident())
icmpHdr.SetChecksum(0)
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
Header: icmpHdr,
Src: ipHdr.SourceAddressSlice(),
Dst: ipHdr.DestinationAddressSlice(),
}))
}
c.source.Store(M.AddrFromIP(ipHdr.SourceAddressSlice())) c.source.Store(M.AddrFromIP(ipHdr.SourceAddressSlice()))
c.logger.TraceContext(c.ctx, "write icmpv6 echo request from ", ipHdr.SourceAddr(), " to ", ipHdr.DestinationAddr()) c.logger.TraceContext(c.ctx, "write icmpv6 echo request from ", ipHdr.SourceAddr(), " to ", ipHdr.DestinationAddr())
return common.Error(c.conn.Write(ipHdr.Payload())) return common.Error(c.conn.Write(ipHdr.Payload()))