summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dhcpv6/modifiers.go8
-rw-r--r--dhcpv6/modifiers_test.go10
-rw-r--r--dhcpv6/option_fqdn.go41
-rw-r--r--dhcpv6/option_fqdn_test.go39
-rw-r--r--dhcpv6/options.go2
5 files changed, 100 insertions, 0 deletions
diff --git a/dhcpv6/modifiers.go b/dhcpv6/modifiers.go
index efd14a5..06eb9d9 100644
--- a/dhcpv6/modifiers.go
+++ b/dhcpv6/modifiers.go
@@ -43,6 +43,14 @@ func WithNetboot(d DHCPv6) {
msg.UpdateOption(oro)
}
+// WithFQDN adds a fully qualified domain name option to the packet
+func WithFQDN(flags uint8, domainname string) Modifier {
+ return func(d DHCPv6) {
+ ofqdn := OptFQDN{Flags: flags, DomainName: domainname}
+ d.AddOption(&ofqdn)
+ }
+}
+
// WithUserClass adds a user class option to the packet
func WithUserClass(uc []byte) Modifier {
// TODO let the user specify multiple user classes
diff --git a/dhcpv6/modifiers_test.go b/dhcpv6/modifiers_test.go
index 324c425..dfef08c 100644
--- a/dhcpv6/modifiers_test.go
+++ b/dhcpv6/modifiers_test.go
@@ -95,3 +95,13 @@ func TestWithDomainSearchList(t *testing.T) {
require.Equal(t, "slackware.it", labels[0])
require.Equal(t, "dhcp.slackware.it", labels[1])
}
+
+func TestWithFQDN(t *testing.T) {
+ var d Message
+ WithFQDN(4, "cnos.localhost")(&d)
+ require.Equal(t, 1, len(d.Options))
+ ofqdn := d.Options[0].(*OptFQDN)
+ require.Equal(t, OptionFQDN, ofqdn.Code())
+ require.Equal(t, uint8(4), ofqdn.Flags)
+ require.Equal(t, "cnos.localhost", ofqdn.DomainName)
+}
diff --git a/dhcpv6/option_fqdn.go b/dhcpv6/option_fqdn.go
new file mode 100644
index 0000000..82d1254
--- /dev/null
+++ b/dhcpv6/option_fqdn.go
@@ -0,0 +1,41 @@
+package dhcpv6
+
+import (
+ "fmt"
+
+ "github.com/u-root/u-root/pkg/uio"
+)
+
+// OptFQDN implements OptionFQDN option.
+//
+// https://tools.ietf.org/html/rfc4704
+type OptFQDN struct {
+ Flags uint8
+ DomainName string
+}
+
+// Code returns the option code.
+func (op *OptFQDN) Code() OptionCode {
+ return OptionFQDN
+}
+
+// ToBytes serializes the option and returns it as a sequence of bytes
+func (op *OptFQDN) ToBytes() []byte {
+ buf := uio.NewBigEndianBuffer(nil)
+ buf.Write8(op.Flags)
+ buf.WriteBytes([]byte(op.DomainName))
+ return buf.Data()
+}
+
+func (op *OptFQDN) String() string {
+ return fmt.Sprintf("OptFQDN{flags=%d, domainname=%s}", op.Flags, op.DomainName)
+}
+
+// ParseOptFQDN deserializes from bytes to build a OptFQDN structure.
+func ParseOptFQDN(data []byte) (*OptFQDN, error) {
+ var opt OptFQDN
+ buf := uio.NewBigEndianBuffer(data)
+ opt.Flags = buf.Read8()
+ opt.DomainName = string(buf.ReadAll())
+ return &opt, buf.FinError()
+}
diff --git a/dhcpv6/option_fqdn_test.go b/dhcpv6/option_fqdn_test.go
new file mode 100644
index 0000000..870ed9d
--- /dev/null
+++ b/dhcpv6/option_fqdn_test.go
@@ -0,0 +1,39 @@
+package dhcpv6
+
+import (
+ "bytes"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestParseOptFQDN(t *testing.T) {
+ data := []byte{
+ 0, // Flags
+ 'c', 'n', 'o', 's', '.', 'l', 'o', 'c', 'a', 'l',
+ 'h', 'o', 's', 't',
+ }
+ opt, err := ParseOptFQDN(data)
+
+ require.NoError(t, err)
+ require.Equal(t, OptionFQDN, opt.Code())
+ require.Equal(t, uint8(0), opt.Flags)
+ require.Equal(t, "cnos.localhost", opt.DomainName)
+ require.Equal(t, "OptFQDN{flags=0, domainname=cnos.localhost}", opt.String())
+}
+
+func TestOptFQDNToBytes(t *testing.T) {
+ opt := OptFQDN{
+ Flags: 0,
+ DomainName: "cnos.localhost",
+ }
+ want := []byte{
+ 0, // Flags
+ 'c', 'n', 'o', 's', '.', 'l', 'o', 'c', 'a', 'l',
+ 'h', 'o', 's', 't',
+ }
+ b := opt.ToBytes()
+ if !bytes.Equal(b, want) {
+ t.Fatalf("opt.ToBytes()=%v, want %v", b, want)
+ }
+}
diff --git a/dhcpv6/options.go b/dhcpv6/options.go
index fb36a38..e653c01 100644
--- a/dhcpv6/options.go
+++ b/dhcpv6/options.go
@@ -73,6 +73,8 @@ func ParseOption(code OptionCode, optData []byte) (Option, error) {
opt, err = ParseOptIAPrefix(optData)
case OptionRemoteID:
opt, err = ParseOptRemoteId(optData)
+ case OptionFQDN:
+ opt, err = ParseOptFQDN(optData)
case OptionBootfileURL:
opt, err = ParseOptBootFileURL(optData)
case OptionBootfileParam: