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  }