github.com/moby/docker@v26.1.3+incompatible/libnetwork/drivers/bridge/setup_ipv6_linux.go (about)

     1  package bridge
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"net/netip"
     8  	"os"
     9  
    10  	"github.com/containerd/log"
    11  	"github.com/vishvananda/netlink"
    12  )
    13  
    14  // bridgeIPv6 is the default, link-local IPv6 address for the bridge (fe80::1/64)
    15  var bridgeIPv6 = &net.IPNet{IP: net.ParseIP("fe80::1"), Mask: net.CIDRMask(64, 128)}
    16  
    17  // Standard link local prefix
    18  var linkLocalPrefix = netip.MustParsePrefix("fe80::/64")
    19  
    20  const (
    21  	ipv6ForwardConfPerm    = 0o644
    22  	ipv6ForwardConfDefault = "/proc/sys/net/ipv6/conf/default/forwarding"
    23  	ipv6ForwardConfAll     = "/proc/sys/net/ipv6/conf/all/forwarding"
    24  )
    25  
    26  func setupBridgeIPv6(config *networkConfiguration, i *bridgeInterface) error {
    27  	procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6"
    28  	ipv6BridgeData, err := os.ReadFile(procFile)
    29  	if err != nil {
    30  		return fmt.Errorf("Cannot read IPv6 setup for bridge %v: %v", config.BridgeName, err)
    31  	}
    32  	// Enable IPv6 on the bridge only if it isn't already enabled
    33  	if ipv6BridgeData[0] != '0' {
    34  		if err := os.WriteFile(procFile, []byte{'0', '\n'}, ipv6ForwardConfPerm); err != nil {
    35  			return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
    36  		}
    37  	}
    38  
    39  	// Remove unwanted addresses from the bridge, add required addresses, and assign
    40  	// values to "i.bridgeIPv6", "i.gatewayIPv6".
    41  	if err := i.programIPv6Addresses(config); err != nil {
    42  		return err
    43  	}
    44  
    45  	// Setting route to global IPv6 subnet
    46  	log.G(context.TODO()).Debugf("Adding route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
    47  	err = i.nlh.RouteAdd(&netlink.Route{
    48  		Scope:     netlink.SCOPE_UNIVERSE,
    49  		LinkIndex: i.Link.Attrs().Index,
    50  		Dst:       config.AddressIPv6,
    51  	})
    52  	if err != nil && !os.IsExist(err) {
    53  		log.G(context.TODO()).Errorf("Could not add route to IPv6 network %s via device %s: %s", config.AddressIPv6.String(), config.BridgeName, err)
    54  	}
    55  
    56  	return nil
    57  }
    58  
    59  func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
    60  	if !config.AddressIPv6.Contains(config.DefaultGatewayIPv6) {
    61  		return &ErrInvalidGateway{}
    62  	}
    63  
    64  	// Store requested default gateway
    65  	i.gatewayIPv6 = config.DefaultGatewayIPv6
    66  
    67  	return nil
    68  }
    69  
    70  func setupIPv6Forwarding(config *networkConfiguration, i *bridgeInterface) error {
    71  	// Get current IPv6 default forwarding setup
    72  	ipv6ForwardDataDefault, err := os.ReadFile(ipv6ForwardConfDefault)
    73  	if err != nil {
    74  		return fmt.Errorf("Cannot read IPv6 default forwarding setup: %v", err)
    75  	}
    76  	// Enable IPv6 default forwarding only if it is not already enabled
    77  	if ipv6ForwardDataDefault[0] != '1' {
    78  		if err := os.WriteFile(ipv6ForwardConfDefault, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
    79  			log.G(context.TODO()).Warnf("Unable to enable IPv6 default forwarding: %v", err)
    80  		}
    81  	}
    82  
    83  	// Get current IPv6 all forwarding setup
    84  	ipv6ForwardDataAll, err := os.ReadFile(ipv6ForwardConfAll)
    85  	if err != nil {
    86  		return fmt.Errorf("Cannot read IPv6 all forwarding setup: %v", err)
    87  	}
    88  	// Enable IPv6 all forwarding only if it is not already enabled
    89  	if ipv6ForwardDataAll[0] != '1' {
    90  		if err := os.WriteFile(ipv6ForwardConfAll, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
    91  			log.G(context.TODO()).Warnf("Unable to enable IPv6 all forwarding: %v", err)
    92  		}
    93  	}
    94  
    95  	return nil
    96  }