github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/drivers/macvlan/macvlan_joinleave.go (about)

     1  package macvlan
     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/sirupsen/logrus"
    12  )
    13  
    14  // Join method is invoked when a Sandbox is attached to an endpoint.
    15  func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
    16  	defer osl.InitOSContext()()
    17  	n, err := d.getNetwork(nid)
    18  	if err != nil {
    19  		return err
    20  	}
    21  	endpoint := n.endpoint(eid)
    22  	if endpoint == nil {
    23  		return fmt.Errorf("could not find endpoint with id %s", eid)
    24  	}
    25  	// generate a name for the iface that will be renamed to eth0 in the sbox
    26  	containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen)
    27  	if err != nil {
    28  		return fmt.Errorf("error generating an interface name: %s", err)
    29  	}
    30  	// create the netlink macvlan interface
    31  	vethName, err := createMacVlan(containerIfName, n.config.Parent, n.config.MacvlanMode)
    32  	if err != nil {
    33  		return err
    34  	}
    35  	// bind the generated iface name to the endpoint
    36  	endpoint.srcName = vethName
    37  	ep := n.endpoint(eid)
    38  	if ep == nil {
    39  		return fmt.Errorf("could not find endpoint with id %s", eid)
    40  	}
    41  	// parse and match the endpoint address with the available v4 subnets
    42  	if !n.config.Internal {
    43  		if len(n.config.Ipv4Subnets) > 0 {
    44  			s := n.getSubnetforIPv4(ep.addr)
    45  			if s == nil {
    46  				return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid)
    47  			}
    48  			v4gw, _, err := net.ParseCIDR(s.GwIP)
    49  			if err != nil {
    50  				return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err)
    51  			}
    52  			err = jinfo.SetGateway(v4gw)
    53  			if err != nil {
    54  				return err
    55  			}
    56  			logrus.Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, MacVlan_Mode: %s, Parent: %s",
    57  				ep.addr.IP.String(), v4gw.String(), n.config.MacvlanMode, n.config.Parent)
    58  		}
    59  		// parse and match the endpoint address with the available v6 subnets
    60  		if len(n.config.Ipv6Subnets) > 0 {
    61  			s := n.getSubnetforIPv6(ep.addrv6)
    62  			if s == nil {
    63  				return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid)
    64  			}
    65  			v6gw, _, err := net.ParseCIDR(s.GwIP)
    66  			if err != nil {
    67  				return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err)
    68  			}
    69  			err = jinfo.SetGatewayIPv6(v6gw)
    70  			if err != nil {
    71  				return err
    72  			}
    73  			logrus.Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s Gateway: %s MacVlan_Mode: %s, Parent: %s",
    74  				ep.addrv6.IP.String(), v6gw.String(), n.config.MacvlanMode, n.config.Parent)
    75  		}
    76  	} else {
    77  		if len(n.config.Ipv4Subnets) > 0 {
    78  			logrus.Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, MacVlan_Mode: %s, Parent: %s",
    79  				ep.addr.IP.String(), n.config.MacvlanMode, n.config.Parent)
    80  		}
    81  		if len(n.config.Ipv6Subnets) > 0 {
    82  			logrus.Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s MacVlan_Mode: %s, Parent: %s",
    83  				ep.addrv6.IP.String(), n.config.MacvlanMode, n.config.Parent)
    84  		}
    85  	}
    86  	iNames := jinfo.InterfaceName()
    87  	err = iNames.SetNames(vethName, containerVethPrefix)
    88  	if err != nil {
    89  		return err
    90  	}
    91  	if err := d.storeUpdate(ep); err != nil {
    92  		return fmt.Errorf("failed to save macvlan endpoint %.7s to store: %v", ep.id, err)
    93  	}
    94  	return nil
    95  }
    96  
    97  // Leave method is invoked when a Sandbox detaches from an endpoint.
    98  func (d *driver) Leave(nid, eid string) error {
    99  	defer osl.InitOSContext()()
   100  	network, err := d.getNetwork(nid)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	endpoint, err := network.getEndpoint(eid)
   105  	if err != nil {
   106  		return err
   107  	}
   108  	if endpoint == nil {
   109  		return fmt.Errorf("could not find endpoint with id %s", eid)
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  // getSubnetforIP returns the ipv4 subnet to which the given IP belongs
   116  func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipv4Subnet {
   117  	for _, s := range n.config.Ipv4Subnets {
   118  		_, snet, err := net.ParseCIDR(s.SubnetIP)
   119  		if err != nil {
   120  			return nil
   121  		}
   122  		// first check if the mask lengths are the same
   123  		i, _ := snet.Mask.Size()
   124  		j, _ := ip.Mask.Size()
   125  		if i != j {
   126  			continue
   127  		}
   128  		if snet.Contains(ip.IP) {
   129  			return s
   130  		}
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  // getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs
   137  func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipv6Subnet {
   138  	for _, s := range n.config.Ipv6Subnets {
   139  		_, snet, err := net.ParseCIDR(s.SubnetIP)
   140  		if err != nil {
   141  			return nil
   142  		}
   143  		// first check if the mask lengths are the same
   144  		i, _ := snet.Mask.Size()
   145  		j, _ := ip.Mask.Size()
   146  		if i != j {
   147  			continue
   148  		}
   149  		if snet.Contains(ip.IP) {
   150  			return s
   151  		}
   152  	}
   153  
   154  	return nil
   155  }