summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6
diff options
context:
space:
mode:
authorPablo Mazzini <pmazzini@gmail.com>2018-08-10 16:00:59 +0200
committerPablo Mazzini <pmazzini@gmail.com>2018-08-10 16:00:59 +0200
commitf55d67dc49bee6d6aa20913f070ed771b9ff725a (patch)
tree2e96a2f52ab0bac9f06e0560208ab21bb2c4bb51 /dhcpv6
parentcff664d4ac7fe61377195a9d439e17259ce5899e (diff)
rename IsRequested to IsRequestedOption
Diffstat (limited to 'dhcpv6')
-rw-r--r--dhcpv6/dhcpv6.go83
-rw-r--r--dhcpv6/dhcpv6_test.go133
-rw-r--r--dhcpv6/dhcpv6message_test.go98
-rw-r--r--dhcpv6/utils.go86
-rw-r--r--dhcpv6/utils_test.go80
5 files changed, 239 insertions, 241 deletions
diff --git a/dhcpv6/dhcpv6.go b/dhcpv6/dhcpv6.go
index 0dabca5..adc52c5 100644
--- a/dhcpv6/dhcpv6.go
+++ b/dhcpv6/dhcpv6.go
@@ -1,8 +1,10 @@
package dhcpv6
import (
+ "errors"
"fmt"
"net"
+ "strings"
)
type DHCPv6 interface {
@@ -199,3 +201,84 @@ func EncapsulateRelay(d DHCPv6, mType MessageType, linkAddr, peerAddr net.IP) (D
outer.AddOption(&orm)
return &outer, nil
}
+
+// IsNetboot function takes a DHCPv6 message and returns true if the machine
+// is trying to netboot. It checks if "boot file" is one of the requested
+// options, which is useful for SOLICIT/REQUEST packet types, it also checks
+// if the "boot file" option is included in the packet, which is useful for
+// ADVERTISE/REPLY packet.
+func IsNetboot(msg DHCPv6) bool {
+ if IsOptionRequested(msg, OptionBootfileURL) {
+ return true
+ }
+ if optbf := msg.GetOneOption(OptionBootfileURL); optbf != nil {
+ return true
+ }
+ return false
+}
+
+// IsOptionRequested function takes a DHCPv6 message and an OptionCode, and
+// returns true if that option is within the requested options of the DHCPv6
+// message.
+func IsOptionRequested(msg DHCPv6, requested OptionCode) bool {
+ for _, optoro := range msg.GetOption(OptionORO) {
+ for _, o := range optoro.(*OptRequestedOption).RequestedOptions() {
+ if o == requested {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// IsUsingUEFI function takes a DHCPv6 message and returns true if
+// the machine trying to netboot is using UEFI of false if it is not.
+func IsUsingUEFI(msg DHCPv6) bool {
+ // RFC 4578 says:
+ // As of the writing of this document, the following pre-boot
+ // architecture types have been requested.
+ // Type Architecture Name
+ // ---- -----------------
+ // 0 Intel x86PC
+ // 1 NEC/PC98
+ // 2 EFI Itanium
+ // 3 DEC Alpha
+ // 4 Arc x86
+ // 5 Intel Lean Client
+ // 6 EFI IA32
+ // 7 EFI BC
+ // 8 EFI Xscale
+ // 9 EFI x86-64
+ if opt := msg.GetOneOption(OptionClientArchType); opt != nil {
+ optat := opt.(*OptClientArchType)
+ // TODO investigate if other types are appropriate
+ if optat.ArchType == EFI_BC || optat.ArchType == EFI_X86_64 {
+ return true
+ }
+ }
+ if opt := msg.GetOneOption(OptionUserClass); opt != nil {
+ optuc := opt.(*OptUserClass)
+ for _, uc := range optuc.UserClasses {
+ if strings.Contains(string(uc), "EFI") {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// GetTransactionID returns a transactionID of a message or its inner message
+// in case of relay
+func GetTransactionID(packet DHCPv6) (uint32, error) {
+ if message, ok := packet.(*DHCPv6Message); ok {
+ return message.TransactionID(), nil
+ }
+ if relay, ok := packet.(*DHCPv6Relay); ok {
+ message, err := relay.GetInnerMessage()
+ if err != nil {
+ return 0, err
+ }
+ return GetTransactionID(message)
+ }
+ return 0, errors.New("Invalid DHCPv6 packet")
+}
diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go
index 4a44e0e..c48df24 100644
--- a/dhcpv6/dhcpv6_test.go
+++ b/dhcpv6/dhcpv6_test.go
@@ -4,7 +4,6 @@ import (
"net"
"testing"
- "github.com/insomniacslk/dhcp/iana"
"github.com/stretchr/testify/require"
)
@@ -126,93 +125,77 @@ func TestFromAndToBytes(t *testing.T) {
require.Equal(t, expected, toBytes)
}
-func TestNewAdvertiseFromSolicit(t *testing.T) {
- s := DHCPv6Message{}
- s.SetMessage(MessageTypeSolicit)
- s.SetTransactionID(0xabcdef)
- cid := OptClientId{}
- s.AddOption(&cid)
- duid := Duid{}
+func TestIsNetboot(t *testing.T) {
+ msg1 := DHCPv6Message{}
+ require.False(t, IsNetboot(&msg1))
- a, err := NewAdvertiseFromSolicit(&s, WithServerID(duid))
- require.NoError(t, err)
- require.Equal(t, a.(*DHCPv6Message).TransactionID(), s.TransactionID())
- require.Equal(t, a.Type(), MessageTypeAdvertise)
+ msg2 := DHCPv6Message{}
+ optro := OptRequestedOption{}
+ optro.AddRequestedOption(OptionBootfileURL)
+ msg2.AddOption(&optro)
+ require.True(t, IsNetboot(&msg2))
+
+ msg3 := DHCPv6Message{}
+ optbf := OptBootFileURL{}
+ msg3.AddOption(&optbf)
+ require.True(t, IsNetboot(&msg3))
}
-func TestNewReplyFromDHCPv6Message(t *testing.T) {
- msg := DHCPv6Message{}
- msg.SetTransactionID(0xabcdef)
- cid := OptClientId{}
- msg.AddOption(&cid)
- sid := OptServerId{}
- duid := Duid{}
- sid.Sid = duid
- msg.AddOption(&sid)
+func TestIsOptionRequested(t *testing.T) {
+ msg1 := DHCPv6Message{}
+ require.False(t, IsOptionRequested(&msg1, OptionDNSRecursiveNameServer))
- msg.SetMessage(MessageTypeConfirm)
- rep, err := NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
- require.NoError(t, err)
- require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
- require.Equal(t, rep.Type(), MessageTypeReply)
-
- msg.SetMessage(MessageTypeRenew)
- rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
- require.NoError(t, err)
- require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
- require.Equal(t, rep.Type(), MessageTypeReply)
+ msg2 := DHCPv6Message{}
+ optro := OptRequestedOption{}
+ optro.AddRequestedOption(OptionDNSRecursiveNameServer)
+ msg2.AddOption(&optro)
+ require.True(t, IsOptionRequested(&msg2, OptionDNSRecursiveNameServer))
+}
- msg.SetMessage(MessageTypeRebind)
- rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
- require.NoError(t, err)
- require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
- require.Equal(t, rep.Type(), MessageTypeReply)
+func TestIsUsingUEFIArchTypeTrue(t *testing.T) {
+ msg := DHCPv6Message{}
+ opt := OptClientArchType{ArchType: EFI_BC}
+ msg.AddOption(&opt)
+ require.True(t, IsUsingUEFI(&msg))
+}
- msg.SetMessage(MessageTypeRelease)
- rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
- require.NoError(t, err)
- require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
- require.Equal(t, rep.Type(), MessageTypeReply)
+func TestIsUsingUEFIArchTypeFalse(t *testing.T) {
+ msg := DHCPv6Message{}
+ opt := OptClientArchType{ArchType: INTEL_X86PC}
+ msg.AddOption(&opt)
+ require.False(t, IsUsingUEFI(&msg))
+}
- msg.SetMessage(MessageTypeSolicit)
- rep, err = NewReplyFromDHCPv6Message(&msg)
- require.Error(t, err)
+func TestIsUsingUEFIUserClassTrue(t *testing.T) {
+ msg := DHCPv6Message{}
+ opt := OptUserClass{UserClasses: [][]byte{[]byte("ipxeUEFI")}}
+ msg.AddOption(&opt)
+ require.True(t, IsUsingUEFI(&msg))
+}
- relay := DHCPv6Relay{}
- rep, err = NewReplyFromDHCPv6Message(&relay)
- require.Error(t, err)
+func TestIsUsingUEFIUserClassFalse(t *testing.T) {
+ msg := DHCPv6Message{}
+ opt := OptUserClass{UserClasses: [][]byte{[]byte("ipxeLegacy")}}
+ msg.AddOption(&opt)
+ require.False(t, IsUsingUEFI(&msg))
}
-func TestNewMessageTypeSolicitWithCID(t *testing.T) {
- hwAddr, err := net.ParseMAC("24:0A:9E:9F:EB:2B")
+func TestGetTransactionIDMessage(t *testing.T) {
+ message, err := NewMessage()
require.NoError(t, err)
-
- duid := Duid{
- Type: DUID_LL,
- HwType: iana.HwTypeEthernet,
- LinkLayerAddr: hwAddr,
- }
-
- s, err := NewSolicitWithCID(duid)
+ transactionID, err := GetTransactionID(message)
require.NoError(t, err)
+ require.Equal(t, transactionID, message.(*DHCPv6Message).TransactionID())
+}
- require.Equal(t, s.Type(), MessageTypeSolicit)
- // Check CID
- cidOption := s.GetOneOption(OptionClientID)
- require.NotNil(t, cidOption)
- cid, ok := cidOption.(*OptClientId)
- require.True(t, ok)
- require.Equal(t, cid.Cid, duid)
-
- // Check ORO
- oroOption := s.GetOneOption(OptionORO)
- require.NotNil(t, oroOption)
- oro, ok := oroOption.(*OptRequestedOption)
- require.True(t, ok)
- opts := oro.RequestedOptions()
- require.Contains(t, opts, OptionDNSRecursiveNameServer)
- require.Contains(t, opts, OptionDomainSearchList)
- require.Equal(t, len(opts), 2)
+func TestGetTransactionIDRelay(t *testing.T) {
+ message, err := NewMessage()
+ require.NoError(t, err)
+ relay, err := EncapsulateRelay(message, MessageTypeRelayForward, nil, nil)
+ require.NoError(t, err)
+ transactionID, err := GetTransactionID(relay)
+ require.NoError(t, err)
+ require.Equal(t, transactionID, message.(*DHCPv6Message).TransactionID())
}
// TODO test NewMessageTypeSolicit
diff --git a/dhcpv6/dhcpv6message_test.go b/dhcpv6/dhcpv6message_test.go
new file mode 100644
index 0000000..ad90be6
--- /dev/null
+++ b/dhcpv6/dhcpv6message_test.go
@@ -0,0 +1,98 @@
+package dhcpv6
+
+import (
+ "net"
+ "testing"
+
+ "github.com/insomniacslk/dhcp/iana"
+ "github.com/stretchr/testify/require"
+)
+
+func TestNewAdvertiseFromSolicit(t *testing.T) {
+ s := DHCPv6Message{}
+ s.SetMessage(MessageTypeSolicit)
+ s.SetTransactionID(0xabcdef)
+ cid := OptClientId{}
+ s.AddOption(&cid)
+ duid := Duid{}
+
+ a, err := NewAdvertiseFromSolicit(&s, WithServerID(duid))
+ require.NoError(t, err)
+ require.Equal(t, a.(*DHCPv6Message).TransactionID(), s.TransactionID())
+ require.Equal(t, a.Type(), MessageTypeAdvertise)
+}
+
+func TestNewReplyFromDHCPv6Message(t *testing.T) {
+ msg := DHCPv6Message{}
+ msg.SetTransactionID(0xabcdef)
+ cid := OptClientId{}
+ msg.AddOption(&cid)
+ sid := OptServerId{}
+ duid := Duid{}
+ sid.Sid = duid
+ msg.AddOption(&sid)
+
+ msg.SetMessage(MessageTypeConfirm)
+ rep, err := NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
+ require.NoError(t, err)
+ require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
+ require.Equal(t, rep.Type(), MessageTypeReply)
+
+ msg.SetMessage(MessageTypeRenew)
+ rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
+ require.NoError(t, err)
+ require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
+ require.Equal(t, rep.Type(), MessageTypeReply)
+
+ msg.SetMessage(MessageTypeRebind)
+ rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
+ require.NoError(t, err)
+ require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
+ require.Equal(t, rep.Type(), MessageTypeReply)
+
+ msg.SetMessage(MessageTypeRelease)
+ rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid))
+ require.NoError(t, err)
+ require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID())
+ require.Equal(t, rep.Type(), MessageTypeReply)
+
+ msg.SetMessage(MessageTypeSolicit)
+ rep, err = NewReplyFromDHCPv6Message(&msg)
+ require.Error(t, err)
+
+ relay := DHCPv6Relay{}
+ rep, err = NewReplyFromDHCPv6Message(&relay)
+ require.Error(t, err)
+}
+
+func TestNewMessageTypeSolicitWithCID(t *testing.T) {
+ hwAddr, err := net.ParseMAC("24:0A:9E:9F:EB:2B")
+ require.NoError(t, err)
+
+ duid := Duid{
+ Type: DUID_LL,
+ HwType: iana.HwTypeEthernet,
+ LinkLayerAddr: hwAddr,
+ }
+
+ s, err := NewSolicitWithCID(duid)
+ require.NoError(t, err)
+
+ require.Equal(t, s.Type(), MessageTypeSolicit)
+ // Check CID
+ cidOption := s.GetOneOption(OptionClientID)
+ require.NotNil(t, cidOption)
+ cid, ok := cidOption.(*OptClientId)
+ require.True(t, ok)
+ require.Equal(t, cid.Cid, duid)
+
+ // Check ORO
+ oroOption := s.GetOneOption(OptionORO)
+ require.NotNil(t, oroOption)
+ oro, ok := oroOption.(*OptRequestedOption)
+ require.True(t, ok)
+ opts := oro.RequestedOptions()
+ require.Contains(t, opts, OptionDNSRecursiveNameServer)
+ require.Contains(t, opts, OptionDomainSearchList)
+ require.Equal(t, len(opts), 2)
+}
diff --git a/dhcpv6/utils.go b/dhcpv6/utils.go
deleted file mode 100644
index d1715da..0000000
--- a/dhcpv6/utils.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package dhcpv6
-
-import (
- "errors"
- "strings"
-)
-
-// IsNetboot function takes a DHCPv6 message and returns true if the machine
-// is trying to netboot. It checks if "boot file" is one of the requested
-// options, which is useful for SOLICIT/REQUEST packet types, it also checks
-// if the "boot file" option is included in the packet, which is useful for
-// ADVERTISE/REPLY packet.
-func IsNetboot(msg DHCPv6) bool {
- if IsRequested(msg, OptionBootfileURL) {
- return true
- }
- if optbf := msg.GetOneOption(OptionBootfileURL); optbf != nil {
- return true
- }
- return false
-}
-
-// IsRequested function takes a DHCPv6 message and an OptionCode, and returns
-// true if that option is within the requested options of the DHCPv6 message.
-func IsRequested(msg DHCPv6, requested OptionCode) bool {
- for _, optoro := range msg.GetOption(OptionORO) {
- for _, o := range optoro.(*OptRequestedOption).RequestedOptions() {
- if o == requested {
- return true
- }
- }
- }
- return false
-}
-
-// IsUsingUEFI function takes a DHCPv6 message and returns true if
-// the machine trying to netboot is using UEFI of false if it is not.
-func IsUsingUEFI(msg DHCPv6) bool {
- // RFC 4578 says:
- // As of the writing of this document, the following pre-boot
- // architecture types have been requested.
- // Type Architecture Name
- // ---- -----------------
- // 0 Intel x86PC
- // 1 NEC/PC98
- // 2 EFI Itanium
- // 3 DEC Alpha
- // 4 Arc x86
- // 5 Intel Lean Client
- // 6 EFI IA32
- // 7 EFI BC
- // 8 EFI Xscale
- // 9 EFI x86-64
- if opt := msg.GetOneOption(OptionClientArchType); opt != nil {
- optat := opt.(*OptClientArchType)
- // TODO investigate if other types are appropriate
- if optat.ArchType == EFI_BC || optat.ArchType == EFI_X86_64 {
- return true
- }
- }
- if opt := msg.GetOneOption(OptionUserClass); opt != nil {
- optuc := opt.(*OptUserClass)
- for _, uc := range optuc.UserClasses {
- if strings.Contains(string(uc), "EFI") {
- return true
- }
- }
- }
- return false
-}
-
-// GetTransactionID returns a transactionID of a message or its inner message
-// in case of relay
-func GetTransactionID(packet DHCPv6) (uint32, error) {
- if message, ok := packet.(*DHCPv6Message); ok {
- return message.TransactionID(), nil
- }
- if relay, ok := packet.(*DHCPv6Relay); ok {
- message, err := relay.GetInnerMessage()
- if err != nil {
- return 0, err
- }
- return GetTransactionID(message)
- }
- return 0, errors.New("Invalid DHCPv6 packet")
-}
diff --git a/dhcpv6/utils_test.go b/dhcpv6/utils_test.go
deleted file mode 100644
index 779d55c..0000000
--- a/dhcpv6/utils_test.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package dhcpv6
-
-import (
- "testing"
-
- "github.com/stretchr/testify/require"
-)
-
-func TestIsNetboot(t *testing.T) {
- msg1 := DHCPv6Message{}
- require.False(t, IsNetboot(&msg1))
-
- msg2 := DHCPv6Message{}
- optro := OptRequestedOption{}
- optro.AddRequestedOption(OptionBootfileURL)
- msg2.AddOption(&optro)
- require.True(t, IsNetboot(&msg2))
-
- msg3 := DHCPv6Message{}
- optbf := OptBootFileURL{}
- msg3.AddOption(&optbf)
- require.True(t, IsNetboot(&msg3))
-}
-
-func TestIsRequetsed(t *testing.T) {
- msg1 := DHCPv6Message{}
- require.False(t, IsRequested(&msg1, OptionDNSRecursiveNameServer))
-
- msg2 := DHCPv6Message{}
- optro := OptRequestedOption{}
- optro.AddRequestedOption(OptionDNSRecursiveNameServer)
- msg2.AddOption(&optro)
- require.True(t, IsRequested(&msg2, OptionDNSRecursiveNameServer))
-}
-
-func TestIsUsingUEFIArchTypeTrue(t *testing.T) {
- msg := DHCPv6Message{}
- opt := OptClientArchType{ArchType: EFI_BC}
- msg.AddOption(&opt)
- require.True(t, IsUsingUEFI(&msg))
-}
-
-func TestIsUsingUEFIArchTypeFalse(t *testing.T) {
- msg := DHCPv6Message{}
- opt := OptClientArchType{ArchType: INTEL_X86PC}
- msg.AddOption(&opt)
- require.False(t, IsUsingUEFI(&msg))
-}
-
-func TestIsUsingUEFIUserClassTrue(t *testing.T) {
- msg := DHCPv6Message{}
- opt := OptUserClass{UserClasses: [][]byte{[]byte("ipxeUEFI")}}
- msg.AddOption(&opt)
- require.True(t, IsUsingUEFI(&msg))
-}
-
-func TestIsUsingUEFIUserClassFalse(t *testing.T) {
- msg := DHCPv6Message{}
- opt := OptUserClass{UserClasses: [][]byte{[]byte("ipxeLegacy")}}
- msg.AddOption(&opt)
- require.False(t, IsUsingUEFI(&msg))
-}
-
-func TestGetTransactionIDMessage(t *testing.T) {
- message, err := NewMessage()
- require.NoError(t, err)
- transactionID, err := GetTransactionID(message)
- require.NoError(t, err)
- require.Equal(t, transactionID, message.(*DHCPv6Message).TransactionID())
-}
-
-func TestGetTransactionIDRelay(t *testing.T) {
- message, err := NewMessage()
- require.NoError(t, err)
- relay, err := EncapsulateRelay(message, MessageTypeRelayForward, nil, nil)
- require.NoError(t, err)
- transactionID, err := GetTransactionID(relay)
- require.NoError(t, err)
- require.Equal(t, transactionID, message.(*DHCPv6Message).TransactionID())
-}