Fix non-privileged (UDP) ping response parsing for OSes not supporting STRIPHDR sock option

Signed-off-by: Evgeniy Makeev <evgeniym@fb.com>
This commit is contained in:
Evgeniy Makeev 2022-08-26 17:16:16 -07:00
parent b89bb75386
commit f4146feb68
4 changed files with 40 additions and 3 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/ping
/dist
.idea

16
ping.go
View File

@ -580,7 +580,8 @@ func (p *Pinger) recvICMP(
case <-p.done:
return nil
default:
bytes := make([]byte, p.getMessageLength())
expectedSize := p.getMessageLength()
bytes := make([]byte, expectedSize)
if err := conn.SetReadDeadline(time.Now().Add(delay)); err != nil {
return err
}
@ -597,7 +598,20 @@ func (p *Pinger) recvICMP(
}
return err
}
// setsockopt sysIP_STRIPHDR may not work, check if we got IP header & need to strip it
if !p.Privileged() && n >= expectedSize {
if p.ipv4 {
if hdr, err := ipv4.ParseHeader(bytes); err == nil && hdr != nil && hdr.TotalLen == n && hdr.Len == ipv4.HeaderLen {
bytes = bytes[hdr.Len:]
}
} else {
if hdr, err := ipv6.ParseHeader(bytes); err == nil && hdr.PayloadLen == p.Size && hdr.NextHeader == protocolIPv6ICMP {
bytes = bytes[ipv6.HeaderLen:]
}
}
}
select {
case <-p.done:
return nil

View File

@ -3,9 +3,20 @@
package ping
import (
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
// Returns the length of an ICMP message.
func (p *Pinger) getMessageLength() int {
return p.Size + 8
if p.Privileged() {
return p.Size + 8
}
if p.ipv4 {
return p.Size + 8 + ipv4.HeaderLen
}
return p.Size + 8 + ipv6.HeaderLen
}
// Attempts to match the ID of an ICMP packet.

View File

@ -3,9 +3,20 @@
package ping
import (
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
// Returns the length of an ICMP message.
func (p *Pinger) getMessageLength() int {
return p.Size + 8
if p.Privileged() {
return p.Size + 8
}
if p.ipv4 {
return p.Size + 8 + ipv4.HeaderLen
}
return p.Size + 8 + ipv6.HeaderLen
}
// Attempts to match the ID of an ICMP packet.