setup_ipv6_linux.go 3.1 KB

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