neigh_linux.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package netlink
  2. import (
  3. "net"
  4. "syscall"
  5. "unsafe"
  6. "github.com/vishvananda/netlink/nl"
  7. )
  8. const (
  9. NDA_UNSPEC = iota
  10. NDA_DST
  11. NDA_LLADDR
  12. NDA_CACHEINFO
  13. NDA_PROBES
  14. NDA_VLAN
  15. NDA_PORT
  16. NDA_VNI
  17. NDA_IFINDEX
  18. NDA_MAX = NDA_IFINDEX
  19. )
  20. // Neighbor Cache Entry States.
  21. const (
  22. NUD_NONE = 0x00
  23. NUD_INCOMPLETE = 0x01
  24. NUD_REACHABLE = 0x02
  25. NUD_STALE = 0x04
  26. NUD_DELAY = 0x08
  27. NUD_PROBE = 0x10
  28. NUD_FAILED = 0x20
  29. NUD_NOARP = 0x40
  30. NUD_PERMANENT = 0x80
  31. )
  32. // Neighbor Flags
  33. const (
  34. NTF_USE = 0x01
  35. NTF_SELF = 0x02
  36. NTF_MASTER = 0x04
  37. NTF_PROXY = 0x08
  38. NTF_ROUTER = 0x80
  39. )
  40. type Ndmsg struct {
  41. Family uint8
  42. Index uint32
  43. State uint16
  44. Flags uint8
  45. Type uint8
  46. }
  47. func deserializeNdmsg(b []byte) *Ndmsg {
  48. var dummy Ndmsg
  49. return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0]))
  50. }
  51. func (msg *Ndmsg) Serialize() []byte {
  52. return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:]
  53. }
  54. func (msg *Ndmsg) Len() int {
  55. return int(unsafe.Sizeof(*msg))
  56. }
  57. // NeighAdd will add an IP to MAC mapping to the ARP table
  58. // Equivalent to: `ip neigh add ....`
  59. func NeighAdd(neigh *Neigh) error {
  60. return pkgHandle.NeighAdd(neigh)
  61. }
  62. // NeighAdd will add an IP to MAC mapping to the ARP table
  63. // Equivalent to: `ip neigh add ....`
  64. func (h *Handle) NeighAdd(neigh *Neigh) error {
  65. return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL)
  66. }
  67. // NeighSet will add or replace an IP to MAC mapping to the ARP table
  68. // Equivalent to: `ip neigh replace....`
  69. func NeighSet(neigh *Neigh) error {
  70. return pkgHandle.NeighSet(neigh)
  71. }
  72. // NeighSet will add or replace an IP to MAC mapping to the ARP table
  73. // Equivalent to: `ip neigh replace....`
  74. func (h *Handle) NeighSet(neigh *Neigh) error {
  75. return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE)
  76. }
  77. // NeighAppend will append an entry to FDB
  78. // Equivalent to: `bridge fdb append...`
  79. func NeighAppend(neigh *Neigh) error {
  80. return pkgHandle.NeighAppend(neigh)
  81. }
  82. // NeighAppend will append an entry to FDB
  83. // Equivalent to: `bridge fdb append...`
  84. func (h *Handle) NeighAppend(neigh *Neigh) error {
  85. return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_APPEND)
  86. }
  87. // NeighAppend will append an entry to FDB
  88. // Equivalent to: `bridge fdb append...`
  89. func neighAdd(neigh *Neigh, mode int) error {
  90. return pkgHandle.neighAdd(neigh, mode)
  91. }
  92. // NeighAppend will append an entry to FDB
  93. // Equivalent to: `bridge fdb append...`
  94. func (h *Handle) neighAdd(neigh *Neigh, mode int) error {
  95. req := h.newNetlinkRequest(syscall.RTM_NEWNEIGH, mode|syscall.NLM_F_ACK)
  96. return neighHandle(neigh, req)
  97. }
  98. // NeighDel will delete an IP address from a link device.
  99. // Equivalent to: `ip addr del $addr dev $link`
  100. func NeighDel(neigh *Neigh) error {
  101. return pkgHandle.NeighDel(neigh)
  102. }
  103. // NeighDel will delete an IP address from a link device.
  104. // Equivalent to: `ip addr del $addr dev $link`
  105. func (h *Handle) NeighDel(neigh *Neigh) error {
  106. req := h.newNetlinkRequest(syscall.RTM_DELNEIGH, syscall.NLM_F_ACK)
  107. return neighHandle(neigh, req)
  108. }
  109. func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
  110. var family int
  111. if neigh.Family > 0 {
  112. family = neigh.Family
  113. } else {
  114. family = nl.GetIPFamily(neigh.IP)
  115. }
  116. msg := Ndmsg{
  117. Family: uint8(family),
  118. Index: uint32(neigh.LinkIndex),
  119. State: uint16(neigh.State),
  120. Type: uint8(neigh.Type),
  121. Flags: uint8(neigh.Flags),
  122. }
  123. req.AddData(&msg)
  124. ipData := neigh.IP.To4()
  125. if ipData == nil {
  126. ipData = neigh.IP.To16()
  127. }
  128. dstData := nl.NewRtAttr(NDA_DST, ipData)
  129. req.AddData(dstData)
  130. if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
  131. hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
  132. req.AddData(hwData)
  133. }
  134. _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
  135. return err
  136. }
  137. // NeighList gets a list of IP-MAC mappings in the system (ARP table).
  138. // Equivalent to: `ip neighbor show`.
  139. // The list can be filtered by link and ip family.
  140. func NeighList(linkIndex, family int) ([]Neigh, error) {
  141. return pkgHandle.NeighList(linkIndex, family)
  142. }
  143. // NeighProxyList gets a list of neighbor proxies in the system.
  144. // Equivalent to: `ip neighbor show proxy`.
  145. // The list can be filtered by link and ip family.
  146. func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
  147. return pkgHandle.NeighProxyList(linkIndex, family)
  148. }
  149. // NeighList gets a list of IP-MAC mappings in the system (ARP table).
  150. // Equivalent to: `ip neighbor show`.
  151. // The list can be filtered by link and ip family.
  152. func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
  153. return h.neighList(linkIndex, family, 0)
  154. }
  155. // NeighProxyList gets a list of neighbor proxies in the system.
  156. // Equivalent to: `ip neighbor show proxy`.
  157. // The list can be filtered by link, ip family.
  158. func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
  159. return h.neighList(linkIndex, family, NTF_PROXY)
  160. }
  161. func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
  162. req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
  163. msg := Ndmsg{
  164. Family: uint8(family),
  165. Index: uint32(linkIndex),
  166. Flags: uint8(flags),
  167. }
  168. req.AddData(&msg)
  169. msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWNEIGH)
  170. if err != nil {
  171. return nil, err
  172. }
  173. var res []Neigh
  174. for _, m := range msgs {
  175. ndm := deserializeNdmsg(m)
  176. if linkIndex != 0 && int(ndm.Index) != linkIndex {
  177. // Ignore messages from other interfaces
  178. continue
  179. }
  180. neigh, err := NeighDeserialize(m)
  181. if err != nil {
  182. continue
  183. }
  184. res = append(res, *neigh)
  185. }
  186. return res, nil
  187. }
  188. func NeighDeserialize(m []byte) (*Neigh, error) {
  189. msg := deserializeNdmsg(m)
  190. neigh := Neigh{
  191. LinkIndex: int(msg.Index),
  192. Family: int(msg.Family),
  193. State: int(msg.State),
  194. Type: int(msg.Type),
  195. Flags: int(msg.Flags),
  196. }
  197. attrs, err := nl.ParseRouteAttr(m[msg.Len():])
  198. if err != nil {
  199. return nil, err
  200. }
  201. for _, attr := range attrs {
  202. switch attr.Attr.Type {
  203. case NDA_DST:
  204. neigh.IP = net.IP(attr.Value)
  205. case NDA_LLADDR:
  206. neigh.HardwareAddr = net.HardwareAddr(attr.Value)
  207. }
  208. }
  209. return &neigh, nil
  210. }