diff --git a/display.go b/display.go index b90f40e0..cab87ff3 100644 --- a/display.go +++ b/display.go @@ -325,11 +325,8 @@ func startBacklightTickers() { dimTicker = time.NewTicker(time.Duration(config.DisplayDimAfterSec) * time.Second) go func() { - for { //nolint:staticcheck - select { - case <-dimTicker.C: - tick_displayDim() - } + for range dimTicker.C { + tick_displayDim() } }() } @@ -339,11 +336,8 @@ func startBacklightTickers() { offTicker = time.NewTicker(time.Duration(config.DisplayOffAfterSec) * time.Second) go func() { - for { //nolint:staticcheck - select { - case <-offTicker.C: - tick_displayOff() - } + for range offTicker.C { + tick_displayOff() } }() } diff --git a/go.mod b/go.mod index 695a9f91..e4ada2c0 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,7 @@ require ( github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mdlayher/ndp v1.1.0 // indirect github.com/mdlayher/packet v1.1.2 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect diff --git a/go.sum b/go.sum index 4a3397b8..9df5e759 100644 --- a/go.sum +++ b/go.sum @@ -99,6 +99,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mdlayher/ndp v1.1.0 h1:QylGKGVtH60sKZUE88+IW5ila1Z/M9/OXhWdsVKuscs= +github.com/mdlayher/ndp v1.1.0/go.mod h1:FmgESgemgjl38vuOIyAHWUUL6vQKA/pQNkvXdWsdQFM= github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY= github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU+x0kew4= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= diff --git a/pkg/nmlite/interface.go b/pkg/nmlite/interface.go index fb3b5304..759b0e02 100644 --- a/pkg/nmlite/interface.go +++ b/pkg/nmlite/interface.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net" + "net/netip" "time" @@ -13,6 +14,7 @@ import ( "github.com/jetkvm/kvm/internal/logging" "github.com/jetkvm/kvm/internal/network/types" "github.com/jetkvm/kvm/pkg/nmlite/link" + "github.com/mdlayher/ndp" "github.com/rs/zerolog" "github.com/vishvananda/netlink" ) @@ -453,6 +455,10 @@ func (im *InterfaceManager) applyIPv6SLAAC() error { return fmt.Errorf("failed to remove non-link-local IPv6 addresses: %w", err) } + if err := im.SendRouterSolicitation(); err != nil { + return fmt.Errorf("failed to send router solicitation: %w", err) + } + // Enable SLAAC return im.staticConfig.EnableIPv6SLAAC() } @@ -545,6 +551,48 @@ func (im *InterfaceManager) handleLinkStateChange(link *link.Link) { } } +// SendRouterSolicitation sends a router solicitation +func (im *InterfaceManager) SendRouterSolicitation() error { + im.logger.Info().Msg("sending router solicitation") + m := &ndp.RouterSolicitation{} + + l, err := im.link() + if err != nil { + return fmt.Errorf("failed to get interface: %w", err) + } + + iface := l.Interface() + if iface == nil { + return fmt.Errorf("failed to get net.Interface for %s", im.ifaceName) + } + + hwAddr := l.HardwareAddr() + if hwAddr == nil { + return fmt.Errorf("failed to get hardware address for %s", im.ifaceName) + } + + c, _, err := ndp.Listen(iface, ndp.LinkLocal) + defer c.Close() + if err != nil { + return fmt.Errorf("failed to create NDP listener on %s: %w", im.ifaceName, err) + } + + m.Options = append(m.Options, &ndp.LinkLayerAddress{ + Addr: hwAddr, + Direction: ndp.Source, + }) + + targetAddr := netip.MustParseAddr("ff02::2") + + if err := c.WriteTo(m, nil, targetAddr); err != nil { + return fmt.Errorf("failed to write to %s: %w", targetAddr.String(), err) + } + + im.logger.Info().Msg("router solicitation sent") + + return nil +} + func (im *InterfaceManager) handleLinkUp() { im.logger.Info().Msg("link up") @@ -553,6 +601,11 @@ func (im *InterfaceManager) handleLinkUp() { if im.config.IPv4Mode.String == "dhcp" { im.dhcpClient.Renew() } + + if im.config.IPv6Mode.String == "slaac" { + im.staticConfig.EnableIPv6SLAAC() + im.SendRouterSolicitation() + } } func (im *InterfaceManager) handleLinkDown() { diff --git a/pkg/nmlite/link/netlink.go b/pkg/nmlite/link/netlink.go index 994935d7..0fc460b2 100644 --- a/pkg/nmlite/link/netlink.go +++ b/pkg/nmlite/link/netlink.go @@ -37,6 +37,7 @@ type Link struct { netlink.Link } +// Refresh refreshes the link func (l *Link) Refresh() error { linkName := l.Link.Attrs().Name link, err := netlink.LinkByName(linkName) @@ -50,6 +51,28 @@ func (l *Link) Refresh() error { return nil } +// Interface returns the interface of the link +func (l *Link) Interface() *net.Interface { + attrs := l.Attrs() + if attrs.Name == "" { + return nil + } + iface, err := net.InterfaceByName(attrs.Name) + if err != nil { + return nil + } + return iface +} + +// HardwareAddr returns the hardware address of the link +func (l *Link) HardwareAddr() net.HardwareAddr { + attrs := l.Attrs() + if attrs.HardwareAddr == nil { + return nil + } + return attrs.HardwareAddr +} + // Attrs returns the attributes of the link func (l *Link) Attrs() *netlink.LinkAttrs { return l.Link.Attrs()