mirror of https://github.com/jetkvm/kvm.git
fix compatibility with new network types
This commit is contained in:
parent
ef0bdc0f65
commit
2f33c08c98
|
|
@ -105,20 +105,46 @@ func (c *NetworkConfig) GetTransportProxyFunc() func(*http.Request) (*url.URL, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DHCPLease represents a DHCP lease
|
// DHCPLease is a network configuration obtained by DHCP.
|
||||||
type DHCPLease struct {
|
type DHCPLease struct {
|
||||||
InterfaceName string `json:"interface_name"`
|
// from https://udhcp.busybox.net/README.udhcpc
|
||||||
IPAddress net.IP `json:"ip_address"`
|
IPAddress net.IP `env:"ip" json:"ip"` // The obtained IP
|
||||||
Netmask net.IP `json:"netmask"`
|
Netmask net.IP `env:"subnet" json:"netmask"` // The assigned subnet mask
|
||||||
Gateway net.IP `json:"gateway"`
|
Broadcast net.IP `env:"broadcast" json:"broadcast"` // The broadcast address for this network
|
||||||
DNS []net.IP `json:"dns"`
|
TTL int `env:"ipttl" json:"ttl,omitempty"` // The TTL to use for this network
|
||||||
SearchList []string `json:"search_list"`
|
MTU int `env:"mtu" json:"mtu,omitempty"` // The MTU to use for this network
|
||||||
Domain string `json:"domain"`
|
HostName string `env:"hostname" json:"hostname,omitempty"` // The assigned hostname
|
||||||
NTPServers []net.IP `json:"ntp_servers"`
|
Domain string `env:"domain" json:"domain,omitempty"` // The domain name of the network
|
||||||
LeaseTime time.Time `json:"lease_time"`
|
SearchList []string `env:"search" json:"search_list,omitempty"` // The search list for the network
|
||||||
RenewalTime time.Time `json:"renewal_time"`
|
BootPNextServer net.IP `env:"siaddr" json:"bootp_next_server,omitempty"` // The bootp next server option
|
||||||
RebindingTime time.Time `json:"rebinding_time"`
|
BootPServerName string `env:"sname" json:"bootp_server_name,omitempty"` // The bootp server name option
|
||||||
ExpiryTime time.Time `json:"expiry_time"`
|
BootPFile string `env:"boot_file" json:"bootp_file,omitempty"` // The bootp boot file option
|
||||||
|
Timezone string `env:"timezone" json:"timezone,omitempty"` // Offset in seconds from UTC
|
||||||
|
Routers []net.IP `env:"router" json:"routers,omitempty"` // A list of routers
|
||||||
|
DNS []net.IP `env:"dns" json:"dns_servers,omitempty"` // A list of DNS servers
|
||||||
|
NTPServers []net.IP `env:"ntpsrv" json:"ntp_servers,omitempty"` // A list of NTP servers
|
||||||
|
LPRServers []net.IP `env:"lprsvr" json:"lpr_servers,omitempty"` // A list of LPR servers
|
||||||
|
TimeServers []net.IP `env:"timesvr" json:"_time_servers,omitempty"` // A list of time servers (obsolete)
|
||||||
|
IEN116NameServers []net.IP `env:"namesvr" json:"_name_servers,omitempty"` // A list of IEN 116 name servers (obsolete)
|
||||||
|
LogServers []net.IP `env:"logsvr" json:"_log_servers,omitempty"` // A list of MIT-LCS UDP log servers (obsolete)
|
||||||
|
CookieServers []net.IP `env:"cookiesvr" json:"_cookie_servers,omitempty"` // A list of RFC 865 cookie servers (obsolete)
|
||||||
|
WINSServers []net.IP `env:"wins" json:"_wins_servers,omitempty"` // A list of WINS servers
|
||||||
|
SwapServer net.IP `env:"swapsvr" json:"_swap_server,omitempty"` // The IP address of the client's swap server
|
||||||
|
BootSize int `env:"bootsize" json:"bootsize,omitempty"` // The length in 512 octect blocks of the bootfile
|
||||||
|
RootPath string `env:"rootpath" json:"root_path,omitempty"` // The path name of the client's root disk
|
||||||
|
LeaseTime time.Duration `env:"lease" json:"lease,omitempty"` // The lease time, in seconds
|
||||||
|
RenewalTime time.Duration `env:"renewal" json:"renewal,omitempty"` // The renewal time, in seconds
|
||||||
|
RebindingTime time.Duration `env:"rebinding" json:"rebinding,omitempty"` // The rebinding time, in seconds
|
||||||
|
DHCPType string `env:"dhcptype" json:"dhcp_type,omitempty"` // DHCP message type (safely ignored)
|
||||||
|
ServerID string `env:"serverid" json:"server_id,omitempty"` // The IP of the server
|
||||||
|
Message string `env:"message" json:"reason,omitempty"` // Reason for a DHCPNAK
|
||||||
|
TFTPServerName string `env:"tftp" json:"tftp,omitempty"` // The TFTP server name
|
||||||
|
BootFileName string `env:"bootfile" json:"bootfile,omitempty"` // The boot file name
|
||||||
|
Uptime time.Duration `env:"uptime" json:"uptime,omitempty"` // The uptime of the device when the lease was obtained, in seconds
|
||||||
|
ClassIdentifier string `env:"classid" json:"class_identifier,omitempty"` // The class identifier
|
||||||
|
LeaseExpiry *time.Time `json:"lease_expiry,omitempty"` // The expiry time of the lease
|
||||||
|
|
||||||
|
InterfaceName string `json:"interface_name,omitempty"` // The name of the interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterfaceState represents the current state of a network interface
|
// InterfaceState represents the current state of a network interface
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ func restartMdns() {
|
||||||
}, true)
|
}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func networkStateChanged(isOnline bool) {
|
func networkStateChanged(iface string, state *types.InterfaceState) {
|
||||||
// do not block the main thread
|
// do not block the main thread
|
||||||
go waitCtrlAndRequestDisplayUpdate(true, "network_state_changed")
|
go waitCtrlAndRequestDisplayUpdate(true, "network_state_changed")
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ func networkStateChanged(isOnline bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the network is now online, trigger an NTP sync if still needed
|
// if the network is now online, trigger an NTP sync if still needed
|
||||||
if isOnline && timeSync != nil && (isTimeSyncNeeded() || !timeSync.IsSyncSuccess()) {
|
if state.Up && timeSync != nil && (isTimeSyncNeeded() || !timeSync.IsSyncSuccess()) {
|
||||||
if err := timeSync.Sync(); err != nil {
|
if err := timeSync.Sync(); err != nil {
|
||||||
logger.Warn().Str("error", err.Error()).Msg("unable to sync time on network state change")
|
logger.Warn().Str("error", err.Error()).Msg("unable to sync time on network state change")
|
||||||
}
|
}
|
||||||
|
|
@ -76,6 +76,7 @@ func initNetwork() error {
|
||||||
ensureConfigLoaded()
|
ensureConfigLoaded()
|
||||||
|
|
||||||
networkManager = nmlite.NewNetworkManager(context.Background(), networkLogger)
|
networkManager = nmlite.NewNetworkManager(context.Background(), networkLogger)
|
||||||
|
networkManager.SetOnInterfaceStateChange(networkStateChanged)
|
||||||
networkManager.AddInterface(NetIfName, config.NetworkConfig)
|
networkManager.AddInterface(NetIfName, config.NetworkConfig)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/insomniacslk/dhcp/dhcpv4/nclient4"
|
"github.com/insomniacslk/dhcp/dhcpv4/nclient4"
|
||||||
"github.com/insomniacslk/dhcp/dhcpv6"
|
"github.com/insomniacslk/dhcp/dhcpv6"
|
||||||
|
"github.com/jetkvm/kvm/internal/network/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -22,44 +23,7 @@ var (
|
||||||
|
|
||||||
// Lease is a network configuration obtained by DHCP.
|
// Lease is a network configuration obtained by DHCP.
|
||||||
type Lease struct {
|
type Lease struct {
|
||||||
// from https://udhcp.busybox.net/README.udhcpc
|
types.DHCPLease
|
||||||
IPAddress net.IP `env:"ip" json:"ip"` // The obtained IP
|
|
||||||
Netmask net.IP `env:"subnet" json:"netmask"` // The assigned subnet mask
|
|
||||||
Broadcast net.IP `env:"broadcast" json:"broadcast"` // The broadcast address for this network
|
|
||||||
TTL int `env:"ipttl" json:"ttl,omitempty"` // The TTL to use for this network
|
|
||||||
MTU int `env:"mtu" json:"mtu,omitempty"` // The MTU to use for this network
|
|
||||||
HostName string `env:"hostname" json:"hostname,omitempty"` // The assigned hostname
|
|
||||||
Domain string `env:"domain" json:"domain,omitempty"` // The domain name of the network
|
|
||||||
SearchList []string `env:"search" json:"search_list,omitempty"` // The search list for the network
|
|
||||||
BootPNextServer net.IP `env:"siaddr" json:"bootp_next_server,omitempty"` // The bootp next server option
|
|
||||||
BootPServerName string `env:"sname" json:"bootp_server_name,omitempty"` // The bootp server name option
|
|
||||||
BootPFile string `env:"boot_file" json:"bootp_file,omitempty"` // The bootp boot file option
|
|
||||||
Timezone string `env:"timezone" json:"timezone,omitempty"` // Offset in seconds from UTC
|
|
||||||
Routers []net.IP `env:"router" json:"routers,omitempty"` // A list of routers
|
|
||||||
DNS []net.IP `env:"dns" json:"dns_servers,omitempty"` // A list of DNS servers
|
|
||||||
NTPServers []net.IP `env:"ntpsrv" json:"ntp_servers,omitempty"` // A list of NTP servers
|
|
||||||
LPRServers []net.IP `env:"lprsvr" json:"lpr_servers,omitempty"` // A list of LPR servers
|
|
||||||
TimeServers []net.IP `env:"timesvr" json:"_time_servers,omitempty"` // A list of time servers (obsolete)
|
|
||||||
IEN116NameServers []net.IP `env:"namesvr" json:"_name_servers,omitempty"` // A list of IEN 116 name servers (obsolete)
|
|
||||||
LogServers []net.IP `env:"logsvr" json:"_log_servers,omitempty"` // A list of MIT-LCS UDP log servers (obsolete)
|
|
||||||
CookieServers []net.IP `env:"cookiesvr" json:"_cookie_servers,omitempty"` // A list of RFC 865 cookie servers (obsolete)
|
|
||||||
WINSServers []net.IP `env:"wins" json:"_wins_servers,omitempty"` // A list of WINS servers
|
|
||||||
SwapServer net.IP `env:"swapsvr" json:"_swap_server,omitempty"` // The IP address of the client's swap server
|
|
||||||
BootSize int `env:"bootsize" json:"bootsize,omitempty"` // The length in 512 octect blocks of the bootfile
|
|
||||||
RootPath string `env:"rootpath" json:"root_path,omitempty"` // The path name of the client's root disk
|
|
||||||
LeaseTime time.Duration `env:"lease" json:"lease,omitempty"` // The lease time, in seconds
|
|
||||||
RenewalTime time.Duration `env:"renewal" json:"renewal,omitempty"` // The renewal time, in seconds
|
|
||||||
RebindingTime time.Duration `env:"rebinding" json:"rebinding,omitempty"` // The rebinding time, in seconds
|
|
||||||
DHCPType string `env:"dhcptype" json:"dhcp_type,omitempty"` // DHCP message type (safely ignored)
|
|
||||||
ServerID string `env:"serverid" json:"server_id,omitempty"` // The IP of the server
|
|
||||||
Message string `env:"message" json:"reason,omitempty"` // Reason for a DHCPNAK
|
|
||||||
TFTPServerName string `env:"tftp" json:"tftp,omitempty"` // The TFTP server name
|
|
||||||
BootFileName string `env:"bootfile" json:"bootfile,omitempty"` // The boot file name
|
|
||||||
Uptime time.Duration `env:"uptime" json:"uptime,omitempty"` // The uptime of the device when the lease was obtained, in seconds
|
|
||||||
ClassIdentifier string `env:"classid" json:"class_identifier,omitempty"` // The class identifier
|
|
||||||
LeaseExpiry *time.Time `json:"lease_expiry,omitempty"` // The expiry time of the lease
|
|
||||||
|
|
||||||
InterfaceName string `json:"interface_name,omitempty"` // The name of the interface
|
|
||||||
|
|
||||||
p4 *nclient4.Lease
|
p4 *nclient4.Lease
|
||||||
p6 *dhcpv6.Message
|
p6 *dhcpv6.Message
|
||||||
|
|
@ -67,6 +31,11 @@ type Lease struct {
|
||||||
isEmpty map[string]bool
|
isEmpty map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToDHCPLease converts a lease to a DHCP lease.
|
||||||
|
func (l *Lease) ToDHCPLease() *types.DHCPLease {
|
||||||
|
return &l.DHCPLease
|
||||||
|
}
|
||||||
|
|
||||||
// fromNclient4Lease creates a lease from a nclient4.Lease.
|
// fromNclient4Lease creates a lease from a nclient4.Lease.
|
||||||
func fromNclient4Lease(l *nclient4.Lease, iface string) *Lease {
|
func fromNclient4Lease(l *nclient4.Lease, iface string) *Lease {
|
||||||
lease := &Lease{}
|
lease := &Lease{}
|
||||||
|
|
|
||||||
|
|
@ -207,26 +207,5 @@ func (dc *DHCPClient) convertLease(lease *dhclient.Lease, isIPv6 bool) *types.DH
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the lease
|
return lease.ToDHCPLease()
|
||||||
convertedLease := &types.DHCPLease{
|
|
||||||
InterfaceName: dc.ifaceName,
|
|
||||||
Domain: lease.Domain,
|
|
||||||
SearchList: lease.SearchList,
|
|
||||||
NTPServers: lease.NTPServers,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set IP address and related information
|
|
||||||
convertedLease.IPAddress = lease.IPAddress
|
|
||||||
convertedLease.Netmask = lease.Netmask
|
|
||||||
if len(lease.Routers) > 0 {
|
|
||||||
convertedLease.Gateway = lease.Routers[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set DNS servers
|
|
||||||
convertedLease.DNS = lease.DNS
|
|
||||||
// convertedLease.LeaseTime = lease.LeaseTime
|
|
||||||
// convertedLease.RenewalTime = lease.RenewalTime
|
|
||||||
// convertedLease.RebindingTime = lease.RebindingTime
|
|
||||||
|
|
||||||
return convertedLease
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,8 @@ func (im *InterfaceManager) GetState() *types.InterfaceState {
|
||||||
defer im.stateMu.RUnlock()
|
defer im.stateMu.RUnlock()
|
||||||
|
|
||||||
// Return a copy to avoid race conditions
|
// Return a copy to avoid race conditions
|
||||||
|
im.logger.Debug().Interface("state", im.state).Msg("getting interface state")
|
||||||
|
|
||||||
state := *im.state
|
state := *im.state
|
||||||
return &state
|
return &state
|
||||||
}
|
}
|
||||||
|
|
@ -453,6 +455,8 @@ func (im *InterfaceManager) getDomain() string {
|
||||||
func (im *InterfaceManager) monitorInterfaceState() {
|
func (im *InterfaceManager) monitorInterfaceState() {
|
||||||
defer im.wg.Done()
|
defer im.wg.Done()
|
||||||
|
|
||||||
|
im.logger.Debug().Msg("monitoring interface state")
|
||||||
|
|
||||||
// TODO: use netlink subscription instead of polling
|
// TODO: use netlink subscription instead of polling
|
||||||
ticker := time.NewTicker(5 * time.Second)
|
ticker := time.NewTicker(5 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
@ -464,6 +468,7 @@ func (im *InterfaceManager) monitorInterfaceState() {
|
||||||
case <-im.stopCh:
|
case <-im.stopCh:
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
|
im.logger.Debug().Msg("checking interface state")
|
||||||
if err := im.updateInterfaceState(); err != nil {
|
if err := im.updateInterfaceState(); err != nil {
|
||||||
im.logger.Error().Err(err).Msg("failed to update interface state")
|
im.logger.Error().Err(err).Msg("failed to update interface state")
|
||||||
}
|
}
|
||||||
|
|
@ -482,7 +487,7 @@ func (im *InterfaceManager) updateInterfaceState() error {
|
||||||
isUp := attrs.OperState == netlink.OperUp
|
isUp := attrs.OperState == netlink.OperUp
|
||||||
|
|
||||||
hasAddrs := false
|
hasAddrs := false
|
||||||
addrs, err := nl.AddrList(link.AfInet)
|
addrs, err := nl.AddrList(link.AfUnspec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get addresses: %w", err)
|
return fmt.Errorf("failed to get addresses: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -504,10 +509,10 @@ func (im *InterfaceManager) updateInterfaceState() error {
|
||||||
stateChanged = true
|
stateChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// if im.state.MACAddr != attrs.HardwareAddr {
|
if im.state.MACAddress != attrs.HardwareAddr.String() {
|
||||||
// im.state.MACAddr = attrs.HardwareAddr
|
im.state.MACAddress = attrs.HardwareAddr.String()
|
||||||
// stateChanged = true
|
stateChanged = true
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Update IP addresses
|
// Update IP addresses
|
||||||
if err := im.updateIPAddresses(nl); err != nil {
|
if err := im.updateIPAddresses(nl); err != nil {
|
||||||
|
|
@ -519,6 +524,7 @@ func (im *InterfaceManager) updateInterfaceState() error {
|
||||||
// Notify callback if state changed
|
// Notify callback if state changed
|
||||||
if stateChanged && im.onStateChange != nil {
|
if stateChanged && im.onStateChange != nil {
|
||||||
state := *im.state
|
state := *im.state
|
||||||
|
im.logger.Debug().Interface("state", state).Msg("notifying state change")
|
||||||
im.onStateChange(&state)
|
im.onStateChange(&state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,6 +544,7 @@ func (im *InterfaceManager) updateIPAddresses(nl *link.Link) error {
|
||||||
var ipv6LinkLocal string
|
var ipv6LinkLocal string
|
||||||
|
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
|
im.logger.Debug().Str("address", addr.IP.String()).Msg("checking address")
|
||||||
if addr.IP.To4() != nil {
|
if addr.IP.To4() != nil {
|
||||||
// IPv4 address
|
// IPv4 address
|
||||||
ipv4Addresses = append(ipv4Addresses, addr.IPNet.String())
|
ipv4Addresses = append(ipv4Addresses, addr.IPNet.String())
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ type NetworkManager struct {
|
||||||
// NewNetworkManager creates a new network manager
|
// NewNetworkManager creates a new network manager
|
||||||
func NewNetworkManager(ctx context.Context, logger *zerolog.Logger) *NetworkManager {
|
func NewNetworkManager(ctx context.Context, logger *zerolog.Logger) *NetworkManager {
|
||||||
if logger == nil {
|
if logger == nil {
|
||||||
logger = logging.GetSubsystemLogger("networkmgr")
|
logger = logging.GetSubsystemLogger("nm")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the NetlinkManager singleton
|
// Initialize the NetlinkManager singleton
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,14 @@ export default function Ipv6NetworkCard({
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-x-6 gap-y-2">
|
<div className="grid grid-cols-2 gap-x-6 gap-y-2">
|
||||||
{networkState?.dhcp_lease?.ip && (
|
<div className="flex flex-col justify-between">
|
||||||
<div className="flex flex-col justify-between">
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
Link-local
|
||||||
Link-local
|
</span>
|
||||||
</span>
|
<span className="text-sm font-medium">
|
||||||
<span className="text-sm font-medium">
|
{networkState?.ipv6_link_local}
|
||||||
{networkState?.ipv6_link_local}
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-3 pt-2">
|
<div className="space-y-3 pt-2">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue