addr_linux.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. package netlink
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "strings"
  7. "syscall"
  8. "github.com/vishvananda/netlink/nl"
  9. "github.com/vishvananda/netns"
  10. )
  11. // IFA_FLAGS is a u32 attribute.
  12. const IFA_FLAGS = 0x8
  13. // AddrAdd will add an IP address to a link device.
  14. // Equivalent to: `ip addr add $addr dev $link`
  15. func AddrAdd(link Link, addr *Addr) error {
  16. return pkgHandle.AddrAdd(link, addr)
  17. }
  18. // AddrAdd will add an IP address to a link device.
  19. // Equivalent to: `ip addr add $addr dev $link`
  20. func (h *Handle) AddrAdd(link Link, addr *Addr) error {
  21. req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
  22. return h.addrHandle(link, addr, req)
  23. }
  24. // AddrReplace will replace (or, if not present, add) an IP address on a link device.
  25. // Equivalent to: `ip addr replace $addr dev $link`
  26. func AddrReplace(link Link, addr *Addr) error {
  27. return pkgHandle.AddrReplace(link, addr)
  28. }
  29. // AddrReplace will replace (or, if not present, add) an IP address on a link device.
  30. // Equivalent to: `ip addr replace $addr dev $link`
  31. func (h *Handle) AddrReplace(link Link, addr *Addr) error {
  32. req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE|syscall.NLM_F_ACK)
  33. return h.addrHandle(link, addr, req)
  34. }
  35. // AddrDel will delete an IP address from a link device.
  36. // Equivalent to: `ip addr del $addr dev $link`
  37. func AddrDel(link Link, addr *Addr) error {
  38. return pkgHandle.AddrDel(link, addr)
  39. }
  40. // AddrDel will delete an IP address from a link device.
  41. // Equivalent to: `ip addr del $addr dev $link`
  42. func (h *Handle) AddrDel(link Link, addr *Addr) error {
  43. req := h.newNetlinkRequest(syscall.RTM_DELADDR, syscall.NLM_F_ACK)
  44. return h.addrHandle(link, addr, req)
  45. }
  46. func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error {
  47. base := link.Attrs()
  48. if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
  49. return fmt.Errorf("label must begin with interface name")
  50. }
  51. h.ensureIndex(base)
  52. family := nl.GetIPFamily(addr.IP)
  53. msg := nl.NewIfAddrmsg(family)
  54. msg.Index = uint32(base.Index)
  55. msg.Scope = uint8(addr.Scope)
  56. prefixlen, masklen := addr.Mask.Size()
  57. msg.Prefixlen = uint8(prefixlen)
  58. req.AddData(msg)
  59. var localAddrData []byte
  60. if family == FAMILY_V4 {
  61. localAddrData = addr.IP.To4()
  62. } else {
  63. localAddrData = addr.IP.To16()
  64. }
  65. localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData)
  66. req.AddData(localData)
  67. var peerAddrData []byte
  68. if addr.Peer != nil {
  69. if family == FAMILY_V4 {
  70. peerAddrData = addr.Peer.IP.To4()
  71. } else {
  72. peerAddrData = addr.Peer.IP.To16()
  73. }
  74. } else {
  75. peerAddrData = localAddrData
  76. }
  77. addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData)
  78. req.AddData(addressData)
  79. if addr.Flags != 0 {
  80. if addr.Flags <= 0xff {
  81. msg.IfAddrmsg.Flags = uint8(addr.Flags)
  82. } else {
  83. b := make([]byte, 4)
  84. native.PutUint32(b, uint32(addr.Flags))
  85. flagsData := nl.NewRtAttr(IFA_FLAGS, b)
  86. req.AddData(flagsData)
  87. }
  88. }
  89. if addr.Broadcast == nil {
  90. calcBroadcast := make(net.IP, masklen/8)
  91. for i := range localAddrData {
  92. calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
  93. }
  94. addr.Broadcast = calcBroadcast
  95. }
  96. req.AddData(nl.NewRtAttr(syscall.IFA_BROADCAST, addr.Broadcast))
  97. if addr.Label != "" {
  98. labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
  99. req.AddData(labelData)
  100. }
  101. _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
  102. return err
  103. }
  104. // AddrList gets a list of IP addresses in the system.
  105. // Equivalent to: `ip addr show`.
  106. // The list can be filtered by link and ip family.
  107. func AddrList(link Link, family int) ([]Addr, error) {
  108. return pkgHandle.AddrList(link, family)
  109. }
  110. // AddrList gets a list of IP addresses in the system.
  111. // Equivalent to: `ip addr show`.
  112. // The list can be filtered by link and ip family.
  113. func (h *Handle) AddrList(link Link, family int) ([]Addr, error) {
  114. req := h.newNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP)
  115. msg := nl.NewIfInfomsg(family)
  116. req.AddData(msg)
  117. msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR)
  118. if err != nil {
  119. return nil, err
  120. }
  121. indexFilter := 0
  122. if link != nil {
  123. base := link.Attrs()
  124. h.ensureIndex(base)
  125. indexFilter = base.Index
  126. }
  127. var res []Addr
  128. for _, m := range msgs {
  129. addr, msgFamily, ifindex, err := parseAddr(m)
  130. if err != nil {
  131. return res, err
  132. }
  133. if link != nil && ifindex != indexFilter {
  134. // Ignore messages from other interfaces
  135. continue
  136. }
  137. if family != FAMILY_ALL && msgFamily != family {
  138. continue
  139. }
  140. res = append(res, addr)
  141. }
  142. return res, nil
  143. }
  144. func parseAddr(m []byte) (addr Addr, family, index int, err error) {
  145. msg := nl.DeserializeIfAddrmsg(m)
  146. family = -1
  147. index = -1
  148. attrs, err1 := nl.ParseRouteAttr(m[msg.Len():])
  149. if err1 != nil {
  150. err = err1
  151. return
  152. }
  153. family = int(msg.Family)
  154. index = int(msg.Index)
  155. var local, dst *net.IPNet
  156. for _, attr := range attrs {
  157. switch attr.Attr.Type {
  158. case syscall.IFA_ADDRESS:
  159. dst = &net.IPNet{
  160. IP: attr.Value,
  161. Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
  162. }
  163. addr.Peer = dst
  164. case syscall.IFA_LOCAL:
  165. local = &net.IPNet{
  166. IP: attr.Value,
  167. Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
  168. }
  169. addr.IPNet = local
  170. case syscall.IFA_BROADCAST:
  171. addr.Broadcast = attr.Value
  172. case syscall.IFA_LABEL:
  173. addr.Label = string(attr.Value[:len(attr.Value)-1])
  174. case IFA_FLAGS:
  175. addr.Flags = int(native.Uint32(attr.Value[0:4]))
  176. case nl.IFA_CACHEINFO:
  177. ci := nl.DeserializeIfaCacheInfo(attr.Value)
  178. addr.PreferedLft = int(ci.IfaPrefered)
  179. addr.ValidLft = int(ci.IfaValid)
  180. }
  181. }
  182. // IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS
  183. if local != nil {
  184. addr.IPNet = local
  185. } else {
  186. addr.IPNet = dst
  187. }
  188. addr.Scope = int(msg.Scope)
  189. return
  190. }
  191. type AddrUpdate struct {
  192. LinkAddress net.IPNet
  193. LinkIndex int
  194. Flags int
  195. Scope int
  196. PreferedLft int
  197. ValidLft int
  198. NewAddr bool // true=added false=deleted
  199. }
  200. // AddrSubscribe takes a chan down which notifications will be sent
  201. // when addresses change. Close the 'done' chan to stop subscription.
  202. func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
  203. return addrSubscribe(netns.None(), netns.None(), ch, done)
  204. }
  205. // AddrSubscribeAt works like AddrSubscribe plus it allows the caller
  206. // to choose the network namespace in which to subscribe (ns).
  207. func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
  208. return addrSubscribe(ns, netns.None(), ch, done)
  209. }
  210. func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
  211. s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
  212. if err != nil {
  213. return err
  214. }
  215. if done != nil {
  216. go func() {
  217. <-done
  218. s.Close()
  219. }()
  220. }
  221. go func() {
  222. defer close(ch)
  223. for {
  224. msgs, err := s.Receive()
  225. if err != nil {
  226. log.Printf("netlink.AddrSubscribe: Receive() error: %v", err)
  227. return
  228. }
  229. for _, m := range msgs {
  230. msgType := m.Header.Type
  231. if msgType != syscall.RTM_NEWADDR && msgType != syscall.RTM_DELADDR {
  232. log.Printf("netlink.AddrSubscribe: bad message type: %d", msgType)
  233. continue
  234. }
  235. addr, _, ifindex, err := parseAddr(m.Data)
  236. if err != nil {
  237. log.Printf("netlink.AddrSubscribe: could not parse address: %v", err)
  238. continue
  239. }
  240. ch <- AddrUpdate{LinkAddress: *addr.IPNet,
  241. LinkIndex: ifindex,
  242. NewAddr: msgType == syscall.RTM_NEWADDR,
  243. Flags: addr.Flags,
  244. Scope: addr.Scope,
  245. PreferedLft: addr.PreferedLft,
  246. ValidLft: addr.ValidLft}
  247. }
  248. }
  249. }()
  250. return nil
  251. }