summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChris Koch <chrisko@google.com>2019-12-28 07:41:20 -0800
committerinsomniac <insomniacslk@users.noreply.github.com>2020-03-05 15:51:55 +0000
commitd9b1a20bc08c08acc5e43e818fe1c3b71612f0a7 (patch)
treebaae82a03470d3d20761de6b46532f4e6eaa71dd
parent26ec6ccc1813d21a91bc0227ce36dee3531c5c96 (diff)
v6: add BootFileURL getter
Signed-off-by: Chris Koch <chrisko@google.com>
-rw-r--r--dhcpv6/dhcpv6message.go12
-rw-r--r--dhcpv6/option_bootfileurl.go25
-rw-r--r--dhcpv6/option_bootfileurl_test.go2
-rw-r--r--dhcpv6/options.go2
-rw-r--r--netboot/netboot.go17
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)