mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-30 13:01:23 +03:00
misc: Introduce ssh_log_hexdump()
The introduced internal function is intended to be a replacement for the deprecated function ssh_print_hexa(). Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Andreas Schneider
parent
c03c9b88d1
commit
33927f3ae8
@@ -83,4 +83,5 @@ int ssh_match_group(const char *group, const char *object);
|
||||
|
||||
void uint64_inc(unsigned char *counter);
|
||||
|
||||
void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len);
|
||||
#endif /* MISC_H_ */
|
||||
|
||||
187
src/misc.c
187
src/misc.c
@@ -389,6 +389,193 @@ void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
|
||||
free(hexa);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log the content of a buffer in hexadecimal format, similar to the
|
||||
* output of 'hexdump -C' command.
|
||||
*
|
||||
* The first logged line is the given description followed by the length.
|
||||
* Then the content of the buffer is logged 16 bytes per line in the following
|
||||
* format:
|
||||
*
|
||||
* (offset) (first 8 bytes) (last 8 bytes) (the 16 bytes as ASCII char values)
|
||||
*
|
||||
* The output for a 16 bytes array containing values from 0x00 to 0x0f would be:
|
||||
*
|
||||
* "Example (16 bytes):"
|
||||
* " 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................"
|
||||
*
|
||||
* The value for each byte as corresponding ASCII character is printed at the
|
||||
* end if the value is printable. Otherwise it is replace with '.'.
|
||||
*
|
||||
* @param[in] descr A description for the content to be logged
|
||||
* @param[in] what The buffer to be logged
|
||||
* @param[in] len The length of the buffer given in what
|
||||
*
|
||||
* @note If a too long description is provided (which would result in a first
|
||||
* line longer than 80 bytes), the function will fail.
|
||||
*/
|
||||
void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
char ascii[17];
|
||||
const unsigned char *pc = NULL;
|
||||
size_t count = 0;
|
||||
ssize_t printed = 0;
|
||||
|
||||
/* The required buffer size is calculated from:
|
||||
*
|
||||
* 2 bytes for spaces at the beginning
|
||||
* 8 bytes for the offset
|
||||
* 2 bytes for spaces
|
||||
* 24 bytes to print the first 8 bytes + spaces
|
||||
* 1 byte for an extra space
|
||||
* 24 bytes to print next 8 bytes + spaces
|
||||
* 2 bytes for extra spaces
|
||||
* 16 bytes for the content as ASCII characters at the end
|
||||
* 1 byte for the ending '\0'
|
||||
*
|
||||
* Resulting in 80 bytes.
|
||||
*
|
||||
* Except for the first line (description + size), all lines have fixed
|
||||
* length. If a too long description is used, the function will fail.
|
||||
* */
|
||||
char buffer[80];
|
||||
|
||||
/* Print description */
|
||||
if (descr != NULL) {
|
||||
printed = snprintf(buffer, sizeof(buffer), "%s ", descr);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
} else {
|
||||
printed = snprintf(buffer, sizeof(buffer), "(NULL description) ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
"(zero length):");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
return;
|
||||
} else {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
"(%zu bytes):", len);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
|
||||
if (what == NULL) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
"(NULL)");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
|
||||
/* Reset state */
|
||||
count = 0;
|
||||
pc = what;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
/* Add one space after printing 8 bytes */
|
||||
if ((i % 8) == 0) {
|
||||
if (i != 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Log previous line and reset state for new line */
|
||||
if ((i % 16) == 0) {
|
||||
if (i != 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
" %s", ascii);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/* Start a new line with the offset */
|
||||
printed = snprintf(buffer, sizeof(buffer),
|
||||
" %08zx ", i);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
|
||||
/* Print the current byte hexadecimal representation */
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
" %02x", pc[i]);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
|
||||
/* If printable, store the ASCII character */
|
||||
if (isprint(pc[i])) {
|
||||
ascii[i % 16] = pc[i];
|
||||
} else {
|
||||
ascii[i % 16] = '.';
|
||||
}
|
||||
ascii[(i % 16) + 1] = '\0';
|
||||
}
|
||||
|
||||
/* Add padding if not exactly 16 characters */
|
||||
while ((i % 16) != 0) {
|
||||
/* Add one space after printing 8 bytes */
|
||||
if ((i % 8) == 0) {
|
||||
if (i != 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
}
|
||||
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Print the last printable part */
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
" %s", ascii);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
SSH_LOG(SSH_LOG_WARN, "Could not print to buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if libssh is the required version or get the version
|
||||
* string.
|
||||
|
||||
Reference in New Issue
Block a user