arp.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package neighbors
  2. import (
  3. "context"
  4. "net"
  5. "os/exec"
  6. "goa.design/clue/log"
  7. )
  8. type (
  9. Interfaces map[string]bool
  10. HardwareAddrStates map[string]State
  11. ARP interface {
  12. Present(ctx context.Context, ifs Interfaces, state State, addrStates HardwareAddrStates) error
  13. Count(count uint)
  14. }
  15. arp struct {
  16. cmd string
  17. arping ARPing
  18. }
  19. )
  20. func NewARP(count uint) (ARP, error) {
  21. cmd, err := exec.LookPath(arpCmd)
  22. if err != nil {
  23. return nil, err
  24. }
  25. arping, err := NewARPing(count)
  26. if err != nil {
  27. return nil, err
  28. }
  29. return &arp{
  30. cmd: cmd,
  31. arping: arping,
  32. }, nil
  33. }
  34. func (a *arp) Present(ctx context.Context, ifs Interfaces, state State, addrStates HardwareAddrStates) (err error) {
  35. as := make(map[string]bool, len(addrStates))
  36. for hw := range addrStates {
  37. as[hw] = false
  38. }
  39. es, err := a.entries(ctx, ifs)
  40. if err != nil {
  41. return
  42. }
  43. for _, e := range es {
  44. log.Debug(ctx, log.KV{K: "IP address", V: e.IPAddress}, log.KV{K: "MAC address", V: e.MACAddress}, log.KV{K: "interface", V: e.Interface})
  45. if ifs[e.Interface] {
  46. var hwa net.HardwareAddr
  47. hwa, err = net.ParseMAC(e.MACAddress)
  48. if err != nil {
  49. return
  50. }
  51. hw := hwa.String()
  52. if _, ok := as[hw]; ok {
  53. ok, err = a.arping.Ping(ctx, e.Interface, hw, e.IPAddress)
  54. if err != nil {
  55. return
  56. }
  57. as[hw] = ok
  58. }
  59. }
  60. }
  61. present := false
  62. for hw, ok := range as {
  63. addrStates[hw].Set(ok)
  64. if ok {
  65. present = true
  66. }
  67. }
  68. state.Set(present)
  69. return
  70. }
  71. func (a *arp) Count(count uint) {
  72. a.arping.Count(count)
  73. }