From fb66f2fcb83d61f8be27990fd4ca8634e93ccfb8 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 3 Nov 2017 15:37:07 -0700 Subject: [PATCH] Added more docs --- dhcp6/options.go | 31 ++++++++++++++++--------------- dhcp6/packet.go | 18 ++++++++++++------ dhcp6/packet_test.go | 14 +++++++------- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/dhcp6/options.go b/dhcp6/options.go index e69a6d3..662fe37 100644 --- a/dhcp6/options.go +++ b/dhcp6/options.go @@ -72,6 +72,7 @@ func MakeOption(id uint16, value []byte) *Option { // Options contains all options of a DHCPv6 packet type Options map[uint16][]*Option +// MakeOptions unmarshals individual Options and returns them in a new Options data structure func MakeOptions(bs []byte) (Options, error) { ret := make(Options) for len(bs) > 0 { @@ -88,8 +89,8 @@ func MakeOptions(bs []byte) (Options, error) { // UnmarshalOption de-serializes an Option func UnmarshalOption(bs []byte) (*Option, error) { optionLength := uint16(binary.BigEndian.Uint16(bs[2:4])) - optionId := uint16(binary.BigEndian.Uint16(bs[0:2])) - switch optionId { + optionID := uint16(binary.BigEndian.Uint16(bs[0:2])) + switch optionID { // parse client_id // parse server_id //parse ipaddr @@ -99,36 +100,36 @@ func UnmarshalOption(bs []byte) (*Option, error) { } default: 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:])) - return nil, fmt.Errorf("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 &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 func (o Options) HumanReadable() []string { - to_ret := make([]string, 0, len(o)) + ret := make([]string, 0, len(o)) for _, multipleOptions := range(o) { for _, option := range(multipleOptions) { switch option.ID { case 3: - to_ret = append(to_ret, o.humanReadableIaNa(*option)...) + ret = append(ret, o.humanReadableIaNa(*option)...) 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 { - to_ret := make([]string, 0) - to_ret = append(to_ret, fmt.Sprintf("Option: OptIaNa | len %d | iaid %x | t1 %d | t2 %d\n", + ret := make([]string, 0) + 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]))) if opt.Length <= 12 { - return to_ret // no options + return ret // no options } iaOptions := opt.Value[12:] @@ -141,17 +142,17 @@ func (o Options) humanReadableIaNa(opt Option) []string { case OptIaAddr: ip := make(net.IP, 16) 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])) 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])) } iaOptions = iaOptions[4+l:] } - return to_ret + return ret } // AddOption adds an option to Options diff --git a/dhcp6/packet.go b/dhcp6/packet.go index 9cc8f49..529d150 100644 --- a/dhcp6/packet.go +++ b/dhcp6/packet.go @@ -5,8 +5,10 @@ import ( "bytes" ) +// MessageType contains ID identifying DHCP message type. See RFC 3315 type MessageType uint8 +// Constants for each of the dhcp message types defined in RFC 3315 const ( MsgSolicit MessageType = iota + 1 MsgAdvertise @@ -23,12 +25,14 @@ const ( MsgRelayRepl ) +// Packet represents a DHCPv6 packet type Packet struct { Type MessageType TransactionID [3]byte Options Options } +// MakePacket creates a Packet out of its serialized representation func MakePacket(bs []byte, packetLength int) (*Packet, error) { options, err := MakeOptions(bs[4:packetLength]) if err != nil { @@ -39,6 +43,7 @@ func MakePacket(bs []byte, packetLength int) (*Packet, error) { return ret, nil } +// Marshal serializes the Packet func (p *Packet) Marshal() ([]byte, error) { marshalledOptions, err := p.Options.Marshal() if err != nil { @@ -53,14 +58,15 @@ func (p *Packet) Marshal() ([]byte, error) { return ret, nil } +// ShouldDiscard returns true if the Packet fails validation func (p *Packet) ShouldDiscard(serverDuid []byte) error { switch p.Type { case MsgSolicit: - return ShouldDiscardSolicit(p) + return shouldDiscardSolicit(p) case MsgRequest: - return ShouldDiscardRequest(p, serverDuid) + return shouldDiscardRequest(p, serverDuid) case MsgInformationRequest: - return ShouldDiscardInformationRequest(p, serverDuid) + return shouldDiscardInformationRequest(p, serverDuid) case MsgRelease: return nil // FIX ME! 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 if !options.HasBootFileURLOption() { return fmt.Errorf("'Solicit' packet doesn't have file url option") @@ -82,7 +88,7 @@ func ShouldDiscardSolicit(p *Packet) error { return nil } -func ShouldDiscardRequest(p *Packet, serverDuid []byte) error { +func shouldDiscardRequest(p *Packet, serverDuid []byte) error { options := p.Options if !options.HasBootFileURLOption() { return fmt.Errorf("'Request' packet doesn't have file url option") @@ -99,7 +105,7 @@ func ShouldDiscardRequest(p *Packet, serverDuid []byte) error { return nil } -func ShouldDiscardInformationRequest(p *Packet, serverDuid []byte) error { +func shouldDiscardInformationRequest(p *Packet, serverDuid []byte) error { options := p.Options if !options.HasBootFileURLOption() { return fmt.Errorf("'Information-request' packet doesn't have boot file url option") diff --git a/dhcp6/packet_test.go b/dhcp6/packet_test.go index e5db49c..fdc46d2 100644 --- a/dhcp6/packet_test.go +++ b/dhcp6/packet_test.go @@ -11,7 +11,7 @@ func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) { options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID}) 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") } } @@ -21,7 +21,7 @@ func TestShouldDiscardSolicitWithoutClientIdOption(t *testing.T) { options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL})) 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") } } @@ -35,7 +35,7 @@ func TestShouldDiscardSolicitWithServerIdOption(t *testing.T) { options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID}) 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") } } @@ -48,7 +48,7 @@ func TestShouldDiscardRequestWithoutBootfileUrlOption(t *testing.T) { options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID}) 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") } } @@ -60,7 +60,7 @@ func TestShouldDiscardRequestWithoutClientIdOption(t *testing.T) { options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID}) 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") } } @@ -72,7 +72,7 @@ func TestShouldDiscardRequestWithoutServerIdOption(t *testing.T) { options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID}) 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") } } @@ -86,7 +86,7 @@ func TestShouldDiscardRequestWithWrongServerId(t *testing.T) { options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID}) 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") } }