lanplus: Make byteswapping generic

Get rid of lanplus-specific yet very generic in nature
lanplus_swap() function that unconditionally swaps bytes
in an arbitrary byte array. Move it to helper module and
add two conditionally working interfaces to it:

 - array_ntoh() for network (BE) to host conversion, and
 - array_letoh() for ipmi (LE) to host conversion.

The added functions will only perform byte swapping if
the target architecture differs in endianness from the
data source. array_ntoh() will only do swap on LE machines,
while array_letoh() will only do it on BE ones.

These functions are introduced for future use in other
places of ipmitool.

Partially resolves ipmitool/ipmitool#26

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
This commit is contained in:
Alexander Amelkin 2018-08-01 11:33:44 +03:00
parent 5491b12596
commit 7747d86cc4
No known key found for this signature in database
GPG Key ID: E893587B5B74178D
3 changed files with 63 additions and 77 deletions

View File

@ -165,6 +165,9 @@ static inline void htoipmi32(uint32_t h, uint8_t *ipmi)
ipmi[3] = (h >> 24) & 0xFF; /* MSB */ ipmi[3] = (h >> 24) & 0xFF; /* MSB */
} }
uint8_t *array_ntoh(uint8_t *buffer, size_t length);
uint8_t *array_letoh(uint8_t *buffer, size_t length);
#define ipmi_open_file_read(file) ipmi_open_file(file, 0) #define ipmi_open_file_read(file) ipmi_open_file(file, 0)
#define ipmi_open_file_write(file) ipmi_open_file(file, 1) #define ipmi_open_file_write(file) ipmi_open_file(file, 1)

View File

@ -228,6 +228,48 @@ void printbuf(const uint8_t * buf, int len, const char * desc)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
/*
* Unconditionally reverse the order of arbitrarily long strings of bytes
*/
static uint8_t *_ipmi_byteswap(uint8_t *buffer, size_t length)
{
size_t i;
uint8_t temp;
size_t max = length - 1;
for (i = 0; i < length / 2; ++i) {
temp = buffer[i];
buffer[i] = buffer[max - i];
buffer[max - i] = temp;
}
return buffer;
}
/* Convert data array from network (big-endian) to host byte order */
uint8_t *array_ntoh(uint8_t *buffer, size_t length)
{
#if WORDS_BIGENDIAN
/* Big-endian host doesn't need conversion from big-endian network */
return buffer;
#else
/* Little-endian host needs conversion from big-endian network */
return _ipmi_byteswap(buffer, length);
#endif
}
/* Convert data array from little-endian to host byte order */
uint8_t *array_letoh(uint8_t *buffer, size_t length)
{
#if WORDS_BIGENDIAN
/* Big-endian host needs conversion from little-endian IPMI */
return _ipmi_byteswap(buffer, length);
#else
/* Little-endian host doesn't need conversion from little-endian IPMI */
return buffer;
#endif
}
/* str2mac - parse-out MAC address from given string and store it /* str2mac - parse-out MAC address from given string and store it
* into buffer. * into buffer.
* *

View File

@ -276,28 +276,6 @@ int lanplus_get_requested_ciphers(int cipher_suite_id,
return 0; return 0;
} }
/*
* Reverse the order of arbitrarily long strings of bytes
*/
void lanplus_swap(
uint8_t * buffer,
int length)
{
int i;
uint8_t temp;
for (i =0; i < length/2; ++i)
{
temp = buffer[i];
buffer[i] = buffer[length - 1 - i];
buffer[length - 1 - i] = temp;
}
}
static const struct valstr plus_payload_types_vals[] = { static const struct valstr plus_payload_types_vals[] = {
{ IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message { IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message
{ IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN) { IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN)
@ -1010,31 +988,19 @@ read_rakp2_message(
/* RAKP response code */ /* RAKP response code */
rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1]; rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1];
/* Console session ID */ /* Console session ID */
memcpy(&(rsp->payload.rakp2_message.console_id), rsp->payload.rakp2_message.console_id = ipmi32toh(&rsp->data[offset + 4]);
rsp->data + offset + 4,
4);
#if WORDS_BIGENDIAN
rsp->payload.rakp2_message.console_id =
BSWAP_32(rsp->payload.rakp2_message.console_id);
#endif
/* BMC random number */ /* BMC random number */
memcpy(&(rsp->payload.rakp2_message.bmc_rand), memcpy(&(rsp->payload.rakp2_message.bmc_rand),
rsp->data + offset + 8, array_letoh(&rsp->data[offset + 8], 16),
16); 16);
#if WORDS_BIGENDIAN
lanplus_swap(rsp->payload.rakp2_message.bmc_rand, 16); /* BMC GUID */
#endif memcpy(&(rsp->payload.rakp2_message.bmc_guid),
array_letoh(&rsp->data[offset + 24], 16),
16);
/* BMC GUID */
memcpy(&(rsp->payload.rakp2_message.bmc_guid),
rsp->data + offset + 24,
16);
#if WORDS_BIGENDIAN
lanplus_swap(rsp->payload.rakp2_message.bmc_guid, 16);
#endif
/* Key exchange authentication code */ /* Key exchange authentication code */
switch (auth_alg) switch (auth_alg)
{ {
@ -1110,16 +1076,9 @@ read_rakp4_message(
/* RAKP response code */ /* RAKP response code */
rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1]; rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1];
/* Console session ID */ /* Console session ID */
memcpy(&(rsp->payload.rakp4_message.console_id), rsp->payload.rakp4_message.console_id = ipmi32toh(&rsp->data[offset + 4]);
rsp->data + offset + 4,
4);
#if WORDS_BIGENDIAN
rsp->payload.rakp4_message.console_id =
BSWAP_32(rsp->payload.rakp4_message.console_id);
#endif
/* Integrity check value */ /* Integrity check value */
switch (auth_alg) switch (auth_alg)
{ {
@ -1230,25 +1189,15 @@ read_session_data_v2x(
rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F; rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F;
/* Session ID */ /* Session ID */
memcpy(&rsp->session.id, rsp->data + *offset, 4); rsp->session.id = ipmi32toh(&rsp->data[*offset]);
*offset += 4; *offset += 4;
#if WORDS_BIGENDIAN
rsp->session.id = BSWAP_32(rsp->session.id);
#endif
/* Ignored, so far */ /* Ignored, so far */
memcpy(&rsp->session.seq, rsp->data + *offset, 4); rsp->session.seq = ipmi32toh(&rsp->data[*offset]);
*offset += 4; *offset += 4;
#if WORDS_BIGENDIAN
rsp->session.seq = BSWAP_32(rsp->session.seq);
#endif
memcpy(&rsp->session.msglen, rsp->data + *offset, 2); rsp->session.msglen = ipmi16toh(&rsp->data[*offset]);
*offset += 2; *offset += 2;
#if WORDS_BIGENDIAN
rsp->session.msglen = BSWAP_16(rsp->session.msglen);
#endif
} }
@ -2807,7 +2756,6 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
struct ipmi_rs * rsp; struct ipmi_rs * rsp;
struct ipmi_rq req; struct ipmi_rq req;
uint8_t msg_data[4]; uint8_t msg_data[4];
uint32_t bmc_session_lsbf;
uint8_t backupBridgePossible; uint8_t backupBridgePossible;
if (intf->session == NULL if (intf->session == NULL
@ -2819,12 +2767,7 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
intf->target_addr = IPMI_BMC_SLAVE_ADDR; intf->target_addr = IPMI_BMC_SLAVE_ADDR;
bridgePossible = 0; bridgePossible = 0;
bmc_session_lsbf = intf->session->v2_data.bmc_id; htoipmi32(intf->session->v2_data.bmc_id, msg_data);
#if WORDS_BIGENDIAN
bmc_session_lsbf = BSWAP_32(bmc_session_lsbf);
#endif
memcpy(&msg_data, &bmc_session_lsbf, 4);
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; req.msg.netfn = IPMI_NETFN_APP;
@ -3101,9 +3044,7 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf)
return 1; return 1;
} }
memcpy(msg + 8, session->v2_data.console_rand, 16); memcpy(msg + 8, session->v2_data.console_rand, 16);
#if WORDS_BIGENDIAN array_letoh(msg + 8, 16);
lanplus_swap(msg + 8, 16);
#endif
if (verbose > 1) if (verbose > 1)
printbuf(session->v2_data.console_rand, 16, printbuf(session->v2_data.console_rand, 16,