diff options
-rw-r--r-- | dhcpv6/dhcpv6message.go | 11 | ||||
-rw-r--r-- | dhcpv6/option_archtype.go | 83 | ||||
-rw-r--r-- | dhcpv6/options.go | 2 |
3 files changed, 87 insertions, 9 deletions
diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go index 8368d6c..cd8ff61 100644 --- a/dhcpv6/dhcpv6message.go +++ b/dhcpv6/dhcpv6message.go @@ -152,15 +152,8 @@ func NewRequestFromAdvertise(advertise DHCPv6) (DHCPv6, error) { }, } req.AddOption(&nii) - // add OPTION_CLIENT_ARCH_TYPE - // TODO implement OptionClientArchType - cat := OptionGeneric{ - OptionCode: OPTION_CLIENT_ARCH_TYPE, - OptionData: []byte{ - 0, // Intel - see rfc4578 - 7, // EFI BC - }, - } + cat := OptClientArchType{} + cat.SetArchType(EFI_BC) req.AddOption(&cat) // add OPTION_VENDOR_CLASS, only if present in the original request // TODO implement OptionVendorClass diff --git a/dhcpv6/option_archtype.go b/dhcpv6/option_archtype.go new file mode 100644 index 0000000..6ed13f8 --- /dev/null +++ b/dhcpv6/option_archtype.go @@ -0,0 +1,83 @@ +package dhcpv6 + +// This module defines the OptClientArchType structure. +// https://www.ietf.org/rfc/rfc5970.txt + +import ( + "encoding/binary" + "fmt" +) + +type ArchType uint16 + +const ( + INTEL_X86PC ArchType = iota + NEC_PC98 + EFI_ITANIUM + DEC_ALPHA + ARC_X86 + INTEL_LEAN_CLIENT + EFI_IA32 + EFI_BC + EFI_XSCALE + EFI_X86_64 +) + +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", +} + +type OptClientArchType struct { + archType ArchType +} + +func (op *OptClientArchType) Code() OptionCode { + return OPTION_CLIENT_ARCH_TYPE +} + +func (op *OptClientArchType) ToBytes() []byte { + buf := make([]byte, 6) + binary.BigEndian.PutUint16(buf[0:2], uint16(OPTION_CLIENT_ARCH_TYPE)) + binary.BigEndian.PutUint16(buf[2:4], 2) + return buf +} + +func (op *OptClientArchType) ArchType() ArchType { + return op.archType +} + +func (op *OptClientArchType) SetArchType(archType ArchType) { + op.archType = archType +} + +func (op *OptClientArchType) Length() int { + return 2 +} + +func (op *OptClientArchType) String() string { + name, ok := ArchTypeToStringMap[op.archType] + if !ok { + name = "Unknown" + } + return fmt.Sprintf("OptClientArchType{archtype=%v}", name) +} + +// build an OptClientArchType structure from a sequence of bytes. +// The input data does not include option code and length bytes. +func ParseOptClientArchType(data []byte) (*OptClientArchType, error) { + opt := OptClientArchType{} + if len(data) != 2 { + return nil, fmt.Errorf("Invalid arch type data length. Expected 2 bytes, got %v", len(data)) + } + opt.archType = ArchType(binary.BigEndian.Uint16(data)) + return &opt, nil +} diff --git a/dhcpv6/options.go b/dhcpv6/options.go index 4ac5977..0268d22 100644 --- a/dhcpv6/options.go +++ b/dhcpv6/options.go @@ -94,6 +94,8 @@ func ParseOption(dataStart []byte) (Option, error) { opt, err = ParseOptRemoteId(optData) case OPTION_INTERFACE_ID: opt, err = ParseOptInterfaceId(optData) + case OPTION_CLIENT_ARCH_TYPE: + opt, err = ParseOptClientArchType(optData) default: opt = &OptionGeneric{OptionCode: code, OptionData: optData} } |