2022-09-06 12:16:29 +00:00
|
|
|
package netlink
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
)
|
|
|
|
|
|
2024-10-14 16:44:05 +00:00
|
|
|
type IPv6SupportLevel uint8
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
IPv6Unsupported = iota
|
|
|
|
|
// IPv6Supported indicates the host supports IPv6 but has no access to the
|
|
|
|
|
// Internet via IPv6. It is true if one IPv6 route is found and no default
|
|
|
|
|
// IPv6 route is found.
|
|
|
|
|
IPv6Supported
|
|
|
|
|
// IPv6Internet indicates the host has access to the Internet via IPv6,
|
|
|
|
|
// which is detected when a default IPv6 route is found.
|
|
|
|
|
IPv6Internet
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func (i IPv6SupportLevel) IsSupported() bool {
|
|
|
|
|
return i == IPv6Supported || i == IPv6Internet
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (n *NetLink) FindIPv6SupportLevel() (level IPv6SupportLevel, err error) {
|
2023-06-08 09:12:46 +00:00
|
|
|
routes, err := n.RouteList(FamilyV6)
|
2022-09-06 12:16:29 +00:00
|
|
|
if err != nil {
|
2024-10-14 16:44:05 +00:00
|
|
|
return IPv6Unsupported, fmt.Errorf("listing IPv6 routes: %w", err)
|
2022-09-06 12:16:29 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-08 09:12:46 +00:00
|
|
|
// Check each route for IPv6 due to Podman bug listing IPv4 routes
|
|
|
|
|
// as IPv6 routes at container start, see:
|
|
|
|
|
// https://github.com/qdm12/gluetun/issues/1241#issuecomment-1333405949
|
2024-10-14 16:44:05 +00:00
|
|
|
level = IPv6Unsupported
|
2023-06-08 09:12:46 +00:00
|
|
|
for _, route := range routes {
|
2024-05-09 18:21:13 +00:00
|
|
|
link, err := n.LinkByIndex(route.LinkIndex)
|
|
|
|
|
if err != nil {
|
2024-10-14 16:44:05 +00:00
|
|
|
return IPv6Unsupported, fmt.Errorf("finding link corresponding to route: %w", err)
|
2024-05-09 18:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
2024-10-14 16:44:05 +00:00
|
|
|
sourceIsIPv4 := route.Src.IsValid() && route.Src.Is4()
|
|
|
|
|
destinationIsIPv4 := route.Dst.IsValid() && route.Dst.Addr().Is4()
|
2023-06-08 09:12:46 +00:00
|
|
|
destinationIsIPv6 := route.Dst.IsValid() && route.Dst.Addr().Is6()
|
2024-05-09 18:21:13 +00:00
|
|
|
switch {
|
2024-10-14 16:44:05 +00:00
|
|
|
case sourceIsIPv4 && destinationIsIPv4,
|
2024-05-09 18:21:13 +00:00
|
|
|
destinationIsIPv6 && route.Dst.Addr().IsLoopback():
|
2024-10-14 16:44:05 +00:00
|
|
|
case route.Dst.Addr().IsUnspecified(): // default ipv6 route
|
|
|
|
|
n.debugLogger.Debugf("IPv6 internet access is enabled on link %s", link.Name)
|
|
|
|
|
return IPv6Internet, nil
|
|
|
|
|
default: // non-default ipv6 route found
|
|
|
|
|
n.debugLogger.Debugf("IPv6 is supported by link %s", link.Name)
|
|
|
|
|
level = IPv6Supported
|
2022-09-06 12:16:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-14 16:44:05 +00:00
|
|
|
if level == IPv6Unsupported {
|
|
|
|
|
n.debugLogger.Debugf("no IPv6 route found in %d routes", len(routes))
|
|
|
|
|
}
|
|
|
|
|
return level, nil
|
2022-09-06 12:16:29 +00:00
|
|
|
}
|