diff options
-rw-r--r-- | dhcpv6/dhcpv6message.go | 12 | ||||
-rw-r--r-- | dhcpv6/option_bootfileurl.go | 25 | ||||
-rw-r--r-- | dhcpv6/option_bootfileurl_test.go | 2 | ||||
-rw-r--r-- | dhcpv6/options.go | 2 | ||||
-rw-r--r-- | netboot/netboot.go | 17 |
5 files changed, 35 insertions, 23 deletions
diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go index 400c46a..d099386 100644 --- a/dhcpv6/dhcpv6message.go +++ b/dhcpv6/dhcpv6message.go @@ -104,6 +104,18 @@ func (mo MessageOptions) DNS() []net.IP { return nil } +// BootFileURL returns the Boot File URL option as defined by RFC 5970. +func (mo MessageOptions) BootFileURL() string { + opt := mo.Options.GetOne(OptionBootfileURL) + if opt == nil { + return "" + } + if u, ok := opt.(optBootFileURL); ok { + return string(u) + } + return "" +} + // Message represents a DHCPv6 Message as defined by RFC 3315 Section 6. type Message struct { MessageType MessageType diff --git a/dhcpv6/option_bootfileurl.go b/dhcpv6/option_bootfileurl.go index d37a186..695f164 100644 --- a/dhcpv6/option_bootfileurl.go +++ b/dhcpv6/option_bootfileurl.go @@ -4,30 +4,29 @@ import ( "fmt" ) -// OptBootFileURL implements the OptionBootfileURL option -// -// This module defines the OptBootFileURL structure. -// https://www.ietf.org/rfc/rfc5970.txt -type OptBootFileURL string +// OptBootFileURL returns a OptionBootfileURL as defined by RFC 5970. +func OptBootFileURL(url string) Option { + return optBootFileURL(url) +} -var _ Option = OptBootFileURL("") +type optBootFileURL string // Code returns the option code -func (op OptBootFileURL) Code() OptionCode { +func (op optBootFileURL) Code() OptionCode { return OptionBootfileURL } // ToBytes serializes the option and returns it as a sequence of bytes -func (op OptBootFileURL) ToBytes() []byte { +func (op optBootFileURL) ToBytes() []byte { return []byte(op) } -func (op OptBootFileURL) String() string { - return fmt.Sprintf("OptBootFileURL(%s)", string(op)) +func (op optBootFileURL) String() string { + return fmt.Sprintf("BootFileURL: %s", string(op)) } -// ParseOptBootFileURL builds an OptBootFileURL structure from a sequence +// parseOptBootFileURL builds an optBootFileURL structure from a sequence // of bytes. The input data does not include option code and length bytes. -func ParseOptBootFileURL(data []byte) (OptBootFileURL, error) { - return OptBootFileURL(string(data)), nil +func parseOptBootFileURL(data []byte) (optBootFileURL, error) { + return optBootFileURL(string(data)), nil } diff --git a/dhcpv6/option_bootfileurl_test.go b/dhcpv6/option_bootfileurl_test.go index 80cdbf0..ac45ef5 100644 --- a/dhcpv6/option_bootfileurl_test.go +++ b/dhcpv6/option_bootfileurl_test.go @@ -9,7 +9,7 @@ import ( func TestOptBootFileURL(t *testing.T) { expected := "https://insomniac.slackware.it" - opt, err := ParseOptBootFileURL([]byte(expected)) + opt, err := parseOptBootFileURL([]byte(expected)) if err != nil { t.Fatal(err) } diff --git a/dhcpv6/options.go b/dhcpv6/options.go index 0db7ebd..9d0ff9d 100644 --- a/dhcpv6/options.go +++ b/dhcpv6/options.go @@ -78,7 +78,7 @@ func ParseOption(code OptionCode, optData []byte) (Option, error) { case OptionFQDN: opt, err = ParseOptFQDN(optData) case OptionBootfileURL: - opt, err = ParseOptBootFileURL(optData) + opt, err = parseOptBootFileURL(optData) case OptionBootfileParam: opt, err = ParseOptBootFileParam(optData) case OptionClientArchType: diff --git a/netboot/netboot.go b/netboot/netboot.go index e771e3d..4e1603c 100644 --- a/netboot/netboot.go +++ b/netboot/netboot.go @@ -96,13 +96,13 @@ func RequestNetbootv4(ifname string, timeout time.Duration, retries int, modifie // ConversationToNetconf extracts network configuration and boot file URL from a // DHCPv6 4-way conversation and returns them, or an error if any. func ConversationToNetconf(conversation []dhcpv6.DHCPv6) (*BootConf, error) { - var advertise, reply, optionsSource dhcpv6.DHCPv6 + var advertise, reply, optionsSource *dhcpv6.Message for _, m := range conversation { switch m.Type() { case dhcpv6.MessageTypeAdvertise: - advertise = m + advertise = m.(*dhcpv6.Message) case dhcpv6.MessageTypeReply: - reply = m + reply = m.(*dhcpv6.Message) } } if reply == nil { @@ -110,24 +110,25 @@ func ConversationToNetconf(conversation []dhcpv6.DHCPv6) (*BootConf, error) { } bootconf := &BootConf{} - netconf, err := GetNetConfFromPacketv6(reply.(*dhcpv6.Message)) + netconf, err := GetNetConfFromPacketv6(reply) if err != nil { return nil, fmt.Errorf("cannot get netconf from packet: %v", err) } bootconf.NetConf = *netconf - if reply.GetOneOption(dhcpv6.OptionBootfileURL) != nil { + if u := reply.Options.BootFileURL(); len(u) > 0 { + bootconf.BootfileURL = u optionsSource = reply } else { log.Printf("no bootfile URL option found in REPLY, fallback to ADVERTISE's value") - if advertise.GetOneOption(dhcpv6.OptionBootfileURL) != nil { + if u := advertise.Options.BootFileURL(); len(u) > 0 { + bootconf.BootfileURL = u optionsSource = advertise } } - if optionsSource == nil { + if len(bootconf.BootfileURL) == 0 { return nil, errors.New("no bootfile URL option found") } - bootconf.BootfileURL = string(optionsSource.GetOneOption(dhcpv6.OptionBootfileURL).(dhcpv6.OptBootFileURL)) if bootfileParamOption := optionsSource.GetOneOption(dhcpv6.OptionBootfileParam); bootfileParamOption != nil { bootconf.BootfileParam = bootfileParamOption.(dhcpv6.OptBootFileParam) |