Is it acceptable to return the response data when using native RMCP interface even if the received data length do not match the payload length specified in the response header ? (Rather than raising a top-level exception)
I can propose something like a FeatureFlag CheckIPMIPayloadLength that is True by default, but if False it disables the verification of the payload.
Problem
My problem is that I have a specific BMC that supports the IPMI Quanta OEM command NetFn=0x30, Cmd=0x49. This command is used to retrieve the last POST codes of the server (self-test codes that happened before the bios). It can returns up to the last 256 POST codes.
The real bug is with the actual implementation of this OEM command on the BMC side : in IPMI v1.5, the field payload length of an IPMI response header is coded on 1 byte and is 1-based. This means an IPMI response payload total length cannot exceed 256 bytes. But an IPMI payload/message contains more than just the payload data : it has also rqAddr, netFn, checksum, cmd, completion code etc. which adds always 8 bytes to the actual response data.
In my case, if the Quanta OEM GetPostCodes command wants to return 256 POST codes, the total payload/message length will be 256+8 = 264 bytes, which can't be coded in the field payload length of the response header. This results in python-ipmi raising the following exception when performing a raw command :
pyipmi.errors.DecodingError: SDU has extra bytes (290,26,8 )
The 26 is the length of the IPMI header. The 290 is the total length of received data, header length + received payload length = 264 + 26 = 290. The 8 is the payload length field in the header, I think it comes from the hex representation of 264: 01 08 but because this field is coded on 1 byte, it only got the 08 part of the hex representation.
If I try the same GetPostCodes raw command with a server that only sends back 128 POST codes for example, everything works fine.
Current behavior
int = interfaces.create_interface(
interface='rmcp',
slave_address=0x81,
host_target_address=0x20,
keep_alive_interval=0
)
ipmi = pyipmi.create_connection(int)
ipmi.session.set_session_type_rmcp(...)
ipmi.session.set_auth_type_user(...)
ipmi.target = ...
ipmi.session.establish()
res = ipmi.interface.send_and_receive_raw(ipmi.target, 0x00, 0x30, b'\x49\x01')
res = array('B', res)
if res[0] != 0:
# Completion code error
raise Exception(f"Wrong completion code: {res[0]}")
print([f"{i:02x}" for i in res.tolist()])
> pyipmi.errors.DecodingError: SDU has extra bytes (290,26,8 )
Expected behavior
int = interfaces.create_interface(
interface='rmcp',
slave_address=0x81,
host_target_address=0x20,
keep_alive_interval=0
)
ipmi = pyipmi.create_connection(int)
ipmi.session.set_session_type_rmcp(...)
ipmi.session.set_auth_type_user(...)
ipmi.target = ...
ipmi.session.establish()
res = ipmi.interface.send_and_receive_raw(ipmi.target, 0x00, 0x30, b'\x49\x01')
res = array('B', res)
if res[0] != 0:
# Completion code error
raise Exception(f"Wrong completion code: {res[0]}")
print([f"{i:02x}" for i in res.tolist()])
> ["00", "A0", "B2", "99", ... , "EC", "FF", "9C"] # list of length 257 (256 POST codes + completion code)
Questions
Does someone have the same issue with a wrong value in the payload length field of the IPMI session header ?
Can pyipmi be more "laxist" about failing if the length do not match (actual received length vs expected length with the header value) ? For example, with the ipmitool binary (a CLI tool that can talk to IPMI devices), when using IPMI v1.5 they don't check this header value but only rely on the total bytes read on a socket. They do check the header field value in IPMI v2.0 . Is something like that conceivable ?
This issue is more a question than a bug. It concerns the following code in
rmcp.py
: https://github.com/kontron/python-ipmi/blob/63079a6937f510dbbb2e0ab4ca524f98ef7abb1e/pyipmi/interfaces/rmcp.py#L326-L328TL;DR
Is it acceptable to return the response data when using native RMCP interface even if the received data length do not match the payload length specified in the response header ? (Rather than raising a top-level exception)
I can propose something like a FeatureFlag
CheckIPMIPayloadLength
that isTrue
by default, but ifFalse
it disables the verification of the payload.Problem
My problem is that I have a specific BMC that supports the IPMI Quanta OEM command
NetFn=0x30, Cmd=0x49
. This command is used to retrieve the last POST codes of the server (self-test codes that happened before the bios). It can returns up to the last 256 POST codes.The real bug is with the actual implementation of this OEM command on the BMC side : in IPMI v1.5, the field
payload length
of an IPMI response header is coded on 1 byte and is 1-based. This means an IPMI response payload total length cannot exceed 256 bytes. But an IPMI payload/message contains more than just the payload data : it has alsorqAddr
,netFn
,checksum
,cmd
,completion code
etc. which adds always 8 bytes to the actual response data.In my case, if the Quanta OEM
GetPostCodes
command wants to return 256 POST codes, the total payload/message length will be 256+8 = 264 bytes, which can't be coded in the fieldpayload length
of the response header. This results inpython-ipmi
raising the following exception when performing a raw command :If I try the same
GetPostCodes
raw command with a server that only sends back128
POST codes for example, everything works fine.Current behavior
Expected behavior
Questions
pyipmi
be more "laxist" about failing if the length do not match (actual received length vs expected length with the header value) ? For example, with theipmitool
binary (a CLI tool that can talk to IPMI devices), when using IPMI v1.5 they don't check this header value but only rely on the total bytes read on a socket. They do check the header field value in IPMI v2.0 . Is something like that conceivable ?