github.com/khulnasoft-lab/khulnasoft@v26.0.1-0.20240328202558-330a6f959fe0+incompatible/libnetwork/default_gateway.go (about) 1 package libnetwork 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 8 "github.com/containerd/log" 9 "github.com/docker/docker/libnetwork/netlabel" 10 "github.com/docker/docker/libnetwork/types" 11 ) 12 13 const ( 14 gwEPlen = 12 15 ) 16 17 var procGwNetwork = make(chan (bool), 1) 18 19 /* 20 libnetwork creates a bridge network "docker_gw_bridge" for providing 21 default gateway for the containers if none of the container's endpoints 22 have GW set by the driver. ICC is set to false for the GW_bridge network. 23 24 If a driver can't provide external connectivity it can choose to not set 25 the GW IP for the endpoint. 26 27 endpoint on the GW_bridge network is managed dynamically by libnetwork. 28 ie: 29 - its created when an endpoint without GW joins the container 30 - its deleted when an endpoint with GW joins the container 31 */ 32 33 func (sb *Sandbox) setupDefaultGW() error { 34 // check if the container already has a GW endpoint 35 if ep := sb.getEndpointInGWNetwork(); ep != nil { 36 return nil 37 } 38 39 c := sb.controller 40 41 // Look for default gw network. In case of error (includes not found), 42 // retry and create it if needed in a serialized execution. 43 n, err := c.NetworkByName(libnGWNetwork) 44 if err != nil { 45 if n, err = c.defaultGwNetwork(); err != nil { 46 return err 47 } 48 } 49 50 createOptions := []EndpointOption{} 51 52 var gwName string 53 if len(sb.containerID) <= gwEPlen { 54 gwName = "gateway_" + sb.containerID 55 } else { 56 gwName = "gateway_" + sb.id[:gwEPlen] 57 } 58 59 sbLabels := sb.Labels() 60 61 if sbLabels[netlabel.PortMap] != nil { 62 createOptions = append(createOptions, CreateOptionPortMapping(sbLabels[netlabel.PortMap].([]types.PortBinding))) 63 } 64 65 if sbLabels[netlabel.ExposedPorts] != nil { 66 createOptions = append(createOptions, CreateOptionExposedPorts(sbLabels[netlabel.ExposedPorts].([]types.TransportPort))) 67 } 68 69 epOption := getPlatformOption() 70 if epOption != nil { 71 createOptions = append(createOptions, epOption) 72 } 73 74 newEp, err := n.CreateEndpoint(gwName, createOptions...) 75 if err != nil { 76 return fmt.Errorf("container %s: endpoint create on GW Network failed: %v", sb.containerID, err) 77 } 78 79 defer func() { 80 if err != nil { 81 if err2 := newEp.Delete(true); err2 != nil { 82 log.G(context.TODO()).Warnf("Failed to remove gw endpoint for container %s after failing to join the gateway network: %v", 83 sb.containerID, err2) 84 } 85 } 86 }() 87 88 if err = newEp.sbJoin(sb); err != nil { 89 return fmt.Errorf("container %s: endpoint join on GW Network failed: %v", sb.containerID, err) 90 } 91 92 return nil 93 } 94 95 // If present, detach and remove the endpoint connecting the sandbox to the default gw network. 96 func (sb *Sandbox) clearDefaultGW() error { 97 var ep *Endpoint 98 99 if ep = sb.getEndpointInGWNetwork(); ep == nil { 100 return nil 101 } 102 if err := ep.sbLeave(sb, false); err != nil { 103 return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err) 104 } 105 if err := ep.Delete(false); err != nil { 106 return fmt.Errorf("container %s: deleting endpoint on GW Network failed: %v", sb.containerID, err) 107 } 108 return nil 109 } 110 111 // Evaluate whether the sandbox requires a default gateway based 112 // on the endpoints to which it is connected. It does not account 113 // for the default gateway network endpoint. 114 115 func (sb *Sandbox) needDefaultGW() bool { 116 var needGW bool 117 118 for _, ep := range sb.Endpoints() { 119 if ep.endpointInGWNetwork() { 120 continue 121 } 122 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" { 123 continue 124 } 125 if ep.getNetwork().Internal() { 126 continue 127 } 128 // During stale sandbox cleanup, joinInfo may be nil 129 if ep.joinInfo != nil && ep.joinInfo.disableGatewayService { 130 continue 131 } 132 // TODO v6 needs to be handled. 133 if len(ep.Gateway()) > 0 { 134 return false 135 } 136 for _, r := range ep.StaticRoutes() { 137 if r.Destination != nil && r.Destination.String() == "0.0.0.0/0" { 138 return false 139 } 140 } 141 needGW = true 142 } 143 144 return needGW 145 } 146 147 func (sb *Sandbox) getEndpointInGWNetwork() *Endpoint { 148 for _, ep := range sb.Endpoints() { 149 if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") { 150 return ep 151 } 152 } 153 return nil 154 } 155 156 func (ep *Endpoint) endpointInGWNetwork() bool { 157 if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") { 158 return true 159 } 160 return false 161 } 162 163 // Looks for the default gw network and creates it if not there. 164 // Parallel executions are serialized. 165 func (c *Controller) defaultGwNetwork() (*Network, error) { 166 procGwNetwork <- true 167 defer func() { <-procGwNetwork }() 168 169 n, err := c.NetworkByName(libnGWNetwork) 170 if _, ok := err.(types.NotFoundError); ok { 171 n, err = c.createGWNetwork() 172 } 173 return n, err 174 } 175 176 // Returns the endpoint which is providing external connectivity to the sandbox 177 func (sb *Sandbox) getGatewayEndpoint() *Endpoint { 178 for _, ep := range sb.Endpoints() { 179 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" { 180 continue 181 } 182 if len(ep.Gateway()) != 0 { 183 return ep 184 } 185 } 186 return nil 187 }