netlink_linux.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Netlink sockets and messages
  5. package unix
  6. import "unsafe"
  7. // Round the length of a netlink message up to align it properly.
  8. func nlmAlignOf(msglen int) int {
  9. return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
  10. }
  11. // Round the length of a netlink route attribute up to align it
  12. // properly.
  13. func rtaAlignOf(attrlen int) int {
  14. return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
  15. }
  16. // NetlinkRouteRequest represents a request message to receive routing
  17. // and link states from the kernel.
  18. type NetlinkRouteRequest struct {
  19. Header NlMsghdr
  20. Data RtGenmsg
  21. }
  22. func (rr *NetlinkRouteRequest) toWireFormat() []byte {
  23. b := make([]byte, rr.Header.Len)
  24. *(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
  25. *(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
  26. *(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
  27. *(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
  28. *(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
  29. b[16] = byte(rr.Data.Family)
  30. return b
  31. }
  32. func newNetlinkRouteRequest(proto, seq, family int) []byte {
  33. rr := &NetlinkRouteRequest{}
  34. rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
  35. rr.Header.Type = uint16(proto)
  36. rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
  37. rr.Header.Seq = uint32(seq)
  38. rr.Data.Family = uint8(family)
  39. return rr.toWireFormat()
  40. }
  41. // NetlinkRIB returns routing information base, as known as RIB, which
  42. // consists of network facility information, states and parameters.
  43. func NetlinkRIB(proto, family int) ([]byte, error) {
  44. s, err := Socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
  45. if err != nil {
  46. return nil, err
  47. }
  48. defer Close(s)
  49. lsa := &SockaddrNetlink{Family: AF_NETLINK}
  50. if err := Bind(s, lsa); err != nil {
  51. return nil, err
  52. }
  53. wb := newNetlinkRouteRequest(proto, 1, family)
  54. if err := Sendto(s, wb, 0, lsa); err != nil {
  55. return nil, err
  56. }
  57. var tab []byte
  58. rbNew := make([]byte, Getpagesize())
  59. done:
  60. for {
  61. rb := rbNew
  62. nr, _, err := Recvfrom(s, rb, 0)
  63. if err != nil {
  64. return nil, err
  65. }
  66. if nr < NLMSG_HDRLEN {
  67. return nil, EINVAL
  68. }
  69. rb = rb[:nr]
  70. tab = append(tab, rb...)
  71. msgs, err := ParseNetlinkMessage(rb)
  72. if err != nil {
  73. return nil, err
  74. }
  75. for _, m := range msgs {
  76. lsa, err := Getsockname(s)
  77. if err != nil {
  78. return nil, err
  79. }
  80. switch v := lsa.(type) {
  81. case *SockaddrNetlink:
  82. if m.Header.Seq != 1 || m.Header.Pid != v.Pid {
  83. return nil, EINVAL
  84. }
  85. default:
  86. return nil, EINVAL
  87. }
  88. if m.Header.Type == NLMSG_DONE {
  89. break done
  90. }
  91. if m.Header.Type == NLMSG_ERROR {
  92. return nil, EINVAL
  93. }
  94. }
  95. }
  96. return tab, nil
  97. }
  98. // NetlinkMessage represents a netlink message.
  99. type NetlinkMessage struct {
  100. Header NlMsghdr
  101. Data []byte
  102. }
  103. // ParseNetlinkMessage parses b as an array of netlink messages and
  104. // returns the slice containing the NetlinkMessage structures.
  105. func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) {
  106. var msgs []NetlinkMessage
  107. for len(b) >= NLMSG_HDRLEN {
  108. h, dbuf, dlen, err := netlinkMessageHeaderAndData(b)
  109. if err != nil {
  110. return nil, err
  111. }
  112. m := NetlinkMessage{Header: *h, Data: dbuf[:int(h.Len)-NLMSG_HDRLEN]}
  113. msgs = append(msgs, m)
  114. b = b[dlen:]
  115. }
  116. return msgs, nil
  117. }
  118. func netlinkMessageHeaderAndData(b []byte) (*NlMsghdr, []byte, int, error) {
  119. h := (*NlMsghdr)(unsafe.Pointer(&b[0]))
  120. if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(b) {
  121. return nil, nil, 0, EINVAL
  122. }
  123. return h, b[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil
  124. }
  125. // NetlinkRouteAttr represents a netlink route attribute.
  126. type NetlinkRouteAttr struct {
  127. Attr RtAttr
  128. Value []byte
  129. }
  130. // ParseNetlinkRouteAttr parses m's payload as an array of netlink
  131. // route attributes and returns the slice containing the
  132. // NetlinkRouteAttr structures.
  133. func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]NetlinkRouteAttr, error) {
  134. var b []byte
  135. switch m.Header.Type {
  136. case RTM_NEWLINK, RTM_DELLINK:
  137. b = m.Data[SizeofIfInfomsg:]
  138. case RTM_NEWADDR, RTM_DELADDR:
  139. b = m.Data[SizeofIfAddrmsg:]
  140. case RTM_NEWROUTE, RTM_DELROUTE:
  141. b = m.Data[SizeofRtMsg:]
  142. default:
  143. return nil, EINVAL
  144. }
  145. var attrs []NetlinkRouteAttr
  146. for len(b) >= SizeofRtAttr {
  147. a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
  148. if err != nil {
  149. return nil, err
  150. }
  151. ra := NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-SizeofRtAttr]}
  152. attrs = append(attrs, ra)
  153. b = b[alen:]
  154. }
  155. return attrs, nil
  156. }
  157. func netlinkRouteAttrAndValue(b []byte) (*RtAttr, []byte, int, error) {
  158. a := (*RtAttr)(unsafe.Pointer(&b[0]))
  159. if int(a.Len) < SizeofRtAttr || int(a.Len) > len(b) {
  160. return nil, nil, 0, EINVAL
  161. }
  162. return a, b[SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
  163. }