summaryrefslogtreecommitdiffhomepage
path: root/dhcpv4/option_userclass.go
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpv4/option_userclass.go')
-rw-r--r--dhcpv4/option_userclass.go38
1 files changed, 33 insertions, 5 deletions
diff --git a/dhcpv4/option_userclass.go b/dhcpv4/option_userclass.go
index 1505dbb..d6ddabc 100644
--- a/dhcpv4/option_userclass.go
+++ b/dhcpv4/option_userclass.go
@@ -12,6 +12,7 @@ import (
// OptUserClass represents an option encapsulating User Classes.
type OptUserClass struct {
UserClasses [][]byte
+ Rfc3004 bool
}
// Code returns the option code
@@ -22,6 +23,9 @@ func (op *OptUserClass) Code() OptionCode {
// ToBytes serializes the option and returns it as a sequence of bytes
func (op *OptUserClass) ToBytes() []byte {
buf := []byte{byte(op.Code()), byte(op.Length())}
+ if !op.Rfc3004 {
+ return append(buf, op.UserClasses[0]...)
+ }
for _, uc := range op.UserClasses {
buf = append(buf, byte(len(uc)))
buf = append(buf, uc...)
@@ -32,6 +36,9 @@ func (op *OptUserClass) ToBytes() []byte {
// Length returns the option length
func (op *OptUserClass) Length() int {
ret := 0
+ if !op.Rfc3004 {
+ return len(op.UserClasses[0])
+ }
for _, uc := range op.UserClasses {
ret += 1 + len(uc)
}
@@ -39,11 +46,15 @@ func (op *OptUserClass) Length() int {
}
func (op *OptUserClass) String() string {
- ucStrings := make([]string, len(op.UserClasses))
- for _, uc := range op.UserClasses {
- ucStrings = append(ucStrings, string(uc))
+ ucStrings := make([]string, 0, len(op.UserClasses))
+ if !op.Rfc3004 {
+ ucStrings = append(ucStrings, string(op.UserClasses[0]))
+ } else {
+ for _, uc := range op.UserClasses {
+ ucStrings = append(ucStrings, string(uc))
+ }
}
- return fmt.Sprintf("OptUserClass{userclass=[%s]}", strings.Join(ucStrings, ", "))
+ return fmt.Sprintf("User Class Information -> %v", strings.Join(ucStrings, ", "))
}
// ParseOptUserClass returns a new OptUserClass from a byte stream or
@@ -51,7 +62,7 @@ func (op *OptUserClass) String() string {
func ParseOptUserClass(data []byte) (*OptUserClass, error) {
opt := OptUserClass{}
- if len(data) < 4 {
+ if len(data) < 3 {
return nil, ErrShortByteStream
}
code := OptionCode(data[0])
@@ -66,6 +77,23 @@ func ParseOptUserClass(data []byte) (*OptUserClass, error) {
totalLength, len(data))
}
+ // Check if option is Microsoft style instead of RFC compliant, issue #113
+
+ // User-class options are, according to RFC3004, supposed to contain a set
+ // of strings each with length UC_Len_i. Here we check that this is so,
+ // by seeing if all the UC_Len_i lengths are consistent with the overall
+ // option length. If the lengths don't add up, we assume that the option
+ // is a single string and non RFC3004 compliant
+ var counting int
+ for counting < totalLength {
+ // UC_Len_i does not include itself so add 1
+ counting += int(data[counting]) + 1
+ }
+ if counting != totalLength {
+ opt.UserClasses = append(opt.UserClasses, data[:totalLength])
+ return &opt, nil
+ }
+ opt.Rfc3004 = true
for i := 0; i < totalLength; {
ucLen := int(data[i])
if ucLen == 0 {