mirror of https://github.com/jetkvm/kvm.git
185 lines
4.9 KiB
Go
185 lines
4.9 KiB
Go
package nmlite
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/jetkvm/kvm/internal/network/types"
|
|
"github.com/jetkvm/kvm/pkg/nmlite/link"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
// StaticConfigManager manages static network configuration
|
|
type StaticConfigManager struct {
|
|
ifaceName string
|
|
logger *zerolog.Logger
|
|
}
|
|
|
|
// NewStaticConfigManager creates a new static configuration manager
|
|
func NewStaticConfigManager(ifaceName string, logger *zerolog.Logger) (*StaticConfigManager, error) {
|
|
if ifaceName == "" {
|
|
return nil, fmt.Errorf("interface name cannot be empty")
|
|
}
|
|
|
|
if logger == nil {
|
|
return nil, fmt.Errorf("logger cannot be nil")
|
|
}
|
|
|
|
return &StaticConfigManager{
|
|
ifaceName: ifaceName,
|
|
logger: logger,
|
|
}, nil
|
|
}
|
|
|
|
// ToIPv4Static applies static IPv4 configuration
|
|
func (scm *StaticConfigManager) ToIPv4Static(config *types.IPv4StaticConfig) (*types.ParsedIPConfig, error) {
|
|
if config == nil {
|
|
return nil, fmt.Errorf("config is nil")
|
|
}
|
|
|
|
// Parse IP address and netmask
|
|
ipNet, err := link.ParseIPv4Netmask(config.Address.String, config.Netmask.String)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
scm.logger.Info().Str("ipNet", ipNet.String()).Interface("ipc", config).Msg("parsed IPv4 address and netmask")
|
|
|
|
// Parse gateway
|
|
gateway := net.ParseIP(config.Gateway.String)
|
|
if gateway == nil {
|
|
return nil, fmt.Errorf("invalid gateway: %s", config.Gateway.String)
|
|
}
|
|
|
|
// Parse DNS servers
|
|
var dns []net.IP
|
|
for _, dnsStr := range config.DNS {
|
|
if err := link.ValidateIPAddress(dnsStr, false); err != nil {
|
|
return nil, fmt.Errorf("invalid DNS server: %w", err)
|
|
}
|
|
dns = append(dns, net.ParseIP(dnsStr))
|
|
}
|
|
|
|
address := types.IPAddress{
|
|
Family: link.AfInet,
|
|
Address: *ipNet,
|
|
Gateway: gateway,
|
|
Secondary: false,
|
|
Permanent: true,
|
|
}
|
|
|
|
return &types.ParsedIPConfig{
|
|
Addresses: []types.IPAddress{address},
|
|
Nameservers: dns,
|
|
Interface: scm.ifaceName,
|
|
}, nil
|
|
}
|
|
|
|
// ToIPv6Static applies static IPv6 configuration
|
|
func (scm *StaticConfigManager) ToIPv6Static(config *types.IPv6StaticConfig) (*types.ParsedIPConfig, error) {
|
|
if config == nil {
|
|
return nil, fmt.Errorf("config is nil")
|
|
}
|
|
|
|
// Parse IP address and prefix
|
|
ipNet, err := link.ParseIPv6Prefix(config.Prefix.String, 64) // Default to /64 if not specified
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Parse gateway
|
|
gateway := net.ParseIP(config.Gateway.String)
|
|
if gateway == nil {
|
|
return nil, fmt.Errorf("invalid gateway: %s", config.Gateway.String)
|
|
}
|
|
|
|
// Parse DNS servers
|
|
var dns []net.IP
|
|
for _, dnsStr := range config.DNS {
|
|
dnsIP := net.ParseIP(dnsStr)
|
|
if dnsIP == nil {
|
|
return nil, fmt.Errorf("invalid DNS server: %s", dnsStr)
|
|
}
|
|
dns = append(dns, dnsIP)
|
|
}
|
|
|
|
address := types.IPAddress{
|
|
Family: link.AfInet6,
|
|
Address: *ipNet,
|
|
Gateway: gateway,
|
|
Secondary: false,
|
|
Permanent: true,
|
|
}
|
|
|
|
return &types.ParsedIPConfig{
|
|
Addresses: []types.IPAddress{address},
|
|
Nameservers: dns,
|
|
Interface: scm.ifaceName,
|
|
}, nil
|
|
}
|
|
|
|
// DisableIPv4 disables IPv4 on the interface
|
|
func (scm *StaticConfigManager) DisableIPv4() error {
|
|
scm.logger.Info().Msg("disabling IPv4")
|
|
|
|
netlinkMgr := getNetlinkManager()
|
|
iface, err := netlinkMgr.GetLinkByName(scm.ifaceName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get interface: %w", err)
|
|
}
|
|
|
|
// Remove all IPv4 addresses
|
|
if err := netlinkMgr.RemoveAllAddresses(iface, link.AfInet); err != nil {
|
|
return fmt.Errorf("failed to remove IPv4 addresses: %w", err)
|
|
}
|
|
|
|
// Remove default route
|
|
if err := scm.removeIPv4DefaultRoute(); err != nil {
|
|
scm.logger.Warn().Err(err).Msg("failed to remove IPv4 default route")
|
|
}
|
|
|
|
scm.logger.Info().Msg("IPv4 disabled")
|
|
return nil
|
|
}
|
|
|
|
// DisableIPv6 disables IPv6 on the interface
|
|
func (scm *StaticConfigManager) DisableIPv6() error {
|
|
scm.logger.Info().Msg("disabling IPv6")
|
|
netlinkMgr := getNetlinkManager()
|
|
return netlinkMgr.DisableIPv6(scm.ifaceName)
|
|
}
|
|
|
|
// EnableIPv6SLAAC enables IPv6 SLAAC
|
|
func (scm *StaticConfigManager) EnableIPv6SLAAC() error {
|
|
scm.logger.Info().Msg("enabling IPv6 SLAAC")
|
|
netlinkMgr := getNetlinkManager()
|
|
return netlinkMgr.EnableIPv6SLAAC(scm.ifaceName)
|
|
}
|
|
|
|
// EnableIPv6LinkLocal enables IPv6 link-local only
|
|
func (scm *StaticConfigManager) EnableIPv6LinkLocal() error {
|
|
scm.logger.Info().Msg("enabling IPv6 link-local only")
|
|
|
|
netlinkMgr := getNetlinkManager()
|
|
if err := netlinkMgr.EnableIPv6LinkLocal(scm.ifaceName); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Remove all non-link-local IPv6 addresses
|
|
link, err := netlinkMgr.GetLinkByName(scm.ifaceName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get interface: %w", err)
|
|
}
|
|
|
|
if err := netlinkMgr.RemoveNonLinkLocalIPv6Addresses(link); err != nil {
|
|
return fmt.Errorf("failed to remove non-link-local IPv6 addresses: %w", err)
|
|
}
|
|
|
|
return netlinkMgr.EnsureInterfaceUp(link)
|
|
}
|
|
|
|
// removeIPv4DefaultRoute removes IPv4 default route
|
|
func (scm *StaticConfigManager) removeIPv4DefaultRoute() error {
|
|
netlinkMgr := getNetlinkManager()
|
|
return netlinkMgr.RemoveDefaultRoute(link.AfInet)
|
|
}
|