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 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 72 uint16_t buf2short(uint8_t * buf) 73 { 74 return (uint16_t)(buf[1] << 8 | buf[0]); 75 } 76 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 * 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 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 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 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 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 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 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 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