diff options
Diffstat (limited to 'dhcpv6')
-rw-r--r-- | dhcpv6/client6/client.go | 6 | ||||
-rw-r--r-- | dhcpv6/dhcpv6.go | 16 | ||||
-rw-r--r-- | dhcpv6/dhcpv6_test.go | 66 | ||||
-rw-r--r-- | dhcpv6/dhcpv6message.go | 84 | ||||
-rw-r--r-- | dhcpv6/dhcpv6message_test.go | 10 | ||||
-rw-r--r-- | dhcpv6/dhcpv6relay.go | 81 | ||||
-rw-r--r-- | dhcpv6/dhcpv6relay_test.go | 20 | ||||
-rw-r--r-- | dhcpv6/iputils.go | 4 | ||||
-rw-r--r-- | dhcpv6/modifiers.go | 4 | ||||
-rw-r--r-- | dhcpv6/modifiers_test.go | 6 | ||||
-rw-r--r-- | dhcpv6/option_relaymsg_test.go | 10 |
11 files changed, 165 insertions, 142 deletions
diff --git a/dhcpv6/client6/client.go b/dhcpv6/client6/client.go index 4075bde..c5b522d 100644 --- a/dhcpv6/client6/client.go +++ b/dhcpv6/client6/client.go @@ -59,7 +59,7 @@ func (c *Client) Exchange(ifname string, modifiers ...dhcpv6.Modifier) ([]dhcpv6 // Decapsulate advertise if it's relayed before passing it to Request if advertise.IsRelay() { - advertiseRelay := advertise.(*dhcpv6.DHCPv6Relay) + advertiseRelay := advertise.(*dhcpv6.RelayMessage) advertise, err = advertiseRelay.GetInnerMessage() if err != nil { return conversation, err @@ -153,7 +153,7 @@ func (c *Client) sendReceive(ifname string, packet dhcpv6.DHCPv6, expectedType d isMessage bool ) defer conn.Close() - msg, ok := packet.(*dhcpv6.DHCPv6Message) + msg, ok := packet.(*dhcpv6.Message) if ok { isMessage = true } @@ -168,7 +168,7 @@ func (c *Client) sendReceive(ifname string, packet dhcpv6.DHCPv6, expectedType d // skip non-DHCP packets continue } - if recvMsg, ok := adv.(*dhcpv6.DHCPv6Message); ok && isMessage { + if recvMsg, ok := adv.(*dhcpv6.Message); ok && isMessage { // if a regular message, check the transaction ID first // XXX should this unpack relay messages and check the XID of the // inner packet too? diff --git a/dhcpv6/dhcpv6.go b/dhcpv6/dhcpv6.go index 7eaf621..79ae299 100644 --- a/dhcpv6/dhcpv6.go +++ b/dhcpv6/dhcpv6.go @@ -33,7 +33,7 @@ func FromBytes(data []byte) (DHCPv6, error) { messageType := MessageType(buf.Read8()) if messageType == MessageTypeRelayForward || messageType == MessageTypeRelayReply { - d := DHCPv6Relay{ + d := RelayMessage{ messageType: messageType, hopCount: buf.Read8(), } @@ -46,7 +46,7 @@ func FromBytes(data []byte) (DHCPv6, error) { } return &d, nil } else { - d := DHCPv6Message{ + d := Message{ messageType: messageType, } buf.ReadBytes(d.transactionID[:]) @@ -63,7 +63,7 @@ func NewMessage(modifiers ...Modifier) (DHCPv6, error) { if err != nil { return nil, err } - msg := DHCPv6Message{ + msg := Message{ messageType: MessageTypeSolicit, transactionID: tid, } @@ -125,20 +125,20 @@ func DecapsulateRelayIndex(l DHCPv6, index int) (DHCPv6, error) { return l, nil } -// EncapsulateRelay creates a DHCPv6Relay message containing the passed DHCPv6 +// EncapsulateRelay creates a RelayMessage message containing the passed DHCPv6 // message as payload. The passed message type must be either RELAY_FORW or // RELAY_REPL func EncapsulateRelay(d DHCPv6, mType MessageType, linkAddr, peerAddr net.IP) (DHCPv6, error) { if mType != MessageTypeRelayForward && mType != MessageTypeRelayReply { return nil, fmt.Errorf("Message type must be either RELAY_FORW or RELAY_REPL") } - outer := DHCPv6Relay{ + outer := RelayMessage{ messageType: mType, linkAddr: linkAddr, peerAddr: peerAddr, } if d.IsRelay() { - relay := d.(*DHCPv6Relay) + relay := d.(*RelayMessage) outer.hopCount = relay.hopCount + 1 } else { outer.hopCount = 0 @@ -189,10 +189,10 @@ func IsUsingUEFI(msg DHCPv6) bool { // GetTransactionID returns a transactionID of a message or its inner message // in case of relay func GetTransactionID(packet DHCPv6) (TransactionID, error) { - if message, ok := packet.(*DHCPv6Message); ok { + if message, ok := packet.(*Message); ok { return message.TransactionID(), nil } - if relay, ok := packet.(*DHCPv6Relay); ok { + if relay, ok := packet.(*RelayMessage); ok { message, err := relay.GetInnerMessage() if err != nil { return TransactionID{0, 0, 0}, err diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go index 81d7ad1..f33f0e9 100644 --- a/dhcpv6/dhcpv6_test.go +++ b/dhcpv6/dhcpv6_test.go @@ -63,12 +63,12 @@ func TestNewMessage(t *testing.T) { require.NoError(t, err) require.NotNil(t, d) require.Equal(t, MessageTypeSolicit, d.Type()) - require.NotEqual(t, 0, d.(*DHCPv6Message).transactionID) - require.Empty(t, d.(*DHCPv6Message).options) + require.NotEqual(t, 0, d.(*Message).transactionID) + require.Empty(t, d.(*Message).options) } func TestDecapsulateRelayIndex(t *testing.T) { - m := DHCPv6Message{} + m := Message{} r1, err := EncapsulateRelay(&m, MessageTypeRelayForward, net.IPv6linklocalallnodes, net.IPv6interfacelocalallnodes) require.NoError(t, err) r2, err := EncapsulateRelay(r1, MessageTypeRelayForward, net.IPv6loopback, net.IPv6linklocalallnodes) @@ -78,7 +78,7 @@ func TestDecapsulateRelayIndex(t *testing.T) { first, err := DecapsulateRelayIndex(r3, 0) require.NoError(t, err) - relay, ok := first.(*DHCPv6Relay) + relay, ok := first.(*RelayMessage) require.True(t, ok) require.Equal(t, relay.HopCount(), uint8(1)) require.Equal(t, relay.LinkAddr(), net.IPv6loopback) @@ -86,7 +86,7 @@ func TestDecapsulateRelayIndex(t *testing.T) { second, err := DecapsulateRelayIndex(r3, 1) require.NoError(t, err) - relay, ok = second.(*DHCPv6Relay) + relay, ok = second.(*RelayMessage) require.True(t, ok) require.Equal(t, relay.HopCount(), uint8(0)) require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) @@ -94,12 +94,12 @@ func TestDecapsulateRelayIndex(t *testing.T) { third, err := DecapsulateRelayIndex(r3, 2) require.NoError(t, err) - _, ok = third.(*DHCPv6Message) + _, ok = third.(*Message) require.True(t, ok) rfirst, err := DecapsulateRelayIndex(r3, -1) require.NoError(t, err) - relay, ok = rfirst.(*DHCPv6Relay) + relay, ok = rfirst.(*RelayMessage) require.True(t, ok) require.Equal(t, relay.HopCount(), uint8(0)) require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) @@ -110,7 +110,7 @@ func TestDecapsulateRelayIndex(t *testing.T) { } func TestSettersAndGetters(t *testing.T) { - d := DHCPv6Message{} + d := Message{} // Message d.SetMessage(MessageTypeSolicit) require.Equal(t, MessageTypeSolicit, d.Type()) @@ -130,7 +130,7 @@ func TestSettersAndGetters(t *testing.T) { } func TestAddOption(t *testing.T) { - d := DHCPv6Message{} + d := Message{} require.Empty(t, d.Options()) opt := OptionGeneric{OptionCode: 0, OptionData: []byte{}} d.AddOption(&opt) @@ -138,7 +138,7 @@ func TestAddOption(t *testing.T) { } func TestToBytes(t *testing.T) { - d := DHCPv6Message{} + d := Message{} d.SetMessage(MessageTypeSolicit) d.SetTransactionID(TransactionID{0xa, 0xb, 0xc}) d.AddOption(&OptionGeneric{OptionCode: 0, OptionData: []byte{}}) @@ -157,7 +157,7 @@ func TestFromAndToBytes(t *testing.T) { } func TestNewAdvertiseFromSolicit(t *testing.T) { - s := DHCPv6Message{} + s := Message{} s.SetMessage(MessageTypeSolicit) xid := TransactionID{0xa, 0xb, 0xc} s.SetTransactionID(xid) @@ -167,12 +167,12 @@ func TestNewAdvertiseFromSolicit(t *testing.T) { a, err := NewAdvertiseFromSolicit(&s, WithServerID(duid)) require.NoError(t, err) - require.Equal(t, a.(*DHCPv6Message).TransactionID(), s.TransactionID()) + require.Equal(t, a.(*Message).TransactionID(), s.TransactionID()) require.Equal(t, a.Type(), MessageTypeAdvertise) } -func TestNewReplyFromDHCPv6Message(t *testing.T) { - msg := DHCPv6Message{} +func TestNewReplyFromMessage(t *testing.T) { + msg := Message{} xid := TransactionID{0xa, 0xb, 0xc} msg.SetTransactionID(xid) cid := OptClientId{} @@ -183,41 +183,41 @@ func TestNewReplyFromDHCPv6Message(t *testing.T) { msg.AddOption(&sid) msg.SetMessage(MessageTypeConfirm) - rep, err := NewReplyFromDHCPv6Message(&msg, WithServerID(duid)) + rep, err := NewReplyFromMessage(&msg, WithServerID(duid)) require.NoError(t, err) - require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID()) + require.Equal(t, rep.(*Message).TransactionID(), msg.TransactionID()) require.Equal(t, rep.Type(), MessageTypeReply) msg.SetMessage(MessageTypeRenew) - rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid)) + rep, err = NewReplyFromMessage(&msg, WithServerID(duid)) require.NoError(t, err) - require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID()) + require.Equal(t, rep.(*Message).TransactionID(), msg.TransactionID()) require.Equal(t, rep.Type(), MessageTypeReply) msg.SetMessage(MessageTypeRebind) - rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid)) + rep, err = NewReplyFromMessage(&msg, WithServerID(duid)) require.NoError(t, err) - require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID()) + require.Equal(t, rep.(*Message).TransactionID(), msg.TransactionID()) require.Equal(t, rep.Type(), MessageTypeReply) msg.SetMessage(MessageTypeRelease) - rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid)) + rep, err = NewReplyFromMessage(&msg, WithServerID(duid)) require.NoError(t, err) - require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID()) + require.Equal(t, rep.(*Message).TransactionID(), msg.TransactionID()) require.Equal(t, rep.Type(), MessageTypeReply) msg.SetMessage(MessageTypeInformationRequest) - rep, err = NewReplyFromDHCPv6Message(&msg, WithServerID(duid)) + rep, err = NewReplyFromMessage(&msg, WithServerID(duid)) require.NoError(t, err) - require.Equal(t, rep.(*DHCPv6Message).TransactionID(), msg.TransactionID()) + require.Equal(t, rep.(*Message).TransactionID(), msg.TransactionID()) require.Equal(t, rep.Type(), MessageTypeReply) msg.SetMessage(MessageTypeSolicit) - rep, err = NewReplyFromDHCPv6Message(&msg) + rep, err = NewReplyFromMessage(&msg) require.Error(t, err) - relay := DHCPv6Relay{} - rep, err = NewReplyFromDHCPv6Message(&relay) + relay := RelayMessage{} + rep, err = NewReplyFromMessage(&relay) require.Error(t, err) } @@ -254,28 +254,28 @@ func TestNewMessageTypeSolicitWithCID(t *testing.T) { } func TestIsUsingUEFIArchTypeTrue(t *testing.T) { - msg := DHCPv6Message{} + msg := Message{} opt := OptClientArchType{ArchTypes: []iana.Arch{iana.EFI_BC}} msg.AddOption(&opt) require.True(t, IsUsingUEFI(&msg)) } func TestIsUsingUEFIArchTypeFalse(t *testing.T) { - msg := DHCPv6Message{} + msg := Message{} opt := OptClientArchType{ArchTypes: []iana.Arch{iana.INTEL_X86PC}} msg.AddOption(&opt) require.False(t, IsUsingUEFI(&msg)) } func TestIsUsingUEFIUserClassTrue(t *testing.T) { - msg := DHCPv6Message{} + msg := Message{} opt := OptUserClass{UserClasses: [][]byte{[]byte("ipxeUEFI")}} msg.AddOption(&opt) require.True(t, IsUsingUEFI(&msg)) } func TestIsUsingUEFIUserClassFalse(t *testing.T) { - msg := DHCPv6Message{} + msg := Message{} opt := OptUserClass{UserClasses: [][]byte{[]byte("ipxeLegacy")}} msg.AddOption(&opt) require.False(t, IsUsingUEFI(&msg)) @@ -286,7 +286,7 @@ func TestGetTransactionIDMessage(t *testing.T) { require.NoError(t, err) transactionID, err := GetTransactionID(message) require.NoError(t, err) - require.Equal(t, transactionID, message.(*DHCPv6Message).TransactionID()) + require.Equal(t, transactionID, message.(*Message).TransactionID()) } func TestGetTransactionIDRelay(t *testing.T) { @@ -296,7 +296,7 @@ func TestGetTransactionIDRelay(t *testing.T) { require.NoError(t, err) transactionID, err := GetTransactionID(relay) require.NoError(t, err) - require.Equal(t, transactionID, message.(*DHCPv6Message).TransactionID()) + require.Equal(t, transactionID, message.(*Message).TransactionID()) } // TODO test NewMessageTypeSolicit diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go index a1e439a..795e9fc 100644 --- a/dhcpv6/dhcpv6message.go +++ b/dhcpv6/dhcpv6message.go @@ -14,7 +14,8 @@ import ( const MessageHeaderSize = 4 -type DHCPv6Message struct { +// Message represents a DHCPv6 Message as defined by RFC 3315 Section 6. +type Message struct { messageType MessageType transactionID TransactionID options Options @@ -48,7 +49,7 @@ func NewSolicitWithCID(duid Duid, modifiers ...Modifier) (DHCPv6, error) { if err != nil { return nil, err } - d.(*DHCPv6Message).SetMessage(MessageTypeSolicit) + d.(*Message).SetMessage(MessageTypeSolicit) d.AddOption(&OptClientId{Cid: duid}) oro := new(OptRequestedOption) oro.SetRequestedOptions([]OptionCode{ @@ -94,12 +95,12 @@ func NewAdvertiseFromSolicit(solicit DHCPv6, modifiers ...Modifier) (DHCPv6, err if solicit.Type() != MessageTypeSolicit { return nil, errors.New("The passed SOLICIT must have SOLICIT type set") } - sol, ok := solicit.(*DHCPv6Message) + sol, ok := solicit.(*Message) if !ok { - return nil, errors.New("The passed SOLICIT must be of DHCPv6Message type") + return nil, errors.New("The passed SOLICIT must be of Message type") } // build ADVERTISE from SOLICIT - adv := DHCPv6Message{} + adv := Message{} adv.SetMessage(MessageTypeAdvertise) adv.SetTransactionID(sol.TransactionID()) // add Client ID @@ -126,12 +127,12 @@ func NewRequestFromAdvertise(advertise DHCPv6, modifiers ...Modifier) (DHCPv6, e if advertise.Type() != MessageTypeAdvertise { return nil, fmt.Errorf("The passed ADVERTISE must have ADVERTISE type set") } - adv, ok := advertise.(*DHCPv6Message) + adv, ok := advertise.(*Message) if !ok { - return nil, fmt.Errorf("The passed ADVERTISE must be of DHCPv6Message type") + return nil, fmt.Errorf("The passed ADVERTISE must be of Message type") } // build REQUEST from ADVERTISE - req := DHCPv6Message{} + req := Message{} req.SetMessage(MessageTypeRequest) req.SetTransactionID(adv.TransactionID()) // add Client ID @@ -176,12 +177,12 @@ func NewRequestFromAdvertise(advertise DHCPv6, modifiers ...Modifier) (DHCPv6, e return d, nil } -// NewReplyFromDHCPv6Message creates a new REPLY packet based on a -// DHCPv6Message. The function is to be used when generating a reply to +// NewReplyFromMessage creates a new REPLY packet based on a +// Message. The function is to be used when generating a reply to // REQUEST, CONFIRM, RENEW, REBIND, RELEASE and INFORMATION-REQUEST packets. -func NewReplyFromDHCPv6Message(message DHCPv6, modifiers ...Modifier) (DHCPv6, error) { +func NewReplyFromMessage(message DHCPv6, modifiers ...Modifier) (DHCPv6, error) { if message == nil { - return nil, errors.New("DHCPv6Message cannot be nil") + return nil, errors.New("Message cannot be nil") } switch message.Type() { case MessageTypeRequest, MessageTypeConfirm, MessageTypeRenew, @@ -189,12 +190,12 @@ func NewReplyFromDHCPv6Message(message DHCPv6, modifiers ...Modifier) (DHCPv6, e default: return nil, errors.New("Cannot create REPLY from the passed message type set") } - msg, ok := message.(*DHCPv6Message) + msg, ok := message.(*Message) if !ok { - return nil, errors.New("The passed MESSAGE must be of DHCPv6Message type") + return nil, errors.New("The passed MESSAGE must be of Message type") } // build REPLY from MESSAGE - rep := DHCPv6Message{} + rep := Message{} rep.SetMessage(MessageTypeReply) rep.SetTransactionID(msg.TransactionID()) // add Client ID @@ -212,11 +213,13 @@ func NewReplyFromDHCPv6Message(message DHCPv6, modifiers ...Modifier) (DHCPv6, e return d, nil } -func (d *DHCPv6Message) Type() MessageType { +// Type is the DHCPv6 message type. +func (d *Message) Type() MessageType { return d.messageType } -func (d *DHCPv6Message) SetMessage(messageType MessageType) { +// SetMessage sets the DHCP message type. +func (d *Message) SetMessage(messageType MessageType) { msgString := messageType.String() if msgString == "" { log.Printf("Warning: unknown DHCPv6 message type: %v", messageType) @@ -228,31 +231,29 @@ func (d *DHCPv6Message) SetMessage(messageType MessageType) { d.messageType = messageType } -func (d *DHCPv6Message) MessageTypeToString() string { - return d.messageType.String() -} - // TransactionID returns this message's transaction id. -func (d *DHCPv6Message) TransactionID() TransactionID { +func (d *Message) TransactionID() TransactionID { return d.transactionID } // SetTransactionID sets this message's transaction id. -func (d *DHCPv6Message) SetTransactionID(tid TransactionID) { +func (d *Message) SetTransactionID(tid TransactionID) { d.transactionID = tid } -func (d *DHCPv6Message) SetOptions(options []Option) { +// SetOptions replaces this message's options. +func (d *Message) SetOptions(options []Option) { d.options = options } -func (d *DHCPv6Message) AddOption(option Option) { +// AddOption adds an option to this message. +func (d *Message) AddOption(option Option) { d.options.Add(option) } // UpdateOption updates the existing options with the passed option, adding it // at the end if not present already -func (d *DHCPv6Message) UpdateOption(option Option) { +func (d *Message) UpdateOption(option Option) { d.options.Update(option) } @@ -260,7 +261,7 @@ func (d *DHCPv6Message) UpdateOption(option Option) { // "boot file" is one of the requested options, which is useful for // SOLICIT/REQUEST packet types, it also checks if the "boot file" option is // included in the packet, which is useful for ADVERTISE/REPLY packet. -func (d *DHCPv6Message) IsNetboot() bool { +func (d *Message) IsNetboot() bool { if d.IsOptionRequested(OptionBootfileURL) { return true } @@ -272,7 +273,7 @@ func (d *DHCPv6Message) IsNetboot() bool { // IsOptionRequested takes an OptionCode and returns true if that option is // within the requested options of the DHCPv6 message. -func (d *DHCPv6Message) IsOptionRequested(requested OptionCode) bool { +func (d *Message) IsOptionRequested(requested OptionCode) bool { for _, optoro := range d.GetOption(OptionORO) { for _, o := range optoro.(*OptRequestedOption).RequestedOptions() { if o == requested { @@ -283,17 +284,19 @@ func (d *DHCPv6Message) IsOptionRequested(requested OptionCode) bool { return false } -func (d *DHCPv6Message) String() string { - return fmt.Sprintf("DHCPv6Message(messageType=%v transactionID=0x%06x, %d options)", +// String returns a short human-readable string for this message. +func (d *Message) String() string { + return fmt.Sprintf("Message(messageType=%v transactionID=%s, %d options)", d.Type().String(), d.TransactionID(), len(d.options), ) } -func (d *DHCPv6Message) Summary() string { +// Summary prints all options associated with this message. +func (d *Message) Summary() string { ret := fmt.Sprintf( - "DHCPv6Message\n"+ + "Message\n"+ " messageType=%v\n"+ - " transactionid=0x%06x\n", + " transactionid=%s\n", d.Type().String(), d.TransactionID(), ) @@ -310,7 +313,7 @@ func (d *DHCPv6Message) Summary() string { // ToBytes returns the serialized version of this message as defined by RFC // 3315, Section 5. -func (d *DHCPv6Message) ToBytes() []byte { +func (d *Message) ToBytes() []byte { buf := uio.NewBigEndianBuffer(nil) buf.Write8(uint8(d.messageType)) buf.WriteBytes(d.transactionID[:]) @@ -318,18 +321,23 @@ func (d *DHCPv6Message) ToBytes() []byte { return buf.Data() } -func (d *DHCPv6Message) Options() []Option { +// Options returns the current set of options associated with this message. +func (d *Message) Options() []Option { return d.options } -func (d *DHCPv6Message) GetOption(code OptionCode) []Option { +// GetOption returns the options associated with the code. +func (d *Message) GetOption(code OptionCode) []Option { return d.options.Get(code) } -func (d *DHCPv6Message) GetOneOption(code OptionCode) Option { +// GetOneOption returns the first associated option with the code from this +// message. +func (d *Message) GetOneOption(code OptionCode) Option { return d.options.GetOne(code) } -func (d *DHCPv6Message) IsRelay() bool { +// IsRelay returns whether this is a relay message or not. +func (d *Message) IsRelay() bool { return false } diff --git a/dhcpv6/dhcpv6message_test.go b/dhcpv6/dhcpv6message_test.go index 5c92a7b..2dd4a1c 100644 --- a/dhcpv6/dhcpv6message_test.go +++ b/dhcpv6/dhcpv6message_test.go @@ -7,26 +7,26 @@ import ( ) func TestIsNetboot(t *testing.T) { - msg1 := DHCPv6Message{} + msg1 := Message{} require.False(t, msg1.IsNetboot()) - msg2 := DHCPv6Message{} + msg2 := Message{} optro := OptRequestedOption{} optro.AddRequestedOption(OptionBootfileURL) msg2.AddOption(&optro) require.True(t, msg2.IsNetboot()) - msg3 := DHCPv6Message{} + msg3 := Message{} optbf := OptBootFileURL{} msg3.AddOption(&optbf) require.True(t, msg3.IsNetboot()) } func TestIsOptionRequested(t *testing.T) { - msg1 := DHCPv6Message{} + msg1 := Message{} require.False(t, msg1.IsOptionRequested(OptionDNSRecursiveNameServer)) - msg2 := DHCPv6Message{} + msg2 := Message{} optro := OptRequestedOption{} optro.AddRequestedOption(OptionDNSRecursiveNameServer) msg2.AddOption(&optro) diff --git a/dhcpv6/dhcpv6relay.go b/dhcpv6/dhcpv6relay.go index 4a690b9..5bca431 100644 --- a/dhcpv6/dhcpv6relay.go +++ b/dhcpv6/dhcpv6relay.go @@ -10,7 +10,9 @@ import ( const RelayHeaderSize = 34 -type DHCPv6Relay struct { +// RelayMessage is a DHCPv6 relay agent message as defined by RFC 3315 Section +// 7. +type RelayMessage struct { messageType MessageType hopCount uint8 linkAddr net.IP @@ -18,25 +20,24 @@ type DHCPv6Relay struct { options Options } -func (r *DHCPv6Relay) Type() MessageType { +// Type is this relay message's types. +func (r *RelayMessage) Type() MessageType { return r.messageType } -func (r *DHCPv6Relay) MessageTypeToString() string { - return r.messageType.String() -} - -func (r *DHCPv6Relay) String() string { +// String prints a short human-readable relay message. +func (r *RelayMessage) String() string { ret := fmt.Sprintf( - "DHCPv6Relay(messageType=%v hopcount=%v, linkaddr=%v, peeraddr=%v, %d options)", + "RelayMessage(messageType=%v hopcount=%v, linkaddr=%v, peeraddr=%v, %d options)", r.Type().String(), r.hopCount, r.linkAddr, r.peerAddr, len(r.options), ) return ret } -func (r *DHCPv6Relay) Summary() string { +// Summary prints all options associated with this relay message. +func (r *RelayMessage) Summary() string { ret := fmt.Sprintf( - "DHCPv6Relay\n"+ + "RelayMessage\n"+ " messageType=%v\n"+ " hopcount=%v\n"+ " linkaddr=%v\n"+ @@ -52,8 +53,8 @@ func (r *DHCPv6Relay) Summary() string { } // ToBytes returns the serialized version of this relay message as defined by -// RFC 3315, Section 6. -func (r *DHCPv6Relay) ToBytes() []byte { +// RFC 3315, Section 7. +func (r *RelayMessage) ToBytes() []byte { buf := uio.NewBigEndianBuffer(make([]byte, 0, RelayHeaderSize)) buf.Write8(byte(r.messageType)) buf.Write8(byte(r.hopCount)) @@ -63,72 +64,86 @@ func (r *DHCPv6Relay) ToBytes() []byte { return buf.Data() } -func (r *DHCPv6Relay) SetMessageType(messageType MessageType) { +// SetMessageType sets the message type of this relay message. +func (r *RelayMessage) SetMessageType(messageType MessageType) { // not enforcing if message type is not a RELAY_FORW or a RELAY_REPL message r.messageType = messageType } -func (r *DHCPv6Relay) HopCount() uint8 { +// HopCount returns the hop count. +func (r *RelayMessage) HopCount() uint8 { return r.hopCount } -func (r *DHCPv6Relay) SetHopCount(hopCount uint8) { +// SetHopCount sets the hop count. +func (r *RelayMessage) SetHopCount(hopCount uint8) { r.hopCount = hopCount } -func (r *DHCPv6Relay) LinkAddr() net.IP { +// LinkAddr returns the link address for this relay message. +func (r *RelayMessage) LinkAddr() net.IP { return r.linkAddr } -func (r *DHCPv6Relay) SetLinkAddr(linkAddr net.IP) { +// SetLinkAddr sets the link address. +func (r *RelayMessage) SetLinkAddr(linkAddr net.IP) { r.linkAddr = linkAddr } -func (r *DHCPv6Relay) PeerAddr() net.IP { +// PeerAddr returns the peer address for this relay message. +func (r *RelayMessage) PeerAddr() net.IP { return r.peerAddr } -func (r *DHCPv6Relay) SetPeerAddr(peerAddr net.IP) { +// SetPeerAddr sets the peer address. +func (r *RelayMessage) SetPeerAddr(peerAddr net.IP) { r.peerAddr = peerAddr } -func (r *DHCPv6Relay) Options() []Option { +// Options returns the current set of options associated with this message. +func (r *RelayMessage) Options() []Option { return r.options } -func (r *DHCPv6Relay) GetOption(code OptionCode) []Option { +// GetOption returns the options associated with the code. +func (r *RelayMessage) GetOption(code OptionCode) []Option { return r.options.Get(code) } -func (r *DHCPv6Relay) GetOneOption(code OptionCode) Option { +// GetOneOption returns the first associated option with the code from this +// message. +func (r *RelayMessage) GetOneOption(code OptionCode) Option { return r.options.GetOne(code) } -func (r *DHCPv6Relay) SetOptions(options []Option) { +// SetOptions replaces this message's options. +func (r *RelayMessage) SetOptions(options []Option) { r.options = options } -func (r *DHCPv6Relay) AddOption(option Option) { +// AddOption adds an option to this message. +func (r *RelayMessage) AddOption(option Option) { r.options.Add(option) } // UpdateOption replaces the first option of the same type as the specified one. -func (r *DHCPv6Relay) UpdateOption(option Option) { +func (r *RelayMessage) UpdateOption(option Option) { r.options.Update(option) } -func (r *DHCPv6Relay) IsRelay() bool { +// IsRelay returns whether this is a relay message or not. +func (r *RelayMessage) IsRelay() bool { return true } -// Recurse into a relay message and extract and return the inner DHCPv6Message. -// Return nil if none found (e.g. not a relay message). -func (d *DHCPv6Relay) GetInnerMessage() (DHCPv6, error) { +// GetInnerMessage recurses into a relay message and extract and return the +// inner Message. Return nil if none found (e.g. not a relay message). +func (r *RelayMessage) GetInnerMessage() (DHCPv6, error) { var ( p DHCPv6 err error ) - p = d + p = r for { if !p.IsRelay() { return p, nil @@ -154,9 +169,9 @@ func NewRelayReplFromRelayForw(relayForw, msg DHCPv6) (DHCPv6, error) { if relayForw == nil { return nil, errors.New("Relay message cannot be nil") } - relay, ok := relayForw.(*DHCPv6Relay) + relay, ok := relayForw.(*RelayMessage) if !ok { - return nil, errors.New("Not a DHCPv6Relay") + return nil, errors.New("Not a RelayMessage") } if relay.Type() != MessageTypeRelayForward { return nil, errors.New("The passed packet is not of type MessageTypeRelayForward") @@ -177,7 +192,7 @@ func NewRelayReplFromRelayForw(relayForw, msg DHCPv6) (DHCPv6, error) { return nil, err } if decap.IsRelay() { - relay = decap.(*DHCPv6Relay) + relay = decap.(*RelayMessage) } else { break } diff --git a/dhcpv6/dhcpv6relay_test.go b/dhcpv6/dhcpv6relay_test.go index d2446ec..87eabbf 100644 --- a/dhcpv6/dhcpv6relay_test.go +++ b/dhcpv6/dhcpv6relay_test.go @@ -8,10 +8,10 @@ import ( "github.com/stretchr/testify/require" ) -func TestDHCPv6Relay(t *testing.T) { +func TestRelayMessage(t *testing.T) { ll := net.IP{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xff, 0xfe, 0xdd, 0xee, 0xff} ma := net.IP{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} - r := DHCPv6Relay{ + r := RelayMessage{ messageType: MessageTypeRelayForward, hopCount: 10, linkAddr: ll, @@ -36,8 +36,8 @@ func TestDHCPv6Relay(t *testing.T) { } } -func TestDHCPv6RelaySettersAndGetters(t *testing.T) { - r := DHCPv6Relay{} +func TestRelayMessageSettersAndGetters(t *testing.T) { + r := RelayMessage{} // set and get message type r.SetMessageType(MessageTypeRelayReply) if mt := r.Type(); mt != MessageTypeRelayReply { @@ -59,14 +59,14 @@ func TestDHCPv6RelaySettersAndGetters(t *testing.T) { t.Fatalf("Invalid peer address. Expected %v, got %v", net.IPv6loopback, pa) } // set and get options - oneOpt := []Option{&OptRelayMsg{relayMessage: &DHCPv6Message{}}} + oneOpt := []Option{&OptRelayMsg{relayMessage: &Message{}}} r.SetOptions(oneOpt) if opts := r.Options(); len(opts) != 1 || opts[0] != oneOpt[0] { t.Fatalf("Invalid options. Expected %v, got %v", oneOpt, opts) } } -func TestDHCPv6RelayToBytes(t *testing.T) { +func TestRelayMessageToBytes(t *testing.T) { expected := []byte{ 12, // MessageTypeRelayForward 1, // hop count @@ -83,14 +83,14 @@ func TestDHCPv6RelayToBytes(t *testing.T) { 0, 2, // length 0, 0, } - r := DHCPv6Relay{ + r := RelayMessage{ messageType: MessageTypeRelayForward, hopCount: 1, linkAddr: net.IPv6interfacelocalallnodes, peerAddr: net.IPv6linklocalallrouters, } opt := OptRelayMsg{ - relayMessage: &DHCPv6Message{ + relayMessage: &Message{ messageType: MessageTypeSolicit, transactionID: TransactionID{0xaa, 0xbb, 0xcc}, options: []Option{ @@ -109,7 +109,7 @@ func TestDHCPv6RelayToBytes(t *testing.T) { func TestNewRelayRepFromRelayForw(t *testing.T) { // create a new relay forward - rf := DHCPv6Relay{} + rf := RelayMessage{} rf.SetMessageType(MessageTypeRelayForward) rf.SetPeerAddr(net.IPv6linklocalallrouters) rf.SetLinkAddr(net.IPv6interfacelocalallnodes) @@ -128,7 +128,7 @@ func TestNewRelayRepFromRelayForw(t *testing.T) { require.NoError(t, err) rr, err := NewRelayReplFromRelayForw(&rf, a) require.NoError(t, err) - relay := rr.(*DHCPv6Relay) + relay := rr.(*RelayMessage) require.Equal(t, rr.Type(), MessageTypeRelayReply) require.Equal(t, relay.HopCount(), rf.HopCount()) require.Equal(t, relay.PeerAddr(), rf.PeerAddr()) diff --git a/dhcpv6/iputils.go b/dhcpv6/iputils.go index 3ad157e..e04a9a7 100644 --- a/dhcpv6/iputils.go +++ b/dhcpv6/iputils.go @@ -74,11 +74,11 @@ func ExtractMAC(packet DHCPv6) (net.HardwareAddr, error) { if err != nil { return nil, err } - ip := inner.(*DHCPv6Relay).PeerAddr() + ip := inner.(*RelayMessage).PeerAddr() if mac, err := GetMacAddressFromEUI64(ip); err == nil { return mac, nil } - msg, err = msg.(*DHCPv6Relay).GetInnerMessage() + msg, err = msg.(*RelayMessage).GetInnerMessage() if err != nil { return nil, err } diff --git a/dhcpv6/modifiers.go b/dhcpv6/modifiers.go index a3d7986..f1be702 100644 --- a/dhcpv6/modifiers.go +++ b/dhcpv6/modifiers.go @@ -28,9 +28,9 @@ func WithServerID(duid Duid) Modifier { // WithNetboot adds bootfile URL and bootfile param options to a DHCPv6 packet. func WithNetboot(d DHCPv6) DHCPv6 { - msg, ok := d.(*DHCPv6Message) + msg, ok := d.(*Message) if !ok { - log.Printf("WithNetboot: not a DHCPv6Message") + log.Printf("WithNetboot: not a Message") return d } // add OptionBootfileURL and OptionBootfileParam diff --git a/dhcpv6/modifiers_test.go b/dhcpv6/modifiers_test.go index 9bf2da4..d505113 100644 --- a/dhcpv6/modifiers_test.go +++ b/dhcpv6/modifiers_test.go @@ -58,7 +58,7 @@ func TestWithIANA(t *testing.T) { IPv6Addr: net.ParseIP("::1"), PreferredLifetime: 3600, ValidLifetime: 5200, - })(&DHCPv6Message{}) + })(&Message{}) require.Equal(t, 1, len(d.Options())) require.Equal(t, OptionIANA, d.Options()[0].Code()) } @@ -67,7 +67,7 @@ func TestWithDNS(t *testing.T) { d := WithDNS([]net.IP{ net.ParseIP("fe80::1"), net.ParseIP("fe80::2"), - }...)(&DHCPv6Message{}) + }...)(&Message{}) require.Equal(t, 1, len(d.Options())) dns := d.Options()[0].(*OptDNSRecursiveNameServer) log.Printf("DNS %+v", dns) @@ -82,7 +82,7 @@ func TestWithDomainSearchList(t *testing.T) { d := WithDomainSearchList([]string{ "slackware.it", "dhcp.slackware.it", - }...)(&DHCPv6Message{}) + }...)(&Message{}) require.Equal(t, 1, len(d.Options())) osl := d.Options()[0].(*OptDomainSearchList) require.Equal(t, OptionDomainSearchList, osl.Code()) diff --git a/dhcpv6/option_relaymsg_test.go b/dhcpv6/option_relaymsg_test.go index 996b514..654cdb8 100644 --- a/dhcpv6/option_relaymsg_test.go +++ b/dhcpv6/option_relaymsg_test.go @@ -67,9 +67,9 @@ func TestRelayMsgParseOptRelayMsgSingleEncapsulation(t *testing.T) { if err != nil { t.Fatal(err) } - r, ok := d.(*DHCPv6Relay) + r, ok := d.(*RelayMessage) if !ok { - t.Fatalf("Invalid DHCPv6 type. Expected DHCPv6Relay, got %v", + t.Fatalf("Invalid DHCPv6 type. Expected RelayMessage, got %v", reflect.TypeOf(d), ) } @@ -91,9 +91,9 @@ func TestRelayMsgParseOptRelayMsgSingleEncapsulation(t *testing.T) { reflect.TypeOf(ro), ) } - innerDHCP, ok := ro.RelayMessage().(*DHCPv6Message) + innerDHCP, ok := ro.RelayMessage().(*Message) if !ok { - t.Fatalf("Invalid relay message type. Expected DHCPv6Message, got %v", + t.Fatalf("Invalid relay message type. Expected Message, got %v", reflect.TypeOf(innerDHCP), ) } @@ -182,7 +182,7 @@ func TestRelayMsgString(t *testing.T) { require.Contains( t, opt.String(), - "relaymsg=DHCPv6Message", + "relaymsg=Message", "String() should contain the relaymsg contents", ) } |