mirror of
https://github.com/danderson/netboot.git
synced 2025-08-12 09:37:12 +02:00
Added more docs
This commit is contained in:
parent
13846a9809
commit
fb66f2fcb8
@ -72,6 +72,7 @@ func MakeOption(id uint16, value []byte) *Option {
|
|||||||
// Options contains all options of a DHCPv6 packet
|
// Options contains all options of a DHCPv6 packet
|
||||||
type Options map[uint16][]*Option
|
type Options map[uint16][]*Option
|
||||||
|
|
||||||
|
// MakeOptions unmarshals individual Options and returns them in a new Options data structure
|
||||||
func MakeOptions(bs []byte) (Options, error) {
|
func MakeOptions(bs []byte) (Options, error) {
|
||||||
ret := make(Options)
|
ret := make(Options)
|
||||||
for len(bs) > 0 {
|
for len(bs) > 0 {
|
||||||
@ -88,8 +89,8 @@ func MakeOptions(bs []byte) (Options, error) {
|
|||||||
// UnmarshalOption de-serializes an Option
|
// UnmarshalOption de-serializes an Option
|
||||||
func UnmarshalOption(bs []byte) (*Option, error) {
|
func UnmarshalOption(bs []byte) (*Option, error) {
|
||||||
optionLength := uint16(binary.BigEndian.Uint16(bs[2:4]))
|
optionLength := uint16(binary.BigEndian.Uint16(bs[2:4]))
|
||||||
optionId := uint16(binary.BigEndian.Uint16(bs[0:2]))
|
optionID := uint16(binary.BigEndian.Uint16(bs[0:2]))
|
||||||
switch optionId {
|
switch optionID {
|
||||||
// parse client_id
|
// parse client_id
|
||||||
// parse server_id
|
// parse server_id
|
||||||
//parse ipaddr
|
//parse ipaddr
|
||||||
@ -99,36 +100,36 @@ func UnmarshalOption(bs []byte) (*Option, error) {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if len(bs[4:]) < int(optionLength) {
|
if len(bs[4:]) < int(optionLength) {
|
||||||
fmt.Printf("option %d claims to have %d bytes of payload, but only has %d bytes", optionId, optionLength, len(bs[4:]))
|
fmt.Printf("option %d claims to have %d bytes of payload, but only has %d bytes", optionID, optionLength, len(bs[4:]))
|
||||||
return nil, fmt.Errorf("option %d claims to have %d bytes of payload, but only has %d bytes", optionId, optionLength, len(bs[4:]))
|
return nil, fmt.Errorf("option %d claims to have %d bytes of payload, but only has %d bytes", optionID, optionLength, len(bs[4:]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Option{ ID: optionId, Length: optionLength, Value: bs[4 : 4+optionLength]}, nil
|
return &Option{ ID: optionID, Length: optionLength, Value: bs[4 : 4+optionLength]}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HumanReadable presents DHCPv6 options in a human-readable form
|
// HumanReadable presents DHCPv6 options in a human-readable form
|
||||||
func (o Options) HumanReadable() []string {
|
func (o Options) HumanReadable() []string {
|
||||||
to_ret := make([]string, 0, len(o))
|
ret := make([]string, 0, len(o))
|
||||||
for _, multipleOptions := range(o) {
|
for _, multipleOptions := range(o) {
|
||||||
for _, option := range(multipleOptions) {
|
for _, option := range(multipleOptions) {
|
||||||
switch option.ID {
|
switch option.ID {
|
||||||
case 3:
|
case 3:
|
||||||
to_ret = append(to_ret, o.humanReadableIaNa(*option)...)
|
ret = append(ret, o.humanReadableIaNa(*option)...)
|
||||||
default:
|
default:
|
||||||
to_ret = append(to_ret, fmt.Sprintf("Option: %d | %d | %d | %s\n", option.ID, option.Length, option.Value, option.Value))
|
ret = append(ret, fmt.Sprintf("Option: %d | %d | %d | %s\n", option.ID, option.Length, option.Value, option.Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return to_ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) humanReadableIaNa(opt Option) []string {
|
func (o Options) humanReadableIaNa(opt Option) []string {
|
||||||
to_ret := make([]string, 0)
|
ret := make([]string, 0)
|
||||||
to_ret = append(to_ret, fmt.Sprintf("Option: OptIaNa | len %d | iaid %x | t1 %d | t2 %d\n",
|
ret = append(ret, fmt.Sprintf("Option: OptIaNa | len %d | iaid %x | t1 %d | t2 %d\n",
|
||||||
opt.Length, opt.Value[0:4], binary.BigEndian.Uint32(opt.Value[4:8]), binary.BigEndian.Uint32(opt.Value[8:12])))
|
opt.Length, opt.Value[0:4], binary.BigEndian.Uint32(opt.Value[4:8]), binary.BigEndian.Uint32(opt.Value[8:12])))
|
||||||
|
|
||||||
if opt.Length <= 12 {
|
if opt.Length <= 12 {
|
||||||
return to_ret // no options
|
return ret // no options
|
||||||
}
|
}
|
||||||
|
|
||||||
iaOptions := opt.Value[12:]
|
iaOptions := opt.Value[12:]
|
||||||
@ -141,17 +142,17 @@ func (o Options) humanReadableIaNa(opt Option) []string {
|
|||||||
case OptIaAddr:
|
case OptIaAddr:
|
||||||
ip := make(net.IP, 16)
|
ip := make(net.IP, 16)
|
||||||
copy(ip, iaOptions[4:20])
|
copy(ip, iaOptions[4:20])
|
||||||
to_ret = append(to_ret, fmt.Sprintf("\tOption: IA_ADDR | len %d | ip %s | preferred %d | valid %d | %v \n",
|
ret = append(ret, fmt.Sprintf("\tOption: IA_ADDR | len %d | ip %s | preferred %d | valid %d | %v \n",
|
||||||
l, ip, binary.BigEndian.Uint32(iaOptions[20:24]), binary.BigEndian.Uint32(iaOptions[24:28]), iaOptions[28:4+l]))
|
l, ip, binary.BigEndian.Uint32(iaOptions[20:24]), binary.BigEndian.Uint32(iaOptions[24:28]), iaOptions[28:4+l]))
|
||||||
default:
|
default:
|
||||||
to_ret = append(to_ret, fmt.Sprintf("\tOption: id %d | len %d | %s\n",
|
ret = append(ret, fmt.Sprintf("\tOption: id %d | len %d | %s\n",
|
||||||
id, l, iaOptions[4:4+l]))
|
id, l, iaOptions[4:4+l]))
|
||||||
}
|
}
|
||||||
|
|
||||||
iaOptions = iaOptions[4+l:]
|
iaOptions = iaOptions[4+l:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return to_ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddOption adds an option to Options
|
// AddOption adds an option to Options
|
||||||
|
@ -5,8 +5,10 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MessageType contains ID identifying DHCP message type. See RFC 3315
|
||||||
type MessageType uint8
|
type MessageType uint8
|
||||||
|
|
||||||
|
// Constants for each of the dhcp message types defined in RFC 3315
|
||||||
const (
|
const (
|
||||||
MsgSolicit MessageType = iota + 1
|
MsgSolicit MessageType = iota + 1
|
||||||
MsgAdvertise
|
MsgAdvertise
|
||||||
@ -23,12 +25,14 @@ const (
|
|||||||
MsgRelayRepl
|
MsgRelayRepl
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Packet represents a DHCPv6 packet
|
||||||
type Packet struct {
|
type Packet struct {
|
||||||
Type MessageType
|
Type MessageType
|
||||||
TransactionID [3]byte
|
TransactionID [3]byte
|
||||||
Options Options
|
Options Options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakePacket creates a Packet out of its serialized representation
|
||||||
func MakePacket(bs []byte, packetLength int) (*Packet, error) {
|
func MakePacket(bs []byte, packetLength int) (*Packet, error) {
|
||||||
options, err := MakeOptions(bs[4:packetLength])
|
options, err := MakeOptions(bs[4:packetLength])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -39,6 +43,7 @@ func MakePacket(bs []byte, packetLength int) (*Packet, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshal serializes the Packet
|
||||||
func (p *Packet) Marshal() ([]byte, error) {
|
func (p *Packet) Marshal() ([]byte, error) {
|
||||||
marshalledOptions, err := p.Options.Marshal()
|
marshalledOptions, err := p.Options.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -53,14 +58,15 @@ func (p *Packet) Marshal() ([]byte, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShouldDiscard returns true if the Packet fails validation
|
||||||
func (p *Packet) ShouldDiscard(serverDuid []byte) error {
|
func (p *Packet) ShouldDiscard(serverDuid []byte) error {
|
||||||
switch p.Type {
|
switch p.Type {
|
||||||
case MsgSolicit:
|
case MsgSolicit:
|
||||||
return ShouldDiscardSolicit(p)
|
return shouldDiscardSolicit(p)
|
||||||
case MsgRequest:
|
case MsgRequest:
|
||||||
return ShouldDiscardRequest(p, serverDuid)
|
return shouldDiscardRequest(p, serverDuid)
|
||||||
case MsgInformationRequest:
|
case MsgInformationRequest:
|
||||||
return ShouldDiscardInformationRequest(p, serverDuid)
|
return shouldDiscardInformationRequest(p, serverDuid)
|
||||||
case MsgRelease:
|
case MsgRelease:
|
||||||
return nil // FIX ME!
|
return nil // FIX ME!
|
||||||
default:
|
default:
|
||||||
@ -68,7 +74,7 @@ func (p *Packet) ShouldDiscard(serverDuid []byte) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ShouldDiscardSolicit(p *Packet) error {
|
func shouldDiscardSolicit(p *Packet) error {
|
||||||
options := p.Options
|
options := p.Options
|
||||||
if !options.HasBootFileURLOption() {
|
if !options.HasBootFileURLOption() {
|
||||||
return fmt.Errorf("'Solicit' packet doesn't have file url option")
|
return fmt.Errorf("'Solicit' packet doesn't have file url option")
|
||||||
@ -82,7 +88,7 @@ func ShouldDiscardSolicit(p *Packet) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ShouldDiscardRequest(p *Packet, serverDuid []byte) error {
|
func shouldDiscardRequest(p *Packet, serverDuid []byte) error {
|
||||||
options := p.Options
|
options := p.Options
|
||||||
if !options.HasBootFileURLOption() {
|
if !options.HasBootFileURLOption() {
|
||||||
return fmt.Errorf("'Request' packet doesn't have file url option")
|
return fmt.Errorf("'Request' packet doesn't have file url option")
|
||||||
@ -99,7 +105,7 @@ func ShouldDiscardRequest(p *Packet, serverDuid []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ShouldDiscardInformationRequest(p *Packet, serverDuid []byte) error {
|
func shouldDiscardInformationRequest(p *Packet, serverDuid []byte) error {
|
||||||
options := p.Options
|
options := p.Options
|
||||||
if !options.HasBootFileURLOption() {
|
if !options.HasBootFileURLOption() {
|
||||||
return fmt.Errorf("'Information-request' packet doesn't have boot file url option")
|
return fmt.Errorf("'Information-request' packet doesn't have boot file url option")
|
||||||
|
@ -11,7 +11,7 @@ func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) {
|
|||||||
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
||||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
if err := shouldDiscardSolicit(solicit); err == nil {
|
||||||
t.Fatalf("Should discard solicit packet without bootfile url option, but didn't")
|
t.Fatalf("Should discard solicit packet without bootfile url option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ func TestShouldDiscardSolicitWithoutClientIdOption(t *testing.T) {
|
|||||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL}))
|
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL}))
|
||||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
if err := shouldDiscardSolicit(solicit); err == nil {
|
||||||
t.Fatalf("Should discard solicit packet without client id option, but didn't")
|
t.Fatalf("Should discard solicit packet without client id option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ func TestShouldDiscardSolicitWithServerIdOption(t *testing.T) {
|
|||||||
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
if err := shouldDiscardSolicit(solicit); err == nil {
|
||||||
t.Fatalf("Should discard solicit packet with server id option, but didn't")
|
t.Fatalf("Should discard solicit packet with server id option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ func TestShouldDiscardRequestWithoutBootfileUrlOption(t *testing.T) {
|
|||||||
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, serverID); err == nil {
|
if err := shouldDiscardRequest(request, serverID); err == nil {
|
||||||
t.Fatalf("Should discard request packet without bootfile url option, but didn't")
|
t.Fatalf("Should discard request packet without bootfile url option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ func TestShouldDiscardRequestWithoutClientIdOption(t *testing.T) {
|
|||||||
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, serverID); err == nil {
|
if err := shouldDiscardRequest(request, serverID); err == nil {
|
||||||
t.Fatalf("Should discard request packet without client id option, but didn't")
|
t.Fatalf("Should discard request packet without client id option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ func TestShouldDiscardRequestWithoutServerIdOption(t *testing.T) {
|
|||||||
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, []byte("serverid")); err == nil {
|
if err := shouldDiscardRequest(request, []byte("serverid")); err == nil {
|
||||||
t.Fatalf("Should discard request packet with server id option, but didn't")
|
t.Fatalf("Should discard request packet with server id option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func TestShouldDiscardRequestWithWrongServerId(t *testing.T) {
|
|||||||
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, []byte("wrongid")); err == nil {
|
if err := shouldDiscardRequest(request, []byte("wrongid")); err == nil {
|
||||||
t.Fatalf("Should discard request packet with wrong server id option, but didn't")
|
t.Fatalf("Should discard request packet with wrong server id option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user