blob: e9a8baf16c5b2768181709fba2ead811032bf5ac [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// Copyright 2019 The GoPacket Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style license that can be found
4// in the LICENSE file in the root of the source tree.
5
6package layers
7
8// This file implements the RMCP ASF Presence Pong message, specified in section
9// 3.2.4.3 of
10// https://www.dmtf.org/sites/default/files/standards/documents/DSP0136.pdf. It
11// also contains non-competing elements from IPMI v2.0, specified in section
12// 13.2.4 of
13// https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ipmi-intelligent-platform-mgt-interface-spec-2nd-gen-v2-0-spec-update.pdf.
14
15import (
16 "encoding/binary"
17 "fmt"
18
19 "github.com/google/gopacket"
20)
21
22type (
23 // ASFEntity is the type of individual entities that a Presence Pong
24 // response can indicate support of. The entities currently implemented by
25 // the spec are IPMI and ASFv1.
26 ASFEntity uint8
27
28 // ASFInteraction is the type of individual interactions that a Presence
29 // Pong response can indicate support for. The interactions currently
30 // implemented by the spec are RMCP security extensions. Although not
31 // specified, IPMI uses this field to indicate support for DASH, which is
32 // supported as well.
33 ASFInteraction uint8
34)
35
36const (
37 // ASFDCMIEnterprise is the IANA-assigned Enterprise Number of the Data
38 // Center Manageability Interface Forum. The Presence Pong response's
39 // Enterprise field being set to this value indicates support for DCMI. The
40 // DCMI spec regards the OEM field as reserved, so these should be null.
41 ASFDCMIEnterprise uint32 = 36465
42
43 // ASFPresencePongEntityIPMI ANDs with Presence Pong's supported entities
44 // field if the managed system supports IPMI.
45 ASFPresencePongEntityIPMI ASFEntity = 1 << 7
46
47 // ASFPresencePongEntityASFv1 ANDs with Presence Pong's supported entities
48 // field if the managed system supports ASF v1.0.
49 ASFPresencePongEntityASFv1 ASFEntity = 1
50
51 // ASFPresencePongInteractionSecurityExtensions ANDs with Presence Pong's
52 // supported interactions field if the managed system supports RMCP v2.0
53 // security extensions. See section 3.2.3.
54 ASFPresencePongInteractionSecurityExtensions ASFInteraction = 1 << 7
55
56 // ASFPresencePongInteractionDASH ANDs with Presence Pong's supported
57 // interactions field if the managed system supports DMTF DASH. See
58 // https://www.dmtf.org/standards/dash.
59 ASFPresencePongInteractionDASH ASFInteraction = 1 << 5
60)
61
62// ASFPresencePong defines the structure of a Presence Pong message's payload.
63// See section 3.2.4.3.
64type ASFPresencePong struct {
65 BaseLayer
66
67 // Enterprise is the IANA Enterprise Number of an entity that has defined
68 // OEM-specific capabilities for the managed client. If no such capabilities
69 // exist, this is set to ASF's IANA Enterprise Number.
70 Enterprise uint32
71
72 // OEM identifies OEM-specific capabilities. Its structure is defined by the
73 // OEM. This is set to 0s if no OEM-specific capabilities exist. This
74 // implementation does not change byte order from the wire for this field.
75 OEM [4]byte
76
77 // We break out entities and interactions into separate booleans as
78 // discovery is the entire point of this type of message, so we assume they
79 // are accessed. It also makes gopacket's default layer printing more
80 // useful.
81
82 // IPMI is true if IPMI is supported by the managed system. There is no
83 // explicit version in the specification, however given the dates, this is
84 // assumed to be IPMI v1.0. Support for IPMI is contained in the "supported
85 // entities" field of the presence pong payload.
86 IPMI bool
87
88 // ASFv1 indicates support for ASF v1.0. This seems somewhat redundant as
89 // ASF must be supported in order to receive a response. This is contained
90 // in the "supported entities" field of the presence pong payload.
91 ASFv1 bool
92
93 // SecurityExtensions indicates support for RMCP Security Extensions,
94 // specified in ASF v2.0. This will always be false for v1.x
95 // implementations. This is contained in the "supported interactions" field
96 // of the presence pong payload. This field is defined in ASF v1.0, but has
97 // no useful value.
98 SecurityExtensions bool
99
100 // DASH is true if DMTF DASH is supported. This is not specified in ASF
101 // v2.0, but in IPMI v2.0, however the former does not preclude it, so we
102 // support it.
103 DASH bool
104
105 // 6 bytes reserved after the entities and interactions fields, set to 0s.
106}
107
108// SupportsDCMI returns whether the Presence Pong message indicates support for
109// the Data Center Management Interface, which is an extension of IPMI v2.0.
110func (a *ASFPresencePong) SupportsDCMI() bool {
111 return a.Enterprise == ASFDCMIEnterprise && a.IPMI && a.ASFv1
112}
113
114// LayerType returns LayerTypeASFPresencePong. It partially satisfies Layer and
115// SerializableLayer.
116func (*ASFPresencePong) LayerType() gopacket.LayerType {
117 return LayerTypeASFPresencePong
118}
119
120// CanDecode returns LayerTypeASFPresencePong. It partially satisfies
121// DecodingLayer.
122func (a *ASFPresencePong) CanDecode() gopacket.LayerClass {
123 return a.LayerType()
124}
125
126// DecodeFromBytes makes the layer represent the provided bytes. It partially
127// satisfies DecodingLayer.
128func (a *ASFPresencePong) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
129 if len(data) < 16 {
130 df.SetTruncated()
131 return fmt.Errorf("invalid ASF presence pong payload, length %v less than 16",
132 len(data))
133 }
134
135 a.BaseLayer.Contents = data[:16]
136 a.BaseLayer.Payload = data[16:]
137
138 a.Enterprise = binary.BigEndian.Uint32(data[:4])
139 copy(a.OEM[:], data[4:8]) // N.B. no byte order change
140 a.IPMI = data[8]&uint8(ASFPresencePongEntityIPMI) != 0
141 a.ASFv1 = data[8]&uint8(ASFPresencePongEntityASFv1) != 0
142 a.SecurityExtensions = data[9]&uint8(ASFPresencePongInteractionSecurityExtensions) != 0
143 a.DASH = data[9]&uint8(ASFPresencePongInteractionDASH) != 0
144 // ignore remaining 6 bytes; should be set to 0s
145 return nil
146}
147
148// NextLayerType returns LayerTypePayload, as there are no further layers to
149// decode. This partially satisfies DecodingLayer.
150func (a *ASFPresencePong) NextLayerType() gopacket.LayerType {
151 return gopacket.LayerTypePayload
152}
153
154// SerializeTo writes the serialized fom of this layer into the SerializeBuffer,
155// partially satisfying SerializableLayer.
156func (a *ASFPresencePong) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
157 bytes, err := b.PrependBytes(16)
158 if err != nil {
159 return err
160 }
161
162 binary.BigEndian.PutUint32(bytes[:4], a.Enterprise)
163
164 copy(bytes[4:8], a.OEM[:])
165
166 bytes[8] = 0
167 if a.IPMI {
168 bytes[8] |= uint8(ASFPresencePongEntityIPMI)
169 }
170 if a.ASFv1 {
171 bytes[8] |= uint8(ASFPresencePongEntityASFv1)
172 }
173
174 bytes[9] = 0
175 if a.SecurityExtensions {
176 bytes[9] |= uint8(ASFPresencePongInteractionSecurityExtensions)
177 }
178 if a.DASH {
179 bytes[9] |= uint8(ASFPresencePongInteractionDASH)
180 }
181
182 // zero-out remaining 6 bytes
183 for i := 10; i < len(bytes); i++ {
184 bytes[i] = 0x00
185 }
186
187 return nil
188}
189
190// decodeASFPresencePong decodes the byte slice into an RMCP-ASF Presence Pong
191// struct.
192func decodeASFPresencePong(data []byte, p gopacket.PacketBuilder) error {
193 return decodingLayerDecoder(&ASFPresencePong{}, data, p)
194}