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",
|
desc: "IBM OEM support",
|
||||||
setup: ipmi_oem_ibm,
|
setup: ipmi_oem_ibm,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "i82571spt",
|
||||||
|
desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode",
|
||||||
|
},
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1568,43 +1568,45 @@ ipmi_sol_red_pill(struct ipmi_intf * intf, int instance)
|
|||||||
FD_SET(0, &read_fds);
|
FD_SET(0, &read_fds);
|
||||||
FD_SET(intf->fd, &read_fds);
|
FD_SET(intf->fd, &read_fds);
|
||||||
|
|
||||||
/* Send periodic keepalive packet */
|
if (!ipmi_oem_active(intf,"i82571spt"))
|
||||||
if(_use_sol_for_keepalive == 0)
|
|
||||||
{
|
{
|
||||||
keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
|
/* Send periodic keepalive packet */
|
||||||
}
|
if(_use_sol_for_keepalive == 0)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
/* no response to Get Device ID keepalive message */
|
keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
|
||||||
bShouldExit = 1;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
retrySol++;
|
keepAliveRet = ipmi_sol_keepalive_using_sol(intf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
if (keepAliveRet != 0)
|
||||||
{
|
{
|
||||||
/* if the keep Alive is successful reset retries to zero */
|
/*
|
||||||
retrySol = 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 */
|
/* Wait up to half a second */
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = 500000;
|
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")) {
|
if (ipmi_oem_active(intf, "intelplus")) {
|
||||||
data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_TRUE;
|
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 {
|
} else {
|
||||||
data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_FALSE;
|
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 */
|
/* Generate our Session Integrity Key, K1, and K2 */
|
||||||
if (lanplus_generate_sik(session))
|
if (lanplus_generate_sik(session, intf))
|
||||||
{
|
{
|
||||||
/* Error */
|
/* Error */
|
||||||
lprintf(LOG_INFO, "> Error generating session integrity key");
|
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
|
* 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);
|
sleep(1);
|
||||||
if (ipmi_get_auth_capabilities_cmd(intf, &auth_cap));
|
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+");
|
lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -3462,11 +3463,11 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|||||||
|
|
||||||
lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
|
lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
|
||||||
|
|
||||||
rc = ipmi_set_session_privlvl_cmd(intf);
|
if (!ipmi_oem_active(intf, "i82571spt")) {
|
||||||
|
rc = ipmi_set_session_privlvl_cmd(intf);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||||
bridgePossible = 1;
|
bridgePossible = 1;
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@
|
|||||||
* return 0 on success (the authcode matches)
|
* return 0 on success (the authcode matches)
|
||||||
* 1 on failure (the authcode does not match)
|
* 1 on failure (the authcode does not match)
|
||||||
*/
|
*/
|
||||||
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
int
|
||||||
const uint8_t * bmc_mac,
|
lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||||
struct ipmi_intf * intf)
|
const uint8_t * bmc_mac, struct ipmi_intf * intf)
|
||||||
{
|
{
|
||||||
uint8_t * buffer;
|
uint8_t * buffer;
|
||||||
int bufferLength, i;
|
int bufferLength, i;
|
||||||
@ -153,6 +153,15 @@ int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
|||||||
/* ROLEm */
|
/* ROLEm */
|
||||||
buffer[56] = session->v2_data.requested_role;
|
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 */
|
/* ULENGTHm */
|
||||||
buffer[57] = strlen((const char *)session->username);
|
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)
|
* 0 on failure (the authcode does not match)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
int
|
||||||
const uint8_t * bmc_mac,
|
lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||||
struct ipmi_intf * intf)
|
const uint8_t * bmc_mac, struct ipmi_intf * intf)
|
||||||
{
|
{
|
||||||
uint8_t * buffer;
|
uint8_t * buffer;
|
||||||
int bufferLength, i;
|
int bufferLength, i;
|
||||||
@ -341,10 +350,10 @@ int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
|||||||
* returns 0 on success
|
* returns 0 on success
|
||||||
* 1 on failure
|
* 1 on failure
|
||||||
*/
|
*/
|
||||||
int lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
int
|
||||||
const struct ipmi_session * session,
|
lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
||||||
uint32_t * mac_length,
|
const struct ipmi_session * session,
|
||||||
struct ipmi_intf * intf)
|
uint32_t * mac_length, struct ipmi_intf * intf)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int input_buffer_length, i;
|
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);
|
memcpy(input_buffer + 16, &SIDm_lsbf, 4);
|
||||||
|
|
||||||
/* ROLEm */
|
/* ROLEm */
|
||||||
if (ipmi_oem_active(intf, "intelplus"))
|
if (ipmi_oem_active(intf, "intelplus") || ipmi_oem_active(intf, "i82571spt"))
|
||||||
input_buffer[20] = session->privlvl;
|
input_buffer[20] = session->privlvl;
|
||||||
else
|
else
|
||||||
input_buffer[20] = session->v2_data.requested_role;
|
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
|
* returns 0 on success
|
||||||
* 1 on failure
|
* 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;
|
uint8_t * input_buffer;
|
||||||
int input_buffer_length, i;
|
int input_buffer_length, i;
|
||||||
@ -516,6 +526,15 @@ int lanplus_generate_sik(struct ipmi_session * session)
|
|||||||
/* ROLEm */
|
/* ROLEm */
|
||||||
input_buffer[32] = session->v2_data.requested_role;
|
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 */
|
/* ULENGTHm */
|
||||||
input_buffer[33] = strlen((const char *)session->username);
|
input_buffer[33] = strlen((const char *)session->username);
|
||||||
|
|
||||||
@ -580,7 +599,8 @@ int lanplus_generate_sik(struct ipmi_session * session)
|
|||||||
* returns 0 on success
|
* returns 0 on success
|
||||||
* 1 on failure
|
* 1 on failure
|
||||||
*/
|
*/
|
||||||
int lanplus_generate_k1(struct ipmi_session * session)
|
int
|
||||||
|
lanplus_generate_k1(struct ipmi_session * session)
|
||||||
{
|
{
|
||||||
uint32_t mac_length;
|
uint32_t mac_length;
|
||||||
|
|
||||||
@ -623,7 +643,8 @@ int lanplus_generate_k1(struct ipmi_session * session)
|
|||||||
* returns 0 on success
|
* returns 0 on success
|
||||||
* 1 on failure
|
* 1 on failure
|
||||||
*/
|
*/
|
||||||
int lanplus_generate_k2(struct ipmi_session * session)
|
int
|
||||||
|
lanplus_generate_k2(struct ipmi_session * session)
|
||||||
{
|
{
|
||||||
uint32_t mac_length;
|
uint32_t mac_length;
|
||||||
|
|
||||||
@ -673,12 +694,11 @@ int lanplus_generate_k2(struct ipmi_session * session)
|
|||||||
* returns 0 on success
|
* returns 0 on success
|
||||||
* 1 on failure
|
* 1 on failure
|
||||||
*/
|
*/
|
||||||
int lanplus_encrypt_payload(uint8_t crypt_alg,
|
int
|
||||||
const uint8_t * key,
|
lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||||
const uint8_t * input,
|
const uint8_t * key, const uint8_t * input,
|
||||||
uint32_t input_length,
|
uint32_t input_length, uint8_t * output,
|
||||||
uint8_t * output,
|
uint16_t * bytes_written)
|
||||||
uint16_t * bytes_written)
|
|
||||||
{
|
{
|
||||||
uint8_t * padded_input;
|
uint8_t * padded_input;
|
||||||
uint32_t mod, i, bytes_encrypted;
|
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)
|
* returns 1 on success (authcode is valid)
|
||||||
* 0 on failure (autchode integrity check failed)
|
* 0 on failure (autchode integrity check failed)
|
||||||
*/
|
*/
|
||||||
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
|
int
|
||||||
struct ipmi_session * session)
|
lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session)
|
||||||
{
|
{
|
||||||
uint8_t * bmc_authcode;
|
uint8_t * bmc_authcode;
|
||||||
uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
|
uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
|
||||||
uint32_t generated_authcode_length;
|
uint32_t generated_authcode_length;
|
||||||
|
|
||||||
|
|
||||||
if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
|
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)
|
* returns 0 on success (we were able to successfully decrypt the packet)
|
||||||
* 1 on failure (we were unable to successfully decrypt the packet)
|
* 1 on failure (we were unable to successfully decrypt the packet)
|
||||||
*/
|
*/
|
||||||
int lanplus_decrypt_payload(uint8_t crypt_alg,
|
int
|
||||||
const uint8_t * key,
|
lanplus_decrypt_payload(uint8_t crypt_alg, const uint8_t * key,
|
||||||
const uint8_t * input,
|
const uint8_t * input, uint32_t input_length,
|
||||||
uint32_t input_length,
|
uint8_t * output, uint16_t * payload_size)
|
||||||
uint8_t * output,
|
|
||||||
uint16_t * payload_size)
|
|
||||||
{
|
{
|
||||||
uint8_t * decrypted_payload;
|
uint8_t * decrypted_payload;
|
||||||
uint32_t bytes_decrypted;
|
uint32_t bytes_decrypted;
|
||||||
@ -897,7 +915,7 @@ int lanplus_decrypt_payload(uint8_t crypt_alg,
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < conf_pad_length; ++i)
|
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");
|
lprintf(LOG_ERR, "Malformed payload padding");
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -51,7 +51,7 @@ int lanplus_generate_rakp3_authcode(uint8_t * buffer,
|
|||||||
const struct ipmi_session * session,
|
const struct ipmi_session * session,
|
||||||
uint32_t * auth_length,
|
uint32_t * auth_length,
|
||||||
struct ipmi_intf * intf);
|
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_k1(struct ipmi_session * session);
|
||||||
int lanplus_generate_k2(struct ipmi_session * session);
|
int lanplus_generate_k2(struct ipmi_session * session);
|
||||||
int lanplus_encrypt_payload(uint8_t crypt_alg,
|
int lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user