handle_linux.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package netlink
  2. import (
  3. "syscall"
  4. "github.com/vishvananda/netlink/nl"
  5. "github.com/vishvananda/netns"
  6. )
  7. // Empty handle used by the netlink package methods
  8. var pkgHandle = &Handle{}
  9. // Handle is an handle for the netlink requests on a
  10. // specific network namespace. All the requests on the
  11. // same netlink family share the same netlink socket,
  12. // which gets released when the handle is deleted.
  13. type Handle struct {
  14. sockets map[int]*nl.SocketHandle
  15. lookupByDump bool
  16. }
  17. // SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
  18. func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
  19. _, ok := h.sockets[nlFamily]
  20. return ok
  21. }
  22. // NewHandle returns a netlink handle on the current network namespace.
  23. // Caller may specify the netlink families the handle should support.
  24. // If no families are specified, all the families the netlink package
  25. // supports will be automatically added.
  26. func NewHandle(nlFamilies ...int) (*Handle, error) {
  27. return newHandle(netns.None(), netns.None(), nlFamilies...)
  28. }
  29. // NewHandle returns a netlink handle on the network namespace
  30. // specified by ns. If ns=netns.None(), current network namespace
  31. // will be assumed
  32. func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
  33. return newHandle(ns, netns.None(), nlFamilies...)
  34. }
  35. // NewHandleAtFrom works as NewHandle but allows client to specify the
  36. // new and the origin netns Handle.
  37. func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
  38. return newHandle(newNs, curNs)
  39. }
  40. func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
  41. h := &Handle{sockets: map[int]*nl.SocketHandle{}}
  42. fams := nl.SupportedNlFamilies
  43. if len(nlFamilies) != 0 {
  44. fams = nlFamilies
  45. }
  46. for _, f := range fams {
  47. s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
  48. if err != nil {
  49. return nil, err
  50. }
  51. h.sockets[f] = &nl.SocketHandle{Socket: s}
  52. }
  53. return h, nil
  54. }
  55. // Delete releases the resources allocated to this handle
  56. func (h *Handle) Delete() {
  57. for _, sh := range h.sockets {
  58. sh.Close()
  59. }
  60. h.sockets = nil
  61. }
  62. func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
  63. // Do this so that package API still use nl package variable nextSeqNr
  64. if h.sockets == nil {
  65. return nl.NewNetlinkRequest(proto, flags)
  66. }
  67. return &nl.NetlinkRequest{
  68. NlMsghdr: syscall.NlMsghdr{
  69. Len: uint32(syscall.SizeofNlMsghdr),
  70. Type: uint16(proto),
  71. Flags: syscall.NLM_F_REQUEST | uint16(flags),
  72. },
  73. Sockets: h.sockets,
  74. }
  75. }