github.com/gopacket/gopacket@v1.1.0/layers/asf_presencepong.go (about) 1 // 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 6 package 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 15 import ( 16 "encoding/binary" 17 "fmt" 18 19 "github.com/gopacket/gopacket" 20 ) 21 22 type ( 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 36 const ( 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. 64 type 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. 110 func (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. 116 func (*ASFPresencePong) LayerType() gopacket.LayerType { 117 return LayerTypeASFPresencePong 118 } 119 120 // CanDecode returns LayerTypeASFPresencePong. It partially satisfies 121 // DecodingLayer. 122 func (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. 128 func (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. 150 func (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. 156 func (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. 192 func decodeASFPresencePong(data []byte, p gopacket.PacketBuilder) error { 193 return decodingLayerDecoder(&ASFPresencePong{}, data, p) 194 }