github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/node/node_address.go (about)

     1  // Copyright 2016-2018 Authors of Cilium
     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  
    15  package node
    16  
    17  import (
    18  	"bufio"
    19  	"fmt"
    20  	"net"
    21  	"os"
    22  	"strconv"
    23  	"strings"
    24  
    25  	"github.com/cilium/cilium/api/v1/models"
    26  	"github.com/cilium/cilium/common"
    27  	"github.com/cilium/cilium/pkg/byteorder"
    28  	"github.com/cilium/cilium/pkg/cidr"
    29  	"github.com/cilium/cilium/pkg/defaults"
    30  	"github.com/cilium/cilium/pkg/logging/logfields"
    31  	"github.com/cilium/cilium/pkg/option"
    32  )
    33  
    34  var (
    35  	ipv4ClusterCidrMaskSize = defaults.DefaultIPv4ClusterPrefixLen
    36  
    37  	ipv4Loopback        net.IP
    38  	ipv4ExternalAddress net.IP
    39  	ipv4InternalAddress net.IP
    40  	ipv4NodePortAddress net.IP
    41  	ipv6Address         net.IP
    42  	ipv6RouterAddress   net.IP
    43  	ipv6NodePortAddress net.IP
    44  	ipv4AllocRange      *cidr.CIDR
    45  	ipv6AllocRange      *cidr.CIDR
    46  
    47  	ipsecKeyIdentity uint8
    48  )
    49  
    50  func makeIPv6HostIP() net.IP {
    51  	ipstr := "fc00::10CA:1"
    52  	ip := net.ParseIP(ipstr)
    53  	if ip == nil {
    54  		log.WithField(logfields.IPAddr, ipstr).Fatal("Unable to parse IP")
    55  	}
    56  
    57  	return ip
    58  }
    59  
    60  // SetIPv4ClusterCidrMaskSize sets the size of the mask of the IPv4 cluster prefix
    61  func SetIPv4ClusterCidrMaskSize(size int) {
    62  	ipv4ClusterCidrMaskSize = size
    63  }
    64  
    65  // InitDefaultPrefix initializes the node address and allocation prefixes with
    66  // default values derived from the system. device can be set to the primary
    67  // network device of the system in which case the first address with global
    68  // scope will be regarded as the system's node address.
    69  func InitDefaultPrefix(device string) {
    70  	if option.Config.EnableIPv4 {
    71  		ip, err := firstGlobalV4Addr(device, GetInternalIPv4())
    72  		if err != nil {
    73  			return
    74  		}
    75  
    76  		if ipv4ExternalAddress == nil {
    77  			ipv4ExternalAddress = ip
    78  		}
    79  
    80  		if ipv4AllocRange == nil {
    81  			// If the IPv6AllocRange is not nil then the IPv4 allocation should be
    82  			// derived from the IPv6AllocRange.
    83  			//                     vvvv vvvv
    84  			// FD00:0000:0000:0000:0000:0000:0000:0000
    85  			if ipv6AllocRange != nil {
    86  				ip = net.IPv4(ipv6AllocRange.IP[8],
    87  					ipv6AllocRange.IP[9],
    88  					ipv6AllocRange.IP[10],
    89  					ipv6AllocRange.IP[11])
    90  			}
    91  			v4range := fmt.Sprintf(defaults.DefaultIPv4Prefix+"/%d",
    92  				ip.To4()[3], defaults.DefaultIPv4PrefixLen)
    93  			_, ip4net, err := net.ParseCIDR(v4range)
    94  			if err != nil {
    95  				log.WithError(err).WithField(logfields.V4Prefix, v4range).Panic("BUG: Invalid default IPv4 prefix")
    96  			}
    97  
    98  			ipv4AllocRange = cidr.NewCIDR(ip4net)
    99  			log.WithField(logfields.V4Prefix, ipv4AllocRange).Info("Using autogenerated IPv4 allocation range")
   100  		}
   101  
   102  		if option.Config.EnableNodePort {
   103  			// device is always non-nil here
   104  			ip, err := firstGlobalV4Addr(device, nil)
   105  			if err != nil {
   106  				return
   107  			}
   108  
   109  			if ipv4NodePortAddress == nil {
   110  				ipv4NodePortAddress = ip
   111  			}
   112  		}
   113  	}
   114  
   115  	if option.Config.EnableIPv6 {
   116  		if ipv6Address == nil {
   117  			// Find a IPv6 node address first
   118  			ipv6Address, _ = firstGlobalV6Addr(device, GetIPv6Router())
   119  			if ipv6Address == nil {
   120  				ipv6Address = makeIPv6HostIP()
   121  			}
   122  		}
   123  
   124  		if ipv6AllocRange == nil && ipv4AllocRange != nil {
   125  			// The IPv6 allocation should be derived from the IPv4 allocation.
   126  			ip := ipv4AllocRange.IP
   127  			v6range := fmt.Sprintf("%s%02x%02x:%02x%02x:0:0/%d",
   128  				option.Config.IPv6ClusterAllocCIDRBase, ip[0], ip[1], ip[2], ip[3],
   129  				defaults.IPv6NodePrefixLen)
   130  
   131  			_, ip6net, err := net.ParseCIDR(v6range)
   132  			if err != nil {
   133  				log.WithError(err).WithField(logfields.V6Prefix, v6range).Panic("BUG: Invalid default IPv6 prefix")
   134  			}
   135  
   136  			ipv6AllocRange = cidr.NewCIDR(ip6net)
   137  			log.WithField(logfields.V6Prefix, ipv6AllocRange).Info("Using autogenerated IPv6 allocation range")
   138  		}
   139  
   140  		if option.Config.EnableNodePort {
   141  			ip, err := firstGlobalV6Addr(device, nil)
   142  			if err != nil {
   143  				return
   144  			}
   145  
   146  			if ipv6NodePortAddress == nil {
   147  				ipv6NodePortAddress = ip
   148  			}
   149  		}
   150  	}
   151  }
   152  
   153  // GetIPv4ClusterRange returns the IPv4 prefix of the cluster
   154  func GetIPv4ClusterRange() *net.IPNet {
   155  	if ipv4AllocRange == nil {
   156  		return nil
   157  	}
   158  
   159  	mask := net.CIDRMask(ipv4ClusterCidrMaskSize, 32)
   160  	return &net.IPNet{
   161  		IP:   ipv4AllocRange.IPNet.IP.Mask(mask),
   162  		Mask: mask,
   163  	}
   164  }
   165  
   166  // GetIPv4Loopback returns the loopback IPv4 address of this node.
   167  func GetIPv4Loopback() net.IP {
   168  	return ipv4Loopback
   169  }
   170  
   171  // SetIPv4Loopback sets the loopback IPv4 address of this node.
   172  func SetIPv4Loopback(ip net.IP) {
   173  	ipv4Loopback = ip
   174  }
   175  
   176  // GetIPv4AllocRange returns the IPv4 allocation prefix of this node
   177  func GetIPv4AllocRange() *cidr.CIDR {
   178  	return ipv4AllocRange
   179  }
   180  
   181  // GetIPv6AllocRange returns the IPv6 allocation prefix of this node
   182  func GetIPv6AllocRange() *cidr.CIDR {
   183  	if ipv6AllocRange == nil {
   184  		return nil
   185  	}
   186  
   187  	mask := net.CIDRMask(defaults.IPv6NodeAllocPrefixLen, 128)
   188  	return cidr.NewCIDR(&net.IPNet{
   189  		IP:   ipv6AllocRange.IPNet.IP.Mask(mask),
   190  		Mask: mask,
   191  	})
   192  }
   193  
   194  // GetIPv6NodeRange returns the IPv6 allocation prefix of this node
   195  func GetIPv6NodeRange() *cidr.CIDR {
   196  	return ipv6AllocRange
   197  }
   198  
   199  // SetExternalIPv4 sets the external IPv4 node address. It must be reachable on the network.
   200  func SetExternalIPv4(ip net.IP) {
   201  	ipv4ExternalAddress = ip
   202  }
   203  
   204  // GetExternalIPv4 returns the external IPv4 node address
   205  func GetExternalIPv4() net.IP {
   206  	return ipv4ExternalAddress
   207  }
   208  
   209  // SetInternalIPv4 sets the internal IPv4 node address, it is allocated from the node prefix
   210  func SetInternalIPv4(ip net.IP) {
   211  	ipv4InternalAddress = ip
   212  }
   213  
   214  // GetInternalIPv4 returns the internal IPv4 node address
   215  func GetInternalIPv4() net.IP {
   216  	return ipv4InternalAddress
   217  }
   218  
   219  // GetHostMasqueradeIPv4 returns the IPv4 address to be used for masquerading
   220  // any traffic that is being forwarded from the host into the Cilium cluster.
   221  func GetHostMasqueradeIPv4() net.IP {
   222  	return ipv4InternalAddress
   223  }
   224  
   225  // SetIPv4AllocRange sets the IPv4 address pool to use when allocating
   226  // addresses for local endpoints
   227  func SetIPv4AllocRange(net *cidr.CIDR) {
   228  	ipv4AllocRange = net
   229  }
   230  
   231  // Uninitialize resets this package to the default state, for use in
   232  // testsuite code.
   233  func Uninitialize() {
   234  	ipv4AllocRange = nil
   235  	ipv6AllocRange = nil
   236  }
   237  
   238  // GetNodePortIPv4 returns the node-port IPv4 address for NAT
   239  func GetNodePortIPv4() net.IP {
   240  	return ipv4NodePortAddress
   241  }
   242  
   243  // GetNodePortIPv6 returns the node-port IPv4 address for NAT
   244  func GetNodePortIPv6() net.IP {
   245  	return ipv6NodePortAddress
   246  }
   247  
   248  // SetIPv6NodeRange sets the IPv6 address pool to be used on this node
   249  func SetIPv6NodeRange(net *net.IPNet) error {
   250  	if ones, _ := net.Mask.Size(); ones != defaults.IPv6NodePrefixLen {
   251  		return fmt.Errorf("prefix length must be /%d", defaults.IPv6NodePrefixLen)
   252  	}
   253  
   254  	copy := *net
   255  	ipv6AllocRange = cidr.NewCIDR(&copy)
   256  
   257  	return nil
   258  }
   259  
   260  // AutoComplete completes the parts of addressing that can be auto derived
   261  func AutoComplete() error {
   262  	if option.Config.EnableHostIPRestore {
   263  		// Read the previous cilium host IPs from node_config.h for backward
   264  		// compatibility
   265  		ipv4GW, ipv6Router := getCiliumHostIPs()
   266  
   267  		if ipv4GW != nil && option.Config.EnableIPv4 {
   268  			log.Infof("Restored IPv4 internal node IP: %s", ipv4GW.String())
   269  			SetInternalIPv4(ipv4GW)
   270  		}
   271  
   272  		if ipv6Router != nil && option.Config.EnableIPv6 {
   273  			log.Infof("Restored IPv6 router IP: %s", ipv6Router.String())
   274  			SetIPv6Router(ipv6Router)
   275  		}
   276  	}
   277  
   278  	if option.Config.Device == "undefined" {
   279  		InitDefaultPrefix("")
   280  	}
   281  
   282  	if option.Config.EnableIPv6 && ipv6AllocRange == nil {
   283  		return fmt.Errorf("IPv6 allocation CIDR is not configured. Please specificy --ipv6-range")
   284  	}
   285  
   286  	if option.Config.EnableIPv4 && ipv4AllocRange == nil {
   287  		return fmt.Errorf("IPv4 allocation CIDR is not configured. Please specificy --ipv4-range")
   288  	}
   289  
   290  	return nil
   291  }
   292  
   293  // ValidatePostInit validates the entire addressing setup and completes it as
   294  // required
   295  func ValidatePostInit() error {
   296  	if option.Config.EnableIPv4 || option.Config.Tunnel != option.TunnelDisabled {
   297  		if ipv4ExternalAddress == nil {
   298  			return fmt.Errorf("external IPv4 node address could not be derived, please configure via --ipv4-node")
   299  		}
   300  	}
   301  
   302  	if option.Config.EnableIPv4 {
   303  		if ipv4InternalAddress == nil {
   304  			return fmt.Errorf("BUG: Internal IPv4 node address was not configured")
   305  		}
   306  
   307  		ones, _ := ipv4AllocRange.Mask.Size()
   308  		if ipv4ClusterCidrMaskSize > ones {
   309  			return fmt.Errorf("IPv4 per node allocation prefix (%s) must be inside cluster prefix (%s)",
   310  				ipv4AllocRange, GetIPv4ClusterRange())
   311  		}
   312  	}
   313  
   314  	return nil
   315  }
   316  
   317  // SetIPv6 sets the IPv6 address of the node
   318  func SetIPv6(ip net.IP) {
   319  	ipv6Address = ip
   320  }
   321  
   322  // GetIPv6 returns the IPv6 address of the node
   323  func GetIPv6() net.IP {
   324  	return ipv6Address
   325  }
   326  
   327  // GetIPv6Router returns the IPv6 address of the node
   328  func GetIPv6Router() net.IP {
   329  	return ipv6RouterAddress
   330  }
   331  
   332  // SetIPv6Router returns the IPv6 address of the node
   333  func SetIPv6Router(ip net.IP) {
   334  	ipv6RouterAddress = ip
   335  }
   336  
   337  // IsHostIPv4 returns true if the IP specified is a host IP
   338  func IsHostIPv4(ip net.IP) bool {
   339  	return ip.Equal(GetInternalIPv4()) || ip.Equal(GetExternalIPv4())
   340  }
   341  
   342  // IsHostIPv6 returns true if the IP specified is a host IP
   343  func IsHostIPv6(ip net.IP) bool {
   344  	return ip.Equal(GetIPv6()) || ip.Equal(GetIPv6Router())
   345  }
   346  
   347  // GetNodeAddressing returns the NodeAddressing model for the local IPs.
   348  func GetNodeAddressing() *models.NodeAddressing {
   349  	a := &models.NodeAddressing{}
   350  
   351  	if option.Config.EnableIPv6 {
   352  		a.IPV6 = &models.NodeAddressingElement{
   353  			Enabled:    option.Config.EnableIPv6,
   354  			IP:         GetIPv6Router().String(),
   355  			AllocRange: GetIPv6AllocRange().String(),
   356  		}
   357  	}
   358  
   359  	if option.Config.EnableIPv4 {
   360  		a.IPV4 = &models.NodeAddressingElement{
   361  			Enabled:    option.Config.EnableIPv4,
   362  			IP:         GetInternalIPv4().String(),
   363  			AllocRange: GetIPv4AllocRange().String(),
   364  		}
   365  	}
   366  
   367  	return a
   368  }
   369  
   370  func getCiliumHostIPsFromFile(nodeConfig string) (ipv4GW, ipv6Router net.IP) {
   371  	var hasIPv4, hasIPv6 bool
   372  	f, err := os.Open(nodeConfig)
   373  	switch {
   374  	case err != nil:
   375  	default:
   376  		defer f.Close()
   377  		scanner := bufio.NewScanner(f)
   378  		for scanner.Scan() {
   379  			txt := scanner.Text()
   380  			switch {
   381  			case !hasIPv6 && strings.Contains(txt, defaults.RestoreV6Addr):
   382  				defineLine := strings.Split(txt, defaults.RestoreV6Addr)
   383  				if len(defineLine) != 2 {
   384  					continue
   385  				}
   386  				ipv6 := common.C2GoArray(defineLine[1])
   387  				if len(ipv6) != net.IPv6len {
   388  					continue
   389  				}
   390  				ipv6Router = net.IP(ipv6)
   391  				hasIPv6 = true
   392  			case !hasIPv4 && strings.Contains(txt, defaults.RestoreV4Addr):
   393  				defineLine := strings.Split(txt, defaults.RestoreV4Addr)
   394  				if len(defineLine) != 2 {
   395  					continue
   396  				}
   397  				ipv4 := common.C2GoArray(defineLine[1])
   398  				if len(ipv4) != net.IPv6len {
   399  					continue
   400  				}
   401  				ipv4GW = net.IP(ipv4)
   402  				hasIPv4 = true
   403  
   404  			// Legacy cases based on the header defines:
   405  			case !hasIPv4 && strings.Contains(txt, "IPV4_GATEWAY"):
   406  				// #define IPV4_GATEWAY 0xee1c000a
   407  				defineLine := strings.Split(txt, " ")
   408  				if len(defineLine) != 3 {
   409  					continue
   410  				}
   411  				ipv4GWHex := strings.TrimPrefix(defineLine[2], "0x")
   412  				ipv4GWint64, err := strconv.ParseInt(ipv4GWHex, 16, 0)
   413  				if err != nil {
   414  					continue
   415  				}
   416  				if ipv4GWint64 != int64(0) {
   417  					bs := make([]byte, net.IPv4len)
   418  					byteorder.NetworkToHostPut(bs, uint32(ipv4GWint64))
   419  					ipv4GW = net.IPv4(bs[0], bs[1], bs[2], bs[3])
   420  					hasIPv4 = true
   421  				}
   422  			case !hasIPv6 && strings.Contains(txt, " ROUTER_IP "):
   423  				// #define ROUTER_IP 0xf0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8a, 0xd6
   424  				defineLine := strings.Split(txt, " ROUTER_IP ")
   425  				if len(defineLine) != 2 {
   426  					continue
   427  				}
   428  				ipv6 := common.C2GoArray(defineLine[1])
   429  				if len(ipv6) != net.IPv6len {
   430  					continue
   431  				}
   432  				ipv6Router = net.IP(ipv6)
   433  				hasIPv6 = true
   434  			}
   435  		}
   436  	}
   437  	return ipv4GW, ipv6Router
   438  }
   439  
   440  // getCiliumHostIPs returns the Cilium IPv4 gateway and router IPv6 address from
   441  // the node_config.h file if is present; or by deriving it from
   442  // defaults.HostDevice interface, on which only the IPv4 is possible to derive.
   443  func getCiliumHostIPs() (ipv4GW, ipv6Router net.IP) {
   444  	nodeConfig := option.Config.GetNodeConfigPath()
   445  	ipv4GW, ipv6Router = getCiliumHostIPsFromFile(nodeConfig)
   446  	if ipv4GW != nil {
   447  		return ipv4GW, ipv6Router
   448  	}
   449  	return getCiliumHostIPsFromNetDev(option.Config.HostDevice)
   450  }
   451  
   452  // SetIPsecKeyIdentity sets the IPsec key identity an opaque value used to
   453  // identity encryption keys used on the node.
   454  func SetIPsecKeyIdentity(id uint8) {
   455  	ipsecKeyIdentity = id
   456  }
   457  
   458  // GetIPsecKeyIdentity returns the IPsec key identity of the node
   459  func GetIPsecKeyIdentity() uint8 {
   460  	return ipsecKeyIdentity
   461  }