mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
ID: 3611254 - OEM handle for Intel 82751 in SPT mode
Intel 82751 MAC has several deviations in its RMCP+ implementation while working in the super pass-through mode. This patch adds a OEM handle which allows IPMItool succesfully interract with boards equipped with this NIC. Commit for Dmitry Bazhenov
This commit is contained in:
parent
38d71179e9
commit
0cea01e42f
@ -63,6 +63,10 @@ static struct ipmi_oem_handle ipmi_oem_list[] = {
|
||||
desc: "IBM OEM support",
|
||||
setup: ipmi_oem_ibm,
|
||||
},
|
||||
{
|
||||
name: "i82571spt",
|
||||
desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode",
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -1568,43 +1568,45 @@ ipmi_sol_red_pill(struct ipmi_intf * intf, int instance)
|
||||
FD_SET(0, &read_fds);
|
||||
FD_SET(intf->fd, &read_fds);
|
||||
|
||||
/* Send periodic keepalive packet */
|
||||
if(_use_sol_for_keepalive == 0)
|
||||
if (!ipmi_oem_active(intf,"i82571spt"))
|
||||
{
|
||||
keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
|
||||
}
|
||||
else
|
||||
{
|
||||
keepAliveRet = ipmi_sol_keepalive_using_sol(intf);
|
||||
}
|
||||
|
||||
if (keepAliveRet != 0)
|
||||
{
|
||||
/*
|
||||
* Retrying the keep Alive before declaring a communication
|
||||
* lost state with the IPMC. Helpful when the payload is
|
||||
* reset and brings down the connection temporarily. Otherwise,
|
||||
* if we send getDevice Id to check the status of IPMC during
|
||||
* this down time when the connection is restarting, SOL will
|
||||
* exit even though the IPMC is available and the session is open.
|
||||
*/
|
||||
if (retrySol == MAX_SOL_RETRY)
|
||||
/* Send periodic keepalive packet */
|
||||
if(_use_sol_for_keepalive == 0)
|
||||
{
|
||||
/* no response to Get Device ID keepalive message */
|
||||
bShouldExit = 1;
|
||||
continue;
|
||||
keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
|
||||
}
|
||||
else
|
||||
{
|
||||
retrySol++;
|
||||
else
|
||||
{
|
||||
keepAliveRet = ipmi_sol_keepalive_using_sol(intf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if the keep Alive is successful reset retries to zero */
|
||||
retrySol = 0;
|
||||
}
|
||||
|
||||
|
||||
if (keepAliveRet != 0)
|
||||
{
|
||||
/*
|
||||
* Retrying the keep Alive before declaring a communication
|
||||
* lost state with the IPMC. Helpful when the payload is
|
||||
* reset and brings down the connection temporarily. Otherwise,
|
||||
* if we send getDevice Id to check the status of IPMC during
|
||||
* this down time when the connection is restarting, SOL will
|
||||
* exit even though the IPMC is available and the session is open.
|
||||
*/
|
||||
if (retrySol == MAX_SOL_RETRY)
|
||||
{
|
||||
/* no response to Get Device ID keepalive message */
|
||||
bShouldExit = 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
retrySol++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if the keep Alive is successful reset retries to zero */
|
||||
retrySol = 0;
|
||||
}
|
||||
} /* !oem="i82571spt" */
|
||||
/* Wait up to half a second */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 500000;
|
||||
@ -1757,6 +1759,20 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
|
||||
|
||||
if (ipmi_oem_active(intf, "intelplus")) {
|
||||
data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_TRUE;
|
||||
} else if (ipmi_oem_active(intf, "i82571spt")) {
|
||||
/*
|
||||
* A quote from Intel: "Engineering believes the problem
|
||||
* lies within the Auxiliary data being sent with the
|
||||
* 'Activate Payload' command from IPMITool. IPMITool
|
||||
* sends a C6h which sets some bits having to do with
|
||||
* encryption and some behavior dealing with CTS DCD/DSR.
|
||||
* I recommend that the customer modify this request
|
||||
* to send 08h instead. This is what our internal utility
|
||||
* sends and it works without issue. I will work with
|
||||
* engineering to ensure the settings that IPMITool uses
|
||||
* (C6h) are supported in the future.
|
||||
*/
|
||||
data[2] = 0x08;
|
||||
} else {
|
||||
data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_FALSE;
|
||||
}
|
||||
|
@ -3164,7 +3164,7 @@ ipmi_lanplus_rakp3(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
/* Generate our Session Integrity Key, K1, and K2 */
|
||||
if (lanplus_generate_sik(session))
|
||||
if (lanplus_generate_sik(session, intf))
|
||||
{
|
||||
/* Error */
|
||||
lprintf(LOG_INFO, "> Error generating session integrity key");
|
||||
@ -3417,7 +3417,8 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
||||
*
|
||||
* I'm not sure why we accept a failure for the first call
|
||||
*/
|
||||
if (ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) {
|
||||
if (!ipmi_oem_active(intf, "i82571spt") &&
|
||||
ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) {
|
||||
sleep(1);
|
||||
if (ipmi_get_auth_capabilities_cmd(intf, &auth_cap));
|
||||
{
|
||||
@ -3427,7 +3428,7 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
||||
}
|
||||
}
|
||||
|
||||
if (! auth_cap.v20_data_available)
|
||||
if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available)
|
||||
{
|
||||
lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
|
||||
goto fail;
|
||||
@ -3462,11 +3463,11 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
||||
|
||||
lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
|
||||
|
||||
rc = ipmi_set_session_privlvl_cmd(intf);
|
||||
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
|
||||
if (!ipmi_oem_active(intf, "i82571spt")) {
|
||||
rc = ipmi_set_session_privlvl_cmd(intf);
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
}
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
bridgePossible = 1;
|
||||
|
||||
|
@ -68,9 +68,9 @@
|
||||
* return 0 on success (the authcode matches)
|
||||
* 1 on failure (the authcode does not match)
|
||||
*/
|
||||
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * bmc_mac,
|
||||
struct ipmi_intf * intf)
|
||||
int
|
||||
lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * bmc_mac, struct ipmi_intf * intf)
|
||||
{
|
||||
uint8_t * buffer;
|
||||
int bufferLength, i;
|
||||
@ -153,6 +153,15 @@ int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
/* ROLEm */
|
||||
buffer[56] = session->v2_data.requested_role;
|
||||
|
||||
if (ipmi_oem_active(intf, "i82571spt")) {
|
||||
/*
|
||||
* The HMAC calculation code in the Intel 82571 GbE
|
||||
* skips this bit! Looks like a GbE bug, but we need
|
||||
* to work around it here anyway...
|
||||
*/
|
||||
buffer[56] &= ~0x10;
|
||||
}
|
||||
|
||||
/* ULENGTHm */
|
||||
buffer[57] = strlen((const char *)session->username);
|
||||
|
||||
@ -213,9 +222,9 @@ int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
* 0 on failure (the authcode does not match)
|
||||
*
|
||||
*/
|
||||
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * bmc_mac,
|
||||
struct ipmi_intf * intf)
|
||||
int
|
||||
lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * bmc_mac, struct ipmi_intf * intf)
|
||||
{
|
||||
uint8_t * buffer;
|
||||
int bufferLength, i;
|
||||
@ -341,10 +350,10 @@ int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
||||
const struct ipmi_session * session,
|
||||
uint32_t * mac_length,
|
||||
struct ipmi_intf * intf)
|
||||
int
|
||||
lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
||||
const struct ipmi_session * session,
|
||||
uint32_t * mac_length, struct ipmi_intf * intf)
|
||||
{
|
||||
int ret = 0;
|
||||
int input_buffer_length, i;
|
||||
@ -396,7 +405,7 @@ int lanplus_generate_rakp3_authcode(uint8_t * output_buffer
|
||||
memcpy(input_buffer + 16, &SIDm_lsbf, 4);
|
||||
|
||||
/* ROLEm */
|
||||
if (ipmi_oem_active(intf, "intelplus"))
|
||||
if (ipmi_oem_active(intf, "intelplus") || ipmi_oem_active(intf, "i82571spt"))
|
||||
input_buffer[20] = session->privlvl;
|
||||
else
|
||||
input_buffer[20] = session->v2_data.requested_role;
|
||||
@ -460,7 +469,8 @@ int lanplus_generate_rakp3_authcode(uint8_t * output_buffer
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int lanplus_generate_sik(struct ipmi_session * session)
|
||||
int
|
||||
lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
|
||||
{
|
||||
uint8_t * input_buffer;
|
||||
int input_buffer_length, i;
|
||||
@ -516,6 +526,15 @@ int lanplus_generate_sik(struct ipmi_session * session)
|
||||
/* ROLEm */
|
||||
input_buffer[32] = session->v2_data.requested_role;
|
||||
|
||||
if (ipmi_oem_active(intf, "i82571spt")) {
|
||||
/*
|
||||
* The HMAC calculation code in the Intel 82571 GbE
|
||||
* skips this bit! Looks like a GbE bug, but we need
|
||||
* to work around it here anyway...
|
||||
*/
|
||||
input_buffer[32] &= ~0x10;
|
||||
}
|
||||
|
||||
/* ULENGTHm */
|
||||
input_buffer[33] = strlen((const char *)session->username);
|
||||
|
||||
@ -580,7 +599,8 @@ int lanplus_generate_sik(struct ipmi_session * session)
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int lanplus_generate_k1(struct ipmi_session * session)
|
||||
int
|
||||
lanplus_generate_k1(struct ipmi_session * session)
|
||||
{
|
||||
uint32_t mac_length;
|
||||
|
||||
@ -623,7 +643,8 @@ int lanplus_generate_k1(struct ipmi_session * session)
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int lanplus_generate_k2(struct ipmi_session * session)
|
||||
int
|
||||
lanplus_generate_k2(struct ipmi_session * session)
|
||||
{
|
||||
uint32_t mac_length;
|
||||
|
||||
@ -673,12 +694,11 @@ int lanplus_generate_k2(struct ipmi_session * session)
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint16_t * bytes_written)
|
||||
int
|
||||
lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||
const uint8_t * key, const uint8_t * input,
|
||||
uint32_t input_length, uint8_t * output,
|
||||
uint16_t * bytes_written)
|
||||
{
|
||||
uint8_t * padded_input;
|
||||
uint32_t mod, i, bytes_encrypted;
|
||||
@ -777,12 +797,12 @@ int lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||
* returns 1 on success (authcode is valid)
|
||||
* 0 on failure (autchode integrity check failed)
|
||||
*/
|
||||
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
|
||||
struct ipmi_session * session)
|
||||
int
|
||||
lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session)
|
||||
{
|
||||
uint8_t * bmc_authcode;
|
||||
uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
|
||||
uint32_t generated_authcode_length;
|
||||
uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
|
||||
uint32_t generated_authcode_length;
|
||||
|
||||
|
||||
if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
|
||||
@ -837,12 +857,10 @@ int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
|
||||
* returns 0 on success (we were able to successfully decrypt the packet)
|
||||
* 1 on failure (we were unable to successfully decrypt the packet)
|
||||
*/
|
||||
int lanplus_decrypt_payload(uint8_t crypt_alg,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint16_t * payload_size)
|
||||
int
|
||||
lanplus_decrypt_payload(uint8_t crypt_alg, const uint8_t * key,
|
||||
const uint8_t * input, uint32_t input_length,
|
||||
uint8_t * output, uint16_t * payload_size)
|
||||
{
|
||||
uint8_t * decrypted_payload;
|
||||
uint32_t bytes_decrypted;
|
||||
@ -897,7 +915,7 @@ int lanplus_decrypt_payload(uint8_t crypt_alg,
|
||||
*/
|
||||
for (i = 0; i < conf_pad_length; ++i)
|
||||
{
|
||||
if (decrypted_payload[*payload_size + i] == i)
|
||||
if (decrypted_payload[*payload_size + i] != (i + 1))
|
||||
{
|
||||
lprintf(LOG_ERR, "Malformed payload padding");
|
||||
assert(0);
|
||||
|
@ -51,7 +51,7 @@ int lanplus_generate_rakp3_authcode(uint8_t * buffer,
|
||||
const struct ipmi_session * session,
|
||||
uint32_t * auth_length,
|
||||
struct ipmi_intf * intf);
|
||||
int lanplus_generate_sik(struct ipmi_session * session);
|
||||
int lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf);
|
||||
int lanplus_generate_k1(struct ipmi_session * session);
|
||||
int lanplus_generate_k2(struct ipmi_session * session);
|
||||
int lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||
|
Loading…
x
Reference in New Issue
Block a user