xref: /openbmc/ipmitool/lib/helper.c (revision 6ca88cb6)
1 /*
2  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * Redistribution of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * Redistribution in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * This software is provided "AS IS," without a warranty of any kind.
20  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>  /* For TIOCNOTTY */
36 
37 #include <stdlib.h>
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <inttypes.h>
41 #include <signal.h>
42 #include <string.h>
43 #include <strings.h>
44 #include <unistd.h>
45 #include <fcntl.h>
46 #include <errno.h>
47 #include <assert.h>
48 
49 #if HAVE_CONFIG_H
50 # include <config.h>
51 #endif
52 
53 #ifdef HAVE_PATHS_H
54 # include <paths.h>
55 #else
56 # define _PATH_VARRUN "/var/run/"
57 #endif
58 
59 #include <ipmitool/ipmi.h>
60 #include <ipmitool/ipmi_intf.h>
61 #include <ipmitool/helper.h>
62 #include <ipmitool/log.h>
63 
64 extern int verbose;
65 
66 uint32_t buf2long(uint8_t * buf)
67 {
68 	return (uint32_t)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]);
69 }
70 
71 uint16_t buf2short(uint8_t * buf)
72 {
73 	return (uint16_t)(buf[1] << 8 | buf[0]);
74 }
75 
76 const char * buf2str(uint8_t * buf, int len)
77 {
78 	static char str[2049];
79 	int i;
80 
81 	if (len <= 0 || len > 1024)
82 		return NULL;
83 
84 	memset(str, 0, 2049);
85 
86 	for (i=0; i<len; i++)
87 		sprintf(str+i+i, "%2.2x", buf[i]);
88 
89 	str[len*2] = '\0';
90 
91 	return (const char *)str;
92 }
93 
94 void printbuf(const uint8_t * buf, int len, const char * desc)
95 {
96 	int i;
97 
98 	if (len <= 0)
99 		return;
100 
101 	if (verbose < 1)
102 		return;
103 
104 	fprintf(stderr, "%s (%d bytes)\n", desc, len);
105 	for (i=0; i<len; i++) {
106 		if (((i%16) == 0) && (i != 0))
107 			fprintf(stderr, "\n");
108 		fprintf(stderr, " %2.2x", buf[i]);
109 	}
110 	fprintf(stderr, "\n");
111 }
112 
113 const char * val2str(uint16_t val, const struct valstr *vs)
114 {
115 	static char un_str[32];
116 	int i;
117 
118 	for (i = 0; vs[i].str != NULL; i++) {
119 		if (vs[i].val == val)
120 			return vs[i].str;
121 	}
122 
123 	memset(un_str, 0, 32);
124 	snprintf(un_str, 32, "Unknown (0x%02X)", val);
125 
126 	return un_str;
127 }
128 
129 const char * oemval2str(uint32_t oem, uint16_t val,
130                                              const struct oemvalstr *vs)
131 {
132 	static char un_str[32];
133 	int i;
134 
135 	for (i = 0; vs[i].oem != 0xffffff &&  vs[i].str != NULL; i++) {
136 		/* FIXME: for now on we assume PICMG capability on all IANAs */
137 		if ( (vs[i].oem == oem || vs[i].oem == IPMI_OEM_PICMG) &&
138 				vs[i].val == val ) {
139 			return vs[i].str;
140 		}
141 	}
142 
143 	memset(un_str, 0, 32);
144 	snprintf(un_str, 32, "Unknown (0x%X)", val);
145 
146 	return un_str;
147 }
148 
149 /* str2double - safely convert string to double
150  *
151  * @str: source string to convert from
152  * @double_ptr: pointer where to store result
153  *
154  * returns zero on success
155  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
156  */
157 int str2double(const char * str, double * double_ptr)
158 {
159 	char * end_ptr = 0;
160 	if (!str || !double_ptr)
161 		return (-1);
162 
163 	*double_ptr = 0;
164 	errno = 0;
165 	*double_ptr = strtod(str, &end_ptr);
166 
167 	if (*end_ptr != '\0')
168 		return (-2);
169 
170 	if (errno != 0)
171 		return (-3);
172 
173 	return 0;
174 } /* str2double(...) */
175 
176 /* str2long - safely convert string to int64_t
177  *
178  * @str: source string to convert from
179  * @lng_ptr: pointer where to store result
180  *
181  * returns zero on success
182  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
183  */
184 int str2long(const char * str, int64_t * lng_ptr)
185 {
186 	char * end_ptr = 0;
187 	if (!str || !lng_ptr)
188 		return (-1);
189 
190 	*lng_ptr = 0;
191 	errno = 0;
192 	*lng_ptr = strtol(str, &end_ptr, 0);
193 
194 	if (*end_ptr != '\0')
195 		return (-2);
196 
197 	if (errno != 0)
198 		return (-3);
199 
200 	return 0;
201 } /* str2long(...) */
202 
203 /* str2ulong - safely convert string to uint64_t
204  *
205  * @str: source string to convert from
206  * @ulng_ptr: pointer where to store result
207  *
208  * returns zero on success
209  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
210  */
211 int str2ulong(const char * str, uint64_t * ulng_ptr)
212 {
213 	char * end_ptr = 0;
214 	if (!str || !ulng_ptr)
215 		return (-1);
216 
217 	*ulng_ptr = 0;
218 	errno = 0;
219 	*ulng_ptr = strtoul(str, &end_ptr, 0);
220 
221 	if (*end_ptr != '\0')
222 		return (-2);
223 
224 	if (errno != 0)
225 		return (-3);
226 
227 	return 0;
228 } /* str2ulong(...) */
229 
230 /* str2int - safely convert string to int32_t
231  *
232  * @str: source string to convert from
233  * @int_ptr: pointer where to store result
234  *
235  * returns zero on success
236  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
237  */
238 int str2int(const char * str, int32_t * int_ptr)
239 {
240 	int rc = 0;
241 	int64_t arg_long = 0;
242 	if (!str || !int_ptr)
243 		return (-1);
244 
245 	if ( (rc = str2long(str, &arg_long)) != 0 ) {
246 		*int_ptr = 0;
247 		return rc;
248 	}
249 
250 	if (arg_long < INT32_MIN || arg_long > INT32_MAX)
251 		return (-3);
252 
253 	*int_ptr = (int32_t)arg_long;
254 	return 0;
255 } /* str2int(...) */
256 
257 /* str2uint - safely convert string to uint32_t
258  *
259  * @str: source string to convert from
260  * @uint_ptr: pointer where to store result
261  *
262  * returns zero on success
263  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
264  */
265 int str2uint(const char * str, uint32_t * uint_ptr)
266 {
267 	int rc = 0;
268 	uint64_t arg_ulong = 0;
269 	if (!str || !uint_ptr)
270 		return (-1);
271 
272 	if ( (rc = str2ulong(str, &arg_ulong)) != 0) {
273 		*uint_ptr = 0;
274 		return rc;
275 	}
276 
277 	if (arg_ulong > UINT32_MAX)
278 		return (-3);
279 
280 	*uint_ptr = (uint32_t)arg_ulong;
281 	return 0;
282 } /* str2uint(...) */
283 
284 /* str2short - safely convert string to int16_t
285  *
286  * @str: source string to convert from
287  * @shrt_ptr: pointer where to store result
288  *
289  * returns zero on success
290  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
291  */
292 int str2short(const char * str, int16_t * shrt_ptr)
293 {
294 	int rc = (-3);
295 	int64_t arg_long = 0;
296 	if (!str || !shrt_ptr)
297 		return (-1);
298 
299 	if ( (rc = str2long(str, &arg_long)) != 0 ) {
300 		*shrt_ptr = 0;
301 		return rc;
302 	}
303 
304 	if (arg_long < INT16_MIN || arg_long > INT16_MAX)
305 		return (-3);
306 
307 	*shrt_ptr = (int16_t)arg_long;
308 	return 0;
309 } /* str2short(...) */
310 
311 /* str2ushort - safely convert string to uint16_t
312  *
313  * @str: source string to convert from
314  * @ushrt_ptr: pointer where to store result
315  *
316  * returns zero on success
317  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
318  */
319 int str2ushort(const char * str, uint16_t * ushrt_ptr)
320 {
321 	int rc = (-3);
322 	uint64_t arg_ulong = 0;
323 	if (!str || !ushrt_ptr)
324 		return (-1);
325 
326 	if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
327 		*ushrt_ptr = 0;
328 		return rc;
329 	}
330 
331 	if (arg_ulong > UINT16_MAX)
332 		return (-3);
333 
334 	*ushrt_ptr = (uint16_t)arg_ulong;
335 	return 0;
336 } /* str2ushort(...) */
337 
338 /* str2char - safely convert string to int8
339  *
340  * @str: source string to convert from
341  * @chr_ptr: pointer where to store result
342  *
343  * returns zero on success
344  * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
345  */
346 int str2char(const char *str, int8_t * chr_ptr)
347 {
348 	int rc = (-3);
349 	int64_t arg_long = 0;
350 	if (!str || !chr_ptr) {
351 		return (-1);
352 	}
353 	if ((rc = str2long(str, &arg_long)) != 0) {
354 		*chr_ptr = 0;
355 		return rc;
356 	}
357 	if (arg_long < INT8_MIN || arg_long > INT8_MAX) {
358 		return (-3);
359 	}
360 	*chr_ptr = (uint8_t)arg_long;
361 	return 0;
362 } /* str2char(...) */
363 
364 /* str2uchar - safely convert string to uint8
365  *
366  * @str: source string to convert from
367  * @uchr_ptr: pointer where to store result
368  *
369  * returns zero on success
370  * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
371  */
372 int str2uchar(const char * str, uint8_t * uchr_ptr)
373 {
374 	int rc = (-3);
375 	uint64_t arg_ulong = 0;
376 	if (!str || !uchr_ptr)
377 		return (-1);
378 
379 	if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
380 		*uchr_ptr = 0;
381 		return rc;
382 	}
383 
384 	if (arg_ulong > UINT8_MAX)
385 		return (-3);
386 
387 	*uchr_ptr = (uint8_t)arg_ulong;
388 	return 0;
389 } /* str2uchar(...) */
390 
391 uint16_t str2val(const char *str, const struct valstr *vs)
392 {
393 	int i;
394 
395 	for (i = 0; vs[i].str != NULL; i++) {
396 		if (strncasecmp(vs[i].str, str, __maxlen(str, vs[i].str)) == 0)
397 			return vs[i].val;
398 	}
399 
400 	return vs[i].val;
401 }
402 
403 /* print_valstr  -  print value string list to log or stdout
404  *
405  * @vs:		value string list to print
406  * @title:	name of this value string list
407  * @loglevel:	what log level to print, -1 for stdout
408  */
409 void
410 print_valstr(const struct valstr * vs, const char * title, int loglevel)
411 {
412 	int i;
413 
414 	if (vs == NULL)
415 		return;
416 
417 	if (title != NULL) {
418 		if (loglevel < 0)
419 			printf("\n%s:\n\n", title);
420 		else
421 			lprintf(loglevel, "\n%s:\n", title);
422 	}
423 
424 	if (loglevel < 0) {
425 		printf("  VALUE\tHEX\tSTRING\n");
426 		printf("==============================================\n");
427 	} else {
428 		lprintf(loglevel, "  VAL\tHEX\tSTRING");
429 		lprintf(loglevel, "==============================================");
430 	}
431 
432 	for (i = 0; vs[i].str != NULL; i++) {
433 		if (loglevel < 0) {
434 			if (vs[i].val < 256)
435 				printf("  %d\t0x%02x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
436 			else
437 				printf("  %d\t0x%04x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
438 		} else {
439 			if (vs[i].val < 256)
440 				lprintf(loglevel, "  %d\t0x%02x\t%s", vs[i].val, vs[i].val, vs[i].str);
441 			else
442 				lprintf(loglevel, "  %d\t0x%04x\t%s", vs[i].val, vs[i].val, vs[i].str);
443 		}
444 	}
445 
446 	if (loglevel < 0)
447 		printf("\n");
448 	else
449 		lprintf(loglevel, "");
450 }
451 
452 /* print_valstr_2col  -  print value string list in two columns to log or stdout
453  *
454  * @vs:		value string list to print
455  * @title:	name of this value string list
456  * @loglevel:	what log level to print, -1 for stdout
457  */
458 void
459 print_valstr_2col(const struct valstr * vs, const char * title, int loglevel)
460 {
461 	int i;
462 
463 	if (vs == NULL)
464 		return;
465 
466 	if (title != NULL) {
467 		if (loglevel < 0)
468 			printf("\n%s:\n\n", title);
469 		else
470 			lprintf(loglevel, "\n%s:\n", title);
471 	}
472 
473 	for (i = 0; vs[i].str != NULL; i++) {
474 		if (vs[i+1].str == NULL) {
475 			/* last one */
476 			if (loglevel < 0) {
477 				printf("  %4d  %-32s\n", vs[i].val, vs[i].str);
478 			} else {
479 				lprintf(loglevel, "  %4d  %-32s\n", vs[i].val, vs[i].str);
480 			}
481 		}
482 		else {
483 			if (loglevel < 0) {
484 				printf("  %4d  %-32s    %4d  %-32s\n",
485 				       vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
486 			} else {
487 				lprintf(loglevel, "  %4d  %-32s    %4d  %-32s\n",
488 					vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
489 			}
490 			i++;
491 		}
492 	}
493 
494 	if (loglevel < 0)
495 		printf("\n");
496 	else
497 		lprintf(loglevel, "");
498 }
499 
500 /* ipmi_csum  -  calculate an ipmi checksum
501  *
502  * @d:		buffer to check
503  * @s:		position in buffer to start checksum from
504  */
505 uint8_t
506 ipmi_csum(uint8_t * d, int s)
507 {
508 	uint8_t c = 0;
509 	for (; s > 0; s--, d++)
510 		c += *d;
511 	return -c;
512 }
513 
514 /* ipmi_open_file  -  safely open a file for reading or writing
515  *
516  * @file:	filename
517  * @rw:		read-write flag, 1=write
518  *
519  * returns pointer to file handler on success
520  * returns NULL on error
521  */
522 FILE *
523 ipmi_open_file(const char * file, int rw)
524 {
525 	struct stat st1, st2;
526 	FILE * fp;
527 
528 	/* verify existance */
529 	if (lstat(file, &st1) < 0) {
530 		if (rw) {
531 			/* does not exist, ok to create */
532 			fp = fopen(file, "w");
533 			if (fp == NULL) {
534 				lperror(LOG_ERR, "Unable to open file %s "
535 					"for write", file);
536 				return NULL;
537 			}
538 			/* created ok, now return the descriptor */
539 			return fp;
540 		} else {
541 			lprintf(LOG_ERR, "File %s does not exist", file);
542 			return NULL;
543 		}
544 	}
545 
546 #ifndef ENABLE_FILE_SECURITY
547 	if (!rw) {
548 		/* on read skip the extra checks */
549 		fp = fopen(file, "r");
550 		if (fp == NULL) {
551 			lperror(LOG_ERR, "Unable to open file %s", file);
552 			return NULL;
553 		}
554 		return fp;
555 	}
556 #endif
557 
558 	/* it exists - only regular files, not links */
559 	if (S_ISREG(st1.st_mode) == 0) {
560 		lprintf(LOG_ERR, "File %s has invalid mode: %d",
561 			file, st1.st_mode);
562 		return NULL;
563 	}
564 
565 	/* allow only files with 1 link (itself) */
566 	if (st1.st_nlink != 1) {
567 		lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
568 		       file, (int)st1.st_nlink);
569 		return NULL;
570 	}
571 
572 	fp = fopen(file, rw ? "w+" : "r");
573 	if (fp == NULL) {
574 		lperror(LOG_ERR, "Unable to open file %s", file);
575 		return NULL;
576 	}
577 
578 	/* stat again */
579 	if (fstat(fileno(fp), &st2) < 0) {
580 		lperror(LOG_ERR, "Unable to stat file %s", file);
581 		fclose(fp);
582 		return NULL;
583 	}
584 
585 	/* verify inode */
586 	if (st1.st_ino != st2.st_ino) {
587 		lprintf(LOG_ERR, "File %s has invalid inode: %d != %d",
588 			file, st1.st_ino, st2.st_ino);
589 		fclose(fp);
590 		return NULL;
591 	}
592 
593 	/* verify owner */
594 	if (st1.st_uid != st2.st_uid) {
595 		lprintf(LOG_ERR, "File %s has invalid user id: %d != %d",
596 			file, st1.st_uid, st2.st_uid);
597 		fclose(fp);
598 		return NULL;
599 	}
600 
601 	/* verify inode */
602 	if (st2.st_nlink != 1) {
603 		lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
604 			file, st2.st_nlink);
605 		fclose(fp);
606 		return NULL;
607 	}
608 
609 	return fp;
610 }
611 
612 void
613 ipmi_start_daemon(struct ipmi_intf *intf)
614 {
615 	pid_t pid;
616 	int fd;
617 #ifdef SIGHUP
618 	sigset_t sighup;
619 #endif
620 
621 #ifdef SIGHUP
622 	sigemptyset(&sighup);
623 	sigaddset(&sighup, SIGHUP);
624 	if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0)
625 		fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
626 	signal(SIGHUP, SIG_IGN);
627 #endif
628 #ifdef SIGTTOU
629 	signal(SIGTTOU, SIG_IGN);
630 #endif
631 #ifdef SIGTTIN
632 	signal(SIGTTIN, SIG_IGN);
633 #endif
634 #ifdef SIGQUIT
635 	signal(SIGQUIT, SIG_IGN);
636 #endif
637 #ifdef SIGTSTP
638 	signal(SIGTSTP, SIG_IGN);
639 #endif
640 
641 	pid = (pid_t) fork();
642 	if (pid < 0 || pid > 0)
643 		exit(0);
644 
645 #if defined(SIGTSTP) && defined(TIOCNOTTY)
646 	if (setpgid(0, getpid()) == -1)
647 		exit(1);
648 	if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
649 		ioctl(fd, TIOCNOTTY, NULL);
650 		close(fd);
651 	}
652 #else
653 	if (setpgid(0, 0) == -1)
654 		exit(1);
655 	pid = (pid_t) fork();
656 	if (pid < 0 || pid > 0)
657 		exit(0);
658 #endif
659 
660 	chdir("/");
661 	umask(0);
662 
663 	for (fd=0; fd<64; fd++) {
664 		if (fd != intf->fd)
665 			close(fd);
666 	}
667 
668 	fd = open("/dev/null", O_RDWR);
669 	assert(0 == fd);
670 	dup(fd);
671 	dup(fd);
672 }
673 
674 /* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed
675  * on error.
676  * FRU ID range: <0..255>
677  *
678  * @argv_ptr: source string to convert from; usually argv
679  * @fru_id_ptr: pointer where to store result
680  *
681  * returns zero on success
682  * returns (-1) on error and message is printed on STDERR
683  */
684 int
685 is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr)
686 {
687 	if (!argv_ptr || !fru_id_ptr) {
688 		lprintf(LOG_ERR, "is_fru_id(): invalid argument(s).");
689 		return (-1);
690 	}
691 
692 	if (str2uchar(argv_ptr, fru_id_ptr) == 0) {
693 		return 0;
694 	}
695 	lprintf(LOG_ERR, "FRU ID '%s' is either invalid or out of range.",
696 			argv_ptr);
697 	return (-1);
698 } /* is_fru_id(...) */
699 
700 /* is_ipmi_channel_num - wrapper for str-2-int Channel conversion. Message is
701  * printed on error.
702  *
703  * 6.3 Channel Numbers, p. 49, IPMIv2 spec. rev1.1
704  * Valid channel numbers are: <0x0..0xB>, <0xE-0xF>
705  * Reserved channel numbers: <0xC-0xD>
706  *
707  * @argv_ptr: source string to convert from; usually argv
708  * @channel_ptr: pointer where to store result
709  *
710  * returns zero on success
711  * returns (-1) on error and message is printed on STDERR
712  */
713 int
714 is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr)
715 {
716 	if (!argv_ptr || !channel_ptr) {
717 		lprintf(LOG_ERR,
718 				"is_ipmi_channel_num(): invalid argument(s).");
719 		return (-1);
720 	}
721 	if ((str2uchar(argv_ptr, channel_ptr) == 0)
722 			&& ((*channel_ptr >= 0x0 && *channel_ptr <= 0xB)
723 				|| (*channel_ptr >= 0xE && *channel_ptr <= 0xF))) {
724 		return 0;
725 	}
726 	lprintf(LOG_ERR,
727 			"Given Channel number '%s' is either invalid or out of range.",
728 			argv_ptr);
729 	lprintf(LOG_ERR, "Channel number must be from ranges: <0x0..0xB>, <0xE..0xF>");
730 	return (-1);
731 }
732 
733 /* is_ipmi_user_id() - wrapper for str-2-uint IPMI UID conversion. Message is
734  * printed on error.
735  *
736  * @argv_ptr: source string to convert from; usually argv
737  * @ipmi_uid_ptr: pointer where to store result
738  *
739  * returns zero on success
740  * returns (-1) on error and message is printed on STDERR
741  */
742 int
743 is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr)
744 {
745 	if (!argv_ptr || !ipmi_uid_ptr) {
746 		lprintf(LOG_ERR,
747 				"is_ipmi_user_id(): invalid argument(s).");
748 		return (-1);
749 	}
750 	if ((str2uchar(argv_ptr, ipmi_uid_ptr) == 0)
751 			&& *ipmi_uid_ptr >= IPMI_UID_MIN
752 			&& *ipmi_uid_ptr <= IPMI_UID_MAX) {
753 		return 0;
754 	}
755 	lprintf(LOG_ERR,
756 			"Given User ID '%s' is either invalid or out of range.",
757 			argv_ptr);
758 	lprintf(LOG_ERR, "User ID is limited to range <%i..%i>.",
759 			IPMI_UID_MIN, IPMI_UID_MAX);
760 	return (-1);
761 }
762 
763 /* is_ipmi_user_priv_limit - check whether given value is valid User Privilege
764  * Limit, eg. IPMI v2 spec, 22.27 Get User Access Command.
765  *
766  * @priv_limit: User Privilege Limit
767  *
768  * returns 0 if Priv Limit is valid
769  * returns (-1) when Priv Limit is invalid
770  */
771 int
772 is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr)
773 {
774 	if (!argv_ptr || !ipmi_priv_limit_ptr) {
775 		lprintf(LOG_ERR,
776 				"is_ipmi_user_priv_limit(): invalid argument(s).");
777 		return (-1);
778 	}
779 	if ((str2uchar(argv_ptr, ipmi_priv_limit_ptr) != 0)
780 			|| ((*ipmi_priv_limit_ptr < 0x01
781 				|| *ipmi_priv_limit_ptr > 0x05)
782 				&& *ipmi_priv_limit_ptr != 0x0F)) {
783 		lprintf(LOG_ERR,
784 				"Given Privilege Limit '%s' is invalid.",
785 				argv_ptr);
786 		lprintf(LOG_ERR,
787 				"Privilege Limit is limited to <0x1..0x5> and <0xF>.");
788 		return (-1);
789 	}
790 	return 0;
791 }
792 
793 uint16_t
794 ipmi_get_oem_id(struct ipmi_intf *intf)
795 {
796 	/* Execute a Get Board ID command to determine the board */
797 	struct ipmi_rs *rsp;
798 	struct ipmi_rq req;
799 	uint16_t oem_id;
800 
801 	memset(&req, 0, sizeof(req));
802 	req.msg.netfn = IPMI_NETFN_TSOL;
803 	req.msg.cmd   = 0x21;
804 	req.msg.data_len = 0;
805 
806 	rsp = intf->sendrecv(intf, &req);
807 	if (rsp == NULL) {
808 		lprintf(LOG_ERR, "Get Board ID command failed");
809 		return 0;
810 	}
811 	if (rsp->ccode > 0) {
812 		lprintf(LOG_ERR, "Get Board ID command failed: %#x %s",
813 			rsp->ccode, val2str(rsp->ccode, completion_code_vals));
814 		return 0;
815 	}
816 	oem_id = rsp->data[0] | (rsp->data[1] << 8);
817 	lprintf(LOG_DEBUG,"Board ID: %x", oem_id);
818 
819 	return oem_id;
820 }
821