helper.c 23 KB

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