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