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}
}
|