diff --git a/dhcp6/boot_configuration.go b/dhcp6/boot_configuration.go index c2a619c..c5182eb 100644 --- a/dhcp6/boot_configuration.go +++ b/dhcp6/boot_configuration.go @@ -1,14 +1,6 @@ package dhcp6 -import ( - "net/http" - "time" - "strings" - "fmt" - "net/url" - "bytes" - "net" -) +import "net" // BootConfiguration implementation provides values for dhcp options served to dhcp clients type BootConfiguration interface { @@ -16,117 +8,3 @@ type BootConfiguration interface { GetPreference() []byte GetRecursiveDNS() []net.IP } - -// StaticBootConfiguration provides values for dhcp options that remain unchanged until restart -type StaticBootConfiguration struct { - HTTPBootURL []byte - IPxeBootURL []byte - RecursiveDNS []net.IP - Preference []byte - UsePreference bool -} - -// MakeStaticBootConfiguration creates a new StaticBootConfiguration with provided values -func MakeStaticBootConfiguration(httpBootURL, ipxeBootURL string, preference uint8, usePreference bool, - dnsServerAddresses []net.IP) *StaticBootConfiguration { - ret := &StaticBootConfiguration{HTTPBootURL: []byte(httpBootURL), IPxeBootURL: []byte(ipxeBootURL), UsePreference: usePreference} - if usePreference { - ret.Preference = make([]byte, 1) - ret.Preference[0] = byte(preference) - } - ret.RecursiveDNS = dnsServerAddresses - return ret -} - -// GetBootURL returns Boot File URL, see RFC 5970 -func (bc *StaticBootConfiguration) GetBootURL(id []byte, clientArchType uint16) ([]byte, error) { - if 0x10 == clientArchType { - return bc.HTTPBootURL, nil - } - return bc.IPxeBootURL, nil -} - -// GetPreference returns server's Preference, see RFC 3315 -func (bc *StaticBootConfiguration) GetPreference() []byte { - return bc.Preference -} - -// GetRecursiveDNS returns list of addresses of recursive DNS servers, see RFC 3646 -func (bc *StaticBootConfiguration) GetRecursiveDNS() []net.IP { - return bc.RecursiveDNS -} - -// APIBootConfiguration provides an interface to retrieve Boot File URL from an external server based on -// client ID and architecture type -type APIBootConfiguration struct { - Client *http.Client - URLPrefix string - RecursiveDNS []net.IP - Preference []byte - UsePreference bool -} - -// MakeAPIBootConfiguration creates a new APIBootConfiguration initialized with provided values -func MakeAPIBootConfiguration(url string, timeout time.Duration, preference uint8, usePreference bool, - dnsServerAddresses []net.IP) *APIBootConfiguration { - if !strings.HasSuffix(url, "/") { - url += "/" - } - ret := &APIBootConfiguration{ - Client: &http.Client{Timeout: timeout}, - URLPrefix: url + "v1", - UsePreference: usePreference, - } - if usePreference { - ret.Preference = make([]byte, 1) - ret.Preference[0] = byte(preference) - } - ret.RecursiveDNS = dnsServerAddresses - - return ret -} - -// GetBootURL returns Boot File URL, see RFC 5970 -func (bc *APIBootConfiguration) GetBootURL(id []byte, clientArchType uint16) ([]byte, error) { - reqURL := fmt.Sprintf("%s/boot/%x/%d", bc.URLPrefix, id, clientArchType) - resp, err := bc.Client.Get(reqURL) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - resp.Body.Close() - return nil, fmt.Errorf("%s: %s", reqURL, http.StatusText(resp.StatusCode)) - } - defer resp.Body.Close() - - buf := new(bytes.Buffer) - buf.ReadFrom(resp.Body) - url, _ := bc.makeURLAbsolute(buf.String()) - - return []byte(url), nil -} - -func (bc *APIBootConfiguration) makeURLAbsolute(urlStr string) (string, error) { - u, err := url.Parse(urlStr) - if err != nil { - return "", fmt.Errorf("%q is not an URL", urlStr) - } - if !u.IsAbs() { - base, err := url.Parse(bc.URLPrefix) - if err != nil { - return "", err - } - u = base.ResolveReference(u) - } - return u.String(), nil -} - -// GetPreference returns server's Preference, see RFC 3315 -func (bc *APIBootConfiguration) GetPreference() []byte { - return bc.Preference -} - -// GetRecursiveDNS returns list of addresses of recursive DNS servers, see RFC 3646 -func (bc *APIBootConfiguration) GetRecursiveDNS() []net.IP { - return bc.RecursiveDNS -} diff --git a/pixiecore/cli/bootipv6cmd.go b/pixiecore/cli/bootipv6cmd.go index 960c38b..234638f 100644 --- a/pixiecore/cli/bootipv6cmd.go +++ b/pixiecore/cli/bootipv6cmd.go @@ -62,7 +62,7 @@ var bootIPv6Cmd = &cobra.Command{ dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress)) } } - s.BootConfig = dhcp6.MakeStaticBootConfiguration(httpBootURL, ipxeURL, preference, + s.BootConfig = pixiecorev6.MakeStaticBootConfiguration(httpBootURL, ipxeURL, preference, cmd.Flags().Changed("preference"), dnsServerAddresses) addressPoolStart, err := cmd.Flags().GetString("address-pool-start") diff --git a/pixiecore/cli/ipv6apicmd.go b/pixiecore/cli/ipv6apicmd.go index 78f1d9c..c059605 100644 --- a/pixiecore/cli/ipv6apicmd.go +++ b/pixiecore/cli/ipv6apicmd.go @@ -59,7 +59,7 @@ var ipv6ApiCmd = &cobra.Command{ dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress)) } } - s.BootConfig = dhcp6.MakeAPIBootConfiguration(apiURL, apiTimeout, preference, + s.BootConfig = pixiecorev6.MakeAPIBootConfiguration(apiURL, apiTimeout, preference, cmd.Flags().Changed("preference"), dnsServerAddresses) addressPoolStart, err := cmd.Flags().GetString("address-pool-start") diff --git a/pixiecorev6/boot_configuration.go b/pixiecorev6/boot_configuration.go new file mode 100644 index 0000000..a109b3f --- /dev/null +++ b/pixiecorev6/boot_configuration.go @@ -0,0 +1,127 @@ +package pixiecorev6 + +import ( + "net/http" + "time" + "strings" + "fmt" + "net/url" + "bytes" + "net" +) + +const X86_HTTP_CLIENT = 0x10 + +// StaticBootConfiguration provides values for dhcp options that remain unchanged until restart +type StaticBootConfiguration struct { + HTTPBootURL []byte + IPxeBootURL []byte + RecursiveDNS []net.IP + Preference []byte + UsePreference bool +} + +// MakeStaticBootConfiguration creates a new StaticBootConfiguration with provided values +func MakeStaticBootConfiguration(httpBootURL, ipxeBootURL string, preference uint8, usePreference bool, + dnsServerAddresses []net.IP) *StaticBootConfiguration { + ret := &StaticBootConfiguration{HTTPBootURL: []byte(httpBootURL), IPxeBootURL: []byte(ipxeBootURL), UsePreference: usePreference} + if usePreference { + ret.Preference = make([]byte, 1) + ret.Preference[0] = byte(preference) + } + ret.RecursiveDNS = dnsServerAddresses + return ret +} + +// GetBootURL returns Boot File URL, see RFC 5970 +func (bc *StaticBootConfiguration) GetBootURL(id []byte, clientArchType uint16) ([]byte, error) { + if clientArchType == X86_HTTP_CLIENT { + return bc.HTTPBootURL, nil + } + return bc.IPxeBootURL, nil +} + +// GetPreference returns server's Preference, see RFC 3315 +func (bc *StaticBootConfiguration) GetPreference() []byte { + return bc.Preference +} + +// GetRecursiveDNS returns list of addresses of recursive DNS servers, see RFC 3646 +func (bc *StaticBootConfiguration) GetRecursiveDNS() []net.IP { + return bc.RecursiveDNS +} + +// APIBootConfiguration provides an interface to retrieve Boot File URL from an external server based on +// client ID and architecture type +type APIBootConfiguration struct { + Client *http.Client + URLPrefix string + RecursiveDNS []net.IP + Preference []byte + UsePreference bool +} + +// MakeAPIBootConfiguration creates a new APIBootConfiguration initialized with provided values +func MakeAPIBootConfiguration(url string, timeout time.Duration, preference uint8, usePreference bool, + dnsServerAddresses []net.IP) *APIBootConfiguration { + if !strings.HasSuffix(url, "/") { + url += "/" + } + ret := &APIBootConfiguration{ + Client: &http.Client{Timeout: timeout}, + URLPrefix: url + "v1", + UsePreference: usePreference, + } + if usePreference { + ret.Preference = make([]byte, 1) + ret.Preference[0] = byte(preference) + } + ret.RecursiveDNS = dnsServerAddresses + + return ret +} + +// GetBootURL returns Boot File URL, see RFC 5970 +func (bc *APIBootConfiguration) GetBootURL(id []byte, clientArchType uint16) ([]byte, error) { + reqURL := fmt.Sprintf("%s/boot/%x/%d", bc.URLPrefix, id, clientArchType) + resp, err := bc.Client.Get(reqURL) + if err != nil { + return nil, err + } + if resp.StatusCode != http.StatusOK { + resp.Body.Close() + return nil, fmt.Errorf("%s: %s", reqURL, http.StatusText(resp.StatusCode)) + } + defer resp.Body.Close() + + buf := new(bytes.Buffer) + buf.ReadFrom(resp.Body) + url, _ := bc.makeURLAbsolute(buf.String()) + + return []byte(url), nil +} + +func (bc *APIBootConfiguration) makeURLAbsolute(urlStr string) (string, error) { + u, err := url.Parse(urlStr) + if err != nil { + return "", fmt.Errorf("%q is not an URL", urlStr) + } + if !u.IsAbs() { + base, err := url.Parse(bc.URLPrefix) + if err != nil { + return "", err + } + u = base.ResolveReference(u) + } + return u.String(), nil +} + +// GetPreference returns server's Preference, see RFC 3315 +func (bc *APIBootConfiguration) GetPreference() []byte { + return bc.Preference +} + +// GetRecursiveDNS returns list of addresses of recursive DNS servers, see RFC 3646 +func (bc *APIBootConfiguration) GetRecursiveDNS() []net.IP { + return bc.RecursiveDNS +}