helper.c 23 KB

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