1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
package bsdp
import (
"fmt"
"net"
"github.com/insomniacslk/dhcp/dhcpv4"
)
// VendorOptions is like dhcpv4.Options, but stringifies using BSDP-specific
// option codes.
type VendorOptions struct {
dhcpv4.Options
}
// String prints the contained options using BSDP-specific option code parsing.
func (v VendorOptions) String() string {
return v.Options.ToString(bsdpHumanizer)
}
// FromBytes parses vendor options from
func (v *VendorOptions) FromBytes(data []byte) error {
v.Options = make(dhcpv4.Options)
return v.Options.FromBytes(data)
}
// DefaultBootImageID returns the default boot image ID in v.
func (v VendorOptions) DefaultBootImageID() *BootImageID {
return getBootImageID(OptionDefaultBootImageID, v.Options)
}
// SelectedBootImageID returns the selected boot image ID in v.
func (v VendorOptions) SelectedBootImageID() *BootImageID {
return getBootImageID(OptionSelectedBootImageID, v.Options)
}
// BootImageList returns the BSDP boot image list in v.
func (v VendorOptions) BootImageList() BootImageList {
val := v.Options.Get(OptionBootImageList)
if val == nil {
return nil
}
var bil BootImageList
if err := bil.FromBytes(val); err != nil {
return nil
}
return bil
}
// MessageType returns the BSDP Message Type in v.
func (v VendorOptions) MessageType() MessageType {
val := v.Options.Get(OptionMessageType)
if val == nil {
return MessageTypeNone
}
var m MessageType
if err := m.FromBytes(val); err != nil {
return MessageTypeNone
}
return m
}
// GetVersion returns the BSDP version in v if present.
func (v VendorOptions) Version() (Version, error) {
val := v.Options.Get(OptionVersion)
if val == nil {
return Version{0, 0}, fmt.Errorf("version not found")
}
var ver Version
if err := ver.FromBytes(val); err != nil {
return Version{0, 0}, err
}
return ver, nil
}
// GetServerIdentifier returns the BSDP Server Identifier value in v if present.
func (v VendorOptions) ServerIdentifier() net.IP {
return dhcpv4.GetIP(OptionServerIdentifier, v.Options)
}
// GetReplyPort returns the BSDP reply port in v if present.
func (v VendorOptions) ReplyPort() (uint16, error) {
return dhcpv4.GetUint16(OptionReplyPort, v.Options)
}
// GetServerPriority returns the BSDP server priority in v if present.
func (v VendorOptions) ServerPriority() (uint16, error) {
return dhcpv4.GetUint16(OptionServerPriority, v.Options)
}
// GetMachineName finds and parses the BSDP Machine Name option from v.
func (v VendorOptions) MachineName() string {
return dhcpv4.GetString(OptionMachineName, v.Options)
}
// OptVendorOptions returns the BSDP Vendor Specific Info in o.
func OptVendorOptions(o ...dhcpv4.Option) dhcpv4.Option {
return dhcpv4.Option{
Code: dhcpv4.OptionVendorSpecificInformation,
Value: VendorOptions{dhcpv4.OptionsFromList(o...)},
}
}
// GetVendorOptions returns a new BSDP Vendor Specific Info option.
func GetVendorOptions(o dhcpv4.Options) *VendorOptions {
v := o.Get(dhcpv4.OptionVendorSpecificInformation)
if v == nil {
return nil
}
var vo VendorOptions
if err := vo.FromBytes(v); err != nil {
return nil
}
return &vo
}
var bsdpHumanizer = dhcpv4.OptionHumanizer{
ValueHumanizer: parseOption,
CodeHumanizer: func(c uint8) dhcpv4.OptionCode {
return optionCode(c)
},
}
// parseOption is similar to dhcpv4.parseOption, except that it interprets
// option codes based on the BSDP-specific options.
func parseOption(code dhcpv4.OptionCode, data []byte) fmt.Stringer {
var d dhcpv4.OptionDecoder
switch code {
case OptionMachineName:
var s dhcpv4.String
d = &s
case OptionServerIdentifier:
d = &dhcpv4.IP{}
case OptionServerPriority, OptionReplyPort:
var u dhcpv4.Uint16
d = &u
case OptionBootImageList:
d = &BootImageList{}
case OptionDefaultBootImageID, OptionSelectedBootImageID:
d = &BootImageID{}
case OptionMessageType:
var m MessageType
d = &m
case OptionVersion:
d = &Version{}
}
if d != nil && d.FromBytes(data) == nil {
return d
}
return dhcpv4.OptionGeneric{Data: data}
}
|