address_linux.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package iproute2
  15. import (
  16. "net"
  17. "syscall"
  18. "github.com/vishvananda/netlink"
  19. )
  20. type Address struct {
  21. *Link
  22. addrBad bool
  23. addrs []*netlink.Addr
  24. testcb func()
  25. }
  26. func nop() {}
  27. func NewAddress(ifname string, addresses ...string) *Address {
  28. l := NewLink(ifname)
  29. r := &Address{
  30. Link: l,
  31. testcb: nop,
  32. }
  33. addrs := make([]*netlink.Addr, len(addresses))
  34. for i, address := range addresses {
  35. addr, err := netlink.ParseAddr(address)
  36. if err != nil {
  37. r.addrBad = true
  38. r.addErr(err, "parse addr")
  39. continue
  40. }
  41. addrs[i] = addr
  42. }
  43. if !r.addrBad {
  44. r.addrs = addrs
  45. }
  46. return r
  47. }
  48. func NewAddressEx(ifname string, addrs ...*netlink.Addr) *Address {
  49. l := NewLink(ifname)
  50. r := &Address{
  51. Link: l,
  52. testcb: nop,
  53. addrs: addrs,
  54. }
  55. return r
  56. }
  57. func (address *Address) link() (link netlink.Link, ok bool) {
  58. if address.addrBad {
  59. return
  60. }
  61. link = address.Link.link
  62. if link != nil {
  63. ok = true
  64. }
  65. return
  66. }
  67. func (address *Address) Exact() *Address {
  68. link, ok := address.link()
  69. if !ok {
  70. return address
  71. }
  72. for _, addr := range address.addrs {
  73. err := netlink.AddrReplace(link, addr)
  74. if err != nil {
  75. address.addErr(err, "Exact: AddrReplace %s", addr)
  76. }
  77. }
  78. oldAddrs, err := netlink.AddrList(link, netlink.FAMILY_ALL)
  79. if err != nil {
  80. address.addErr(err, "Exact: AddrList")
  81. }
  82. address.testcb()
  83. for _, oldAddr := range oldAddrs {
  84. del := true
  85. for _, addr := range address.addrs {
  86. if oldAddr.Equal(*addr) {
  87. del = false
  88. break
  89. }
  90. }
  91. if del {
  92. err := netlink.AddrDel(link, &oldAddr)
  93. if err != nil {
  94. if errno, ok := err.(syscall.Errno); ok {
  95. switch errno {
  96. case syscall.EADDRNOTAVAIL:
  97. // "cannot assign requested address"
  98. continue
  99. }
  100. }
  101. address.addErr(err, "Exact: AddrDel %s", oldAddr)
  102. }
  103. }
  104. }
  105. return address
  106. }
  107. func (address *Address) Add() *Address {
  108. link, ok := address.link()
  109. if !ok {
  110. return address
  111. }
  112. for _, addr := range address.addrs {
  113. err := netlink.AddrReplace(link, addr)
  114. if err != nil {
  115. address.addErr(err, "Add: AddrReplace %s ", addr)
  116. }
  117. }
  118. return address
  119. }
  120. func (address *Address) Del() *Address {
  121. link, ok := address.link()
  122. if !ok {
  123. return address
  124. }
  125. for _, addr := range address.addrs {
  126. err := netlink.AddrDel(link, addr)
  127. if err != nil {
  128. address.addErr(err, "Del: AddrDel %s ", addr)
  129. }
  130. }
  131. return address
  132. }
  133. func (address *Address) List4() ([]net.IPNet, error) {
  134. link, ok := address.link()
  135. if !ok {
  136. return nil, address.Err()
  137. }
  138. oldAddrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
  139. if err != nil {
  140. return nil, err
  141. }
  142. r := make([]net.IPNet, len(oldAddrs))
  143. for i, oldAddr := range oldAddrs {
  144. r[i] = *oldAddr.IPNet
  145. }
  146. return r, nil
  147. }
  148. func (address *Address) List6() ([]net.IPNet, error) {
  149. link, ok := address.link()
  150. if !ok {
  151. return nil, address.Err()
  152. }
  153. oldAddrs, err := netlink.AddrList(link, netlink.FAMILY_V6)
  154. if err != nil {
  155. return nil, err
  156. }
  157. r := make([]net.IPNet, len(oldAddrs))
  158. for i, oldAddr := range oldAddrs {
  159. r[i] = *oldAddr.IPNet
  160. }
  161. return r, nil
  162. }