summaryrefslogtreecommitdiffhomepage
path: root/dhcpv4
diff options
context:
space:
mode:
authorSean Karlage <skarlage@fb.com>2018-08-15 10:34:04 -0700
committerSean Karlage <skarlage@fb.com>2018-08-15 10:34:04 -0700
commit40169a2169f788c41cb806c9d344148e72a3a0bd (patch)
tree6cfee5029c946710e4ed7789151ac02e62fa852b /dhcpv4
parent8ea2525c898436a2a935580de67727bbe7035c85 (diff)
parent926a42d133247d7a4fa388548e4323b77421f798 (diff)
Merge branch 'master' into dhcpv4-moar-tests
Diffstat (limited to 'dhcpv4')
-rw-r--r--dhcpv4/bsdp/client.go12
-rw-r--r--dhcpv4/dhcpv4.go13
-rw-r--r--dhcpv4/dhcpv4_test.go10
-rw-r--r--dhcpv4/option_archtype.go42
-rw-r--r--dhcpv4/option_archtype_test.go9
-rw-r--r--dhcpv4/options.go3
-rw-r--r--dhcpv4/options_test.go5
7 files changed, 43 insertions, 51 deletions
diff --git a/dhcpv4/bsdp/client.go b/dhcpv4/bsdp/client.go
index 2683e2a..38de094 100644
--- a/dhcpv4/bsdp/client.go
+++ b/dhcpv4/bsdp/client.go
@@ -38,8 +38,8 @@ func castVendorOpt(ack *dhcpv4.DHCPv4) {
// Exchange runs a full BSDP exchange (Inform[list], Ack, Inform[select],
// Ack). Returns a list of DHCPv4 structures representing the exchange.
-func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]dhcpv4.DHCPv4, error) {
- conversation := make([]dhcpv4.DHCPv4, 1)
+func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]*dhcpv4.DHCPv4, error) {
+ conversation := make([]*dhcpv4.DHCPv4, 1)
var err error
// Get our file descriptor for the broadcast socket.
@@ -73,7 +73,7 @@ func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]dhcpv4.DH
return conversation, err
}
}
- conversation[0] = *informList
+ conversation[0] = informList
// ACK[LIST]
ackForList, err := dhcpv4.BroadcastSendReceive(sendFd, recvFd, informList, c.ReadTimeout, c.WriteTimeout, dhcpv4.MessageTypeAck)
@@ -83,7 +83,7 @@ func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]dhcpv4.DH
// Rewrite vendor-specific option for pretty printing.
castVendorOpt(ackForList)
- conversation = append(conversation, *ackForList)
+ conversation = append(conversation, ackForList)
// Parse boot images sent back by server
bootImages, err := ParseBootImageListFromAck(*ackForList)
@@ -99,7 +99,7 @@ func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]dhcpv4.DH
if err != nil {
return conversation, err
}
- conversation = append(conversation, *informSelect)
+ conversation = append(conversation, informSelect)
// ACK[SELECT]
ackForSelect, err := dhcpv4.BroadcastSendReceive(sendFd, recvFd, informSelect, c.ReadTimeout, c.WriteTimeout, dhcpv4.MessageTypeAck)
@@ -107,5 +107,5 @@ func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]dhcpv4.DH
if err != nil {
return conversation, err
}
- return append(conversation, *ackForSelect), nil
+ return append(conversation, ackForSelect), nil
}
diff --git a/dhcpv4/dhcpv4.go b/dhcpv4/dhcpv4.go
index d452f6e..972d103 100644
--- a/dhcpv4/dhcpv4.go
+++ b/dhcpv4/dhcpv4.go
@@ -656,6 +656,19 @@ func (d *DHCPv4) ValidateOptions() {
}
}
+// IsOptionRequested returns true if that option is within the requested
+// options of the DHCPv4 message.
+func (d *DHCPv4) IsOptionRequested(requested OptionCode) bool {
+ for _, optprl := range d.GetOption(OptionParameterRequestList) {
+ for _, o := range optprl.(*OptParameterRequestList).RequestedOpts {
+ if o == requested {
+ return true
+ }
+ }
+ }
+ return false
+}
+
// ToBytes encodes a DHCPv4 structure into a sequence of bytes in its wire
// format.
func (d *DHCPv4) ToBytes() []byte {
diff --git a/dhcpv4/dhcpv4_test.go b/dhcpv4/dhcpv4_test.go
index fe9fe0d..28f38d4 100644
--- a/dhcpv4/dhcpv4_test.go
+++ b/dhcpv4/dhcpv4_test.go
@@ -493,5 +493,15 @@ func TestNewInform(t *testing.T) {
require.True(t, m.ClientIPAddr().Equal(localIP))
}
+func TestIsOptionRequested(t *testing.T) {
+ pkt, err := New()
+ require.NoError(t, err)
+ require.False(t, pkt.IsOptionRequested(OptionDomainNameServer))
+
+ optprl := OptParameterRequestList{RequestedOpts: []OptionCode{OptionDomainNameServer}}
+ pkt.AddOption(&optprl)
+ require.True(t, pkt.IsOptionRequested(OptionDomainNameServer))
+}
+
// TODO
// test Summary() and String()
diff --git a/dhcpv4/option_archtype.go b/dhcpv4/option_archtype.go
index 16ca98d..8eafc55 100644
--- a/dhcpv4/option_archtype.go
+++ b/dhcpv4/option_archtype.go
@@ -6,43 +6,14 @@ package dhcpv4
import (
"encoding/binary"
"fmt"
-)
-
-//ArchType encodes an architecture type in an uint16
-type ArchType uint16
-// see rfc4578
-const (
- INTEL_X86PC ArchType = 0
- NEC_PC98 ArchType = 1
- EFI_ITANIUM ArchType = 2
- DEC_ALPHA ArchType = 3
- ARC_X86 ArchType = 4
- INTEL_LEAN_CLIENT ArchType = 5
- EFI_IA32 ArchType = 6
- EFI_BC ArchType = 7
- EFI_XSCALE ArchType = 8
- EFI_X86_64 ArchType = 9
+ "github.com/insomniacslk/dhcp/iana"
)
-// ArchTypeToStringMap maps an ArchType to a mnemonic name
-var ArchTypeToStringMap = map[ArchType]string{
- INTEL_X86PC: "Intel x86PC",
- NEC_PC98: "NEC/PC98",
- EFI_ITANIUM: "EFI Itanium",
- DEC_ALPHA: "DEC Alpha",
- ARC_X86: "Arc x86",
- INTEL_LEAN_CLIENT: "Intel Lean Client",
- EFI_IA32: "EFI IA32",
- EFI_BC: "EFI BC",
- EFI_XSCALE: "EFI Xscale",
- EFI_X86_64: "EFI x86-64",
-}
-
// OptClientArchType represents an option encapsulating the Client System
// Architecture Type option Definition.
type OptClientArchType struct {
- ArchTypes []ArchType
+ ArchTypes []iana.ArchType
}
// Code returns the option code.
@@ -71,10 +42,7 @@ func (o *OptClientArchType) Length() int {
func (o *OptClientArchType) String() string {
var archTypes string
for idx, at := range o.ArchTypes {
- name, ok := ArchTypeToStringMap[at]
- if !ok {
- name = "Unknown"
- }
+ name := iana.ArchTypeToString(at)
archTypes += name
if idx < len(o.ArchTypes)-1 {
archTypes += ", "
@@ -100,10 +68,10 @@ func ParseOptClientArchType(data []byte) (*OptClientArchType, error) {
if len(data) < 2+length {
return nil, ErrShortByteStream
}
- archTypes := make([]ArchType, 0, length%2)
+ archTypes := make([]iana.ArchType, 0, length%2)
for idx := 0; idx < length; idx += 2 {
b := data[2+idx : 2+idx+2]
- archTypes = append(archTypes, ArchType(binary.BigEndian.Uint16(b)))
+ archTypes = append(archTypes, iana.ArchType(binary.BigEndian.Uint16(b)))
}
return &OptClientArchType{ArchTypes: archTypes}, nil
}
diff --git a/dhcpv4/option_archtype_test.go b/dhcpv4/option_archtype_test.go
index cb9bc3f..d803328 100644
--- a/dhcpv4/option_archtype_test.go
+++ b/dhcpv4/option_archtype_test.go
@@ -3,6 +3,7 @@ package dhcpv4
import (
"testing"
+ "github.com/insomniacslk/dhcp/iana"
"github.com/stretchr/testify/require"
)
@@ -14,7 +15,7 @@ func TestParseOptClientArchType(t *testing.T) {
}
opt, err := ParseOptClientArchType(data)
require.NoError(t, err)
- require.Equal(t, opt.ArchTypes[0], EFI_IA32)
+ require.Equal(t, opt.ArchTypes[0], iana.EFI_IA32)
}
func TestParseOptClientArchTypeMultiple(t *testing.T) {
@@ -26,8 +27,8 @@ func TestParseOptClientArchTypeMultiple(t *testing.T) {
}
opt, err := ParseOptClientArchType(data)
require.NoError(t, err)
- require.Equal(t, opt.ArchTypes[0], EFI_IA32)
- require.Equal(t, opt.ArchTypes[1], EFI_ITANIUM)
+ require.Equal(t, opt.ArchTypes[0], iana.EFI_IA32)
+ require.Equal(t, opt.ArchTypes[1], iana.EFI_ITANIUM)
}
func TestParseOptClientArchTypeInvalid(t *testing.T) {
@@ -61,7 +62,7 @@ func TestOptClientArchTypeParseAndToBytesMultiple(t *testing.T) {
func TestOptClientArchType(t *testing.T) {
opt := OptClientArchType{
- ArchTypes: []ArchType{EFI_ITANIUM},
+ ArchTypes: []iana.ArchType{iana.EFI_ITANIUM},
}
require.Equal(t, opt.Length(), 2)
require.Equal(t, opt.Code(), OptionClientSystemArchitectureType)
diff --git a/dhcpv4/options.go b/dhcpv4/options.go
index d869b7d..02fa6e4 100644
--- a/dhcpv4/options.go
+++ b/dhcpv4/options.go
@@ -126,6 +126,9 @@ func OptionsFromBytesWithoutMagicCookie(data []byte) ([]Option, error) {
return nil, err
}
options = append(options, opt)
+ if opt.Code() == OptionEnd {
+ break
+ }
// Options with zero length have no length byte, so here we handle the
// ones with nonzero length
diff --git a/dhcpv4/options_test.go b/dhcpv4/options_test.go
index 0268483..899fb2c 100644
--- a/dhcpv4/options_test.go
+++ b/dhcpv4/options_test.go
@@ -167,12 +167,9 @@ func TestOptionsFromBytes(t *testing.T) {
}
opts, err := OptionsFromBytes(options)
require.NoError(t, err)
- require.Equal(t, 5, len(opts))
+ require.Equal(t, 2, len(opts))
require.Equal(t, opts[0].(*OptionGeneric), &OptionGeneric{OptionCode: OptionNameServer, Data: []byte{192, 168, 1, 1}})
require.Equal(t, opts[1].(*OptionGeneric), &OptionGeneric{OptionCode: OptionEnd})
- require.Equal(t, opts[2].(*OptionGeneric), &OptionGeneric{OptionCode: OptionPad})
- require.Equal(t, opts[3].(*OptionGeneric), &OptionGeneric{OptionCode: OptionPad})
- require.Equal(t, opts[4].(*OptionGeneric), &OptionGeneric{OptionCode: OptionPad})
}
func TestOptionsFromBytesZeroLength(t *testing.T) {