2015-02-23 01:58:52 +00:00
|
|
|
package bridge
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
2015-10-05 21:53:25 +00:00
|
|
|
"os"
|
2015-02-23 01:58:52 +00:00
|
|
|
|
2015-05-28 23:30:36 +00:00
|
|
|
"github.com/Sirupsen/logrus"
|
2016-01-07 02:13:08 +00:00
|
|
|
"github.com/docker/libnetwork/types"
|
2015-02-23 01:58:52 +00:00
|
|
|
"github.com/vishvananda/netlink"
|
|
|
|
)
|
|
|
|
|
2015-03-04 21:25:43 +00:00
|
|
|
var bridgeIPv6 *net.IPNet
|
2015-02-23 01:58:52 +00:00
|
|
|
|
2015-05-28 23:30:36 +00:00
|
|
|
const (
|
2015-07-27 11:31:03 +00:00
|
|
|
bridgeIPv6Str = "fe80::1/64"
|
|
|
|
ipv6ForwardConfPerm = 0644
|
|
|
|
ipv6ForwardConfDefault = "/proc/sys/net/ipv6/conf/default/forwarding"
|
|
|
|
ipv6ForwardConfAll = "/proc/sys/net/ipv6/conf/all/forwarding"
|
2015-05-28 23:30:36 +00:00
|
|
|
)
|
2015-02-23 01:58:52 +00:00
|
|
|
|
|
|
|
func init() {
|
|
|
|
// We allow ourselves to panic in this special case because we indicate a
|
|
|
|
// failure to parse a compile-time define constant.
|
2016-01-07 02:13:08 +00:00
|
|
|
var err error
|
|
|
|
if bridgeIPv6, err = types.ParseCIDR(bridgeIPv6Str); err != nil {
|
2015-03-04 21:25:43 +00:00
|
|
|
panic(fmt.Sprintf("Cannot parse default bridge IPv6 address %q: %v", bridgeIPv6Str, err))
|
2015-02-23 01:58:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-22 17:56:36 +00:00
|
|
|
func setupBridgeIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
2015-04-15 05:25:42 +00:00
|
|
|
procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6"
|
2015-07-27 11:31:03 +00:00
|
|
|
ipv6BridgeData, err := ioutil.ReadFile(procFile)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Cannot read IPv6 setup for bridge %v: %v", config.BridgeName, err)
|
|
|
|
}
|
|
|
|
// Enable IPv6 on the bridge only if it isn't already enabled
|
|
|
|
if ipv6BridgeData[0] != '0' {
|
|
|
|
if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, ipv6ForwardConfPerm); err != nil {
|
|
|
|
return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
|
|
|
|
}
|
2015-02-23 01:58:52 +00:00
|
|
|
}
|
2015-02-27 17:11:53 +00:00
|
|
|
|
2015-04-24 22:13:44 +00:00
|
|
|
// Store bridge network and default gateway
|
2015-04-10 16:02:25 +00:00
|
|
|
i.bridgeIPv6 = bridgeIPv6
|
2015-04-24 22:13:44 +00:00
|
|
|
i.gatewayIPv6 = i.bridgeIPv6.IP
|
|
|
|
|
2016-01-07 02:13:08 +00:00
|
|
|
if err := i.programIPv6Address(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-10-05 21:53:25 +00:00
|
|
|
if config.AddressIPv6 == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-01-07 02:13:08 +00:00
|
|
|
// Store the user specified bridge network and network gateway and program it
|
2015-12-15 17:52:03 +00:00
|
|
|
i.bridgeIPv6 = config.AddressIPv6
|
|
|
|
i.gatewayIPv6 = config.AddressIPv6.IP
|
2016-01-07 02:13:08 +00:00
|
|
|
|
|
|
|
if err := i.programIPv6Address(); err != nil {
|
|
|
|
return err
|
2015-12-15 17:52:03 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 21:53:25 +00:00
|
|
|
// Setting route to global IPv6 subnet
|
|
|
|
logrus.Debugf("Adding route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
|
2016-05-16 18:51:40 +00:00
|
|
|
err = i.nlh.RouteAdd(&netlink.Route{
|
2015-10-05 21:53:25 +00:00
|
|
|
Scope: netlink.SCOPE_UNIVERSE,
|
|
|
|
LinkIndex: i.Link.Attrs().Index,
|
|
|
|
Dst: config.AddressIPv6,
|
|
|
|
})
|
|
|
|
if err != nil && !os.IsExist(err) {
|
|
|
|
logrus.Errorf("Could not add route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
|
|
|
|
}
|
|
|
|
|
2015-04-24 22:13:44 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-05-22 17:56:36 +00:00
|
|
|
func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
2015-10-05 21:53:25 +00:00
|
|
|
if config.AddressIPv6 == nil {
|
|
|
|
return &ErrInvalidContainerSubnet{}
|
|
|
|
}
|
|
|
|
if !config.AddressIPv6.Contains(config.DefaultGatewayIPv6) {
|
|
|
|
return &ErrInvalidGateway{}
|
|
|
|
}
|
|
|
|
|
2015-04-24 22:13:44 +00:00
|
|
|
// Store requested default gateway
|
|
|
|
i.gatewayIPv6 = config.DefaultGatewayIPv6
|
2015-10-05 21:53:25 +00:00
|
|
|
|
2015-02-27 17:11:53 +00:00
|
|
|
return nil
|
2015-02-23 01:58:52 +00:00
|
|
|
}
|
2015-05-28 23:30:36 +00:00
|
|
|
|
|
|
|
func setupIPv6Forwarding(config *networkConfiguration, i *bridgeInterface) error {
|
2015-07-27 11:31:03 +00:00
|
|
|
// Get current IPv6 default forwarding setup
|
|
|
|
ipv6ForwardDataDefault, err := ioutil.ReadFile(ipv6ForwardConfDefault)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Cannot read IPv6 default forwarding setup: %v", err)
|
2015-05-28 23:30:36 +00:00
|
|
|
}
|
2015-07-27 11:31:03 +00:00
|
|
|
// Enable IPv6 default forwarding only if it is not already enabled
|
|
|
|
if ipv6ForwardDataDefault[0] != '1' {
|
|
|
|
if err := ioutil.WriteFile(ipv6ForwardConfDefault, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
|
|
|
|
logrus.Warnf("Unable to enable IPv6 default forwarding: %v", err)
|
|
|
|
}
|
2015-05-28 23:30:36 +00:00
|
|
|
}
|
2015-07-27 11:31:03 +00:00
|
|
|
|
|
|
|
// Get current IPv6 all forwarding setup
|
|
|
|
ipv6ForwardDataAll, err := ioutil.ReadFile(ipv6ForwardConfAll)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Cannot read IPv6 all forwarding setup: %v", err)
|
|
|
|
}
|
|
|
|
// Enable IPv6 all forwarding only if it is not already enabled
|
|
|
|
if ipv6ForwardDataAll[0] != '1' {
|
|
|
|
if err := ioutil.WriteFile(ipv6ForwardConfAll, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
|
|
|
|
logrus.Warnf("Unable to enable IPv6 all forwarding: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-28 23:30:36 +00:00
|
|
|
return nil
|
|
|
|
}
|