package netstack
import (
"fmt"
"net"
"strings"
)
type DNSConfig struct {
Nameservers []string `json:"nameservers,omitempty"`
Domain string `json:"domain,omitempty"`
Search []string `json:"search,omitempty"`
Options []string `json:"options,omitempty"`
}
type GuestNetworkConfig struct {
GuestIP string `json:"guestIP"`
PrefixLength int `json:"prefixLength"`
Gateway string `json:"gateway"`
DNS DNSConfig `json:"dns"`
}
func (c DNSConfig) Clone() DNSConfig {
return DNSConfig{
Nameservers: append([]string(nil), c.Nameservers...),
Domain: c.Domain,
Search: append([]string(nil), c.Search...),
Options: append([]string(nil), c.Options...),
}
}
func (c GuestNetworkConfig) Clone() GuestNetworkConfig {
c.DNS = c.DNS.Clone()
return c
}
func (c GuestNetworkConfig) Validate() error {
ip := net.ParseIP(strings.TrimSpace(c.GuestIP))
if ip == nil || ip.To4() == nil {
return fmt.Errorf("guestIP %q must be a valid IPv4 address", c.GuestIP)
}
gw := net.ParseIP(strings.TrimSpace(c.Gateway))
if gw == nil || gw.To4() == nil {
return fmt.Errorf("gateway %q must be a valid IPv4 address", c.Gateway)
}
if c.PrefixLength < 1 || c.PrefixLength > 32 {
return fmt.Errorf("prefixLength %d must be within [1, 32]", c.PrefixLength)
}
mask := net.CIDRMask(c.PrefixLength, 32)
if !ip.Mask(mask).Equal(gw.Mask(mask)) {
return fmt.Errorf("guestIP %s/%d and gateway %s are not in the same subnet", ip, c.PrefixLength, gw)
}
if ip.Equal(gw) {
return fmt.Errorf("guestIP and gateway must be different")
}
if _, err := NormalizeDNS(c.DNS); err != nil {
return fmt.Errorf("invalid DNS config: %w", err)
}
return nil
}