genetlink_linux.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package netlink
  2. import (
  3. "fmt"
  4. "syscall"
  5. "github.com/vishvananda/netlink/nl"
  6. )
  7. type GenlOp struct {
  8. ID uint32
  9. Flags uint32
  10. }
  11. type GenlMulticastGroup struct {
  12. ID uint32
  13. Name string
  14. }
  15. type GenlFamily struct {
  16. ID uint16
  17. HdrSize uint32
  18. Name string
  19. Version uint32
  20. MaxAttr uint32
  21. Ops []GenlOp
  22. Groups []GenlMulticastGroup
  23. }
  24. func parseOps(b []byte) ([]GenlOp, error) {
  25. attrs, err := nl.ParseRouteAttr(b)
  26. if err != nil {
  27. return nil, err
  28. }
  29. ops := make([]GenlOp, 0, len(attrs))
  30. for _, a := range attrs {
  31. nattrs, err := nl.ParseRouteAttr(a.Value)
  32. if err != nil {
  33. return nil, err
  34. }
  35. var op GenlOp
  36. for _, na := range nattrs {
  37. switch na.Attr.Type {
  38. case nl.GENL_CTRL_ATTR_OP_ID:
  39. op.ID = native.Uint32(na.Value)
  40. case nl.GENL_CTRL_ATTR_OP_FLAGS:
  41. op.Flags = native.Uint32(na.Value)
  42. }
  43. }
  44. ops = append(ops, op)
  45. }
  46. return ops, nil
  47. }
  48. func parseMulticastGroups(b []byte) ([]GenlMulticastGroup, error) {
  49. attrs, err := nl.ParseRouteAttr(b)
  50. if err != nil {
  51. return nil, err
  52. }
  53. groups := make([]GenlMulticastGroup, 0, len(attrs))
  54. for _, a := range attrs {
  55. nattrs, err := nl.ParseRouteAttr(a.Value)
  56. if err != nil {
  57. return nil, err
  58. }
  59. var g GenlMulticastGroup
  60. for _, na := range nattrs {
  61. switch na.Attr.Type {
  62. case nl.GENL_CTRL_ATTR_MCAST_GRP_NAME:
  63. g.Name = nl.BytesToString(na.Value)
  64. case nl.GENL_CTRL_ATTR_MCAST_GRP_ID:
  65. g.ID = native.Uint32(na.Value)
  66. }
  67. }
  68. groups = append(groups, g)
  69. }
  70. return groups, nil
  71. }
  72. func (f *GenlFamily) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
  73. for _, a := range attrs {
  74. switch a.Attr.Type {
  75. case nl.GENL_CTRL_ATTR_FAMILY_NAME:
  76. f.Name = nl.BytesToString(a.Value)
  77. case nl.GENL_CTRL_ATTR_FAMILY_ID:
  78. f.ID = native.Uint16(a.Value)
  79. case nl.GENL_CTRL_ATTR_VERSION:
  80. f.Version = native.Uint32(a.Value)
  81. case nl.GENL_CTRL_ATTR_HDRSIZE:
  82. f.HdrSize = native.Uint32(a.Value)
  83. case nl.GENL_CTRL_ATTR_MAXATTR:
  84. f.MaxAttr = native.Uint32(a.Value)
  85. case nl.GENL_CTRL_ATTR_OPS:
  86. ops, err := parseOps(a.Value)
  87. if err != nil {
  88. return err
  89. }
  90. f.Ops = ops
  91. case nl.GENL_CTRL_ATTR_MCAST_GROUPS:
  92. groups, err := parseMulticastGroups(a.Value)
  93. if err != nil {
  94. return err
  95. }
  96. f.Groups = groups
  97. }
  98. }
  99. return nil
  100. }
  101. func parseFamilies(msgs [][]byte) ([]*GenlFamily, error) {
  102. families := make([]*GenlFamily, 0, len(msgs))
  103. for _, m := range msgs {
  104. attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
  105. if err != nil {
  106. return nil, err
  107. }
  108. family := &GenlFamily{}
  109. if err := family.parseAttributes(attrs); err != nil {
  110. return nil, err
  111. }
  112. families = append(families, family)
  113. }
  114. return families, nil
  115. }
  116. func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) {
  117. msg := &nl.Genlmsg{
  118. Command: nl.GENL_CTRL_CMD_GETFAMILY,
  119. Version: nl.GENL_CTRL_VERSION,
  120. }
  121. req := h.newNetlinkRequest(nl.GENL_ID_CTRL, syscall.NLM_F_DUMP)
  122. req.AddData(msg)
  123. msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
  124. if err != nil {
  125. return nil, err
  126. }
  127. return parseFamilies(msgs)
  128. }
  129. func GenlFamilyList() ([]*GenlFamily, error) {
  130. return pkgHandle.GenlFamilyList()
  131. }
  132. func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
  133. msg := &nl.Genlmsg{
  134. Command: nl.GENL_CTRL_CMD_GETFAMILY,
  135. Version: nl.GENL_CTRL_VERSION,
  136. }
  137. req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0)
  138. req.AddData(msg)
  139. req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name)))
  140. msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
  141. if err != nil {
  142. return nil, err
  143. }
  144. families, err := parseFamilies(msgs)
  145. if len(families) != 1 {
  146. return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY")
  147. }
  148. return families[0], nil
  149. }
  150. func GenlFamilyGet(name string) (*GenlFamily, error) {
  151. return pkgHandle.GenlFamilyGet(name)
  152. }