github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/drivers/ipvlan/ipvlan_joinleave.go (about) 1 package ipvlan 2 3 import ( 4 "fmt" 5 "net" 6 7 "github.com/docker/libnetwork/driverapi" 8 "github.com/docker/libnetwork/netutils" 9 "github.com/docker/libnetwork/ns" 10 "github.com/docker/libnetwork/osl" 11 "github.com/docker/libnetwork/types" 12 "github.com/sirupsen/logrus" 13 ) 14 15 type staticRoute struct { 16 Destination *net.IPNet 17 RouteType int 18 NextHop net.IP 19 } 20 21 const ( 22 defaultV4RouteCidr = "0.0.0.0/0" 23 defaultV6RouteCidr = "::/0" 24 ) 25 26 // Join method is invoked when a Sandbox is attached to an endpoint. 27 func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { 28 defer osl.InitOSContext()() 29 n, err := d.getNetwork(nid) 30 if err != nil { 31 return err 32 } 33 endpoint := n.endpoint(eid) 34 if endpoint == nil { 35 return fmt.Errorf("could not find endpoint with id %s", eid) 36 } 37 // generate a name for the iface that will be renamed to eth0 in the sbox 38 containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen) 39 if err != nil { 40 return fmt.Errorf("error generating an interface name: %v", err) 41 } 42 // create the netlink ipvlan interface 43 vethName, err := createIPVlan(containerIfName, n.config.Parent, n.config.IpvlanMode) 44 if err != nil { 45 return err 46 } 47 // bind the generated iface name to the endpoint 48 endpoint.srcName = vethName 49 ep := n.endpoint(eid) 50 if ep == nil { 51 return fmt.Errorf("could not find endpoint with id %s", eid) 52 } 53 if !n.config.Internal { 54 if n.config.IpvlanMode == modeL3 { 55 // disable gateway services to add a default gw using dev eth0 only 56 jinfo.DisableGatewayService() 57 defaultRoute, err := ifaceGateway(defaultV4RouteCidr) 58 if err != nil { 59 return err 60 } 61 if err := jinfo.AddStaticRoute(defaultRoute.Destination, defaultRoute.RouteType, defaultRoute.NextHop); err != nil { 62 return fmt.Errorf("failed to set an ipvlan l3 mode ipv4 default gateway: %v", err) 63 } 64 logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Ipvlan_Mode: %s, Parent: %s", 65 ep.addr.IP.String(), n.config.IpvlanMode, n.config.Parent) 66 // If the endpoint has a v6 address, set a v6 default route 67 if ep.addrv6 != nil { 68 default6Route, err := ifaceGateway(defaultV6RouteCidr) 69 if err != nil { 70 return err 71 } 72 if err = jinfo.AddStaticRoute(default6Route.Destination, default6Route.RouteType, default6Route.NextHop); err != nil { 73 return fmt.Errorf("failed to set an ipvlan l3 mode ipv6 default gateway: %v", err) 74 } 75 logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Ipvlan_Mode: %s, Parent: %s", 76 ep.addrv6.IP.String(), n.config.IpvlanMode, n.config.Parent) 77 } 78 } 79 if n.config.IpvlanMode == modeL2 { 80 // parse and correlate the endpoint v4 address with the available v4 subnets 81 if len(n.config.Ipv4Subnets) > 0 { 82 s := n.getSubnetforIPv4(ep.addr) 83 if s == nil { 84 return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid) 85 } 86 v4gw, _, err := net.ParseCIDR(s.GwIP) 87 if err != nil { 88 return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err) 89 } 90 err = jinfo.SetGateway(v4gw) 91 if err != nil { 92 return err 93 } 94 logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s", 95 ep.addr.IP.String(), v4gw.String(), n.config.IpvlanMode, n.config.Parent) 96 } 97 // parse and correlate the endpoint v6 address with the available v6 subnets 98 if len(n.config.Ipv6Subnets) > 0 { 99 s := n.getSubnetforIPv6(ep.addrv6) 100 if s == nil { 101 return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid) 102 } 103 v6gw, _, err := net.ParseCIDR(s.GwIP) 104 if err != nil { 105 return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err) 106 } 107 err = jinfo.SetGatewayIPv6(v6gw) 108 if err != nil { 109 return err 110 } 111 logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s", 112 ep.addrv6.IP.String(), v6gw.String(), n.config.IpvlanMode, n.config.Parent) 113 } 114 } 115 } else { 116 if len(n.config.Ipv4Subnets) > 0 { 117 logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, IpVlan_Mode: %s, Parent: %s", 118 ep.addr.IP.String(), n.config.IpvlanMode, n.config.Parent) 119 } 120 if len(n.config.Ipv6Subnets) > 0 { 121 logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s IpVlan_Mode: %s, Parent: %s", 122 ep.addrv6.IP.String(), n.config.IpvlanMode, n.config.Parent) 123 } 124 } 125 iNames := jinfo.InterfaceName() 126 err = iNames.SetNames(vethName, containerVethPrefix) 127 if err != nil { 128 return err 129 } 130 if err = d.storeUpdate(ep); err != nil { 131 return fmt.Errorf("failed to save ipvlan endpoint %.7s to store: %v", ep.id, err) 132 } 133 134 return nil 135 } 136 137 // Leave method is invoked when a Sandbox detaches from an endpoint. 138 func (d *driver) Leave(nid, eid string) error { 139 defer osl.InitOSContext()() 140 network, err := d.getNetwork(nid) 141 if err != nil { 142 return err 143 } 144 endpoint, err := network.getEndpoint(eid) 145 if err != nil { 146 return err 147 } 148 if endpoint == nil { 149 return fmt.Errorf("could not find endpoint with id %s", eid) 150 } 151 152 return nil 153 } 154 155 // ifaceGateway returns a static route for either v4/v6 to be set to the container eth0 156 func ifaceGateway(dfNet string) (*staticRoute, error) { 157 nh, dst, err := net.ParseCIDR(dfNet) 158 if err != nil { 159 return nil, fmt.Errorf("unable to parse default route %v", err) 160 } 161 defaultRoute := &staticRoute{ 162 Destination: dst, 163 RouteType: types.CONNECTED, 164 NextHop: nh, 165 } 166 167 return defaultRoute, nil 168 } 169 170 // getSubnetforIPv4 returns the ipv4 subnet to which the given IP belongs 171 func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipv4Subnet { 172 for _, s := range n.config.Ipv4Subnets { 173 _, snet, err := net.ParseCIDR(s.SubnetIP) 174 if err != nil { 175 return nil 176 } 177 // first check if the mask lengths are the same 178 i, _ := snet.Mask.Size() 179 j, _ := ip.Mask.Size() 180 if i != j { 181 continue 182 } 183 if snet.Contains(ip.IP) { 184 return s 185 } 186 } 187 188 return nil 189 } 190 191 // getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs 192 func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipv6Subnet { 193 for _, s := range n.config.Ipv6Subnets { 194 _, snet, err := net.ParseCIDR(s.SubnetIP) 195 if err != nil { 196 return nil 197 } 198 // first check if the mask lengths are the same 199 i, _ := snet.Mask.Size() 200 j, _ := ip.Mask.Size() 201 if i != j { 202 continue 203 } 204 if snet.Contains(ip.IP) { 205 return s 206 } 207 } 208 209 return nil 210 }