Skip to content

Commit

Permalink
Add helpers for AutoConfigure from RFC 2563
Browse files Browse the repository at this point in the history
Signed-off-by: Brian Candler <[email protected]>
  • Loading branch information
candlerb committed Feb 27, 2024
1 parent ca2dc33 commit a052884
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 0 deletions.
9 changes: 9 additions & 0 deletions dhcpv4/dhcpv4.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,15 @@ func (d *DHCPv4) MaxMessageSize() (uint16, error) {
return GetUint16(OptionMaximumDHCPMessageSize, d.Options)
}

// AutoConfigure returns the value of the AutoConfigure option, and a
// boolean indicating if it was present.
//
// The AutoConfigure option is described by RFC 2563, Section 2.
func (d *DHCPv4) AutoConfigure() (AutoConfiguration, bool) {
v, err := GetByte(OptionAutoConfigure, d.Options)
return AutoConfiguration(v), err == nil
}

// MessageType returns the DHCPv4 Message Type option.
func (d *DHCPv4) MessageType() MessageType {
v := d.Options.Get(OptionDHCPMessageType)
Expand Down
61 changes: 61 additions & 0 deletions dhcpv4/option_autoconfigure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package dhcpv4

import (
"fmt"
)

// AutoConfiguration implements encoding and decoding functions for a
// byte enumeration as used in RFC 2563, Section 2.
type AutoConfiguration byte

const (
DoNotAutoConfigure AutoConfiguration = 0
AutoConfigure AutoConfiguration = 1
)

var autoConfigureToString = map[AutoConfiguration]string{
DoNotAutoConfigure: "DoNotAutoConfigure",
AutoConfigure: "AutoConfigure",
}

// ToBytes returns a serialized stream of bytes for this option.
func (o AutoConfiguration) ToBytes() []byte {
return []byte{byte(o)}
}

// String returns a human-readable string for this option.
func (o AutoConfiguration) String() string {
s := autoConfigureToString[o]
if s != "" {
return s
}
return fmt.Sprintf("UNKNOWN (%d)", byte(o))
}

// FromBytes parses a a single byte into AutoConfiguration
func (o *AutoConfiguration) FromBytes(data []byte) error {
if len(data) == 1 {
*o = AutoConfiguration(data[0])
return nil
}
return fmt.Errorf("Invalid buffer length (%d)", len(data))

Check warning on line 41 in dhcpv4/option_autoconfigure.go

View check run for this annotation

Codecov / codecov/patch

dhcpv4/option_autoconfigure.go#L41

Added line #L41 was not covered by tests
}

// GetByte parses any single-byte option
func GetByte(code OptionCode, o Options) (byte, error) {
data := o.Get(code)
if data == nil {
return 0, fmt.Errorf("option not present")
}
if len(data) != 1 {
return 0, fmt.Errorf("Invalid buffer length (%d)", len(data))
}
return data[0], nil
}

// OptAutoConfigure returns a new AutoConfigure option.
//
// The AutoConfigure option is described by RFC 2563, Section 2.
func OptAutoConfigure(autoconf AutoConfiguration) Option {
return Option{Code: OptionAutoConfigure, Value: autoconf}
}
46 changes: 46 additions & 0 deletions dhcpv4/option_autoconfigure_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dhcpv4

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestOptAutoConfigure(t *testing.T) {
o := OptAutoConfigure(0)
require.Equal(t, OptionAutoConfigure, o.Code, "Code")
require.Equal(t, []byte{0}, o.Value.ToBytes(), "ToBytes")
require.Equal(t, "Auto-Configure: DoNotAutoConfigure", o.String())

o = OptAutoConfigure(1)
require.Equal(t, OptionAutoConfigure, o.Code, "Code")
require.Equal(t, []byte{1}, o.Value.ToBytes(), "ToBytes")
require.Equal(t, "Auto-Configure: AutoConfigure", o.String())

o = OptAutoConfigure(2)
require.Equal(t, OptionAutoConfigure, o.Code, "Code")
require.Equal(t, []byte{2}, o.Value.ToBytes(), "ToBytes")
require.Equal(t, "Auto-Configure: UNKNOWN (2)", o.String())
}

func TestGetAutoConfigure(t *testing.T) {
m, _ := New(WithGeneric(OptionAutoConfigure, []byte{1}))
o, ok := m.AutoConfigure()
require.True(t, ok)
require.Equal(t, AutoConfigure, o)

// Missing
m, _ = New()
_, ok = m.AutoConfigure()
require.False(t, ok, "should get error if option missing")

// Short byte stream
m, _ = New(WithGeneric(OptionAutoConfigure, []byte{}))
_, ok = m.AutoConfigure()
require.False(t, ok, "should get error from short byte stream")

// Bad length
m, _ = New(WithGeneric(OptionAutoConfigure, []byte{2, 2}))
_, ok = m.AutoConfigure()
require.False(t, ok, "should get error from bad length")
}
4 changes: 4 additions & 0 deletions dhcpv4/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@ func getOption(code OptionCode, data []byte, vendorDecoder OptionDecoder) fmt.St
d = &s
}

case OptionAutoConfigure:
var a AutoConfiguration
d = &a

case OptionVendorIdentifyingVendorClass:
d = &VIVCIdentifiers{}

Expand Down
5 changes: 5 additions & 0 deletions dhcpv4/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ func TestParseOption(t *testing.T) {
value: []byte{1, 2},
want: "258",
},
{
code: OptionAutoConfigure,
value: []byte{0},
want: "DoNotAutoConfigure",
},
{
code: OptionUserClassInformation,
value: []byte{4, 't', 'e', 's', 't', 3, 'f', 'o', 'o'},
Expand Down

0 comments on commit a052884

Please sign in to comment.