From fafee2841d9aa4218f5de9506d45b1255ded393b Mon Sep 17 00:00:00 2001 From: Sean Karlage Date: Mon, 1 Oct 2018 09:21:23 -0700 Subject: BSDP: Add MessageTypeFromPacket helper This is a helper function to extract the BSDP message type from a given `dhcpv4.DHCPv4` packet structure. It's useful in helping to identify what kind of BSDP packet you're dealing with (since the distinction is only made in one of the vendor-specific options encapsulated in Option 43). --- dhcpv4/bsdp/bsdp.go | 20 ++++++++++++++ dhcpv4/bsdp/bsdp_test.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) (limited to 'dhcpv4/bsdp') diff --git a/dhcpv4/bsdp/bsdp.go b/dhcpv4/bsdp/bsdp.go index e15c59c..8c843d3 100644 --- a/dhcpv4/bsdp/bsdp.go +++ b/dhcpv4/bsdp/bsdp.go @@ -51,6 +51,26 @@ func needsReplyPort(replyPort uint16) bool { return replyPort != 0 && replyPort != dhcpv4.ClientPort } +func MessageTypeFromPacket(packet *dhcpv4.DHCPv4) (MessageType, bool) { + var ( + messageType MessageType + vendorOpts *OptVendorSpecificInformation + err error + ) + for _, opt := range packet.GetOption(dhcpv4.OptionVendorSpecificInformation) { + if vendorOpts, err = ParseOptVendorSpecificInformation(opt.ToBytes()); err != nil { + return messageType, false + } + if o := vendorOpts.GetOneOption(OptionMessageType); o != nil { + if optMessageType, ok := o.(*OptMessageType); ok { + return optMessageType.Type, true + } + return messageType, false + } + } + return messageType, false +} + // NewInformListForInterface creates a new INFORM packet for interface ifname // with configuration options specified by config. func NewInformListForInterface(ifname string, replyPort uint16) (*dhcpv4.DHCPv4, error) { diff --git a/dhcpv4/bsdp/bsdp_test.go b/dhcpv4/bsdp/bsdp_test.go index 7da4dfa..c9c868a 100644 --- a/dhcpv4/bsdp/bsdp_test.go +++ b/dhcpv4/bsdp/bsdp_test.go @@ -371,3 +371,72 @@ func TestNewReplyForInformSelect(t *testing.T) { RequireHasOption(t, vendorOpts, &OptMessageType{Type: MessageTypeSelect}) RequireHasOption(t, vendorOpts, &OptSelectedBootImageID{ID: images[0].ID}) } + +func TestMessageTypeForPacket(t *testing.T) { + var ( + pkt *dhcpv4.DHCPv4 + gotMessageType MessageType + gotOK bool + ) + + testcases := []struct { + tcName string + opts []dhcpv4.Option + wantOK bool + wantMessageType MessageType + }{ + { + tcName: "No options", + opts: []dhcpv4.Option{}, + wantOK: false, + }, + { + tcName: "Some options, no vendor opts", + opts: []dhcpv4.Option{ + &dhcpv4.OptHostName{HostName: "foobar1234"}, + }, + wantOK: false, + }, + { + tcName: "Vendor opts, no message type", + opts: []dhcpv4.Option{ + &dhcpv4.OptHostName{HostName: "foobar1234"}, + &OptVendorSpecificInformation{ + Options: []dhcpv4.Option{ + &OptVersion{Version: Version1_1}, + }, + }, + }, + wantOK: false, + }, + { + tcName: "Vendor opts, with message type", + opts: []dhcpv4.Option{ + &dhcpv4.OptHostName{HostName: "foobar1234"}, + &OptVendorSpecificInformation{ + Options: []dhcpv4.Option{ + &OptVersion{Version: Version1_1}, + &OptMessageType{Type: MessageTypeList}, + }, + }, + }, + wantOK: true, + wantMessageType: MessageTypeList, + }, + } + for _, tt := range testcases { + t.Run(tt.tcName, func(t *testing.T) { + pkt, _ = dhcpv4.New() + for _, opt := range tt.opts { + pkt.AddOption(opt) + } + gotMessageType, gotOK = MessageTypeFromPacket(pkt) + if tt.wantOK { + require.True(t, gotOK) + require.Equal(t, tt.wantMessageType, gotMessageType) + } else { + require.False(t, gotOK) + } + }) + } +} -- cgit v1.2.3 From ba3b7482ed35104b7a7d0d55eab3df02762a8aad Mon Sep 17 00:00:00 2001 From: Sean Karlage Date: Mon, 1 Oct 2018 09:26:25 -0700 Subject: add comment --- dhcpv4/bsdp/bsdp.go | 3 +++ 1 file changed, 3 insertions(+) (limited to 'dhcpv4/bsdp') diff --git a/dhcpv4/bsdp/bsdp.go b/dhcpv4/bsdp/bsdp.go index 8c843d3..172399b 100644 --- a/dhcpv4/bsdp/bsdp.go +++ b/dhcpv4/bsdp/bsdp.go @@ -51,6 +51,9 @@ func needsReplyPort(replyPort uint16) bool { return replyPort != 0 && replyPort != dhcpv4.ClientPort } +// MessageTypeFromPacket extracts the BSDP message type (LIST, SELECT) from the +// vendor-specific options and returns it. If the message type option cannot be +// found, returns false. func MessageTypeFromPacket(packet *dhcpv4.DHCPv4) (MessageType, bool) { var ( messageType MessageType -- cgit v1.2.3