netlink_linux.go 4.6 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 syscall
  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 := cloexecSocket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
  45. if err != nil {
  46. return nil, err
  47. }
  48. defer Close(s)
  49. sa := &SockaddrNetlink{Family: AF_NETLINK}
  50. if err := Bind(s, sa); err != nil {
  51. return nil, err
  52. }
  53. wb := newNetlinkRouteRequest(proto, 1, family)
  54. if err := Sendto(s, wb, 0, sa); err != nil {
  55. return nil, err
  56. }
  57. lsa, err := Getsockname(s)
  58. if err != nil {
  59. return nil, err
  60. }
  61. lsanl, ok := lsa.(*SockaddrNetlink)
  62. if !ok {
  63. return nil, EINVAL
  64. }
  65. var tab []byte
  66. rbNew := make([]byte, Getpagesize())
  67. done:
  68. for {
  69. rb := rbNew
  70. nr, _, err := Recvfrom(s, rb, 0)
  71. if err != nil {
  72. return nil, err
  73. }
  74. if nr < NLMSG_HDRLEN {
  75. return nil, EINVAL
  76. }
  77. rb = rb[:nr]
  78. tab = append(tab, rb...)
  79. msgs, err := ParseNetlinkMessage(rb)
  80. if err != nil {
  81. return nil, err
  82. }
  83. for _, m := range msgs {
  84. if m.Header.Seq != 1 || m.Header.Pid != lsanl.Pid {
  85. return nil, EINVAL
  86. }
  87. if m.Header.Type == NLMSG_DONE {
  88. break done
  89. }
  90. if m.Header.Type == NLMSG_ERROR {
  91. return nil, EINVAL
  92. }
  93. }
  94. }
  95. return tab, nil
  96. }
  97. // NetlinkMessage represents a netlink message.
  98. type NetlinkMessage struct {
  99. Header NlMsghdr
  100. Data []byte
  101. }
  102. // ParseNetlinkMessage parses b as an array of netlink messages and
  103. // returns the slice containing the NetlinkMessage structures.
  104. func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) {
  105. var msgs []NetlinkMessage
  106. for len(b) >= NLMSG_HDRLEN {
  107. h, dbuf, dlen, err := netlinkMessageHeaderAndData(b)
  108. if err != nil {
  109. return nil, err
  110. }
  111. m := NetlinkMessage{Header: *h, Data: dbuf[:int(h.Len)-NLMSG_HDRLEN]}
  112. msgs = append(msgs, m)
  113. b = b[dlen:]
  114. }
  115. return msgs, nil
  116. }
  117. func netlinkMessageHeaderAndData(b []byte) (*NlMsghdr, []byte, int, error) {
  118. h := (*NlMsghdr)(unsafe.Pointer(&b[0]))
  119. l := nlmAlignOf(int(h.Len))
  120. if int(h.Len) < NLMSG_HDRLEN || l > len(b) {
  121. return nil, nil, 0, EINVAL
  122. }
  123. return h, b[NLMSG_HDRLEN:], l, 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. }