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