summaryrefslogtreecommitdiff
path: root/lib/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/helper.c')
-rw-r--r--lib/helper.c183
1 files changed, 174 insertions, 9 deletions
diff --git a/lib/helper.c b/lib/helper.c
index 022a9c9..de91438 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -51,6 +51,7 @@
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
+#include <ctype.h>
#if HAVE_CONFIG_H
# include <config.h>
@@ -79,22 +80,139 @@ uint16_t buf2short(uint8_t * buf)
return (uint16_t)(buf[1] << 8 | buf[0]);
}
-const char * buf2str(uint8_t * buf, int len)
+/* buf2str_extended - convert sequence of bytes to hexadecimal string with
+ * optional separator
+ *
+ * @param buf - data to convert
+ * @param len - size of data
+ * @param sep - optional separator (can be NULL)
+ *
+ * @returns buf representation in hex, possibly truncated to fit
+ * allocated static memory
+ */
+const char *
+buf2str_extended(const uint8_t *buf, int len, const char *sep)
{
- static char str[2049];
+ static char str[BUF2STR_MAXIMUM_OUTPUT_SIZE];
+ char *cur;
int i;
+ int sz;
+ int left;
+ int sep_len;
- if (len <= 0 || len > 1024)
- return NULL;
+ if (buf == NULL) {
+ snprintf(str, sizeof(str), "<NULL>");
+ return (const char *)str;
+ }
+ cur = str;
+ left = sizeof(str);
+ if (sep) {
+ sep_len = strlen(sep);
+ } else {
+ sep_len = 0;
+ }
+ for (i = 0; i < len; i++) {
+ /* may return more than 2, depending on locale */
+ sz = snprintf(cur, left, "%2.2x", buf[i]);
+ if (sz >= left) {
+ /* buffer overflow, truncate */
+ break;
+ }
+ cur += sz;
+ left -= sz;
+ /* do not write separator after last byte */
+ if (sep && i != (len - 1)) {
+ if (sep_len >= left) {
+ break;
+ }
+ strncpy(cur, sep, left - sz);
+ cur += sep_len;
+ left -= sep_len;
+ }
+ }
+ *cur = '\0';
- memset(str, 0, 2049);
+ return (const char *)str;
+}
- for (i=0; i<len; i++)
- sprintf(str+i+i, "%2.2x", buf[i]);
+const char *
+buf2str(const uint8_t *buf, int len)
+{
+ return buf2str_extended(buf, len, NULL);
+}
- str[len*2] = '\0';
+/* ipmi_parse_hex - convert hexadecimal numbers to ascii string
+ * Input string must be composed of two-characer
+ * hexadecimal numbers.
+ * There is no separator between the numbers. Each number
+ * results in one byte of the converted string.
+ *
+ * Example: ipmi_parse_hex("50415353574F5244")
+ * returns 'PASSWORD'
+ *
+ * @param str: input string. It must contain only even number
+ * of '0'-'9','a'-'f' and 'A-F' characters.
+ * @param out: pointer to output data
+ * @param size: size of the output buffer
+ * @returns 0 for empty input string
+ * -1 for string with odd length
+ * -2 if out is NULL
+ * -3 if there is non-hexadecimal char in string
+ * >0 length of resulting binary data even if it is > size
+ */
+int
+ipmi_parse_hex(const char *str, uint8_t *out, int size)
+{
+ const char *p;
+ uint8_t *q;
+ uint8_t d = 0;
+ uint8_t b = 0;
+ int shift = 4;
+ int len;
+
+ len = strlen(str);
+ if (len == 0) {
+ return 0;
+ }
- return (const char *)str;
+ if (len % 2 != 0) {
+ return -1;
+ }
+
+ len /= 2; /* out bytes */
+ if (out == NULL) {
+ return -2;
+ }
+
+ for (p = str, q = out; *p; p++) {
+ if (!isxdigit(*p)) {
+ return -3;
+ }
+
+ if (*p < 'A') {
+ /* it must be 0-9 */
+ d = *p - '0';
+ } else {
+ /* it's A-F or a-f */
+ /* convert to lowercase and to 10-15 */
+ d = (*p | 0x20) - 'a' + 10;
+ }
+
+ if (q < (out + size)) {
+ /* there is space, store */
+ b += d << shift;
+ if (shift) {
+ shift = 0;
+ } else {
+ shift = 4;
+ *q = b;
+ b = 0;
+ q++;
+ }
+ }
+ }
+
+ return len;
}
void printbuf(const uint8_t * buf, int len, const char * desc)
@@ -116,6 +234,53 @@ void printbuf(const uint8_t * buf, int len, const char * desc)
fprintf(stderr, "\n");
}
+/* str2mac - parse-out MAC address from given string and store it
+ * into buffer.
+ *
+ * @arg: string to be parsed.
+ * @buf: buffer of 6 to hold parsed MAC address.
+ *
+ * returns zero on success, (-1) on error and error message is printed-out.
+ */
+int
+str2mac(const char *arg, uint8_t *buf)
+{
+ unsigned int m1 = 0;
+ unsigned int m2 = 0;
+ unsigned int m3 = 0;
+ unsigned int m4 = 0;
+ unsigned int m5 = 0;
+ unsigned int m6 = 0;
+ if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x",
+ &m1, &m2, &m3, &m4, &m5, &m6) != 6) {
+ lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
+ return -1;
+ }
+ if (m1 > UINT8_MAX || m2 > UINT8_MAX
+ || m3 > UINT8_MAX || m4 > UINT8_MAX
+ || m5 > UINT8_MAX || m6 > UINT8_MAX) {
+ lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
+ return -1;
+ }
+ buf[0] = (uint8_t)m1;
+ buf[1] = (uint8_t)m2;
+ buf[2] = (uint8_t)m3;
+ buf[3] = (uint8_t)m4;
+ buf[4] = (uint8_t)m5;
+ buf[5] = (uint8_t)m6;
+ return 0;
+}
+
+/* mac2str -- return MAC address as a string
+ *
+ * @buf: buffer of 6 to hold parsed MAC address.
+ */
+const char *
+mac2str(const uint8_t *buf)
+{
+ return buf2str_extended(buf, 6, ":");
+}
+
const char * val2str(uint16_t val, const struct valstr *vs)
{
static char un_str[32];