netlink_android.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 anet
  6. import (
  7. "syscall"
  8. "unsafe"
  9. )
  10. // Round the length of a netlink message up to align it properly.
  11. func nlmAlignOf(msglen int) int {
  12. return (msglen + syscall.NLMSG_ALIGNTO - 1) & ^(syscall.NLMSG_ALIGNTO - 1)
  13. }
  14. // Round the length of a netlink route attribute up to align it
  15. // properly.
  16. func rtaAlignOf(attrlen int) int {
  17. return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
  18. }
  19. // NetlinkRouteRequest represents a request message to receive routing
  20. // and link states from the kernel.
  21. type NetlinkRouteRequest struct {
  22. Header syscall.NlMsghdr
  23. Data syscall.RtGenmsg
  24. }
  25. func (rr *NetlinkRouteRequest) toWireFormat() []byte {
  26. b := make([]byte, rr.Header.Len)
  27. *(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
  28. *(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
  29. *(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
  30. *(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
  31. *(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
  32. b[16] = byte(rr.Data.Family)
  33. return b
  34. }
  35. func newNetlinkRouteRequest(proto, seq, family int) []byte {
  36. rr := &NetlinkRouteRequest{}
  37. rr.Header.Len = uint32(syscall.NLMSG_HDRLEN + syscall.SizeofRtGenmsg)
  38. rr.Header.Type = uint16(proto)
  39. rr.Header.Flags = syscall.NLM_F_DUMP | syscall.NLM_F_REQUEST
  40. rr.Header.Seq = uint32(seq)
  41. rr.Data.Family = uint8(family)
  42. return rr.toWireFormat()
  43. }
  44. // NetlinkRIB returns routing information base, as known as RIB, which
  45. // consists of network facility information, states and parameters.
  46. func NetlinkRIB(proto, family int) ([]byte, error) {
  47. s, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW|syscall.SOCK_CLOEXEC, syscall.NETLINK_ROUTE)
  48. if err != nil {
  49. return nil, err
  50. }
  51. defer syscall.Close(s)
  52. sa := &syscall.SockaddrNetlink{Family: syscall.AF_NETLINK}
  53. wb := newNetlinkRouteRequest(proto, 1, family)
  54. if err := syscall.Sendto(s, wb, 0, sa); err != nil {
  55. return nil, err
  56. }
  57. lsa, err := syscall.Getsockname(s)
  58. if err != nil {
  59. return nil, err
  60. }
  61. lsanl, ok := lsa.(*syscall.SockaddrNetlink)
  62. if !ok {
  63. return nil, syscall.EINVAL
  64. }
  65. var tab []byte
  66. rbNew := make([]byte, syscall.Getpagesize())
  67. done:
  68. for {
  69. rb := rbNew
  70. nr, _, err := syscall.Recvfrom(s, rb, 0)
  71. if err != nil {
  72. return nil, err
  73. }
  74. if nr < syscall.NLMSG_HDRLEN {
  75. return nil, syscall.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, syscall.EINVAL
  86. }
  87. if m.Header.Type == syscall.NLMSG_DONE {
  88. break done
  89. }
  90. if m.Header.Type == syscall.NLMSG_ERROR {
  91. return nil, syscall.EINVAL
  92. }
  93. }
  94. }
  95. return tab, nil
  96. }
  97. // NetlinkMessage represents a netlink message.
  98. type NetlinkMessage struct {
  99. Header syscall.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) >= syscall.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)-syscall.NLMSG_HDRLEN]}
  112. msgs = append(msgs, m)
  113. b = b[dlen:]
  114. }
  115. return msgs, nil
  116. }
  117. func netlinkMessageHeaderAndData(b []byte) (*syscall.NlMsghdr, []byte, int, error) {
  118. h := (*syscall.NlMsghdr)(unsafe.Pointer(&b[0]))
  119. l := nlmAlignOf(int(h.Len))
  120. if int(h.Len) < syscall.NLMSG_HDRLEN || l > len(b) {
  121. return nil, nil, 0, syscall.EINVAL
  122. }
  123. return h, b[syscall.NLMSG_HDRLEN:], l, nil
  124. }
  125. // NetlinkRouteAttr represents a netlink route attribute.
  126. type NetlinkRouteAttr struct {
  127. Attr syscall.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 syscall.RTM_NEWLINK, syscall.RTM_DELLINK:
  137. b = m.Data[syscall.SizeofIfInfomsg:]
  138. case syscall.RTM_NEWADDR, syscall.RTM_DELADDR:
  139. b = m.Data[syscall.SizeofIfAddrmsg:]
  140. case syscall.RTM_NEWROUTE, syscall.RTM_DELROUTE:
  141. b = m.Data[syscall.SizeofRtMsg:]
  142. default:
  143. return nil, syscall.EINVAL
  144. }
  145. var attrs []NetlinkRouteAttr
  146. for len(b) >= syscall.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)-syscall.SizeofRtAttr]}
  152. attrs = append(attrs, ra)
  153. b = b[alen:]
  154. }
  155. return attrs, nil
  156. }
  157. func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
  158. a := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
  159. if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) {
  160. return nil, nil, 0, syscall.EINVAL
  161. }
  162. return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
  163. }