Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix panic when running ICMPv4 probe with DontFragment #686

Merged
merged 1 commit into from
Aug 29, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 28 additions & 21 deletions prober/icmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr
setupStart := time.Now()
level.Info(logger).Log("msg", "Creating socket")

unprivileged := false
privileged := true
// Unprivileged sockets are supported on Darwin and Linux only.
tryUnprivileged := runtime.GOOS == "darwin" || runtime.GOOS == "linux"

Expand All @@ -119,11 +119,11 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr
if err != nil {
level.Debug(logger).Log("msg", "Unable to do unprivileged listen on socket, will attempt privileged", "err", err)
} else {
unprivileged = true
privileged = false
}
}

if !unprivileged {
if privileged {
icmpConn, err = icmp.ListenPacket("ip6:ipv6-icmp", srcIP.String())
if err != nil {
level.Error(logger).Log("msg", "Error listening to socket", "err", err)
Expand All @@ -140,42 +140,49 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr
srcIP = net.ParseIP("0.0.0.0")
}

var icmpConn *icmp.PacketConn
// If the user has set the don't fragment option we cannot use unprivileged
// sockets as it is not possible to set IP header level options.
if tryUnprivileged && !module.ICMP.DontFragment {
icmpConn, err = icmp.ListenPacket("udp4", srcIP.String())
if err != nil {
level.Debug(logger).Log("msg", "Unable to do unprivileged listen on socket, will attempt privileged", "err", err)
} else {
unprivileged = true
}
}

if !unprivileged {
icmpConn, err = icmp.ListenPacket("ip4:icmp", srcIP.String())
if module.ICMP.DontFragment {
// If the user has set the don't fragment option we cannot use unprivileged
// sockets as it is not possible to set IP header level options.
icmpConn, err := net.ListenPacket("ip4:icmp", srcIP.String())
if err != nil {
level.Error(logger).Log("msg", "Error listening to socket", "err", err)
return
}
}

if module.ICMP.DontFragment {
rc, err := ipv4.NewRawConn(icmpConn)
if err != nil {
level.Error(logger).Log("msg", "Error creating raw connection", "err", err)
return
}
socket = &v4Conn{c: rc, df: true}
} else {
var icmpConn *icmp.PacketConn

if tryUnprivileged {
icmpConn, err = icmp.ListenPacket("udp4", srcIP.String())
if err != nil {
level.Debug(logger).Log("msg", "Unable to do unprivileged listen on socket, will attempt privileged", "err", err)
} else {
privileged = false
}
}

if privileged {
icmpConn, err = icmp.ListenPacket("ip4:icmp", srcIP.String())
if err != nil {
level.Error(logger).Log("msg", "Error listening to socket", "err", err)
return
}
}

socket = icmpConn
}
}

defer socket.Close()

var dst net.Addr = ip
if unprivileged {
if !privileged {
dst = &net.UDPAddr{IP: ip.IP, Zone: ip.Zone}
}

Expand Down Expand Up @@ -217,7 +224,7 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr
// unprivileged sockets were used and the kernel used its own.
wm.Type = replyType
// Unprivileged cannot set IDs on Linux.
idUnknown := unprivileged && runtime.GOOS == "linux"
idUnknown := !privileged && runtime.GOOS == "linux"
if idUnknown {
body.ID = 0
}
Expand Down