github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/utils/net/route.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 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 net 16 17 import ( 18 "errors" 19 "fmt" 20 "net" 21 "os" 22 "strings" 23 "syscall" 24 25 "github.com/sirupsen/logrus" 26 "github.com/vishvananda/netlink" 27 k8snet "k8s.io/apimachinery/pkg/util/net" 28 k8sutilsnet "k8s.io/utils/net" 29 30 "github.com/sealerio/sealer/common" 31 "github.com/sealerio/sealer/utils/exec" 32 ) 33 34 const ( 35 RouteArg = "%s via %s dev %s metric 50" 36 BackupAndDelStaticRouteFile = `if [ -f /etc/sysconfig/network-scripts/route-%s ]; then 37 yes | cp /etc/sysconfig/network-scripts/route-%s /etc/sysconfig/network-scripts/.route-%s 38 sed -i "/%s/d" /etc/sysconfig/network-scripts/route-%s 39 fi` 40 AddStaticRouteFile = `cat /etc/sysconfig/network-scripts/route-%s|grep "%s" || echo "%s" >> /etc/sysconfig/network-scripts/route-%s` 41 ) 42 43 const ( 44 RouteOK = "ok" 45 RouteFailed = "failed" 46 ) 47 48 var ErrNotIPV4 = errors.New("IP addresses are not IPV4 rules") 49 50 type Route struct { 51 Host net.IP 52 Gateway net.IP 53 } 54 55 func NewRouter(host, gateway net.IP) *Route { 56 return &Route{ 57 Host: host, 58 Gateway: gateway, 59 } 60 } 61 62 func CheckIsDefaultRoute(host net.IP) error { 63 ok, err := isDefaultRouteIP(host) 64 if err == nil && ok { 65 _, err = common.StdOut.WriteString(RouteOK) 66 } 67 if err == nil && !ok { 68 _, err = common.StdErr.WriteString(RouteFailed) 69 } 70 return err 71 } 72 73 // SetRoute ip route add $route 74 func (r *Route) SetRoute() error { 75 if !k8sutilsnet.IsIPv4(r.Gateway) || !k8sutilsnet.IsIPv4(r.Host) { 76 logrus.Warningf("%v, skip", ErrNotIPV4) 77 return nil 78 } 79 err := addRouteGatewayViaHost(r.Host, r.Gateway, 50) 80 if err != nil && !errors.Is(err, os.ErrExist) /* return if route already exist */ { 81 return fmt.Errorf("failed to add %s route gateway via host err: %v", r.Host, err) 82 } 83 84 netInterface, err := GetHostNetInterface(r.Gateway) 85 if err != nil { 86 return err 87 } 88 if netInterface != "" { 89 route := fmt.Sprintf(RouteArg, r.Host, r.Gateway, netInterface) 90 _, err = exec.RunSimpleCmd(fmt.Sprintf(AddStaticRouteFile, netInterface, route, route, netInterface)) 91 if err != nil { 92 return err 93 } 94 } 95 logrus.Info(fmt.Sprintf("success to set route.(host:%s, gateway:%s)", r.Host, r.Gateway)) 96 return nil 97 } 98 99 // DelRoute ip route del $route 100 func (r *Route) DelRoute() error { 101 if !k8sutilsnet.IsIPv4(r.Gateway) || !k8sutilsnet.IsIPv4(r.Host) { 102 logrus.Warningf("%v, skip", ErrNotIPV4) 103 return nil 104 } 105 err := delRouteGatewayViaHost(r.Host, r.Gateway) 106 if err != nil && !errors.Is(err, syscall.ESRCH) /* return if route does not exist */ { 107 return fmt.Errorf("failed to delete %s route gateway via host: %v", r.Host, err) 108 } 109 netInterface, err := GetHostNetInterface(r.Gateway) 110 if err != nil { 111 return err 112 } 113 if netInterface != "" { 114 route := fmt.Sprintf(RouteArg, r.Host, r.Gateway, netInterface) 115 out, err := exec.RunSimpleCmd(fmt.Sprintf(BackupAndDelStaticRouteFile, netInterface, netInterface, netInterface, route, netInterface)) 116 if err != nil { 117 logrus.Info(out) 118 return err 119 } 120 } 121 logrus.Info(fmt.Sprintf("success to del route(host:%s, gateway:%s)", r.Host, r.Gateway)) 122 return nil 123 } 124 125 // isDefaultRouteIP return true if host equal default route ip host. 126 func isDefaultRouteIP(host net.IP) (bool, error) { 127 netIP, err := k8snet.ChooseHostInterface() 128 if err != nil { 129 return false, fmt.Errorf("failed to get default route ip, err: %v", err) 130 } 131 return netIP.Equal(host), nil 132 } 133 134 func addRouteGatewayViaHost(host, gateway net.IP, priority int) error { 135 Dst := &net.IPNet{ 136 IP: host, 137 Mask: net.CIDRMask(32, 32), 138 } 139 r := &netlink.Route{ 140 Dst: Dst, 141 Gw: gateway, 142 Priority: priority, 143 } 144 return netlink.RouteAdd(r) 145 } 146 147 func delRouteGatewayViaHost(host, gateway net.IP) error { 148 Dst := &net.IPNet{ 149 IP: host, 150 Mask: net.CIDRMask(32, 32), 151 } 152 r := &netlink.Route{ 153 Dst: Dst, 154 Gw: gateway, 155 } 156 return netlink.RouteDel(r) 157 } 158 159 func IsIpv4(ip string) bool { 160 arr := strings.Split(ip, ".") 161 if len(arr) != 4 { 162 return false 163 } 164 for _, v := range arr { 165 if v == "" { 166 return false 167 } 168 if len(v) > 1 && v[0] == '0' { 169 return false 170 } 171 num := 0 172 for _, c := range v { 173 if c >= '0' && c <= '9' { 174 num = num*10 + int(c-'0') 175 } else { 176 return false 177 } 178 } 179 if num > 255 { 180 return false 181 } 182 } 183 return true 184 }