arping.go 858 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. package neighbors
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "os/exec"
  7. )
  8. type (
  9. ARPing interface {
  10. Ping(ctx context.Context, ifi, hw, ip string) (bool, error)
  11. }
  12. arping struct {
  13. cmd, sudoCmd, count string
  14. }
  15. )
  16. func NewARPing(count uint) (ARPing, error) {
  17. cmd, err := exec.LookPath("arping")
  18. if err != nil {
  19. return nil, err
  20. }
  21. sudoCmd, err := exec.LookPath("sudo")
  22. if err != nil {
  23. return nil, err
  24. }
  25. return &arping{cmd: cmd, sudoCmd: sudoCmd, count: fmt.Sprint(count)}, nil
  26. }
  27. func (a *arping) Ping(ctx context.Context, ifi, hw, ip string) (ok bool, err error) {
  28. cmd := exec.CommandContext(ctx, a.sudoCmd, a.cmd, "-c", a.count, "-i", ifi, "-t", hw, "-q", ip)
  29. err = cmd.Run()
  30. if err == nil {
  31. ok = true
  32. } else {
  33. var exitError *exec.ExitError
  34. if errors.As(err, &exitError) && len(exitError.Stderr) == 0 {
  35. err = nil
  36. }
  37. }
  38. return
  39. }