Giter Site home page Giter Site logo

go-ping's Introduction

go-ping

GoDoc Build Status Codecov Go Report Card

A simple ICMP Echo implementation, based on golang.org/x/net/icmp.

Some sample programs are provided in cmd/:

  • ping-test is a really simple ping clone
  • multiping provides an interactive TUI to ping multiple hosts
  • ping-monitor pings multiple hosts in parallel, but just prints the summary every so often
  • pingnet allows to ping every host in a CIDR range (e.g. 0.0.0.0/0 :-))

Features

  • IPv4 and IPv6 support
  • Unicast and multicast support
  • configurable retry amount and timeout duration
  • configurable payload size (and content)
  • round trip time measurement

Contribute

Simply fork and create a pull-request. We'll try to respond in a timely fashion.

Software using this library

Please create a pull request to get your software listed.

License

MIT License, Copyright (c) 2018 Digineo GmbH

https://www.digineo.de

go-ping's People

Contributors

corny avatar dmke avatar foogod avatar muesli avatar stapelberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-ping's Issues

occasional panic with `close of closed channel`

Hi,

Sometimes my pings cause a panic with a close of closed channel error, with the stack trace below. This isn't consistent and I suspect it has to do with a timeout. Will it make sense for the request object to keep track of whether the close method was already called?

Cheers,
Shmul

	/Users/shmul/.gb/cache/feff65bd4f236b80ca0533a1a4dce8698f5038eb/src/github.com/digineo/go-ping/request.go:55 +0x2e
github.com/digineo/go-ping.(*Pinger).sendRequest(0xc420206a20, 0xc420206bd8, 0x18f13e0, 0xc4202ce380, 0xc4202c0000, 0x0, 0x0)
	/Users/shmul/.gb/cache/feff65bd4f236b80ca0533a1a4dce8698f5038eb/src/github.com/digineo/go-ping/sending.go:149 +0x34d
github.com/digineo/go-ping.(*Pinger).PingContext(0xc420206a20, 0x18f2820, 0xc4202e26c0, 0xc420206bd8, 0x1d142e0, 0x18f2820, 0xc4202e26c0)
	/Users/shmul/.gb/cache/feff65bd4f236b80ca0533a1a4dce8698f5038eb/src/github.com/digineo/go-ping/sending.go:45 +0x78
github.com/digineo/go-ping.(*Pinger).Ping(0xc420206a20, 0xc420206bd8, 0x2540be400, 0x0, 0x0, 0x0)
	/Users/shmul/.gb/cache/feff65bd4f236b80ca0533a1a4dce8698f5038eb/src/github.com/digineo/go-ping/sending.go:37 +0xea
github.com/digineo/go-ping/monitor.(*Target).ping(0xc420206bd0)
	/Users/shmul/.gb/cache/feff65bd4f236b80ca0533a1a4dce8698f5038eb/src/github.com/digineo/go-ping/monitor/target.go:69 +0x40
created by github.com/digineo/go-ping/monitor.(*Target).run
	/Users/shmul/.gb/cache/feff65bd4f236b80ca0533a1a4dce8698f5038eb/src/github.com/digineo/go-ping/monitor/target.go:52 +0x89```

Pinger.New() can only create privileged icmp.PacketConn

Pinger.New() runs connectICMP() which runs icmp.ListenPacket(network, address) using static value "ip4:icmp" as network. Per icmp.ListenPacket() def, this only allows usage of privileged endpoints.

ListenPacket listens for incoming ICMP packets addressed to address. See net.Dial for the syntax of address.

For non-privileged datagram-oriented ICMP endpoints, network must be "udp4" or "udp6". The endpoint allows to read, write a few limited ICMP messages such as echo request and echo reply. Currently only Darwin and Linux support this.

Memory leak

There appears to be a memory leak somewhere in the program:

leak

I'm utilizing the included ping-monitor code, without any modifications.

I'm running the script in a PowerShell terminal, with these arguments:
go run . -pingInterval 1s -pingTimeout 1s -reportInterval 1s 8.8.8.8 10.10.10.10

At first I thought the leak might have been in the summary printing, since I was running it on 1s intervals, but increasing it to 5s didn't seem to affect the memory leak rate. Though, decreasing the -pingInterval did change the leak rate noticeably.
(1MB of RAM filled up in 17 seconds with 50ms intervals, pinging the same 2 IPs)

Large number of hosts unstable results

I'm adding 300+ hosts to a monitor instance with a ping interval of 60s, report interval 120s, and timeout of 4. The results indicate lost packets for IPs that are indeed up, etc.

After adding some error messages it looks like it is timeout i/o error. Are there any suggestions for pinging >100 addresses?

Monitor, not pinging hosts, unstable results

Hi,

I've used your example code to add 593 of our hosts to the monitor tool, since it basically should do what I need (I need a statistics every 60 seconds which I would want to log away).

  • Of those 593 hosts only 255 are ever reported in the ticker (always 255, always the first 255 I add as targets). It makes no difference weather I use AddTarget or AddTargetDelayed, it's always 255.

  • Hosts which are certainly available are being reported as PacketLoss 100 %, while Wireshark sees the successful UDP packages:
    image

The monitor reports the following:
2020/12/03 14:14:17 hanco: {PacketsSent:10 PacketsLost:10 Best:0 Worst:0 Median:NaN Mean:NaN StdDev:NaN}

Which is certainly the host and it can be pinged:
image

It is certainly true that several of the hosts are currently "down" because behind Firewalls and I'm not testing in the same zone, but I'd expect it to report the loss at the "right" hosts ... and all 593 instead of just 255 ofc ;-).

Current code, which pretty much reflects the example with some little changes:

package slaping

import (
	"net"
	"os"
	"time"
	"log"
	"os/signal"
	"syscall"

	"github.com/digineo/go-ping"
	"github.com/digineo/go-ping/monitor"
)

var (
	pingInterval        = 5 * time.Second
	pingTimeout         = 4 * time.Second
	reportInterval      = 60 * time.Second
	size           uint = 56
	pinger         *ping.Pinger
	targets        []string
)

func (p *SLAPing) PingHosts() {
	// setup, we need to populate cache once before we start to actually have host and maint info
	CMDBHosts, err := p.CMDB.GetSLAHosts()

	if err != nil {
		log.Println(err)
	}

	// Bind to sockets
	if pi, err := ping.New("0.0.0.0", "::"); err != nil {
		log.Printf("Unable to bind: %s\nRunning as root?\n", err)
		os.Exit(2)
	} else {
		pinger = pi
	}
	pinger.SetPayloadSize(uint16(size))
	defer pinger.Close()

	// Create monitor
	monitor := monitor.New(pinger, pingInterval, pingTimeout)
	defer monitor.Stop()

	// Add targets
	targets := CMDBHosts
	validtargets := 0
	for i, target := range CMDBHosts {
		ipAddr, err := net.ResolveIPAddr("", target)
		if err != nil {
			// currently irrelevant
			continue
		}

		err = monitor.AddTarget(string([]byte{byte(i)}), *ipAddr)
		//err = monitor.AddTargetDelayed(string([]byte{byte(i)}), *ipAddr, 10*time.Millisecond*time.Duration(i))

		if err != nil {
			// currently irrelevant
			continue
		}
		validtargets = validtargets + 1
	}

	log.Printf("Total targets: %d, Valid targets: %d, Errors: %d\n", len(targets), validtargets, len(targets)-validtargets)

	// Start report routine
	ticker := time.NewTicker(reportInterval)
	defer ticker.Stop()
	go func() {
		for range ticker.C {
			for i, metrics := range monitor.ExportAndClear() {
				log.Printf("%s: %+v\n", targets[[]byte(i)[0]], *metrics)
			}
		}
	}()

	// Handle SIGINT and SIGTERM.
	// in other words we wait here until interrupted and let the ticker tick
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	log.Println("received", <-ch)
}

[edit]
My initial thought was that it may be connected to the ICMP pings getting blocked by firewalls and threads are getting locked up due to the timeouts not properly working there, since it's an uncommon case and may not be that well tested.
Now, due to the result "shuffle" I'm not sure but I have systems in the results which actually are blocked by firewalls, going through the slice sequentially that could explain why it's always the same number, but I didn't see any max threads number to get locked in the library, is there a limit where the channel / parallel work of the library blocking?

[edit2]
I could test it now on a host which has the necessary firewall permissions to actually run this without getting blocked, the results are still the same. Something is wrong here, just can't make out what.

Windows sub millisecond resolution

When running on Windows and pinging targets on LAN with sub millisecond rtt, go-ping displays only 0.

C:\>ping-monitor -pingInterval 1s -reportInterval 1s 192.168.1.1
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0 Worst:0 Median:0 Mean:0 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0 Worst:0 Median:0 Mean:0 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0 Worst:0 Median:0 Mean:0 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0 Worst:0 Median:0 Mean:0 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0 Worst:0 Median:0 Mean:0 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0 Worst:0 Median:0 Mean:0 StdDev:0}

When equivalent is run on Linux or WSL, correct numbers are shows:

# ping-monitor -pingInterval 1s -reportInterval 1s 192.168.1.1
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0.5619 Worst:0.5619 Median:0.5619 Mean:0.5619 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0.6725 Worst:0.6725 Median:0.6725 Mean:0.6725 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0.6144 Worst:0.6144 Median:0.6144 Mean:0.6144 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0.4926 Worst:0.4926 Median:0.4926 Mean:0.4926 StdDev:0}
192.168.1.1: {PacketsSent:1 PacketsLost:0 Best:0.4771 Worst:0.4771 Median:0.4771 Mean:0.4771 StdDev:0}

If RTT is above 1ms then no problem is observed.

feature request: obtain source address of ICMP reply packet

When doing a broadcast/multicast ping (e.g. to ip6-allrouters, i.e. ff02::2), I’m interested in the source address of the ICMP reply packet.

Unfortunately, this package does not offer a way to obtain the source address AFAICT. Could a way be added? If you lack the time, I’m happy to contribute a PR, but figured I’d check with you first regarding the preferred API for the feature, provided you’re okay with accepting it.

Thanks in advance!

Help me please with this library

I'm newbie in golang, help me please. How to convert functionality of this library to one simple function:
func ping(timeout time.Duration, attemts int) (rtts []int, err error)
No one library that i have found provide such simple interface like this.
And i want to be able run about 500 instances of this function concurrently to monitor my network.

If anyone can help I would be very grateful :)

Listening for a ping and responding

I'm trying to build an app (using TUN) that listens to pings and responds to them (instead of the native) ping app. I'm new to networking, but wondered if this library can facilitate this?
Most of its for educational reasons really, I want to see if I can force increased ping latency etc

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.