neighbor_table_linux.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //go:build linux
  2. package route
  3. import (
  4. "net"
  5. "net/netip"
  6. "slices"
  7. "github.com/sagernet/sing-box/adapter"
  8. E "github.com/sagernet/sing/common/exceptions"
  9. "github.com/jsimonetti/rtnetlink"
  10. "github.com/mdlayher/netlink"
  11. "golang.org/x/sys/unix"
  12. )
  13. func ReadNeighborEntries() ([]adapter.NeighborEntry, error) {
  14. connection, err := rtnetlink.Dial(nil)
  15. if err != nil {
  16. return nil, E.Cause(err, "dial rtnetlink")
  17. }
  18. defer connection.Close()
  19. neighbors, err := connection.Neigh.List()
  20. if err != nil {
  21. return nil, E.Cause(err, "list neighbors")
  22. }
  23. var entries []adapter.NeighborEntry
  24. for _, neighbor := range neighbors {
  25. if neighbor.Attributes == nil {
  26. continue
  27. }
  28. if neighbor.Attributes.LLAddress == nil || len(neighbor.Attributes.Address) == 0 {
  29. continue
  30. }
  31. address, ok := netip.AddrFromSlice(neighbor.Attributes.Address)
  32. if !ok {
  33. continue
  34. }
  35. entries = append(entries, adapter.NeighborEntry{
  36. Address: address,
  37. MACAddress: slices.Clone(neighbor.Attributes.LLAddress),
  38. })
  39. }
  40. return entries, nil
  41. }
  42. func ParseNeighborMessage(message netlink.Message) (address netip.Addr, macAddress net.HardwareAddr, isDelete bool, ok bool) {
  43. var neighMessage rtnetlink.NeighMessage
  44. err := neighMessage.UnmarshalBinary(message.Data)
  45. if err != nil {
  46. return
  47. }
  48. if neighMessage.Attributes == nil || len(neighMessage.Attributes.Address) == 0 {
  49. return
  50. }
  51. address, ok = netip.AddrFromSlice(neighMessage.Attributes.Address)
  52. if !ok {
  53. return
  54. }
  55. isDelete = message.Header.Type == unix.RTM_DELNEIGH
  56. if !isDelete && neighMessage.Attributes.LLAddress == nil {
  57. ok = false
  58. return
  59. }
  60. macAddress = slices.Clone(neighMessage.Attributes.LLAddress)
  61. return
  62. }