address.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. package rtnetlink
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "github.com/jsimonetti/rtnetlink/internal/unix"
  7. "github.com/mdlayher/netlink"
  8. )
  9. var (
  10. // errInvalidaddressMessage is returned when a AddressMessage is malformed.
  11. errInvalidAddressMessage = errors.New("rtnetlink AddressMessage is invalid or too short")
  12. )
  13. var _ Message = &AddressMessage{}
  14. // A AddressMessage is a route netlink address message.
  15. type AddressMessage struct {
  16. // Address family (current unix.AF_INET or unix.AF_INET6)
  17. Family uint8
  18. // Prefix length
  19. PrefixLength uint8
  20. // Contains address flags
  21. Flags uint8
  22. // Address Scope
  23. Scope uint8
  24. // Interface index
  25. Index uint32
  26. // Optional attributes which are appended when not nil.
  27. Attributes *AddressAttributes
  28. }
  29. // MarshalBinary marshals a AddressMessage into a byte slice.
  30. func (m *AddressMessage) MarshalBinary() ([]byte, error) {
  31. b := make([]byte, unix.SizeofIfAddrmsg)
  32. b[0] = m.Family
  33. b[1] = m.PrefixLength
  34. b[2] = m.Flags
  35. b[3] = m.Scope
  36. nativeEndian.PutUint32(b[4:8], m.Index)
  37. if m.Attributes == nil {
  38. // No attributes to encode.
  39. return b, nil
  40. }
  41. ae := netlink.NewAttributeEncoder()
  42. err := m.Attributes.encode(ae)
  43. if err != nil {
  44. return nil, err
  45. }
  46. a, err := ae.Encode()
  47. if err != nil {
  48. return nil, err
  49. }
  50. return append(b, a...), nil
  51. }
  52. // UnmarshalBinary unmarshals the contents of a byte slice into a AddressMessage.
  53. func (m *AddressMessage) UnmarshalBinary(b []byte) error {
  54. l := len(b)
  55. if l < unix.SizeofIfAddrmsg {
  56. return errInvalidAddressMessage
  57. }
  58. m.Family = uint8(b[0])
  59. m.PrefixLength = uint8(b[1])
  60. m.Flags = uint8(b[2])
  61. m.Scope = uint8(b[3])
  62. m.Index = nativeEndian.Uint32(b[4:8])
  63. if l > unix.SizeofIfAddrmsg {
  64. ad, err := netlink.NewAttributeDecoder(b[unix.SizeofIfAddrmsg:])
  65. if err != nil {
  66. return err
  67. }
  68. var aa AddressAttributes
  69. if err := aa.decode(ad); err != nil {
  70. return err
  71. }
  72. // Must consume errors from decoder before returning.
  73. if err := ad.Err(); err != nil {
  74. return fmt.Errorf("invalid address message attributes: %v", err)
  75. }
  76. m.Attributes = &aa
  77. }
  78. return nil
  79. }
  80. // rtMessage is an empty method to sattisfy the Message interface.
  81. func (*AddressMessage) rtMessage() {}
  82. // AddressService is used to retrieve rtnetlink family information.
  83. type AddressService struct {
  84. c *Conn
  85. }
  86. // New creates a new address using the AddressMessage information.
  87. func (a *AddressService) New(req *AddressMessage) error {
  88. flags := netlink.Request | netlink.Create | netlink.Acknowledge | netlink.Excl
  89. _, err := a.c.Execute(req, unix.RTM_NEWADDR, flags)
  90. if err != nil {
  91. return err
  92. }
  93. return nil
  94. }
  95. // Delete removes an address using the AddressMessage information.
  96. func (a *AddressService) Delete(req *AddressMessage) error {
  97. flags := netlink.Request | netlink.Acknowledge
  98. _, err := a.c.Execute(req, unix.RTM_DELADDR, flags)
  99. if err != nil {
  100. return err
  101. }
  102. return nil
  103. }
  104. // List retrieves all addresses.
  105. func (a *AddressService) List() ([]AddressMessage, error) {
  106. req := AddressMessage{}
  107. flags := netlink.Request | netlink.Dump
  108. msgs, err := a.c.Execute(&req, unix.RTM_GETADDR, flags)
  109. if err != nil {
  110. return nil, err
  111. }
  112. addresses := make([]AddressMessage, len(msgs))
  113. for i := range msgs {
  114. addresses[i] = *msgs[i].(*AddressMessage)
  115. }
  116. return addresses, nil
  117. }
  118. // AddressAttributes contains all attributes for an interface.
  119. type AddressAttributes struct {
  120. Address net.IP // Interface Ip address
  121. Local net.IP // Local Ip address
  122. Label string
  123. Broadcast net.IP // Broadcast Ip address
  124. Anycast net.IP // Anycast Ip address
  125. CacheInfo CacheInfo // Address information
  126. Multicast net.IP // Multicast Ip address
  127. Flags uint32 // Address flags
  128. }
  129. func (a *AddressAttributes) decode(ad *netlink.AttributeDecoder) error {
  130. for ad.Next() {
  131. switch ad.Type() {
  132. case unix.IFA_UNSPEC:
  133. // unused attribute
  134. case unix.IFA_ADDRESS:
  135. ad.Do(decodeIP(&a.Address))
  136. case unix.IFA_LOCAL:
  137. ad.Do(decodeIP(&a.Local))
  138. case unix.IFA_LABEL:
  139. a.Label = ad.String()
  140. case unix.IFA_BROADCAST:
  141. ad.Do(decodeIP(&a.Broadcast))
  142. case unix.IFA_ANYCAST:
  143. ad.Do(decodeIP(&a.Anycast))
  144. case unix.IFA_CACHEINFO:
  145. ad.Do(a.CacheInfo.decode)
  146. case unix.IFA_MULTICAST:
  147. ad.Do(decodeIP(&a.Multicast))
  148. case unix.IFA_FLAGS:
  149. a.Flags = ad.Uint32()
  150. }
  151. }
  152. return nil
  153. }
  154. func (a *AddressAttributes) encode(ae *netlink.AttributeEncoder) error {
  155. ae.Uint16(unix.IFA_UNSPEC, 0)
  156. ae.Do(unix.IFA_ADDRESS, encodeIP(a.Address))
  157. if a.Local != nil {
  158. ae.Do(unix.IFA_LOCAL, encodeIP(a.Local))
  159. }
  160. if a.Broadcast != nil {
  161. ae.Do(unix.IFA_BROADCAST, encodeIP(a.Broadcast))
  162. }
  163. if a.Anycast != nil {
  164. ae.Do(unix.IFA_ANYCAST, encodeIP(a.Anycast))
  165. }
  166. if a.Multicast != nil {
  167. ae.Do(unix.IFA_MULTICAST, encodeIP(a.Multicast))
  168. }
  169. if a.Label != "" {
  170. ae.String(unix.IFA_LABEL, a.Label)
  171. }
  172. ae.Uint32(unix.IFA_FLAGS, a.Flags)
  173. return nil
  174. }
  175. // CacheInfo contains address information
  176. type CacheInfo struct {
  177. Prefered uint32
  178. Valid uint32
  179. Created uint32
  180. Updated uint32
  181. }
  182. // decode decodes raw bytes into a CacheInfo's fields.
  183. func (c *CacheInfo) decode(b []byte) error {
  184. if len(b) != 16 {
  185. return fmt.Errorf("rtnetlink: incorrect CacheInfo size, want: 16, got: %d", len(b))
  186. }
  187. c.Prefered = nativeEndian.Uint32(b[0:4])
  188. c.Valid = nativeEndian.Uint32(b[4:8])
  189. c.Created = nativeEndian.Uint32(b[8:12])
  190. c.Updated = nativeEndian.Uint32(b[12:16])
  191. return nil
  192. }
  193. // encodeIP is a helper for validating and encoding IPv4 and IPv6 addresses as
  194. // appropriate for the specified netlink attribute type. It should be used
  195. // with (*netlink.AttributeEncoder).Do.
  196. func encodeIP(ip net.IP) func() ([]byte, error) {
  197. return func() ([]byte, error) {
  198. // Don't allow nil or non 4/16-byte addresses.
  199. if ip == nil || ip.To16() == nil {
  200. return nil, fmt.Errorf("rtnetlink: cannot encode invalid IP address: %s", ip)
  201. }
  202. if ip4 := ip.To4(); ip4 != nil {
  203. // IPv4 address.
  204. return ip4, nil
  205. }
  206. // IPv6 address.
  207. return ip, nil
  208. }
  209. }
  210. // decodeIP is a helper for validating and decoding IPv4 and IPv6 addresses as
  211. // appropriate for the specified netlink attribute type. It should be used with
  212. // (*netlink.AttributeDecoder).Do.
  213. func decodeIP(ip *net.IP) func(b []byte) error {
  214. return func(b []byte) error {
  215. if l := len(b); l != 4 && l != 16 {
  216. return fmt.Errorf("rtnetlink: invalid IP address length: %d", l)
  217. }
  218. // We cannot retain b outside the closure, so make a copy into ip.
  219. *ip = make(net.IP, len(b))
  220. copy(*ip, b)
  221. return nil
  222. }
  223. }