Blame lib/helper.c

Packit Service ed0f68
/*
Packit Service ed0f68
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution and use in source and binary forms, with or without
Packit Service ed0f68
 * modification, are permitted provided that the following conditions
Packit Service ed0f68
 * are met:
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution of source code must retain the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution in binary form must reproduce the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer in the
Packit Service ed0f68
 * documentation and/or other materials provided with the distribution.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit Service ed0f68
 * contributors may be used to endorse or promote products derived
Packit Service ed0f68
 * from this software without specific prior written permission.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * This software is provided "AS IS," without a warranty of any kind.
Packit Service ed0f68
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit Service ed0f68
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit Service ed0f68
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit Service ed0f68
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit Service ed0f68
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit Service ed0f68
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit Service ed0f68
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit Service ed0f68
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit Service ed0f68
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit Service ed0f68
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit Service ed0f68
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit Service ed0f68
 */
Packit Service ed0f68
#define _POSIX_SOURCE
Packit Service ed0f68
#define /* glibc 2.19 and earlier */ _BSD_SOURCE || \
Packit Service ed0f68
	/* Since glibc 2.20 */_DEFAULT_SOURCE || \
Packit Service ed0f68
	_XOPEN_SOURCE >= 500 || \
Packit Service ed0f68
	_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || \
Packit Service ed0f68
	/* Since glibc 2.10: */ _POSIX_C_SOURCE >= 200112L \
Packit Service ed0f68
Packit Service ed0f68
#include <sys/types.h>
Packit Service ed0f68
#include <sys/stat.h>
Packit Service ed0f68
#include <sys/ioctl.h>  /* For TIOCNOTTY */
Packit Service ed0f68
Packit Service ed0f68
#include <stdlib.h>
Packit Service ed0f68
#include <stdint.h>
Packit Service ed0f68
#include <stdio.h>
Packit Service ed0f68
#include <inttypes.h>
Packit Service ed0f68
#include <signal.h>
Packit Service ed0f68
#include <string.h>
Packit Service ed0f68
#include <strings.h>
Packit Service ed0f68
#include <unistd.h>
Packit Service ed0f68
#include <fcntl.h>
Packit Service ed0f68
#include <errno.h>
Packit Service ed0f68
#include <assert.h>
Packit Service ed0f68
#include <ctype.h>
Packit Service ed0f68
Packit Service ed0f68
#if HAVE_CONFIG_H
Packit Service ed0f68
# include <config.h>
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
#ifdef HAVE_PATHS_H
Packit Service ed0f68
# include <paths.h>
Packit Service ed0f68
#else
Packit Service ed0f68
# define _PATH_VARRUN "/var/run/"
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
#include <ipmitool/ipmi.h>
Packit Service ed0f68
#include <ipmitool/ipmi_intf.h>
Packit Service ed0f68
#include <ipmitool/helper.h>
Packit Service ed0f68
#include <ipmitool/log.h>
Packit Service ed0f68
Packit Service ed0f68
extern int verbose;
Packit Service ed0f68
Packit Service ed0f68
uint32_t buf2long(uint8_t * buf)
Packit Service ed0f68
{
Packit Service ed0f68
	return (uint32_t)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
uint16_t buf2short(uint8_t * buf)
Packit Service ed0f68
{
Packit Service ed0f68
	return (uint16_t)(buf[1] << 8 | buf[0]);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* buf2str_extended - convert sequence of bytes to hexadecimal string with
Packit Service ed0f68
 * optional separator
Packit Service ed0f68
 *
Packit Service ed0f68
 * @param buf - data to convert
Packit Service ed0f68
 * @param len - size of data
Packit Service ed0f68
 * @param sep - optional separator (can be NULL)
Packit Service ed0f68
 *
Packit Service ed0f68
 * @returns     buf representation in hex, possibly truncated to fit
Packit Service ed0f68
 *              allocated static memory
Packit Service ed0f68
 */
Packit Service ed0f68
const char *
Packit Service ed0f68
buf2str_extended(const uint8_t *buf, int len, const char *sep)
Packit Service ed0f68
{
Packit Service ed0f68
	static char str[BUF2STR_MAXIMUM_OUTPUT_SIZE];
Packit Service ed0f68
	char *cur;
Packit Service ed0f68
	int i;
Packit Service ed0f68
	int sz;
Packit Service ed0f68
	int left;
Packit Service ed0f68
	int sep_len;
Packit Service ed0f68
Packit Service ed0f68
	if (buf == NULL) {
Packit Service ed0f68
		snprintf(str, sizeof(str), "<NULL>");
Packit Service ed0f68
		return (const char *)str;
Packit Service ed0f68
	}
Packit Service ed0f68
	cur = str;
Packit Service ed0f68
	left = sizeof(str);
Packit Service ed0f68
	if (sep) {
Packit Service ed0f68
		sep_len = strlen(sep);
Packit Service ed0f68
	} else {
Packit Service ed0f68
		sep_len = 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	for (i = 0; i < len; i++) {
Packit Service ed0f68
		/* may return more than 2, depending on locale */
Packit Service ed0f68
		sz = snprintf(cur, left, "%2.2x", buf[i]);
Packit Service ed0f68
		if (sz >= left) {
Packit Service ed0f68
			/* buffer overflow, truncate */
Packit Service ed0f68
			break;
Packit Service ed0f68
		}
Packit Service ed0f68
		cur += sz;
Packit Service ed0f68
		left -= sz;
Packit Service ed0f68
		/* do not write separator after last byte */
Packit Service ed0f68
		if (sep && i != (len - 1)) {
Packit Service ed0f68
			if (sep_len >= left) {
Packit Service ed0f68
				break;
Packit Service ed0f68
			}
Packit Service ed0f68
			strncpy(cur, sep, left - sz);
Packit Service ed0f68
			cur += sep_len;
Packit Service ed0f68
			left -= sep_len;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
	*cur = '\0';
Packit Service ed0f68
Packit Service ed0f68
	return (const char *)str;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
const char *
Packit Service ed0f68
buf2str(const uint8_t *buf, int len)
Packit Service ed0f68
{
Packit Service ed0f68
	return buf2str_extended(buf, len, NULL);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* ipmi_parse_hex - convert hexadecimal numbers to ascii string
Packit Service ed0f68
 *                  Input string must be composed of two-characer
Packit Service ed0f68
 *                  hexadecimal numbers.
Packit Service ed0f68
 *                  There is no separator between the numbers. Each number
Packit Service ed0f68
 *                  results in one byte of the converted string.
Packit Service ed0f68
 *
Packit Service ed0f68
 *                  Example: ipmi_parse_hex("50415353574F5244")
Packit Service ed0f68
 *                  returns 'PASSWORD'
Packit Service ed0f68
 *
Packit Service ed0f68
 * @param str:  input string. It must contain only even number
Packit Service ed0f68
 *              of '0'-'9','a'-'f' and 'A-F' characters.
Packit Service ed0f68
 * @param out: pointer to output data
Packit Service ed0f68
 * @param size: size of the output buffer
Packit Service ed0f68
 * @returns 0 for empty input string
Packit Service ed0f68
 *         -1 for string with odd length
Packit Service ed0f68
 *         -2 if out is NULL
Packit Service ed0f68
 *         -3 if there is non-hexadecimal char in string
Packit Service ed0f68
 *         >0 length of resulting binary data even if it is > size
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
ipmi_parse_hex(const char *str, uint8_t *out, int size)
Packit Service ed0f68
{
Packit Service ed0f68
	const char *p;
Packit Service ed0f68
	uint8_t *q;
Packit Service ed0f68
	uint8_t d = 0;
Packit Service ed0f68
	uint8_t b = 0;
Packit Service ed0f68
	int shift = 4;
Packit Service ed0f68
	int len;
Packit Service ed0f68
Packit Service ed0f68
	len = strlen(str);
Packit Service ed0f68
	if (len == 0) {
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (len % 2 != 0) {
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	len /= 2; /* out bytes */
Packit Service ed0f68
	if (out == NULL) {
Packit Service ed0f68
		return -2;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	for (p = str, q = out; *p; p++) {
Packit Service ed0f68
		if (!isxdigit(*p)) {
Packit Service ed0f68
			return -3;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		if (*p < 'A') {
Packit Service ed0f68
			/* it must be 0-9 */
Packit Service ed0f68
			d = *p - '0';
Packit Service ed0f68
		} else {
Packit Service ed0f68
			/* it's A-F or a-f */
Packit Service ed0f68
			/* convert to lowercase and to 10-15 */
Packit Service ed0f68
			d = (*p | 0x20) - 'a' + 10;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		if (q < (out + size)) {
Packit Service ed0f68
			/* there is space, store */
Packit Service ed0f68
			b += d << shift;
Packit Service ed0f68
			if (shift) {
Packit Service ed0f68
				shift = 0;
Packit Service ed0f68
			} else {
Packit Service ed0f68
				shift = 4;
Packit Service ed0f68
				*q = b;
Packit Service ed0f68
				b = 0;
Packit Service ed0f68
				q++;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return len;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
void printbuf(const uint8_t * buf, int len, const char * desc)
Packit Service ed0f68
{
Packit Service ed0f68
	int i;
Packit Service ed0f68
Packit Service ed0f68
	if (len <= 0)
Packit Service ed0f68
		return;
Packit Service ed0f68
Packit Service ed0f68
	if (verbose < 1)
Packit Service ed0f68
		return;
Packit Service ed0f68
Packit Service ed0f68
	fprintf(stderr, "%s (%d bytes)\n", desc, len);
Packit Service ed0f68
	for (i=0; i
Packit Service ed0f68
		if (((i%16) == 0) && (i != 0))
Packit Service ed0f68
			fprintf(stderr, "\n");
Packit Service ed0f68
		fprintf(stderr, " %2.2x", buf[i]);
Packit Service ed0f68
	}
Packit Service ed0f68
	fprintf(stderr, "\n");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* str2mac - parse-out MAC address from given string and store it
Packit Service ed0f68
 * into buffer.
Packit Service ed0f68
 *
Packit Service ed0f68
 * @arg: string to be parsed.
Packit Service ed0f68
 * @buf: buffer of 6 to hold parsed MAC address.
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success, (-1) on error and error message is printed-out.
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
str2mac(const char *arg, uint8_t *buf)
Packit Service ed0f68
{
Packit Service ed0f68
	unsigned int m1 = 0;
Packit Service ed0f68
	unsigned int m2 = 0;
Packit Service ed0f68
	unsigned int m3 = 0;
Packit Service ed0f68
	unsigned int m4 = 0;
Packit Service ed0f68
	unsigned int m5 = 0;
Packit Service ed0f68
	unsigned int m6 = 0;
Packit Service ed0f68
	if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x",
Packit Service ed0f68
		   &m1, &m2, &m3, &m4, &m5, &m6) != 6) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
	if (m1 > UINT8_MAX || m2 > UINT8_MAX
Packit Service ed0f68
			|| m3 > UINT8_MAX || m4 > UINT8_MAX
Packit Service ed0f68
			|| m5 > UINT8_MAX || m6 > UINT8_MAX) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
	buf[0] = (uint8_t)m1;
Packit Service ed0f68
	buf[1] = (uint8_t)m2;
Packit Service ed0f68
	buf[2] = (uint8_t)m3;
Packit Service ed0f68
	buf[3] = (uint8_t)m4;
Packit Service ed0f68
	buf[4] = (uint8_t)m5;
Packit Service ed0f68
	buf[5] = (uint8_t)m6;
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* mac2str   -- return MAC address as a string
Packit Service ed0f68
 *
Packit Service ed0f68
 * @buf: buffer of 6 to hold parsed MAC address.
Packit Service ed0f68
 */
Packit Service ed0f68
const char *
Packit Service ed0f68
mac2str(const uint8_t *buf)
Packit Service ed0f68
{
Packit Service ed0f68
	return buf2str_extended(buf, 6, ":");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
const char * val2str(uint16_t val, const struct valstr *vs)
Packit Service ed0f68
{
Packit Service ed0f68
	static char un_str[32];
Packit Service ed0f68
	int i;
Packit Service ed0f68
Packit Service ed0f68
	for (i = 0; vs[i].str != NULL; i++) {
Packit Service ed0f68
		if (vs[i].val == val)
Packit Service ed0f68
			return vs[i].str;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	memset(un_str, 0, 32);
Packit Service ed0f68
	snprintf(un_str, 32, "Unknown (0x%02X)", val);
Packit Service ed0f68
Packit Service ed0f68
	return un_str;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
const char * oemval2str(uint32_t oem, uint16_t val,
Packit Service ed0f68
                                             const struct oemvalstr *vs)
Packit Service ed0f68
{
Packit Service ed0f68
	static char un_str[32];
Packit Service ed0f68
	int i;
Packit Service ed0f68
Packit Service ed0f68
	for (i = 0; vs[i].oem != 0xffffff &&  vs[i].str != NULL; i++) {
Packit Service ed0f68
		/* FIXME: for now on we assume PICMG capability on all IANAs */
Packit Service ed0f68
		if ( (vs[i].oem == oem || vs[i].oem == IPMI_OEM_PICMG) &&
Packit Service ed0f68
				vs[i].val == val ) {
Packit Service ed0f68
			return vs[i].str;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	memset(un_str, 0, 32);
Packit Service ed0f68
	snprintf(un_str, 32, "Unknown (0x%X)", val);
Packit Service ed0f68
Packit Service ed0f68
	return un_str;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* str2double - safely convert string to double
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @double_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
Packit Service ed0f68
 */
Packit Service ed0f68
int str2double(const char * str, double * double_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	char * end_ptr = 0;
Packit Service ed0f68
	if (!str || !double_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	*double_ptr = 0;
Packit Service ed0f68
	errno = 0;
Packit Service ed0f68
	*double_ptr = strtod(str, &end_ptr);
Packit Service ed0f68
Packit Service ed0f68
	if (*end_ptr != '\0')
Packit Service ed0f68
		return (-2);
Packit Service ed0f68
Packit Service ed0f68
	if (errno != 0)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2double(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2long - safely convert string to int64_t
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @lng_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
Packit Service ed0f68
 */
Packit Service ed0f68
int str2long(const char * str, int64_t * lng_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	char * end_ptr = 0;
Packit Service ed0f68
	if (!str || !lng_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	*lng_ptr = 0;
Packit Service ed0f68
	errno = 0;
Packit Service ed0f68
	*lng_ptr = strtol(str, &end_ptr, 0);
Packit Service ed0f68
Packit Service ed0f68
	if (*end_ptr != '\0')
Packit Service ed0f68
		return (-2);
Packit Service ed0f68
Packit Service ed0f68
	if (errno != 0)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2long(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2ulong - safely convert string to uint64_t
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @ulng_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
Packit Service ed0f68
 */
Packit Service ed0f68
int str2ulong(const char * str, uint64_t * ulng_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	char * end_ptr = 0;
Packit Service ed0f68
	if (!str || !ulng_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	*ulng_ptr = 0;
Packit Service ed0f68
	errno = 0;
Packit Service ed0f68
	*ulng_ptr = strtoul(str, &end_ptr, 0);
Packit Service ed0f68
Packit Service ed0f68
	if (*end_ptr != '\0')
Packit Service ed0f68
		return (-2);
Packit Service ed0f68
Packit Service ed0f68
	if (errno != 0)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2ulong(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2int - safely convert string to int32_t
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @int_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
Packit Service ed0f68
 */
Packit Service ed0f68
int str2int(const char * str, int32_t * int_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	int rc = 0;
Packit Service ed0f68
	int64_t arg_long = 0;
Packit Service ed0f68
	if (!str || !int_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	if ( (rc = str2long(str, &arg_long)) != 0 ) {
Packit Service ed0f68
		*int_ptr = 0;
Packit Service ed0f68
		return rc;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (arg_long < INT32_MIN || arg_long > INT32_MAX)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	*int_ptr = (int32_t)arg_long;
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2int(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2uint - safely convert string to uint32_t
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @uint_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
Packit Service ed0f68
 */
Packit Service ed0f68
int str2uint(const char * str, uint32_t * uint_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	int rc = 0;
Packit Service ed0f68
	uint64_t arg_ulong = 0;
Packit Service ed0f68
	if (!str || !uint_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	if ( (rc = str2ulong(str, &arg_ulong)) != 0) {
Packit Service ed0f68
		*uint_ptr = 0;
Packit Service ed0f68
		return rc;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (arg_ulong > UINT32_MAX)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	*uint_ptr = (uint32_t)arg_ulong;
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2uint(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2short - safely convert string to int16_t
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @shrt_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
Packit Service ed0f68
 */
Packit Service ed0f68
int str2short(const char * str, int16_t * shrt_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	int rc = (-3);
Packit Service ed0f68
	int64_t arg_long = 0;
Packit Service ed0f68
	if (!str || !shrt_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	if ( (rc = str2long(str, &arg_long)) != 0 ) {
Packit Service ed0f68
		*shrt_ptr = 0;
Packit Service ed0f68
		return rc;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (arg_long < INT16_MIN || arg_long > INT16_MAX)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	*shrt_ptr = (int16_t)arg_long;
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2short(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2ushort - safely convert string to uint16_t
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @ushrt_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
Packit Service ed0f68
 */
Packit Service ed0f68
int str2ushort(const char * str, uint16_t * ushrt_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	int rc = (-3);
Packit Service ed0f68
	uint64_t arg_ulong = 0;
Packit Service ed0f68
	if (!str || !ushrt_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
Packit Service ed0f68
		*ushrt_ptr = 0;
Packit Service ed0f68
		return rc;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (arg_ulong > UINT16_MAX)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	*ushrt_ptr = (uint16_t)arg_ulong;
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2ushort(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2char - safely convert string to int8
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @chr_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
Packit Service ed0f68
 */
Packit Service ed0f68
int str2char(const char *str, int8_t * chr_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	int rc = (-3);
Packit Service ed0f68
	int64_t arg_long = 0;
Packit Service ed0f68
	if (!str || !chr_ptr) {
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
	if ((rc = str2long(str, &arg_long)) != 0) {
Packit Service ed0f68
		*chr_ptr = 0;
Packit Service ed0f68
		return rc;
Packit Service ed0f68
	}
Packit Service ed0f68
	if (arg_long < INT8_MIN || arg_long > INT8_MAX) {
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
	}
Packit Service ed0f68
	*chr_ptr = (uint8_t)arg_long;
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2char(...) */
Packit Service ed0f68
Packit Service ed0f68
/* str2uchar - safely convert string to uint8
Packit Service ed0f68
 *
Packit Service ed0f68
 * @str: source string to convert from
Packit Service ed0f68
 * @uchr_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
Packit Service ed0f68
 */
Packit Service ed0f68
int str2uchar(const char * str, uint8_t * uchr_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	int rc = (-3);
Packit Service ed0f68
	uint64_t arg_ulong = 0;
Packit Service ed0f68
	if (!str || !uchr_ptr)
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
Packit Service ed0f68
	if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
Packit Service ed0f68
		*uchr_ptr = 0;
Packit Service ed0f68
		return rc;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (arg_ulong > UINT8_MAX)
Packit Service ed0f68
		return (-3);
Packit Service ed0f68
Packit Service ed0f68
	*uchr_ptr = (uint8_t)arg_ulong;
Packit Service ed0f68
	return 0;
Packit Service ed0f68
} /* str2uchar(...) */
Packit Service ed0f68
Packit Service ed0f68
uint16_t str2val(const char *str, const struct valstr *vs)
Packit Service ed0f68
{
Packit Service ed0f68
	int i;
Packit Service ed0f68
Packit Service ed0f68
	for (i = 0; vs[i].str != NULL; i++) {
Packit Service ed0f68
		if (strncasecmp(vs[i].str, str, __maxlen(str, vs[i].str)) == 0)
Packit Service ed0f68
			return vs[i].val;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return vs[i].val;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* print_valstr  -  print value string list to log or stdout
Packit Service ed0f68
 *
Packit Service ed0f68
 * @vs:		value string list to print
Packit Service ed0f68
 * @title:	name of this value string list
Packit Service ed0f68
 * @loglevel:	what log level to print, -1 for stdout
Packit Service ed0f68
 */
Packit Service ed0f68
void
Packit Service ed0f68
print_valstr(const struct valstr * vs, const char * title, int loglevel)
Packit Service ed0f68
{
Packit Service ed0f68
	int i;
Packit Service ed0f68
Packit Service ed0f68
	if (vs == NULL)
Packit Service ed0f68
		return;
Packit Service ed0f68
Packit Service ed0f68
	if (title != NULL) {
Packit Service ed0f68
		if (loglevel < 0)
Packit Service ed0f68
			printf("\n%s:\n\n", title);
Packit Service ed0f68
		else
Packit Service ed0f68
			lprintf(loglevel, "\n%s:\n", title);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (loglevel < 0) {
Packit Service ed0f68
		printf("  VALUE\tHEX\tSTRING\n");
Packit Service ed0f68
		printf("==============================================\n");
Packit Service ed0f68
	} else {
Packit Service ed0f68
		lprintf(loglevel, "  VAL\tHEX\tSTRING");
Packit Service ed0f68
		lprintf(loglevel, "==============================================");
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	for (i = 0; vs[i].str != NULL; i++) {
Packit Service ed0f68
		if (loglevel < 0) {
Packit Service ed0f68
			if (vs[i].val < 256)
Packit Service ed0f68
				printf("  %d\t0x%02x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
Packit Service ed0f68
			else
Packit Service ed0f68
				printf("  %d\t0x%04x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
Packit Service ed0f68
		} else {
Packit Service ed0f68
			if (vs[i].val < 256)
Packit Service ed0f68
				lprintf(loglevel, "  %d\t0x%02x\t%s", vs[i].val, vs[i].val, vs[i].str);
Packit Service ed0f68
			else
Packit Service ed0f68
				lprintf(loglevel, "  %d\t0x%04x\t%s", vs[i].val, vs[i].val, vs[i].str);
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (loglevel < 0)
Packit Service ed0f68
		printf("\n");
Packit Service ed0f68
	else
Packit Service ed0f68
		lprintf(loglevel, "");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* print_valstr_2col  -  print value string list in two columns to log or stdout
Packit Service ed0f68
 *
Packit Service ed0f68
 * @vs:		value string list to print
Packit Service ed0f68
 * @title:	name of this value string list
Packit Service ed0f68
 * @loglevel:	what log level to print, -1 for stdout
Packit Service ed0f68
 */
Packit Service ed0f68
void
Packit Service ed0f68
print_valstr_2col(const struct valstr * vs, const char * title, int loglevel)
Packit Service ed0f68
{
Packit Service ed0f68
	int i;
Packit Service ed0f68
Packit Service ed0f68
	if (vs == NULL)
Packit Service ed0f68
		return;
Packit Service ed0f68
Packit Service ed0f68
	if (title != NULL) {
Packit Service ed0f68
		if (loglevel < 0)
Packit Service ed0f68
			printf("\n%s:\n\n", title);
Packit Service ed0f68
		else
Packit Service ed0f68
			lprintf(loglevel, "\n%s:\n", title);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	for (i = 0; vs[i].str != NULL; i++) {
Packit Service ed0f68
		if (vs[i+1].str == NULL) {
Packit Service ed0f68
			/* last one */
Packit Service ed0f68
			if (loglevel < 0) {
Packit Service ed0f68
				printf("  %4d  %-32s\n", vs[i].val, vs[i].str);
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(loglevel, "  %4d  %-32s\n", vs[i].val, vs[i].str);
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		else {
Packit Service ed0f68
			if (loglevel < 0) {
Packit Service ed0f68
				printf("  %4d  %-32s    %4d  %-32s\n",
Packit Service ed0f68
				       vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(loglevel, "  %4d  %-32s    %4d  %-32s\n",
Packit Service ed0f68
					vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
Packit Service ed0f68
			}
Packit Service ed0f68
			i++;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (loglevel < 0)
Packit Service ed0f68
		printf("\n");
Packit Service ed0f68
	else
Packit Service ed0f68
		lprintf(loglevel, "");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* ipmi_csum  -  calculate an ipmi checksum
Packit Service ed0f68
 *
Packit Service ed0f68
 * @d:		buffer to check
Packit Service ed0f68
 * @s:		position in buffer to start checksum from
Packit Service ed0f68
 */
Packit Service ed0f68
uint8_t
Packit Service ed0f68
ipmi_csum(uint8_t * d, int s)
Packit Service ed0f68
{
Packit Service ed0f68
	uint8_t c = 0;
Packit Service ed0f68
	for (; s > 0; s--, d++)
Packit Service ed0f68
		c += *d;
Packit Service ed0f68
	return -c;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* ipmi_open_file  -  safely open a file for reading or writing
Packit Service ed0f68
 *
Packit Service ed0f68
 * @file:	filename
Packit Service ed0f68
 * @rw:		read-write flag, 1=write
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns pointer to file handler on success
Packit Service ed0f68
 * returns NULL on error
Packit Service ed0f68
 */
Packit Service ed0f68
FILE *
Packit Service ed0f68
ipmi_open_file(const char * file, int rw)
Packit Service ed0f68
{
Packit Service ed0f68
	struct stat st1, st2;
Packit Service ed0f68
	FILE * fp;
Packit Service ed0f68
Packit Service ed0f68
	/* verify existance */
Packit Service ed0f68
	if (lstat(file, &st1) < 0) {
Packit Service ed0f68
		if (rw) {
Packit Service ed0f68
			/* does not exist, ok to create */
Packit Service ed0f68
			fp = fopen(file, "w");
Packit Service ed0f68
			if (fp == NULL) {
Packit Service ed0f68
				lperror(LOG_ERR, "Unable to open file %s "
Packit Service ed0f68
					"for write", file);
Packit Service ed0f68
				return NULL;
Packit Service ed0f68
			}
Packit Service ed0f68
			/* created ok, now return the descriptor */
Packit Service ed0f68
			return fp;
Packit Service ed0f68
		} else {
Packit Service ed0f68
			lprintf(LOG_ERR, "File %s does not exist", file);
Packit Service ed0f68
			return NULL;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
#ifndef ENABLE_FILE_SECURITY
Packit Service ed0f68
	if (!rw) {
Packit Service ed0f68
		/* on read skip the extra checks */
Packit Service ed0f68
		fp = fopen(file, "r");
Packit Service ed0f68
		if (fp == NULL) {
Packit Service ed0f68
			lperror(LOG_ERR, "Unable to open file %s", file);
Packit Service ed0f68
			return NULL;
Packit Service ed0f68
		}
Packit Service ed0f68
		return fp;
Packit Service ed0f68
	}
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
	/* it exists - only regular files, not links */
Packit Service ed0f68
	if (S_ISREG(st1.st_mode) == 0) {
Packit Service ed0f68
		lprintf(LOG_ERR, "File %s has invalid mode: %d",
Packit Service ed0f68
			file, st1.st_mode);
Packit Service ed0f68
		return NULL;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/* allow only files with 1 link (itself) */
Packit Service ed0f68
	if (st1.st_nlink != 1) {
Packit Service ed0f68
		lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
Packit Service ed0f68
		       file, (int)st1.st_nlink);
Packit Service ed0f68
		return NULL;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	fp = fopen(file, rw ? "w+" : "r");
Packit Service ed0f68
	if (fp == NULL) {
Packit Service ed0f68
		lperror(LOG_ERR, "Unable to open file %s", file);
Packit Service ed0f68
		return NULL;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/* stat again */
Packit Service ed0f68
	if (fstat(fileno(fp), &st2) < 0) {
Packit Service ed0f68
		lperror(LOG_ERR, "Unable to stat file %s", file);
Packit Service ed0f68
		fclose(fp);
Packit Service ed0f68
		return NULL;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/* verify inode */
Packit Service ed0f68
	if (st1.st_ino != st2.st_ino) {
Packit Service ed0f68
		lprintf(LOG_ERR, "File %s has invalid inode: %d != %d",
Packit Service ed0f68
			file, st1.st_ino, st2.st_ino);
Packit Service ed0f68
		fclose(fp);
Packit Service ed0f68
		return NULL;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/* verify owner */
Packit Service ed0f68
	if (st1.st_uid != st2.st_uid) {
Packit Service ed0f68
		lprintf(LOG_ERR, "File %s has invalid user id: %d != %d",
Packit Service ed0f68
			file, st1.st_uid, st2.st_uid);
Packit Service ed0f68
		fclose(fp);
Packit Service ed0f68
		return NULL;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/* verify inode */
Packit Service ed0f68
	if (st2.st_nlink != 1) {
Packit Service ed0f68
		lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
Packit Service ed0f68
			file, st2.st_nlink);
Packit Service ed0f68
		fclose(fp);
Packit Service ed0f68
		return NULL;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return fp;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
void
Packit Service ed0f68
ipmi_start_daemon(struct ipmi_intf *intf)
Packit Service ed0f68
{
Packit Service ed0f68
	pid_t pid;
Packit Service ed0f68
	int fd;
Packit Service ed0f68
#ifdef SIGHUP
Packit Service ed0f68
	sigset_t sighup;
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
#ifdef SIGHUP
Packit Service ed0f68
	sigemptyset(&sighup);
Packit Service ed0f68
	sigaddset(&sighup, SIGHUP);
Packit Service ed0f68
	if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0)
Packit Service ed0f68
		fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
Packit Service ed0f68
	signal(SIGHUP, SIG_IGN);
Packit Service ed0f68
#endif
Packit Service ed0f68
#ifdef SIGTTOU
Packit Service ed0f68
	signal(SIGTTOU, SIG_IGN);
Packit Service ed0f68
#endif
Packit Service ed0f68
#ifdef SIGTTIN
Packit Service ed0f68
	signal(SIGTTIN, SIG_IGN);
Packit Service ed0f68
#endif
Packit Service ed0f68
#ifdef SIGQUIT
Packit Service ed0f68
	signal(SIGQUIT, SIG_IGN);
Packit Service ed0f68
#endif
Packit Service ed0f68
#ifdef SIGTSTP
Packit Service ed0f68
	signal(SIGTSTP, SIG_IGN);
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
	pid = (pid_t) fork();
Packit Service ed0f68
	if (pid < 0 || pid > 0)
Packit Service ed0f68
		exit(0);
Packit Service ed0f68
Packit Service ed0f68
#if defined(SIGTSTP) && defined(TIOCNOTTY)
Packit Service ed0f68
	if (setpgid(0, getpid()) == -1)
Packit Service ed0f68
		exit(1);
Packit Service ed0f68
	if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
Packit Service ed0f68
		ioctl(fd, TIOCNOTTY, NULL);
Packit Service ed0f68
		close(fd);
Packit Service ed0f68
	}
Packit Service ed0f68
#else
Packit Service ed0f68
	if (setpgid(0, 0) == -1)
Packit Service ed0f68
		exit(1);
Packit Service ed0f68
	pid = (pid_t) fork();
Packit Service ed0f68
	if (pid < 0 || pid > 0)
Packit Service ed0f68
		exit(0);
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
	chdir("/");
Packit Service ed0f68
	umask(0);
Packit Service ed0f68
Packit Service ed0f68
	for (fd=0; fd<64; fd++) {
Packit Service ed0f68
		if (fd != intf->fd)
Packit Service ed0f68
			close(fd);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	fd = open("/dev/null", O_RDWR);
Packit Service ed0f68
	assert(0 == fd);
Packit Service ed0f68
	dup(fd);
Packit Service ed0f68
	dup(fd);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* eval_ccode - evaluate return value of _ipmi_* functions and print error error
Packit Service ed0f68
 * message, if conditions are met.
Packit Service ed0f68
 *
Packit Service ed0f68
 * @ccode - return value of _ipmi_* function.
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns - 0 if ccode is 0, otherwise (-1) and error might get printed-out.
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
eval_ccode(const int ccode)
Packit Service ed0f68
{
Packit Service ed0f68
	if (ccode == 0) {
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	} else if (ccode < 0) {
Packit Service ed0f68
		switch (ccode) {
Packit Service ed0f68
			case (-1):
Packit Service ed0f68
				lprintf(LOG_ERR, "IPMI response is NULL.");
Packit Service ed0f68
				break;
Packit Service ed0f68
			case (-2):
Packit Service ed0f68
				lprintf(LOG_ERR, "Unexpected data length received.");
Packit Service ed0f68
				break;
Packit Service ed0f68
			case (-3):
Packit Service ed0f68
				lprintf(LOG_ERR, "Invalid function parameter.");
Packit Service ed0f68
				break;
Packit Service ed0f68
			case (-4):
Packit Service ed0f68
				lprintf(LOG_ERR, "ipmitool: malloc failure.");
Packit Service ed0f68
				break;
Packit Service ed0f68
			default:
Packit Service ed0f68
				break;
Packit Service ed0f68
		}
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	} else {
Packit Service ed0f68
		lprintf(LOG_ERR, "IPMI command failed: %s",
Packit Service ed0f68
				val2str(ccode, completion_code_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed
Packit Service ed0f68
 * on error.
Packit Service ed0f68
 * FRU ID range: <0..255>
Packit Service ed0f68
 *
Packit Service ed0f68
 * @argv_ptr: source string to convert from; usually argv
Packit Service ed0f68
 * @fru_id_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) on error and message is printed on STDERR
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	if (!argv_ptr || !fru_id_ptr) {
Packit Service ed0f68
		lprintf(LOG_ERR, "is_fru_id(): invalid argument(s).");
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (str2uchar(argv_ptr, fru_id_ptr) == 0) {
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	lprintf(LOG_ERR, "FRU ID '%s' is either invalid or out of range.",
Packit Service ed0f68
			argv_ptr);
Packit Service ed0f68
	return (-1);
Packit Service ed0f68
} /* is_fru_id(...) */
Packit Service ed0f68
Packit Service ed0f68
/* is_ipmi_channel_num - wrapper for str-2-int Channel conversion. Message is
Packit Service ed0f68
 * printed on error.
Packit Service ed0f68
 *
Packit Service ed0f68
 * 6.3 Channel Numbers, p. 49, IPMIv2 spec. rev1.1
Packit Service ed0f68
 * Valid channel numbers are: <0x0..0xB>, <0xE-0xF>
Packit Service ed0f68
 * Reserved channel numbers: <0xC-0xD>
Packit Service ed0f68
 *
Packit Service ed0f68
 * @argv_ptr: source string to convert from; usually argv
Packit Service ed0f68
 * @channel_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) on error and message is printed on STDERR
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	if (!argv_ptr || !channel_ptr) {
Packit Service ed0f68
		lprintf(LOG_ERR,
Packit Service ed0f68
				"is_ipmi_channel_num(): invalid argument(s).");
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
	if ((str2uchar(argv_ptr, channel_ptr) == 0)
Packit Service ed0f68
			&& (*channel_ptr <= 0xB
Packit Service ed0f68
				|| (*channel_ptr >= 0xE && *channel_ptr <= 0xF))) {
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	lprintf(LOG_ERR,
Packit Service ed0f68
			"Given Channel number '%s' is either invalid or out of range.",
Packit Service ed0f68
			argv_ptr);
Packit Service ed0f68
	lprintf(LOG_ERR, "Channel number must be from ranges: <0x0..0xB>, <0xE..0xF>");
Packit Service ed0f68
	return (-1);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* is_ipmi_user_id() - wrapper for str-2-uint IPMI UID conversion. Message is
Packit Service ed0f68
 * printed on error.
Packit Service ed0f68
 *
Packit Service ed0f68
 * @argv_ptr: source string to convert from; usually argv
Packit Service ed0f68
 * @ipmi_uid_ptr: pointer where to store result
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns zero on success
Packit Service ed0f68
 * returns (-1) on error and message is printed on STDERR
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	if (!argv_ptr || !ipmi_uid_ptr) {
Packit Service ed0f68
		lprintf(LOG_ERR,
Packit Service ed0f68
				"is_ipmi_user_id(): invalid argument(s).");
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
	if ((str2uchar(argv_ptr, ipmi_uid_ptr) == 0)
Packit Service ed0f68
			&& *ipmi_uid_ptr >= IPMI_UID_MIN
Packit Service ed0f68
			&& *ipmi_uid_ptr <= IPMI_UID_MAX) {
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	lprintf(LOG_ERR,
Packit Service ed0f68
			"Given User ID '%s' is either invalid or out of range.",
Packit Service ed0f68
			argv_ptr);
Packit Service ed0f68
	lprintf(LOG_ERR, "User ID is limited to range <%i..%i>.",
Packit Service ed0f68
			IPMI_UID_MIN, IPMI_UID_MAX);
Packit Service ed0f68
	return (-1);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
/* is_ipmi_user_priv_limit - check whether given value is valid User Privilege
Packit Service ed0f68
 * Limit, eg. IPMI v2 spec, 22.27 Get User Access Command.
Packit Service ed0f68
 *
Packit Service ed0f68
 * @priv_limit: User Privilege Limit
Packit Service ed0f68
 *
Packit Service ed0f68
 * returns 0 if Priv Limit is valid
Packit Service ed0f68
 * returns (-1) when Priv Limit is invalid
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr)
Packit Service ed0f68
{
Packit Service ed0f68
	if (!argv_ptr || !ipmi_priv_limit_ptr) {
Packit Service ed0f68
		lprintf(LOG_ERR,
Packit Service ed0f68
				"is_ipmi_user_priv_limit(): invalid argument(s).");
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
	if ((str2uchar(argv_ptr, ipmi_priv_limit_ptr) != 0)
Packit Service ed0f68
			|| ((*ipmi_priv_limit_ptr < 0x01
Packit Service ed0f68
				|| *ipmi_priv_limit_ptr > 0x05)
Packit Service ed0f68
				&& *ipmi_priv_limit_ptr != 0x0F)) {
Packit Service ed0f68
		lprintf(LOG_ERR,
Packit Service ed0f68
				"Given Privilege Limit '%s' is invalid.",
Packit Service ed0f68
				argv_ptr);
Packit Service ed0f68
		lprintf(LOG_ERR,
Packit Service ed0f68
				"Privilege Limit is limited to <0x1..0x5> and <0xF>.");
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
uint16_t
Packit Service ed0f68
ipmi_get_oem_id(struct ipmi_intf *intf)
Packit Service ed0f68
{
Packit Service ed0f68
	/* Execute a Get Board ID command to determine the board */
Packit Service ed0f68
	struct ipmi_rs *rsp;
Packit Service ed0f68
	struct ipmi_rq req;
Packit Service ed0f68
	uint16_t oem_id;
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn = IPMI_NETFN_TSOL;
Packit Service ed0f68
	req.msg.cmd   = 0x21;
Packit Service ed0f68
	req.msg.data_len = 0;
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Get Board ID command failed");
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	if (rsp->ccode > 0) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Get Board ID command failed: %#x %s",
Packit Service ed0f68
			rsp->ccode, val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	oem_id = rsp->data[0] | (rsp->data[1] << 8);
Packit Service ed0f68
	lprintf(LOG_DEBUG,"Board ID: %x", oem_id);
Packit Service ed0f68
Packit Service ed0f68
	return oem_id;
Packit Service ed0f68
}